diff --git a/chrome/browser/resources/pdf/pdf_viewer.js b/chrome/browser/resources/pdf/pdf_viewer.js
index 760160c8652a9..d5a432f6385db 100644
--- a/chrome/browser/resources/pdf/pdf_viewer.js
+++ b/chrome/browser/resources/pdf/pdf_viewer.js
@@ -1291,6 +1291,9 @@ export class PDFViewer {
           type: 'touchSelectionOccurred',
         });
         return;
+      case 'documentFocusChanged':
+        // TODO(crbug.com/1069370): Draw a focus rect around plugin.
+        return;
     }
     assertNotReached('Unknown message type received: ' + data.type);
   }
diff --git a/pdf/out_of_process_instance.cc b/pdf/out_of_process_instance.cc
index 0ae0e1637bbd4..780c73aaa122d 100644
--- a/pdf/out_of_process_instance.cc
+++ b/pdf/out_of_process_instance.cc
@@ -186,6 +186,10 @@ constexpr char kJSIsSelecting[] = "isSelecting";
 constexpr char kJSFieldFocusType[] = "formFocusChange";
 constexpr char kJSFieldFocus[] = "focused";
 
+// Notify when document is focused (Plugin -> Page)
+constexpr char kJSDocumentFocusChangedType[] = "documentFocusChanged";
+constexpr char kJSDocumentHasFocus[] = "hasFocus";
+
 constexpr int kFindResultCooldownMs = 100;
 
 // Do not save forms with over 100 MB. This cap should be kept in sync with and
@@ -1934,6 +1938,13 @@ float OutOfProcessInstance::GetToolbarHeightInScreenCoords() {
   return top_toolbar_height_in_viewport_coords_ * device_scale_;
 }
 
