Send PDF Searchifier running state to browser to show UX elements.
To show PDF Searchify promo and progress state in browser, PDF searchifier's rough state is passed to the PDF document helper in the browser process. This state will be used in the next CLs to show the promo and manage the progress bubble. UX design: https://docs.google.com/presentation/d/17zeY-H3bYpTkyNos_kHEQXaaFOHECHqMLlXorj4DLb0/edit?resourcekey=0-f0k0VHM3j--WirgSZSp5ow#slide=id.YEkgNTa AX-Relnotes: n/a Bug: 360803943 Change-Id: I97a9b7ab40b3404fa4162b9651bf5819ad8ad988 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5968218 Reviewed-by: Lei Zhang <thestig@chromium.org> Reviewed-by: Kinuko Yasuda <kinuko@chromium.org> Reviewed-by: Antonio Sartori <antoniosartori@chromium.org> Auto-Submit: Ramin Halavati <rhalavati@chromium.org> Commit-Queue: Ramin Halavati <rhalavati@chromium.org> Cr-Commit-Position: refs/heads/main@{#1377711}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
04cb0be1b2
commit
a957501802
chrome/browser/ui/pdf
components/pdf/browser
BUILD.gnDEPSpdf_document_helper.ccpdf_document_helper.hpdf_document_helper_browsertest.ccpdf_document_helper_client.h
pdf
@ -19,5 +19,6 @@ source_set("pdf") {
|
||||
"//components/pdf/browser",
|
||||
"//extensions/browser",
|
||||
"//pdf:features",
|
||||
"//services/screen_ai/buildflags",
|
||||
]
|
||||
}
|
||||
|
@ -87,3 +87,11 @@ void ChromePDFDocumentHelperClient::SetPluginCanSave(
|
||||
guest_view->SetPluginCanSave(can_save);
|
||||
}
|
||||
}
|
||||
|
||||
#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
|
||||
void ChromePDFDocumentHelperClient::OnSearchifyStateChange(
|
||||
bool busy,
|
||||
content::WebContents* contents) {
|
||||
// TODO(crbug.com/360803943): Show promo and manage progress bubble.
|
||||
}
|
||||
#endif
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define CHROME_BROWSER_UI_PDF_CHROME_PDF_DOCUMENT_HELPER_CLIENT_H_
|
||||
|
||||
#include "components/pdf/browser/pdf_document_helper_client.h"
|
||||
#include "services/screen_ai/buildflags/buildflags.h"
|
||||
|
||||
class ChromePDFDocumentHelperClient : public pdf::PDFDocumentHelperClient {
|
||||
public:
|
||||
@ -25,6 +26,10 @@ class ChromePDFDocumentHelperClient : public pdf::PDFDocumentHelperClient {
|
||||
void OnSaveURL(content::WebContents* contents) override;
|
||||
void SetPluginCanSave(content::RenderFrameHost* render_frame_host,
|
||||
bool can_save) override;
|
||||
#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
|
||||
void OnSearchifyStateChange(bool busy,
|
||||
content::WebContents* contents) override;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // CHROME_BROWSER_UI_PDF_CHROME_PDF_DOCUMENT_HELPER_CLIENT_H_
|
||||
|
@ -30,6 +30,7 @@ source_set("browser") {
|
||||
"//components/pdf/common:util",
|
||||
"//content/public/common",
|
||||
"//pdf:features",
|
||||
"//services/screen_ai/buildflags",
|
||||
"//ui/base",
|
||||
"//ui/gfx/geometry",
|
||||
]
|
||||
|
@ -10,6 +10,7 @@ include_rules = [
|
||||
"+services/network/public/cpp",
|
||||
"+services/network/public/mojom",
|
||||
"+services/network/test",
|
||||
"+services/screen_ai/buildflags",
|
||||
"+third_party/blink/public/common/associated_interfaces/associated_interface_provider.h",
|
||||
"+third_party/skia/include/core",
|
||||
"+ui/base",
|
||||
|
@ -128,6 +128,12 @@ void PDFDocumentHelper::SetPluginCanSave(bool can_save) {
|
||||
can_save);
|
||||
}
|
||||
|
||||
#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
|
||||
void PDFDocumentHelper::OnSearchifyStateChange(bool busy) {
|
||||
client_->OnSearchifyStateChange(busy, &GetWebContents());
|
||||
}
|
||||
#endif
|
||||
|
||||
void PDFDocumentHelper::DidScroll() {
|
||||
if (!touch_selection_controller_client_manager_) {
|
||||
InitTouchSelectionClientManager();
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "mojo/public/cpp/bindings/pending_remote.h"
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
#include "pdf/mojom/pdf.mojom.h"
|
||||
#include "services/screen_ai/buildflags/buildflags.h"
|
||||
#include "ui/touch_selection/selection_event_type.h"
|
||||
#include "ui/touch_selection/touch_selection_controller.h"
|
||||
#include "ui/touch_selection/touch_selection_menu_runner.h"
|
||||
@ -86,6 +87,9 @@ class PDFDocumentHelper
|
||||
const gfx::PointF& right,
|
||||
int32_t right_height) override;
|
||||
void SetPluginCanSave(bool can_save) override;
|
||||
#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
|
||||
void OnSearchifyStateChange(bool busy) override;
|
||||
#endif
|
||||
|
||||
void GetPdfBytes(uint32_t size_limit,
|
||||
pdf::mojom::PdfListener::GetPdfBytesCallback callback);
|
||||
|
@ -71,6 +71,8 @@ class TestPDFDocumentHelperClient : public PDFDocumentHelperClient {
|
||||
start_ = start;
|
||||
end_ = end;
|
||||
}
|
||||
void OnSearchifyStateChange(bool busy,
|
||||
content::WebContents* contents) override {}
|
||||
|
||||
private:
|
||||
// The last bounds reported by PDFDocumentHelper.
|
||||
|
@ -35,6 +35,10 @@ class PDFDocumentHelperClient {
|
||||
// Lets the client observe scroll events. Only used for testing.
|
||||
virtual void OnDidScroll(const gfx::SelectionBound& start,
|
||||
const gfx::SelectionBound& end) {}
|
||||
|
||||
// See the comment for `OnSearchifyStateChange` in pdf/pdf.mojom.
|
||||
virtual void OnSearchifyStateChange(bool busy,
|
||||
content::WebContents* contents) = 0;
|
||||
};
|
||||
|
||||
} // namespace pdf
|
||||
|
@ -405,6 +405,7 @@ if (enable_pdf) {
|
||||
"//cc:test_support",
|
||||
"//pdf/loader",
|
||||
"//printing",
|
||||
"//services/screen_ai/buildflags",
|
||||
"//testing/gmock",
|
||||
"//testing/gtest",
|
||||
"//third_party/blink/public:blink",
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
import("//build/config/features.gni")
|
||||
import("//mojo/public/tools/bindings/mojom.gni")
|
||||
import("//services/screen_ai/buildflags/features.gni")
|
||||
|
||||
mojom("mojom") {
|
||||
sources = [ "pdf.mojom" ]
|
||||
@ -15,4 +16,8 @@ mojom("mojom") {
|
||||
]
|
||||
|
||||
cpp_only = true
|
||||
|
||||
if (enable_screen_ai_service) {
|
||||
enabled_features = [ "enable_screen_ai_service" ]
|
||||
}
|
||||
}
|
||||
|
@ -55,4 +55,11 @@ interface PdfHost {
|
||||
|
||||
// Notifies the embedder know the plugin can handle save commands internally.
|
||||
SetPluginCanSave(bool can_save);
|
||||
|
||||
// Notifies that PDF searchifier has switched between busy or not busy.
|
||||
// A busy state is when it has some queued pages to process or is processing a
|
||||
// page at the moment. It comes out of this state either when all tasks are
|
||||
// completed or canceled.
|
||||
[EnableIf=enable_screen_ai_service]
|
||||
OnSearchifyStateChange(bool busy);
|
||||
};
|
||||
|
@ -1338,6 +1338,12 @@ bool PdfViewWebPlugin::IsInAnnotationMode() const {
|
||||
}
|
||||
#endif // BUILDFLAG(ENABLE_PDF_INK2)
|
||||
|
||||
#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
|
||||
void PdfViewWebPlugin::OnSearchifyStateChange(bool busy) {
|
||||
pdf_host_->OnSearchifyStateChange(busy);
|
||||
}
|
||||
#endif
|
||||
|
||||
void PdfViewWebPlugin::SetCaretPosition(const gfx::PointF& position) {
|
||||
engine_->SetCaretPosition(FrameToPdfCoordinates(position));
|
||||
}
|
||||
|
@ -389,6 +389,9 @@ class PdfViewWebPlugin final : public PDFiumEngineClient,
|
||||
#if BUILDFLAG(ENABLE_PDF_INK2)
|
||||
bool IsInAnnotationMode() const override;
|
||||
#endif // BUILDFLAG(ENABLE_PDF_INK2)
|
||||
#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
|
||||
void OnSearchifyStateChange(bool busy) override;
|
||||
#endif
|
||||
|
||||
// pdf::mojom::PdfListener:
|
||||
void SetCaretPosition(const gfx::PointF& position) override;
|
||||
|
@ -353,6 +353,9 @@ class FakePdfHost : public pdf::mojom::PdfHost {
|
||||
(const gfx::PointF&, int32_t, const gfx::PointF&, int32_t),
|
||||
(override));
|
||||
MOCK_METHOD(void, SetPluginCanSave, (bool), (override));
|
||||
#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
|
||||
MOCK_METHOD(void, OnSearchifyStateChange, (bool), (override));
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
@ -4265,6 +4265,10 @@ void PDFiumEngine::CancelPendingSearchify(int page_index) {
|
||||
searchifier_->CancelPage(page_index);
|
||||
}
|
||||
}
|
||||
|
||||
void PDFiumEngine::OnSearchifyStateChange(bool busy) {
|
||||
client_->OnSearchifyStateChange(busy);
|
||||
}
|
||||
#endif // BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
|
||||
|
||||
void PDFiumEngine::UpdateLinkUnderCursor(const std::string& target_url) {
|
||||
|
@ -387,10 +387,13 @@ class PDFiumEngine : public DocumentLoader::Client, public IFSDK_PAUSE {
|
||||
// if the page is not scheduled for searchify.
|
||||
void CancelPendingSearchify(int page_index);
|
||||
|
||||
// See the comment for `OnSearchifyStateChange` in pdf/pdf.mojom.
|
||||
void OnSearchifyStateChange(bool busy);
|
||||
|
||||
PDFiumOnDemandSearchifier* GetSearchifierForTesting() {
|
||||
return searchifier_.get();
|
||||
}
|
||||
#endif
|
||||
#endif // BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
|
||||
|
||||
void UnsupportedFeature(const std::string& feature);
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include "base/functional/callback.h"
|
||||
#include "pdf/buildflags.h"
|
||||
#include "services/screen_ai/buildflags/buildflags.h"
|
||||
#include "third_party/skia/include/core/SkColor.h"
|
||||
#include "ui/base/cursor/mojom/cursor_type.mojom-forward.h"
|
||||
#include "ui/base/window_open_disposition.h"
|
||||
@ -202,6 +203,11 @@ class PDFiumEngineClient {
|
||||
// Returns true if the client is in annotation mode.
|
||||
virtual bool IsInAnnotationMode() const = 0;
|
||||
#endif // BUILDFLAG(ENABLE_PDF_INK2)
|
||||
|
||||
#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
|
||||
// See the comment for `OnSearchifyStateChange` in pdf/pdf.mojom.
|
||||
virtual void OnSearchifyStateChange(bool busy) = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
@ -133,6 +133,9 @@ class MockTestClient : public TestClient {
|
||||
#if BUILDFLAG(ENABLE_PDF_INK2)
|
||||
MOCK_METHOD(bool, IsInAnnotationMode, (), (const override));
|
||||
#endif // BUILDFLAG(ENABLE_PDF_INK2)
|
||||
#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
|
||||
MOCK_METHOD(void, OnSearchifyStateChange, (bool), (override));
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
@ -66,6 +66,7 @@ void PDFiumOnDemandSearchifier::OnOcrDisconnected() {
|
||||
current_page_ = nullptr;
|
||||
pages_queue_.clear();
|
||||
state_ = State::kFailed;
|
||||
engine_->OnSearchifyStateChange(/*busy=*/false);
|
||||
return;
|
||||
|
||||
case State::kFailed:
|
||||
@ -90,6 +91,9 @@ void PDFiumOnDemandSearchifier::SchedulePage(int page_index) {
|
||||
if (IsPageScheduled(page_index)) {
|
||||
return;
|
||||
}
|
||||
if (!current_page_ && pages_queue_.empty() && state_ == State::kIdle) {
|
||||
engine_->OnSearchifyStateChange(/*busy=*/true);
|
||||
}
|
||||
pages_queue_.push_back(page_index);
|
||||
if (state_ == State::kWaitingForResults || !perform_ocr_callback_) {
|
||||
return;
|
||||
@ -123,6 +127,7 @@ void PDFiumOnDemandSearchifier::SearchifyNextPage() {
|
||||
|
||||
if (pages_queue_.empty()) {
|
||||
state_ = State::kIdle;
|
||||
engine_->OnSearchifyStateChange(/*busy=*/false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,25 @@ using VisualAnnotationPtr = screen_ai::mojom::VisualAnnotationPtr;
|
||||
|
||||
constexpr base::TimeDelta kOcrDelay = base::Milliseconds(100);
|
||||
|
||||
class SearchifierTestClient : public TestClient {
|
||||
public:
|
||||
explicit SearchifierTestClient() = default;
|
||||
SearchifierTestClient(const SearchifierTestClient&) = delete;
|
||||
SearchifierTestClient& operator=(const SearchifierTestClient&) = delete;
|
||||
~SearchifierTestClient() override = default;
|
||||
|
||||
void OnSearchifyStateChange(bool busy) override {
|
||||
if (busy) {
|
||||
busy_state_changed_count_++;
|
||||
} else {
|
||||
idle_state_changed_count_++;
|
||||
}
|
||||
}
|
||||
|
||||
int busy_state_changed_count_ = 0;
|
||||
int idle_state_changed_count_ = 0;
|
||||
};
|
||||
|
||||
void WaitUntilIdle(PDFiumOnDemandSearchifier* searchifier,
|
||||
base::OnceClosure callback) {
|
||||
if (searchifier->IsIdleForTesting()) {
|
||||
@ -130,11 +149,17 @@ class PDFiumOnDemandSearchifierTest : public PDFiumTestBase {
|
||||
|
||||
int performed_ocrs() const { return performed_ocrs_; }
|
||||
PDFiumEngine* engine() { return engine_.get(); }
|
||||
int busy_state_changed_count() const {
|
||||
return client_.busy_state_changed_count_;
|
||||
}
|
||||
int idle_state_changed_count() const {
|
||||
return client_.idle_state_changed_count_;
|
||||
}
|
||||
|
||||
private:
|
||||
base::test::ScopedFeatureList scoped_feature_list_;
|
||||
std::unique_ptr<PDFiumEngine> engine_;
|
||||
TestClient client_;
|
||||
SearchifierTestClient client_;
|
||||
int performed_ocrs_ = 0;
|
||||
};
|
||||
|
||||
@ -372,6 +397,60 @@ TEST_P(PDFiumOnDemandSearchifierTest, OcrCancellation) {
|
||||
ASSERT_LT(performed_ocrs(), kPageCount);
|
||||
}
|
||||
|
||||
TEST_P(PDFiumOnDemandSearchifierTest, SearchifyStateChanges) {
|
||||
CreateEngine(FILE_PATH_LITERAL("multi_page_no_text.pdf"));
|
||||
|
||||
// Trigger one page load.
|
||||
GetPDFiumPageForTest(*engine(), 0).GetPage();
|
||||
|
||||
EXPECT_EQ(busy_state_changed_count(), 1);
|
||||
EXPECT_EQ(idle_state_changed_count(), 0);
|
||||
|
||||
StartSearchify(/*empty_results=*/false);
|
||||
|
||||
EXPECT_EQ(busy_state_changed_count(), 1);
|
||||
EXPECT_EQ(idle_state_changed_count(), 0);
|
||||
|
||||
// Wait for searchifier to process all pending tasks.
|
||||
{
|
||||
base::test::TestFuture<void> future;
|
||||
WaitUntilIdle(engine()->GetSearchifierForTesting(), future.GetCallback());
|
||||
ASSERT_TRUE(future.Wait());
|
||||
}
|
||||
|
||||
EXPECT_EQ(busy_state_changed_count(), 1);
|
||||
EXPECT_EQ(idle_state_changed_count(), 1);
|
||||
|
||||
// Trigger more page loads.
|
||||
GetPDFiumPageForTest(*engine(), 1).GetPage();
|
||||
GetPDFiumPageForTest(*engine(), 2).GetPage();
|
||||
|
||||
EXPECT_EQ(busy_state_changed_count(), 2);
|
||||
EXPECT_EQ(idle_state_changed_count(), 1);
|
||||
|
||||
// Wait for searchifier to process all pending tasks.
|
||||
{
|
||||
base::test::TestFuture<void> future;
|
||||
WaitUntilIdle(engine()->GetSearchifierForTesting(), future.GetCallback());
|
||||
ASSERT_TRUE(future.Wait());
|
||||
}
|
||||
|
||||
EXPECT_EQ(busy_state_changed_count(), 2);
|
||||
EXPECT_EQ(idle_state_changed_count(), 2);
|
||||
|
||||
// Trigger more page loads.
|
||||
GetPDFiumPageForTest(*engine(), 3).GetPage();
|
||||
|
||||
EXPECT_EQ(busy_state_changed_count(), 3);
|
||||
EXPECT_EQ(idle_state_changed_count(), 2);
|
||||
|
||||
// Disconnect OCR before searchifier processes the pending task.
|
||||
engine()->GetOcrDisconnectHandler().Run();
|
||||
|
||||
EXPECT_EQ(busy_state_changed_count(), 3);
|
||||
EXPECT_EQ(idle_state_changed_count(), 3);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(All, PDFiumOnDemandSearchifierTest, testing::Bool());
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
@ -178,4 +178,8 @@ bool PreviewModeClient::IsInAnnotationMode() const {
|
||||
}
|
||||
#endif // BUILDFLAG(ENABLE_PDF_INK2)
|
||||
|
||||
#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
|
||||
void PreviewModeClient::OnSearchifyStateChange(bool busy) {}
|
||||
#endif
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "pdf/buildflags.h"
|
||||
#include "pdf/pdfium/pdfium_engine_client.h"
|
||||
#include "services/screen_ai/buildflags/buildflags.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
@ -77,6 +78,9 @@ class PreviewModeClient : public PDFiumEngineClient {
|
||||
#if BUILDFLAG(ENABLE_PDF_INK2)
|
||||
bool IsInAnnotationMode() const override;
|
||||
#endif // BUILDFLAG(ENABLE_PDF_INK2)
|
||||
#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
|
||||
void OnSearchifyStateChange(bool busy) override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
const raw_ptr<Client> client_;
|
||||
|
@ -78,4 +78,8 @@ bool TestClient::IsInAnnotationMode() const {
|
||||
}
|
||||
#endif // BUILDFLAG(ENABLE_PDF_INK2)
|
||||
|
||||
#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
|
||||
void TestClient::OnSearchifyStateChange(bool busy) {}
|
||||
#endif
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "pdf/buildflags.h"
|
||||
#include "pdf/pdfium/pdfium_engine_client.h"
|
||||
#include "services/screen_ai/buildflags/buildflags.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
@ -47,6 +48,9 @@ class TestClient : public PDFiumEngineClient {
|
||||
#if BUILDFLAG(ENABLE_PDF_INK2)
|
||||
bool IsInAnnotationMode() const override;
|
||||
#endif // BUILDFLAG(ENABLE_PDF_INK2)
|
||||
#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
|
||||
void OnSearchifyStateChange(bool busy) override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
// Not owned. Expected to dangle briefly, as the engine usually is destroyed
|
||||
|
Reference in New Issue
Block a user