0

Merge ContainerWrapper into PdfViewWebPlugin::Client

Merges ContainerWrapper into Client for easier testing. Client is passed
in at construction time, and therefore supports injecting fakes more
naturally; while PdfViewWebPlugin normally creates ContainerWrapper
internally, and requires the InitializeForTesting() API to fake.

Bug: 1323307
Change-Id: I2c48e456badffca1d06f41bb67009c87fb20ac14
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3641434
Commit-Queue: K. Moon <kmoon@chromium.org>
Reviewed-by: Nigi <nigi@chromium.org>
Reviewed-by: Ahmed Fakhry <afakhry@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1003179}
This commit is contained in:
K. Moon
2022-05-13 17:17:36 +00:00
committed by Chromium LUCI CQ
parent 347c90211d
commit 892cdd4857
9 changed files with 273 additions and 285 deletions

@ -43,6 +43,8 @@ static_library("renderer") {
"//third_party/blink/public:blink",
"//third_party/blink/public/strings:accessibility_strings",
"//third_party/icu",
"//ui/display",
"//ui/gfx/geometry",
"//url",
"//v8",
]

@ -16,5 +16,6 @@ include_rules = [
"+third_party/skia/include/core",
"+ui/accessibility",
"+ui/base",
"+ui/display",
"+v8/include",
]