+void OutOfProcessInstance::DocumentFocusChanged(bool document_has_focus) {
+  pp::VarDictionary message;
+  message.Set(pp::Var(kType), pp::Var(kJSDocumentFocusChangedType));
+  message.Set(pp::Var(kJSDocumentHasFocus), pp::Var(document_has_focus));
+  PostMessage(message);
+}
+
 void OutOfProcessInstance::ProcessPreviewPageInfo(const std::string& url,
                                                   int dest_page_index) {
   DCHECK(IsPrintPreview());
diff --git a/pdf/out_of_process_instance.h b/pdf/out_of_process_instance.h
index e8c00636d7a01..6ac651287735a 100644
--- a/pdf/out_of_process_instance.h
+++ b/pdf/out_of_process_instance.h
@@ -146,6 +146,7 @@ class OutOfProcessInstance : public pp::Instance,
   void SelectionChanged(const pp::Rect& left, const pp::Rect& right) override;
   void IsEditModeChanged(bool is_edit_mode) override;
   float GetToolbarHeightInScreenCoords() override;
+  void DocumentFocusChanged(bool document_has_focus) override;
 
   // PreviewModeClient::Client implementation.
   void PreviewDocumentLoadComplete() override;
diff --git a/pdf/pdf_engine.h b/pdf/pdf_engine.h
index 33dbe762bd186..51284e1177faf 100644
--- a/pdf/pdf_engine.h
+++ b/pdf/pdf_engine.h
@@ -266,6 +266,9 @@ class PDFEngine {
     // Gets the height of the top toolbar in screen coordinates. This is
     // independent of whether it is hidden or not at the moment.
     virtual float GetToolbarHeightInScreenCoords() = 0;
+
+    // Notifies the client about focus changes for the document.
+    virtual void DocumentFocusChanged(bool document_has_focus) {}
   };
 
   struct AccessibilityLinkInfo {
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc
index 3adfadd68513b..425ac23b26e57 100644
--- a/pdf/pdfium/pdfium_engine.cc
+++ b/pdf/pdfium/pdfium_engine.cc
@@ -947,7 +947,7 @@ void PDFiumEngine::KillFormFocus() {
 
 void PDFiumEngine::UpdateFocus(bool has_focus) {
   if (has_focus) {
-    focus_item_type_ = last_focused_item_type_;
+    UpdateFocusItemType(last_focused_item_type_);
     if (focus_item_type_ == FocusElementType::kPage &&
         PageIndexInBounds(last_focused_page_) &&
         last_focused_annot_index_ != -1) {
@@ -961,7 +961,7 @@ void PDFiumEngine::UpdateFocus(bool has_focus) {
   } else {
     last_focused_item_type_ = focus_item_type_;
     if (focus_item_type_ == FocusElementType::kDocument) {
-      focus_item_type_ = FocusElementType::kNone;
+      UpdateFocusItemType(FocusElementType::kNone);
     } else if (focus_item_type_ == FocusElementType::kPage) {
       FPDF_ANNOTATION last_focused_annot = nullptr;
       FPDF_BOOL ret = FORM_GetFocusedAnnot(form(), &last_focused_page_,
@@ -1119,7 +1119,7 @@ bool PDFiumEngine::OnLeftMouseDown(const pp::MouseInputEvent& event) {
     return true;
 
   if (page_index != -1) {
-    focus_item_type_ = FocusElementType::kPage;
+    UpdateFocusItemType(FocusElementType::kPage);
     last_focused_page_ = page_index;
     double page_x;
     double page_y;
@@ -3849,7 +3849,7 @@ bool PDFiumEngine::HandleTabEventWithModifiers(uint32_t modifiers) {
 
 bool PDFiumEngine::HandleTabForward(uint32_t modifiers) {
   if (focus_item_type_ == FocusElementType::kNone) {
-    focus_item_type_ = FocusElementType::kDocument;
+    UpdateFocusItemType(FocusElementType::kDocument);
     return true;
   }
 
@@ -3867,17 +3867,17 @@ bool PDFiumEngine::HandleTabForward(uint32_t modifiers) {
 
   if (did_tab_forward) {
     last_focused_page_ = page_index;
-    focus_item_type_ = FocusElementType::kPage;
+    UpdateFocusItemType(FocusElementType::kPage);
   } else {
     last_focused_page_ = -1;
-    focus_item_type_ = FocusElementType::kNone;
+    UpdateFocusItemType(FocusElementType::kNone);
   }
   return did_tab_forward;
 }
 
 bool PDFiumEngine::HandleTabBackward(uint32_t modifiers) {
   if (focus_item_type_ == FocusElementType::kDocument) {
-    focus_item_type_ = FocusElementType::kNone;
+    UpdateFocusItemType(FocusElementType::kNone);
     return false;
   }
 
@@ -3895,7 +3895,7 @@ bool PDFiumEngine::HandleTabBackward(uint32_t modifiers) {
 
   if (did_tab_backward) {
     last_focused_page_ = page_index;
-    focus_item_type_ = FocusElementType::kPage;
+    UpdateFocusItemType(FocusElementType::kPage);
   } else {
     // No focusable annotation found in pages. Possible scenarios:
     // Case 1: |focus_item_type_| is None. Since no object in any page can take
@@ -3908,11 +3908,11 @@ bool PDFiumEngine::HandleTabBackward(uint32_t modifiers) {
       case FocusElementType::kNone:
         did_tab_backward = true;
         last_focused_page_ = -1;
-        focus_item_type_ = FocusElementType::kDocument;
+        UpdateFocusItemType(FocusElementType::kDocument);
         KillFormFocus();
         break;
       case FocusElementType::kDocument:
-        focus_item_type_ = FocusElementType::kNone;
+        UpdateFocusItemType(FocusElementType::kNone);
         break;
       default:
         NOTREACHED();
@@ -3922,6 +3922,16 @@ bool PDFiumEngine::HandleTabBackward(uint32_t modifiers) {
   return did_tab_backward;
 }
 
+void PDFiumEngine::UpdateFocusItemType(FocusElementType focus_item_type) {
+  if (focus_item_type_ == focus_item_type)
+    return;
+  if (focus_item_type_ == FocusElementType::kDocument)
+    client_->DocumentFocusChanged(false);
+  focus_item_type_ = focus_item_type;
+  if (focus_item_type_ == FocusElementType::kDocument)
+    client_->DocumentFocusChanged(true);
+}
+
 #if defined(PDF_ENABLE_XFA)
 void PDFiumEngine::UpdatePageCount() {
   InvalidateAllPages();
diff --git a/pdf/pdfium/pdfium_engine.h b/pdf/pdfium/pdfium_engine.h
index 16e33cf32e315..c79ee7fd80897 100644
--- a/pdf/pdfium/pdfium_engine.h
+++ b/pdf/pdfium/pdfium_engine.h
@@ -606,6 +606,10 @@ class PDFiumEngine : public PDFEngine,
   bool HandleTabForward(uint32_t modifiers);
   bool HandleTabBackward(uint32_t modifiers);
 
+  // Updates the currently focused object stored in |focus_item_type_|. Notifies
+  // |client_| about document focus change, if any.
+  void UpdateFocusItemType(FocusElementType focus_item_type);
+
   void UpdateLinkUnderCursor(const std::string& target_url);
   void SetLinkUnderCursorForAnnotation(FPDF_ANNOTATION annot, int page_index);
 
diff --git a/pdf/pdfium/pdfium_engine_unittest.cc b/pdf/pdfium/pdfium_engine_unittest.cc
index 623c8e11b4aeb..b112703fa9a4c 100644
--- a/pdf/pdfium/pdfium_engine_unittest.cc
+++ b/pdf/pdfium/pdfium_engine_unittest.cc
@@ -227,6 +227,17 @@ TEST_F(PDFiumEngineTest, GetBadPdfVersion) {
 
 }  // namespace
 
+class TabbingTestClient : public TestClient {
+ public:
+  TabbingTestClient() = default;
+  ~TabbingTestClient() override = default;
+  TabbingTestClient(const TabbingTestClient&) = delete;
+  TabbingTestClient& operator=(const TabbingTestClient&) = delete;
+
+  // Mock PDFEngine::Client methods.
+  MOCK_METHOD1(DocumentFocusChanged, void(bool));
+};
+
 class PDFiumEngineTabbingTest : public PDFiumTestBase {
  public:
   PDFiumEngineTabbingTest() = default;
@@ -376,13 +387,20 @@ TEST_F(PDFiumEngineTabbingTest, TabbingForwardTest) {
    * ++ Page 2
    * ++++ Annotation
    */
-  TestClient client;
+  TabbingTestClient client;
   std::unique_ptr<PDFiumEngine> engine = InitializeEngine(
       &client, FILE_PATH_LITERAL("annotation_form_fields.pdf"));
   ASSERT_TRUE(engine);
 
   ASSERT_EQ(2, engine->GetNumberOfPages());
 
+  static constexpr bool kExpectedFocusState[] = {true, false};
+  {
+    InSequence sequence;
+    for (auto focused : kExpectedFocusState)
+      EXPECT_CALL(client, DocumentFocusChanged(focused));
+  }
+
   ASSERT_EQ(PDFiumEngine::FocusElementType::kNone,
             GetFocusedElementType(engine.get()));
   EXPECT_EQ(-1, GetLastFocusedPage(engine.get()));
@@ -421,13 +439,20 @@ TEST_F(PDFiumEngineTabbingTest, TabbingBackwardTest) {
    * ++ Page 2
    * ++++ Annotation
    */
-  TestClient client;
+  TabbingTestClient client;
   std::unique_ptr<PDFiumEngine> engine = InitializeEngine(
       &client, FILE_PATH_LITERAL("annotation_form_fields.pdf"));
   ASSERT_TRUE(engine);
 
   ASSERT_EQ(2, engine->GetNumberOfPages());
 
+  static constexpr bool kExpectedFocusState[] = {true, false};
+  {
+    InSequence sequence;
+    for (auto focused : kExpectedFocusState)
+      EXPECT_CALL(client, DocumentFocusChanged(focused));
+  }
+
   ASSERT_EQ(PDFiumEngine::FocusElementType::kNone,
             GetFocusedElementType(engine.get()));
   EXPECT_EQ(-1, GetLastFocusedPage(engine.get()));
@@ -510,13 +535,20 @@ TEST_F(PDFiumEngineTabbingTest, NoFocusableItemTabbingTest) {
    * ++ Page 1
    * ++ Page 2
    */
-  TestClient client;
+  TabbingTestClient client;
   std::unique_ptr<PDFiumEngine> engine =
       InitializeEngine(&client, FILE_PATH_LITERAL("hello_world2.pdf"));
   ASSERT_TRUE(engine);
 
   ASSERT_EQ(2, engine->GetNumberOfPages());
 
+  static constexpr bool kExpectedFocusState[] = {true, false, true, false};
+  {
+    InSequence sequence;
+    for (auto focused : kExpectedFocusState)
+      EXPECT_CALL(client, DocumentFocusChanged(focused));
+  }
+
   ASSERT_EQ(PDFiumEngine::FocusElementType::kNone,
             GetFocusedElementType(engine.get()));
   EXPECT_EQ(-1, GetLastFocusedPage(engine.get()));
@@ -550,13 +582,20 @@ TEST_F(PDFiumEngineTabbingTest, RestoringDocumentFocusTest) {
    * ++ Page 2
    * ++++ Annotation
    */
-  TestClient client;
+  TabbingTestClient client;
   std::unique_ptr<PDFiumEngine> engine = InitializeEngine(
       &client, FILE_PATH_LITERAL("annotation_form_fields.pdf"));
   ASSERT_TRUE(engine);
 
   ASSERT_EQ(2, engine->GetNumberOfPages());
 
+  static constexpr bool kExpectedFocusState[] = {true, false, true};
+  {
+    InSequence sequence;
+    for (auto focused : kExpectedFocusState)
+      EXPECT_CALL(client, DocumentFocusChanged(focused));
+  }
+
   EXPECT_EQ(PDFiumEngine::FocusElementType::kNone,
             GetFocusedElementType(engine.get()));
   EXPECT_EQ(-1, GetLastFocusedPage(engine.get()));
@@ -588,13 +627,20 @@ TEST_F(PDFiumEngineTabbingTest, RestoringAnnotFocusTest) {
    * ++ Page 2
    * ++++ Annotation
    */
-  TestClient client;
+  TabbingTestClient client;
   std::unique_ptr<PDFiumEngine> engine = InitializeEngine(
       &client, FILE_PATH_LITERAL("annotation_form_fields.pdf"));
   ASSERT_TRUE(engine);
 
   ASSERT_EQ(2, engine->GetNumberOfPages());
 
+  static constexpr bool kExpectedFocusState[] = {true, false};
+  {
+    InSequence sequence;
+    for (auto focused : kExpectedFocusState)
+      EXPECT_CALL(client, DocumentFocusChanged(focused));
+  }
+
   EXPECT_EQ(PDFiumEngine::FocusElementType::kNone,
             GetFocusedElementType(engine.get()));
   EXPECT_EQ(-1, GetLastFocusedPage(engine.get()));