@ -4,6 +4,8 @@
#include "components/pdf/renderer/pdf_view_web_plugin_client.h"
#include <memory>
#include <string>
#include <utility>
#include "base/check_op.h"
@ -12,13 +14,23 @@
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/v8_value_converter.h"
#include "printing/buildflags/buildflags.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/public/web/web_associated_url_loader.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_dom_message_event.h"
#include "third_party/blink/public/web/web_element.h"
#include "third_party/blink/public/web/web_frame_widget.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_plugin_container.h"
#include "third_party/blink/public/web/web_serialized_script_value.h"
#include "third_party/blink/public/web/web_view.h"
#include "third_party/blink/public/web/web_widget.h"
#include "ui/display/screen_info.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/rect.h"
#include "v8/include/v8-context.h"
#include "v8/include/v8-isolate.h"
#include "v8/include/v8-local-handle.h"
@ -76,6 +88,132 @@ void PdfViewWebPluginClient::PostMessage(base::Value::Dict message) {
blink::WebSerializedScriptValue::Serialize(isolate_, converted_message));
}
void PdfViewWebPluginClient::Invalidate() {
plugin_container_->Invalidate();
}
void PdfViewWebPluginClient::RequestTouchEventType(
blink::WebPluginContainer::TouchEventRequestType request_type) {
plugin_container_->RequestTouchEventType(request_type);
}
void PdfViewWebPluginClient::ReportFindInPageMatchCount(int identifier,
int total,
bool final_update) {
plugin_container_->ReportFindInPageMatchCount(identifier, total,
final_update);
}
void PdfViewWebPluginClient::ReportFindInPageSelection(int identifier,
int index) {
plugin_container_->ReportFindInPageSelection(identifier, index);
}
void PdfViewWebPluginClient::ReportFindInPageTickmarks(
const std::vector<gfx::Rect>& tickmarks) {
blink::WebLocalFrame* frame = GetFrame();
if (frame) {
frame->SetTickmarks(blink::WebElement(),
blink::WebVector<gfx::Rect>(tickmarks));
}
}
float PdfViewWebPluginClient::DeviceScaleFactor() {
// Do not rely on `blink::WebPluginContainer::DeviceScaleFactor()`, since it
// doesn't always reflect the real screen's device scale. Instead, get the
// device scale from the top-level frame's `display::ScreenInfo`.
blink::WebWidget* widget = GetFrame()->LocalRoot()->FrameWidget();
return widget->GetOriginalScreenInfo().device_scale_factor;
}
gfx::PointF PdfViewWebPluginClient::GetScrollPosition() {
// Note that `blink::WebLocalFrame::GetScrollOffset()` actually returns a
// scroll position (a point relative to the top-left corner).
return GetFrame()->GetScrollOffset();
}
void PdfViewWebPluginClient::UsePluginAsFindHandler() {
plugin_container_->UsePluginAsFindHandler();
}
void PdfViewWebPluginClient::SetReferrerForRequest(
blink::WebURLRequest& request,
const blink::WebURL& referrer_url) {
GetFrame()->SetReferrerForRequest(request, referrer_url);
}
void PdfViewWebPluginClient::Alert(const blink::WebString& message) {
blink::WebLocalFrame* frame = GetFrame();
if (frame)
frame->Alert(message);
}
bool PdfViewWebPluginClient::Confirm(const blink::WebString& message) {
blink::WebLocalFrame* frame = GetFrame();
return frame && frame->Confirm(message);
}
blink::WebString PdfViewWebPluginClient::Prompt(
const blink::WebString& message,
const blink::WebString& default_value) {
blink::WebLocalFrame* frame = GetFrame();
return frame ? frame->Prompt(message, default_value) : blink::WebString();
}
void PdfViewWebPluginClient::TextSelectionChanged(
const blink::WebString& selection_text,
uint32_t offset,
const gfx::Range& range) {
// Focus the plugin's containing frame before changing the text selection.
// TODO(crbug.com/1234559): Would it make more sense not to change the text
// selection at all in this case? Maybe we only have this problem because we
// support a "selectAll" message.
blink::WebLocalFrame* frame = GetFrame();
frame->View()->SetFocusedFrame(frame);
frame->TextSelectionChanged(selection_text, offset, range);
}
std::unique_ptr<blink::WebAssociatedURLLoader>
PdfViewWebPluginClient::CreateAssociatedURLLoader(
const blink::WebAssociatedURLLoaderOptions& options) {
return GetFrame()->CreateAssociatedURLLoader(options);
}
void PdfViewWebPluginClient::UpdateTextInputState() {
// `widget` is null in Print Preview.
auto* widget = GetFrame()->FrameWidget();
if (widget)
widget->UpdateTextInputState();
}
void PdfViewWebPluginClient::UpdateSelectionBounds() {
// `widget` is null in Print Preview.
auto* widget = GetFrame()->FrameWidget();
if (widget)
widget->UpdateSelectionBounds();
}
std::string PdfViewWebPluginClient::GetEmbedderOriginString() {
auto* frame = GetFrame();
if (!frame)
return {};
auto* parent_frame = frame->Parent();
if (!parent_frame)
return {};
return GURL(parent_frame->GetSecurityOrigin().ToString().Utf8()).spec();
}
blink::WebLocalFrame* PdfViewWebPluginClient::GetFrame() {
return plugin_container_->GetDocument().GetFrame();
}
blink::WebLocalFrameClient* PdfViewWebPluginClient::GetWebLocalFrameClient() {
return GetFrame()->Client();
}
void PdfViewWebPluginClient::Print(const blink::WebElement& element) {
DCHECK(!element.IsNull());
#if BUILDFLAG(ENABLE_PRINTING)

@ -40,6 +40,34 @@ class PdfViewWebPluginClient : public chrome_pdf::PdfViewWebPlugin::Client {
void SetPluginContainer(blink::WebPluginContainer* container) override;
blink::WebPluginContainer* PluginContainer() override;
void PostMessage(base::Value::Dict message) override;
void Invalidate() override;
void RequestTouchEventType(
blink::WebPluginContainer::TouchEventRequestType request_type) override;
void ReportFindInPageMatchCount(int identifier,
int total,
bool final_update) override;
void ReportFindInPageSelection(int identifier, int index) override;
void ReportFindInPageTickmarks(
const std::vector<gfx::Rect>& tickmarks) override;
float DeviceScaleFactor() override;
gfx::PointF GetScrollPosition() override;
void UsePluginAsFindHandler() override;
void SetReferrerForRequest(blink::WebURLRequest& request,
const blink::WebURL& referrer_url) override;
void Alert(const blink::WebString& message) override;
bool Confirm(const blink::WebString& message) override;
blink::WebString Prompt(const blink::WebString& message,
const blink::WebString& default_value) override;
void TextSelectionChanged(const blink::WebString& selection_text,
uint32_t offset,
const gfx::Range& range) override;
std::unique_ptr<blink::WebAssociatedURLLoader> CreateAssociatedURLLoader(
const blink::WebAssociatedURLLoaderOptions& options) override;
void UpdateTextInputState() override;
void UpdateSelectionBounds() override;
std::string GetEmbedderOriginString() override;
blink::WebLocalFrame* GetFrame() override;
blink::WebLocalFrameClient* GetWebLocalFrameClient() override;
void Print(const blink::WebElement& element) override;
void RecordComputedAction(const std::string& action) override;
std::unique_ptr<chrome_pdf::PdfAccessibilityDataHandler>

@ -295,7 +295,6 @@ if (enable_pdf) {
"//third_party/blink/public/common:headers",
"//ui/base/cursor",
"//ui/base/cursor/mojom:cursor_type",
"//ui/display",
"//ui/events/blink",
"//v8",
]

@ -9,7 +9,6 @@ include_rules = [
"+third_party/blink/public",
"+third_party/skia/include/core",
"+ui/base",
"+ui/display",
"+ui/events",
"+ui/gfx",
"+v8/include",

@ -54,21 +54,15 @@
#include "third_party/blink/public/mojom/input/focus_type.mojom-shared.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_input_event_result.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_text_input_type.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/platform/web_url_error.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/public/platform/web_url_response.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/public/web/web_associated_url_loader.h"
#include "third_party/blink/public/web/web_associated_url_loader_options.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_element.h"
#include "third_party/blink/public/web/web_frame.h"
#include "third_party/blink/public/web/web_frame_widget.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_plugin_container.h"
#include "third_party/blink/public/web/web_plugin_params.h"
@ -81,7 +75,6 @@
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
#include "ui/base/text/bytes_formatting.h"
#include "ui/display/screen_info.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/blink/blink_event_util.h"
#include "ui/events/keycodes/keyboard_codes.h"
@ -147,139 +140,6 @@ class PerProcessInitializer final {
THREAD_CHECKER(thread_checker_);
};
class BlinkContainerWrapper final : public PdfViewWebPlugin::ContainerWrapper {
public:
explicit BlinkContainerWrapper(blink::WebPluginContainer* container)
: container_(container) {
DCHECK(container_);
}
BlinkContainerWrapper(const BlinkContainerWrapper&) = delete;
BlinkContainerWrapper& operator=(const BlinkContainerWrapper&) = delete;
~BlinkContainerWrapper() override = default;
void Invalidate() override { container_->Invalidate(); }
void RequestTouchEventType(
blink::WebPluginContainer::TouchEventRequestType request_type) override {
container_->RequestTouchEventType(request_type);
}
void ReportFindInPageMatchCount(int identifier,
int total,
bool final_update) override {
container_->ReportFindInPageMatchCount(identifier, total, final_update);
}
void ReportFindInPageSelection(int identifier, int index) override {
container_->ReportFindInPageSelection(identifier, index);
}
void ReportFindInPageTickmarks(
const std::vector<gfx::Rect>& tickmarks) override {
blink::WebLocalFrame* frame = GetFrame();
if (frame) {
frame->SetTickmarks(blink::WebElement(),
blink::WebVector<gfx::Rect>(tickmarks));
}
}
float DeviceScaleFactor() override {
// Do not reply on the device scale returned by
// `container_->DeviceScaleFactor()`, since it doesn't always reflect the
// real screen's device scale. Instead, get the real device scale from the
// top-level `blink::WebLocalFrame`'s screen info.
blink::WebWidget* widget = GetFrame()->LocalRoot()->FrameWidget();
return widget->GetOriginalScreenInfo().device_scale_factor;
}
gfx::PointF GetScrollPosition() override {
// Note that `blink::WebLocalFrame::GetScrollOffset()` actually returns a
// scroll position (a point relative to the top-left corner).
return GetFrame()->GetScrollOffset();
}
void UsePluginAsFindHandler() override {
container_->UsePluginAsFindHandler();
}
void SetReferrerForRequest(blink::WebURLRequest& request,
const blink::WebURL& referrer_url) override {
GetFrame()->SetReferrerForRequest(request, referrer_url);
}
void Alert(const blink::WebString& message) override {
blink::WebLocalFrame* frame = GetFrame();
if (frame)
frame->Alert(message);
}
bool Confirm(const blink::WebString& message) override {
blink::WebLocalFrame* frame = GetFrame();
return frame && frame->Confirm(message);
}
blink::WebString Prompt(const blink::WebString& message,
const blink::WebString& default_value) override {
blink::WebLocalFrame* frame = GetFrame();
return frame ? frame->Prompt(message, default_value) : blink::WebString();
}
void TextSelectionChanged(const blink::WebString& selection_text,
uint32_t offset,
const gfx::Range& range) override {
// Focus the plugin's containing frame before changing the text selection.
// TODO(crbug.com/1234559): Would it make more sense not to change the text
// selection at all in this case? Maybe we only have this problem because we
// support a "selectAll" message.
blink::WebLocalFrame* frame = GetFrame();
frame->View()->SetFocusedFrame(frame);
frame->TextSelectionChanged(selection_text, offset, range);
}
std::unique_ptr<blink::WebAssociatedURLLoader> CreateAssociatedURLLoader(
const blink::WebAssociatedURLLoaderOptions& options) override {
return GetFrame()->CreateAssociatedURLLoader(options);
}
void UpdateTextInputState() override {
// `widget` is null in Print Preview.
auto* widget = GetFrame()->FrameWidget();
if (widget)
widget->UpdateTextInputState();
}
void UpdateSelectionBounds() override {
// `widget` is null in Print Preview.
auto* widget = GetFrame()->FrameWidget();
if (widget)
widget->UpdateSelectionBounds();
}
std::string GetEmbedderOriginString() override {
auto* frame = GetFrame();
if (!frame)
return {};
auto* parent_frame = frame->Parent();
if (!parent_frame)
return {};
return GURL(parent_frame->GetSecurityOrigin().ToString().Utf8()).spec();
}
blink::WebLocalFrame* GetFrame() override {
return container_->GetDocument().GetFrame();
}
blink::WebLocalFrameClient* GetWebLocalFrameClient() override {
return GetFrame()->Client();
}
private:
const raw_ptr<blink::WebPluginContainer> container_;
};
} // namespace
std::unique_ptr<PdfAccessibilityDataHandler>
@ -309,29 +169,24 @@ bool PdfViewWebPlugin::Initialize(blink::WebPluginContainer* container) {
client_->SetPluginContainer(container);
DCHECK_EQ(container->Plugin(), this);
return InitializeCommon(std::make_unique<BlinkContainerWrapper>(container),
/*engine_override=*/nullptr);
return InitializeCommon(/*engine_override=*/nullptr);
}
bool PdfViewWebPlugin::InitializeForTesting(
std::unique_ptr<ContainerWrapper> container_wrapper,
std::unique_ptr<PDFiumEngine> engine,
std::unique_ptr<UrlLoader> loader) {
test_loader_ = std::move(loader);
return InitializeCommon(std::move(container_wrapper), std::move(engine));
return InitializeCommon(std::move(engine));
}
bool PdfViewWebPlugin::InitializeCommon(
std::unique_ptr<ContainerWrapper> container_wrapper,
std::unique_ptr<PDFiumEngine> engine_override) {
container_wrapper_ = std::move(container_wrapper);
// Allow the plugin to handle touch events.
container_wrapper_->RequestTouchEventType(
client_->RequestTouchEventType(
blink::WebPluginContainer::kTouchEventRequestTypeRaw);
// Allow the plugin to handle find requests.
container_wrapper_->UsePluginAsFindHandler();
client_->UsePluginAsFindHandler();
absl::optional<ParsedParams> params = ParseWebPluginParams(initial_params_);
@ -354,16 +209,15 @@ bool PdfViewWebPlugin::InitializeCommon(
base::debug::SetCrashKeyString(subresource_url, params->original_url);
PerProcessInitializer::GetInstance().Acquire();
InitializeBase(
engine_override
? std::move(engine_override)
: std::make_unique<PDFiumEngine>(this, params->script_option),
/*embedder_origin=*/container_wrapper_->GetEmbedderOriginString(),
/*src_url=*/params->src_url,
/*original_url=*/params->original_url,
/*full_frame=*/params->full_frame,
/*background_color=*/params->background_color,
/*has_edits=*/params->has_edits);
InitializeBase(engine_override ? std::move(engine_override)
: std::make_unique<PDFiumEngine>(
this, params->script_option),
/*embedder_origin=*/client_->GetEmbedderOriginString(),
/*src_url=*/params->src_url,
/*original_url=*/params->original_url,
/*full_frame=*/params->full_frame,
/*background_color=*/params->background_color,
/*has_edits=*/params->has_edits);
SendSetSmoothScrolling();
@ -471,9 +325,9 @@ void PdfViewWebPlugin::UpdateGeometry(const gfx::Rect& window_rect,
if (window_rect.IsEmpty())
return;
OnViewportChanged(window_rect, container_wrapper_->DeviceScaleFactor());
OnViewportChanged(window_rect, client_->DeviceScaleFactor());
gfx::PointF scroll_position = container_wrapper_->GetScrollPosition();
gfx::PointF scroll_position = client_->GetScrollPosition();
// Convert back to CSS pixels.
scroll_position.Scale(1.0f / device_scale());
UpdateScroll(scroll_position);
@ -483,8 +337,8 @@ void PdfViewWebPlugin::UpdateFocus(bool focused,
blink::mojom::FocusType focus_type) {
if (has_focus_ != focused) {
engine()->UpdateFocus(focused);
container_wrapper_->UpdateTextInputState();
container_wrapper_->UpdateSelectionBounds();
client_->UpdateTextInputState();
client_->UpdateSelectionBounds();
}
has_focus_ = focused;
@ -657,7 +511,7 @@ void PdfViewWebPlugin::StopFind() {
find_identifier_ = -1;
engine()->StopFind();
tickmarks_.clear();
container_wrapper_->ReportFindInPageTickmarks(tickmarks_);
client_->ReportFindInPageTickmarks(tickmarks_);
}
bool PdfViewWebPlugin::CanRotateView() {
@ -739,11 +593,10 @@ void PdfViewWebPlugin::NotifyNumberOfFindResultsChanged(int total,
// be a NotifyNumberOfFindResultsChanged notification pending from engine.
// Just ignore them.
if (find_identifier_ != -1) {
container_wrapper_->ReportFindInPageMatchCount(find_identifier_, total,
final_result);
client_->ReportFindInPageMatchCount(find_identifier_, total, final_result);
}
container_wrapper_->ReportFindInPageTickmarks(tickmarks_);
client_->ReportFindInPageTickmarks(tickmarks_);
if (final_result)
return;
@ -757,12 +610,11 @@ void PdfViewWebPlugin::NotifyNumberOfFindResultsChanged(int total,
}
void PdfViewWebPlugin::NotifySelectedFindResultChanged(int current_find_index) {
if (find_identifier_ == -1 || !container_wrapper_)
if (find_identifier_ == -1 || !client_->PluginContainer())
return;
DCHECK_GE(current_find_index, -1);
container_wrapper_->ReportFindInPageSelection(find_identifier_,
current_find_index + 1);
client_->ReportFindInPageSelection(find_identifier_, current_find_index + 1);
}
void PdfViewWebPlugin::CaretChanged(const gfx::Rect& caret_rect) {
@ -771,16 +623,16 @@ void PdfViewWebPlugin::CaretChanged(const gfx::Rect& caret_rect) {
}
void PdfViewWebPlugin::Alert(const std::string& message) {
container_wrapper_->Alert(blink::WebString::FromUTF8(message));
client_->Alert(blink::WebString::FromUTF8(message));
}
bool PdfViewWebPlugin::Confirm(const std::string& message) {
return container_wrapper_->Confirm(blink::WebString::FromUTF8(message));
return client_->Confirm(blink::WebString::FromUTF8(message));
}
std::string PdfViewWebPlugin::Prompt(const std::string& question,
const std::string& default_answer) {
return container_wrapper_
return client_
->Prompt(blink::WebString::FromUTF8(question),
blink::WebString::FromUTF8(default_answer))
.Utf8();
@ -802,8 +654,8 @@ PdfViewWebPlugin::SearchString(const char16_t* string,
void PdfViewWebPlugin::SetSelectedText(const std::string& selected_text) {
selected_text_ = blink::WebString::FromUTF8(selected_text);
container_wrapper_->TextSelectionChanged(
selected_text_, /*offset=*/0, gfx::Range(0, selected_text_.length()));
client_->TextSelectionChanged(selected_text_, /*offset=*/0,
gfx::Range(0, selected_text_.length()));
}
bool PdfViewWebPlugin::IsValidLink(const std::string& url) {
@ -824,7 +676,7 @@ void PdfViewWebPlugin::SetSelectionBounds(const gfx::PointF& base,
}
bool PdfViewWebPlugin::IsValid() const {
return container_wrapper_ && container_wrapper_->GetFrame();
return client_->PluginContainer() && client_->GetFrame();
}
blink::WebURL PdfViewWebPlugin::CompleteURL(
@ -841,13 +693,13 @@ net::SiteForCookies PdfViewWebPlugin::SiteForCookies() const {
void PdfViewWebPlugin::SetReferrerForRequest(
blink::WebURLRequest& request,
const blink::WebURL& referrer_url) {
container_wrapper_->SetReferrerForRequest(request, referrer_url);
client_->SetReferrerForRequest(request, referrer_url);
}
std::unique_ptr<blink::WebAssociatedURLLoader>
PdfViewWebPlugin::CreateAssociatedURLLoader(
const blink::WebAssociatedURLLoaderOptions& options) {
return container_wrapper_->CreateAssociatedURLLoader(options);
return client_->CreateAssociatedURLLoader(options);
}
void PdfViewWebPlugin::OnMessage(const base::Value::Dict& message) {
@ -855,7 +707,7 @@ void PdfViewWebPlugin::OnMessage(const base::Value::Dict& message) {
}
void PdfViewWebPlugin::InvalidatePluginContainer() {
container_wrapper_->Invalidate();
client_->Invalidate();
}
void PdfViewWebPlugin::UpdateSnapshot(sk_sp<SkImage> snapshot) {
@ -939,7 +791,7 @@ void PdfViewWebPlugin::SaveAs() {
void PdfViewWebPlugin::SetFormTextFieldInFocus(bool in_focus) {
text_input_type_ = in_focus ? blink::WebTextInputType::kWebTextInputTypeText
: blink::WebTextInputType::kWebTextInputTypeNone;
container_wrapper_->UpdateTextInputState();
client_->UpdateTextInputState();
}
void PdfViewWebPlugin::SetAccessibilityDocInfo(AccessibilityDocInfo doc_info) {
@ -986,7 +838,7 @@ void PdfViewWebPlugin::SetPluginCanSave(bool can_save) {
}
void PdfViewWebPlugin::PluginDidStartLoading() {
auto* client = container_wrapper_->GetWebLocalFrameClient();
auto* client = client_->GetWebLocalFrameClient();
if (!client)
return;
@ -994,7 +846,7 @@ void PdfViewWebPlugin::PluginDidStartLoading() {
}
void PdfViewWebPlugin::PluginDidStopLoading() {
auto* client = container_wrapper_->GetWebLocalFrameClient();
auto* client = client_->GetWebLocalFrameClient();
if (!client)
return;

@ -63,9 +63,23 @@ class PdfViewWebPlugin final : public PdfViewPluginBase,
public PostMessageReceiver::Client,
public PdfAccessibilityActionHandler {
public:
class ContainerWrapper {
// Provides services from the plugin's container.
class Client : public V8ValueConverter {
public:
virtual ~ContainerWrapper() = default;
virtual ~Client() = default;
virtual base::WeakPtr<Client> GetWeakPtr() = 0;
// Passes the plugin container to the client. This is first called in
// `Initialize()`, and cleared to null in `Destroy()`. The container may
// also be null for testing.
virtual void SetPluginContainer(blink::WebPluginContainer* container) = 0;
// Returns the plugin container set by `SetPluginContainer()`.
virtual blink::WebPluginContainer* PluginContainer() = 0;
// Enqueues a "message" event carrying `message` to the plugin embedder.
virtual void PostMessage(base::Value::Dict message) {}
// Invalidates the entire web plugin container and schedules a paint of the
// page in it.
@ -136,25 +150,6 @@ class PdfViewWebPlugin final : public PdfViewPluginBase,
// Returns the local frame's client (render frame). May be null in unit
// tests.
virtual blink::WebLocalFrameClient* GetWebLocalFrameClient() = 0;
};
// Allows for dependency injections into `PdfViewWebPlugin`.
class Client : public V8ValueConverter {
public:
virtual ~Client() = default;
virtual base::WeakPtr<Client> GetWeakPtr() = 0;
// Passes the plugin container to the client. This is first called in
// `Initialize()`, and cleared to null in `Destroy()`. The container may
// also be null for testing.
virtual void SetPluginContainer(blink::WebPluginContainer* container) = 0;
// Returns the plugin container set by `SetPluginContainer()`.
virtual blink::WebPluginContainer* PluginContainer() = 0;
// Enqueues a "message" event carrying `message` to the plugin embedder.
virtual void PostMessage(base::Value::Dict message) {}
// Prints the given `element`.
virtual void Print(const blink::WebElement& element) {}
@ -285,10 +280,9 @@ class PdfViewWebPlugin final : public PdfViewPluginBase,
void HandleAccessibilityAction(
const AccessibilityActionData& action_data) override;
// Initializes the plugin using the `container_wrapper` and `engine` provided
// by tests. Lets CreateUrlLoaderInternal() return `loader` on its first call.
bool InitializeForTesting(std::unique_ptr<ContainerWrapper> container_wrapper,
std::unique_ptr<PDFiumEngine> engine,
// Initializes the plugin using the `engine` provided by tests. Lets
// `CreateUrlLoaderInternal()` return `loader` on its first call.
bool InitializeForTesting(std::unique_ptr<PDFiumEngine> engine,
std::unique_ptr<UrlLoader> loader);
const gfx::Rect& GetPluginRectForTesting() const { return plugin_rect(); }
@ -329,8 +323,7 @@ class PdfViewWebPlugin final : public PdfViewPluginBase,
// Passing in a null `engine_override` allows InitializeCommon() to create a
// PDFiumEngine normally. Otherwise, `engine_override` is used.
bool InitializeCommon(std::unique_ptr<ContainerWrapper> container_wrapper,
std::unique_ptr<PDFiumEngine> engine_override);
bool InitializeCommon(std::unique_ptr<PDFiumEngine> engine_override);
// Sends whether to do smooth scrolling.
void SendSetSmoothScrolling();
@ -418,8 +411,6 @@ class PdfViewWebPlugin final : public PdfViewPluginBase,
blink::WebPluginParams initial_params_;
std::unique_ptr<ContainerWrapper> container_wrapper_;
v8::Persistent<v8::Object> scriptable_receiver_;
// The current image snapshot.

@ -147,23 +147,34 @@ blink::WebMouseEvent CreateDefaultMouseDownEvent() {
return web_event;
}
class FakeContainerWrapper : public PdfViewWebPlugin::ContainerWrapper {
class FakePdfViewWebPluginClient : public PdfViewWebPlugin::Client {
public:
explicit FakeContainerWrapper(PdfViewWebPlugin* web_plugin)
: web_plugin_(web_plugin) {
void SetPlugin(PdfViewWebPlugin* web_plugin) {
web_plugin_ = web_plugin;
ON_CALL(*this, UpdateTextInputState)
.WillByDefault(Invoke(
this, &FakeContainerWrapper::UpdateTextInputStateFromPlugin));
this, &FakePdfViewWebPluginClient::UpdateTextInputStateFromPlugin));
UpdateTextInputStateFromPlugin();
}
FakeContainerWrapper(const FakeContainerWrapper&) = delete;
FakeContainerWrapper& operator=(const FakeContainerWrapper&) = delete;
~FakeContainerWrapper() override = default;
// PdfViewWebPlugin::Client:
MOCK_METHOD(std::unique_ptr<base::Value>,
FromV8Value,
(v8::Local<v8::Value>, v8::Local<v8::Context>),
(override));
// PdfViewWebPlugin::ContainerWrapper:
void Invalidate() override {}
MOCK_METHOD(base::WeakPtr<Client>, GetWeakPtr, (), (override));
MOCK_METHOD(void,
SetPluginContainer,
(blink::WebPluginContainer*),
(override));
MOCK_METHOD(blink::WebPluginContainer*, PluginContainer, (), (override));
MOCK_METHOD(void, PostMessage, (base::Value::Dict), (override));
MOCK_METHOD(void, Invalidate, (), (override));
MOCK_METHOD(void,
RequestTouchEventType,
@ -240,28 +251,6 @@ class FakeContainerWrapper : public PdfViewWebPlugin::ContainerWrapper {
blink::WebTextInputType widget_text_input_type_;
raw_ptr<PdfViewWebPlugin> web_plugin_;
};
class FakePdfViewWebPluginClient : public PdfViewWebPlugin::Client {
public:
FakePdfViewWebPluginClient() = default;
FakePdfViewWebPluginClient(const FakePdfViewWebPluginClient&) = delete;
FakePdfViewWebPluginClient& operator=(const FakePdfViewWebPluginClient&) =
delete;
~FakePdfViewWebPluginClient() override = default;
// PdfViewWebPlugin::Client:
MOCK_METHOD(std::unique_ptr<base::Value>,
FromV8Value,
(v8::Local<v8::Value>, v8::Local<v8::Context>),
(override));
MOCK_METHOD(base::WeakPtr<Client>, GetWeakPtr, (), (override));
MOCK_METHOD(void,
SetPluginContainer,
(blink::WebPluginContainer*),
(override));
MOCK_METHOD(blink::WebPluginContainer*, PluginContainer, (), (override));
MOCK_METHOD(void, PostMessage, (base::Value::Dict), (override));
private:
base::WeakPtrFactory<FakePdfViewWebPluginClient> weak_factory_{this};
@ -313,6 +302,8 @@ class PdfViewWebPluginWithoutInitializeTest : public testing::Test {
plugin_ =
std::unique_ptr<PdfViewWebPlugin, PluginDeleter>(new PdfViewWebPlugin(
std::move(client), std::move(unbound_remote), params));
client_ptr_->SetPlugin(plugin_.get());
}
void TearDown() override { plugin_.reset(); }
@ -326,19 +317,10 @@ class PdfViewWebPluginTest : public PdfViewWebPluginWithoutInitializeTest {
void SetUp() override {
PdfViewWebPluginWithoutInitializeTest::SetUp();
auto wrapper =
std::make_unique<NiceMock<FakeContainerWrapper>>(plugin_.get());
wrapper_ptr_ = wrapper.get();
auto engine = CreateEngine();
engine_ptr_ = engine.get();
EXPECT_TRUE(plugin_->InitializeForTesting(
std::move(wrapper), std::move(engine), CreateLoader()));
}
void TearDown() override {
wrapper_ptr_ = nullptr;
PdfViewWebPluginWithoutInitializeTest::TearDown();
EXPECT_TRUE(
plugin_->InitializeForTesting(std::move(engine), CreateLoader()));
}
// Allow derived test classes to create their own custom TestPDFiumEngine.
@ -382,8 +364,7 @@ class PdfViewWebPluginTest : public PdfViewWebPluginWithoutInitializeTest {
const gfx::Rect& window_rect) {
// The plugin container's device scale must be set before calling
// UpdateGeometry().
ASSERT_TRUE(wrapper_ptr_);
wrapper_ptr_->set_device_scale(device_scale);
client_ptr_->set_device_scale(device_scale);
plugin_->UpdateGeometry(window_rect, window_rect, window_rect,
/*is_visible=*/true);
}
@ -444,22 +425,19 @@ class PdfViewWebPluginTest : public PdfViewWebPluginWithoutInitializeTest {
}
raw_ptr<TestPDFiumEngine> engine_ptr_;
raw_ptr<FakeContainerWrapper> wrapper_ptr_;
// Provides the cc::PaintCanvas for painting.
gfx::Canvas canvas_{kCanvasSize, /*image_scale=*/1.0f, /*is_opaque=*/true};
};
TEST_F(PdfViewWebPluginWithoutInitializeTest, Initialize) {
auto wrapper =
std::make_unique<NiceMock<FakeContainerWrapper>>(plugin_.get());
auto engine = std::make_unique<NiceMock<TestPDFiumEngine>>(plugin_.get());
EXPECT_CALL(*wrapper,
EXPECT_CALL(*client_ptr_,
RequestTouchEventType(
blink::WebPluginContainer::kTouchEventRequestTypeRaw));
EXPECT_TRUE(plugin_->InitializeForTesting(
std::move(wrapper), std::move(engine), /*loader=*/nullptr));
EXPECT_TRUE(
plugin_->InitializeForTesting(std::move(engine), /*loader=*/nullptr));
}
TEST_F(PdfViewWebPluginTest, UpdateGeometrySetsPluginRect) {
@ -501,7 +479,7 @@ TEST_F(PdfViewWebPluginTest,
TEST_F(PdfViewWebPluginTest, UpdateGeometryScroll) {
SetDocumentDimensions({100, 200});
EXPECT_CALL(*wrapper_ptr_, GetScrollPosition)
EXPECT_CALL(*client_ptr_, GetScrollPosition)
.WillRepeatedly(Return(gfx::PointF(4.0f, 6.0f)));
EXPECT_CALL(*engine_ptr_, ScrolledToXPosition(4));
EXPECT_CALL(*engine_ptr_, ScrolledToYPosition(6));
@ -675,7 +653,7 @@ class PdfViewWebPluginMouseEventsTest : public PdfViewWebPluginTest {
};
TEST_F(PdfViewWebPluginMouseEventsTest, HandleInputEvent) {
wrapper_ptr_->set_device_scale(kDeviceScale);
client_ptr_->set_device_scale(kDeviceScale);
UpdatePluginGeometry(kDeviceScale, gfx::Rect(20, 20));
ui::Cursor dummy_cursor;
@ -776,7 +754,7 @@ TEST_F(PdfViewWebPluginTest, ChangeTextSelection) {
ASSERT_TRUE(plugin_->SelectionAsMarkup().IsEmpty());
static constexpr char kSelectedText[] = "1234";
EXPECT_CALL(*wrapper_ptr_,
EXPECT_CALL(*client_ptr_,
TextSelectionChanged(blink::WebString::FromUTF8(kSelectedText), 0,
gfx::Range(0, 4)));
@ -786,7 +764,7 @@ TEST_F(PdfViewWebPluginTest, ChangeTextSelection) {
EXPECT_EQ(kSelectedText, plugin_->SelectionAsMarkup().Utf8());
static constexpr char kEmptyText[] = "";
EXPECT_CALL(*wrapper_ptr_,
EXPECT_CALL(*client_ptr_,
TextSelectionChanged(blink::WebString::FromUTF8(kEmptyText), 0,
gfx::Range(0, 0)));
plugin_->SetSelectedText(kEmptyText);
@ -797,41 +775,41 @@ TEST_F(PdfViewWebPluginTest, ChangeTextSelection) {
TEST_F(PdfViewWebPluginTest, FormTextFieldFocusChangeUpdatesTextInputType) {
ASSERT_EQ(blink::WebTextInputType::kWebTextInputTypeNone,
wrapper_ptr_->widget_text_input_type());
client_ptr_->widget_text_input_type());
MockFunction<void()> checkpoint;
{
InSequence sequence;
EXPECT_CALL(*wrapper_ptr_, UpdateTextInputState);
EXPECT_CALL(*client_ptr_, UpdateTextInputState);
EXPECT_CALL(checkpoint, Call);
EXPECT_CALL(*wrapper_ptr_, UpdateTextInputState);
EXPECT_CALL(*client_ptr_, UpdateTextInputState);
EXPECT_CALL(checkpoint, Call);
EXPECT_CALL(*wrapper_ptr_, UpdateTextInputState);
EXPECT_CALL(*client_ptr_, UpdateTextInputState);
EXPECT_CALL(checkpoint, Call);
EXPECT_CALL(*wrapper_ptr_, UpdateTextInputState);
EXPECT_CALL(*client_ptr_, UpdateTextInputState);
}
plugin_->FormFieldFocusChange(PDFEngine::FocusFieldType::kText);
EXPECT_EQ(blink::WebTextInputType::kWebTextInputTypeText,
wrapper_ptr_->widget_text_input_type());
client_ptr_->widget_text_input_type());
checkpoint.Call();
plugin_->FormFieldFocusChange(PDFEngine::FocusFieldType::kNoFocus);
EXPECT_EQ(blink::WebTextInputType::kWebTextInputTypeNone,
wrapper_ptr_->widget_text_input_type());
client_ptr_->widget_text_input_type());
checkpoint.Call();
plugin_->FormFieldFocusChange(PDFEngine::FocusFieldType::kText);
EXPECT_EQ(blink::WebTextInputType::kWebTextInputTypeText,
wrapper_ptr_->widget_text_input_type());
client_ptr_->widget_text_input_type());
checkpoint.Call();
plugin_->FormFieldFocusChange(PDFEngine::FocusFieldType::kNonText);
EXPECT_EQ(blink::WebTextInputType::kWebTextInputTypeNone,
wrapper_ptr_->widget_text_input_type());
client_ptr_->widget_text_input_type());
}
TEST_F(PdfViewWebPluginTest, SearchString) {
@ -862,8 +840,8 @@ TEST_F(PdfViewWebPluginTest, UpdateFocus) {
InSequence sequence;
// Focus false -> true: Triggers updates.
EXPECT_CALL(*wrapper_ptr_, UpdateTextInputState);
EXPECT_CALL(*wrapper_ptr_, UpdateSelectionBounds);
EXPECT_CALL(*client_ptr_, UpdateTextInputState);
EXPECT_CALL(*client_ptr_, UpdateSelectionBounds);
EXPECT_CALL(checkpoint, Call(1));
// Focus true -> true: No updates.
@ -872,16 +850,16 @@ TEST_F(PdfViewWebPluginTest, UpdateFocus) {
// Focus true -> false: Triggers updates. `UpdateTextInputState` is called
// twice because it also gets called due to
// `PDFiumEngine::UpdateFocus(false)`.
EXPECT_CALL(*wrapper_ptr_, UpdateTextInputState).Times(2);
EXPECT_CALL(*wrapper_ptr_, UpdateSelectionBounds);
EXPECT_CALL(*client_ptr_, UpdateTextInputState).Times(2);
EXPECT_CALL(*client_ptr_, UpdateSelectionBounds);
EXPECT_CALL(checkpoint, Call(3));
// Focus false -> false: No updates.
EXPECT_CALL(checkpoint, Call(4));
// Focus false -> true: Triggers updates.
EXPECT_CALL(*wrapper_ptr_, UpdateTextInputState);
EXPECT_CALL(*wrapper_ptr_, UpdateSelectionBounds);
EXPECT_CALL(*client_ptr_, UpdateTextInputState);
EXPECT_CALL(*client_ptr_, UpdateSelectionBounds);
}
// The focus type does not matter in this test.
@ -914,8 +892,8 @@ TEST_F(PdfViewWebPluginTest, NotifyNumberOfFindResultsChanged) {
const std::vector<gfx::Rect> tickmarks = {gfx::Rect(1, 2), gfx::Rect(3, 4)};
plugin_->UpdateTickMarks(tickmarks);
EXPECT_CALL(*wrapper_ptr_, ReportFindInPageTickmarks(tickmarks));
EXPECT_CALL(*wrapper_ptr_, ReportFindInPageMatchCount(123, 5, true));
EXPECT_CALL(*client_ptr_, ReportFindInPageTickmarks(tickmarks));
EXPECT_CALL(*client_ptr_, ReportFindInPageMatchCount(123, 5, true));
plugin_->NotifyNumberOfFindResultsChanged(/*total=*/5, /*final_result=*/true);
}