0

Merge PdfViewPluginBase into PdfViewWebPlugin.

Finish merging these 2 classes together. Delete all the code needed to
support communication between the 2 classes.

Bug: 1302059
Change-Id: Iefd0e792db933c53f48c059b53998582f6257e9d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3964862
Reviewed-by: K. Moon <kmoon@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1061163}
This commit is contained in:
Lei Zhang
2022-10-19 18:40:15 +00:00
committed by Chromium LUCI CQ
parent 3a46dc3ced
commit de81e050ec
5 changed files with 245 additions and 593 deletions

@ -95,8 +95,6 @@ if (enable_pdf) {
"pdf_transform.h",
"pdf_utils/dates.cc",
"pdf_utils/dates.h",
"pdf_view_plugin_base.cc",
"pdf_view_plugin_base.h",
"pdfium/pdfium_api_string_buffer_adapter.cc",
"pdfium/pdfium_api_string_buffer_adapter.h",
"pdfium/pdfium_document.cc",

@ -1,215 +0,0 @@
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "pdf/pdf_view_plugin_base.h"
#include <algorithm>
#include <cmath>
#include <iterator>
#include <memory>
#include <sstream>
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/callback.h"
#include "base/check.h"
#include "base/check_op.h"
#include "base/containers/span.h"
#include "base/cxx17_backports.h"
#include "base/feature_list.h"
#include "base/location.h"
#include "base/memory/weak_ptr.h"
#include "base/notreached.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/values.h"
#include "pdf/accessibility.h"
#include "pdf/accessibility_structs.h"
#include "pdf/buildflags.h"
#include "pdf/content_restriction.h"
#include "pdf/document_layout.h"
#include "pdf/document_metadata.h"
#include "pdf/paint_ready_rect.h"
#include "pdf/pdf_engine.h"
#include "pdf/pdf_features.h"
#include "pdf/pdfium/pdfium_engine.h"
#include "pdf/pdfium/pdfium_form_filler.h"
#include "pdf/ui/file_name.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/common/input/web_mouse_event.h"
#include "third_party/blink/public/common/input/web_touch_event.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "ui/events/blink/blink_event_util.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/skia_conversions.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/geometry/vector2d_f.h"
#include "url/gurl.h"
namespace chrome_pdf {
namespace {
// A delay to wait between each accessibility page to keep the system
// responsive.
constexpr base::TimeDelta kAccessibilityPageDelay = base::Milliseconds(100);
} // namespace
PdfViewPluginBase::PdfViewPluginBase() = default;
PdfViewPluginBase::~PdfViewPluginBase() = default;
void PdfViewPluginBase::DocumentLoadComplete() {
DCHECK_EQ(DocumentLoadState::kLoading, document_load_state());
set_document_load_state(DocumentLoadState::kComplete);
UserMetricsRecordAction("PDF.LoadSuccess");
// Clear the focus state for on-screen keyboards.
FormFieldFocusChange(PDFEngine::FocusFieldType::kNoFocus);
if (IsPrintPreview())
OnPrintPreviewLoaded();
OnDocumentLoadComplete();
if (!full_frame())
return;
DidStopLoading();
SetContentRestrictions(GetContentRestrictions());
}
void PdfViewPluginBase::DocumentLoadFailed() {
DCHECK_EQ(DocumentLoadState::kLoading, document_load_state());
set_document_load_state(DocumentLoadState::kFailed);
UserMetricsRecordAction("PDF.LoadFailure");
// Send a progress value of -1 to indicate a failure.
SendLoadingProgress(-1);
DidStopLoading();
paint_manager().InvalidateRect(gfx::Rect(plugin_rect().size()));
}
void PdfViewPluginBase::SelectionChanged(const gfx::Rect& left,
const gfx::Rect& right) {
gfx::PointF left_point(left.x() + available_area().x(), left.y());
gfx::PointF right_point(right.x() + available_area().x(), right.y());
const float inverse_scale = 1.0f / device_scale();
left_point.Scale(inverse_scale);
right_point.Scale(inverse_scale);
NotifySelectionChanged(left_point, left.height() * inverse_scale, right_point,
right.height() * inverse_scale);
if (accessibility_state() == AccessibilityState::kLoaded)
PrepareAndSetAccessibilityViewportInfo();
}
int PdfViewPluginBase::GetContentRestrictions() const {
int content_restrictions = kContentRestrictionCut | kContentRestrictionPaste;
if (!engine()->HasPermission(DocumentPermission::kCopy))
content_restrictions |= kContentRestrictionCopy;
if (!engine()->HasPermission(DocumentPermission::kPrintLowQuality) &&
!engine()->HasPermission(DocumentPermission::kPrintHighQuality)) {
content_restrictions |= kContentRestrictionPrint;
}
return content_restrictions;
}
AccessibilityDocInfo PdfViewPluginBase::GetAccessibilityDocInfo() const {
AccessibilityDocInfo doc_info;
doc_info.page_count = engine()->GetNumberOfPages();
doc_info.text_accessible =
engine()->HasPermission(DocumentPermission::kCopyAccessible);
doc_info.text_copyable = engine()->HasPermission(DocumentPermission::kCopy);
return doc_info;
}
void PdfViewPluginBase::PrepareAndSetAccessibilityPageInfo(int32_t page_index) {
// Outdated calls are ignored.
if (page_index != next_accessibility_page_index())
return;
increment_next_accessibility_page_index();
AccessibilityPageInfo page_info;
std::vector<AccessibilityTextRunInfo> text_runs;
std::vector<AccessibilityCharInfo> chars;
AccessibilityPageObjects page_objects;
if (!GetAccessibilityInfo(engine(), page_index, page_info, text_runs, chars,
page_objects)) {
return;
}
SetAccessibilityPageInfo(std::move(page_info), std::move(text_runs),
std::move(chars), std::move(page_objects));
// Schedule loading the next page.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&PdfViewPluginBase::PrepareAndSetAccessibilityPageInfo,
GetWeakPtr(), page_index + 1),
kAccessibilityPageDelay);
}
void PdfViewPluginBase::PrepareAndSetAccessibilityViewportInfo() {
AccessibilityViewportInfo viewport_info;
viewport_info.offset = gfx::ScaleToFlooredPoint(
available_area().origin(), 1 / (device_scale() * zoom()));
viewport_info.zoom = zoom();
viewport_info.scale = device_scale();
viewport_info.focus_info = {FocusObjectType::kNone, 0, 0};
engine()->GetSelection(&viewport_info.selection_start_page_index,
&viewport_info.selection_start_char_index,
&viewport_info.selection_end_page_index,
&viewport_info.selection_end_char_index);
SetAccessibilityViewportInfo(std::move(viewport_info));
}
void PdfViewPluginBase::LoadAccessibility() {
set_accessibility_state(AccessibilityState::kLoaded);
// A new document layout will trigger the creation of a new accessibility
// tree, so `next_accessibility_page_index_` should be reset to ignore
// outdated asynchronous calls of PrepareAndSetAccessibilityPageInfo().
reset_next_accessibility_page_index();
SetAccessibilityDocInfo(GetAccessibilityDocInfo());
// If the document contents isn't accessible, don't send anything more.
if (!(engine()->HasPermission(DocumentPermission::kCopy) ||
engine()->HasPermission(DocumentPermission::kCopyAccessible))) {
return;
}
PrepareAndSetAccessibilityViewportInfo();
// Schedule loading the first page.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&PdfViewPluginBase::PrepareAndSetAccessibilityPageInfo,
GetWeakPtr(), /*page_index=*/0),
kAccessibilityPageDelay);
}
} // namespace chrome_pdf

@ -1,159 +0,0 @@
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PDF_PDF_VIEW_PLUGIN_BASE_H_
#define PDF_PDF_VIEW_PLUGIN_BASE_H_
#include <stdint.h>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string_piece.h"
#include "base/values.h"
#include "pdf/accessibility_structs.h"
#include "pdf/paint_manager.h"
#include "pdf/pdf_engine.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/web/web_print_params.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/geometry/rect.h"
namespace gfx {
class PointF;
} // namespace gfx
namespace chrome_pdf {
class PDFiumEngine;
struct AccessibilityCharInfo;
struct AccessibilityDocInfo;
struct AccessibilityPageInfo;
struct AccessibilityPageObjects;
struct AccessibilityTextRunInfo;
struct AccessibilityViewportInfo;
// TODO(crbug.com/1302059): Merge with PdfViewWebPlugin.
class PdfViewPluginBase : public PDFEngine::Client {
public:
enum class AccessibilityState {
kOff = 0, // Off.
kPending, // Enabled but waiting for doc to load.
kLoaded, // Fully loaded.
};
enum class DocumentLoadState {
kLoading = 0,
kComplete,
kFailed,
};
PdfViewPluginBase(const PdfViewPluginBase& other) = delete;
PdfViewPluginBase& operator=(const PdfViewPluginBase& other) = delete;
// PDFEngine::Client:
void DocumentLoadComplete() override;
void DocumentLoadFailed() override;
void SelectionChanged(const gfx::Rect& left, const gfx::Rect& right) override;
protected:
PdfViewPluginBase();
~PdfViewPluginBase() override;
virtual const PDFiumEngine* engine() const = 0;
virtual PDFiumEngine* engine() = 0;
// Gets a weak pointer with a lifetime matching the derived class.
virtual base::WeakPtr<PdfViewPluginBase> GetWeakPtr() = 0;
// Runs when document load completes in Print Preview, before
// `OnDocumentLoadComplete()`.
virtual void OnPrintPreviewLoaded() = 0;
// Runs when document load completes.
virtual void OnDocumentLoadComplete() = 0;
// Sends the loading progress, where `percentage` represents the progress, or
// -1 for loading error.
virtual void SendLoadingProgress(double percentage) = 0;
// Sets the accessibility information about the PDF document in the renderer.
virtual void SetAccessibilityDocInfo(AccessibilityDocInfo doc_info) = 0;
// Sets the accessibility information about the given `page_index` in the
// renderer.
void PrepareAndSetAccessibilityPageInfo(int32_t page_index);
// Sets the accessibility information about the page in the renderer.
virtual void SetAccessibilityPageInfo(
AccessibilityPageInfo page_info,
std::vector<AccessibilityTextRunInfo> text_runs,
std::vector<AccessibilityCharInfo> chars,
AccessibilityPageObjects page_objects) = 0;
// Prepares the accessibility information about the current viewport. Calls
// SetAccessibilityViewportInfo() internally to set this information in the
// renderer. This is done once when accessibility is first loaded and again
// when the geometry changes.
void PrepareAndSetAccessibilityViewportInfo();
// Sets the accessibility information about the current viewport in the
// renderer.
virtual void SetAccessibilityViewportInfo(
AccessibilityViewportInfo viewport_info) = 0;
// Disables browser commands because of restrictions on how the data is to be
// used (i.e. can't copy/print). `content_restrictions` should have its bits
// set by `chrome_pdf::ContentRestriction` enum values.
virtual void SetContentRestrictions(int content_restrictions) = 0;
// Sends start/stop loading notifications to the plugin's render frame.
virtual void DidStartLoading() = 0;
virtual void DidStopLoading() = 0;
// Notifies the embedder of the top-left and bottom-right coordinates of the
// current selection.
virtual void NotifySelectionChanged(const gfx::PointF& left,
int left_height,
const gfx::PointF& right,
int right_height) = 0;
// Records user actions.
virtual void UserMetricsRecordAction(const std::string& action) = 0;
virtual PaintManager& paint_manager() = 0;
virtual const gfx::Rect& available_area() const = 0;
virtual double zoom() const = 0;
virtual bool full_frame() const = 0;
// TODO(crbug.com/1288847): Don't provide direct access to the origin of
// `plugin_rect_`, as this exposes the unintuitive "paint offset."
virtual const gfx::Rect& plugin_rect() const = 0;
virtual float device_scale() const = 0;
virtual DocumentLoadState document_load_state() const = 0;
virtual void set_document_load_state(DocumentLoadState state) = 0;
virtual AccessibilityState accessibility_state() const = 0;
virtual void set_accessibility_state(AccessibilityState state) = 0;
virtual int32_t next_accessibility_page_index() const = 0;
virtual void increment_next_accessibility_page_index() = 0;
virtual void reset_next_accessibility_page_index() = 0;
// Starts loading accessibility information.
void LoadAccessibility();
// Gets the content restrictions based on the permissions which `engine_` has.
int GetContentRestrictions() const;
// Gets the accessibility doc info based on the information from `engine_`.
AccessibilityDocInfo GetAccessibilityDocInfo() const;
};
} // namespace chrome_pdf
#endif // PDF_PDF_VIEW_PLUGIN_BASE_H_

@ -46,6 +46,7 @@
#include "cc/paint/paint_image.h"
#include "cc/paint/paint_image_builder.h"
#include "net/cookies/site_for_cookies.h"
#include "pdf/accessibility.h"
#include "pdf/accessibility_structs.h"
#include "pdf/buildflags.h"
#include "pdf/content_restriction.h"
@ -54,6 +55,7 @@
#include "pdf/loader/url_loader.h"
#include "pdf/metrics_handler.h"
#include "pdf/mojom/pdf.mojom.h"
#include "pdf/paint_manager.h"
#include "pdf/paint_ready_rect.h"
#include "pdf/parsed_params.h"
#include "pdf/pdf_accessibility_data_handler.h"
@ -121,6 +123,10 @@ namespace {
// The minimum zoom level allowed.
constexpr double kMinZoom = 0.01;
// A delay to wait between each accessibility page to keep the system
// responsive.
constexpr base::TimeDelta kAccessibilityPageDelay = base::Milliseconds(100);
constexpr base::TimeDelta kFindResultCooldown = base::Milliseconds(100);
constexpr base::StringPiece kChromeExtensionHost =
@ -284,16 +290,6 @@ PdfViewWebPlugin::PdfViewWebPlugin(
PdfViewWebPlugin::~PdfViewWebPlugin() = default;
// TODO(crbug.com/1302059): Delete after merging with `PdfViewPluginBase`.
const PDFiumEngine* PdfViewWebPlugin::engine() const {
return engine_.get();
}
// TODO(crbug.com/1302059): Delete after merging with `PdfViewPluginBase`.
PDFiumEngine* PdfViewWebPlugin::engine() {
return engine_.get();
}
bool PdfViewWebPlugin::Initialize(blink::WebPluginContainer* container) {
DCHECK(container);
client_->SetPluginContainer(container);
@ -1034,6 +1030,35 @@ void PdfViewWebPlugin::DidFormOpen(int32_t result) {
form_loader_.reset();
}
void PdfViewWebPlugin::DidStartLoading() {
if (did_call_start_loading_)
return;
client_->DidStartLoading();
did_call_start_loading_ = true;
}
void PdfViewWebPlugin::DidStopLoading() {
if (!did_call_start_loading_)
return;
client_->DidStopLoading();
did_call_start_loading_ = false;
}
int PdfViewWebPlugin::GetContentRestrictions() const {
int content_restrictions = kContentRestrictionCut | kContentRestrictionPaste;
if (!engine_->HasPermission(DocumentPermission::kCopy))
content_restrictions |= kContentRestrictionCopy;
if (!engine_->HasPermission(DocumentPermission::kPrintLowQuality) &&
!engine_->HasPermission(DocumentPermission::kPrintHighQuality)) {
content_restrictions |= kContentRestrictionPrint;
}
return content_restrictions;
}
std::unique_ptr<UrlLoader> PdfViewWebPlugin::CreateUrlLoader() {
if (full_frame_) {
DidStartLoading();
@ -1041,7 +1066,8 @@ std::unique_ptr<UrlLoader> PdfViewWebPlugin::CreateUrlLoader() {
// Disable save and print until the document is fully loaded, since they
// would generate an incomplete document. This needs to be done each time
// DidStartLoading() is called because that resets the content restrictions.
SetContentRestrictions(kContentRestrictionSave | kContentRestrictionPrint);
pdf_service_->UpdateContentRestrictions(kContentRestrictionSave |
kContentRestrictionPrint);
}
return std::make_unique<UrlLoader>(weak_factory_.GetWeakPtr());
@ -1061,6 +1087,62 @@ PdfViewWebPlugin::SearchString(const char16_t* string,
return results;
}
void PdfViewWebPlugin::DocumentLoadComplete() {
DCHECK_EQ(DocumentLoadState::kLoading, document_load_state_);
document_load_state_ = DocumentLoadState::kComplete;
client_->RecordComputedAction("PDF.LoadSuccess");
// Clear the focus state for on-screen keyboards.
FormFieldFocusChange(PDFEngine::FocusFieldType::kNoFocus);
if (IsPrintPreview()) {
// Scroll location is retained across document loads in Print Preview, so
// there's no need to override the scroll position by scrolling again.
if (IsPreviewingPDF(print_preview_page_count_)) {
SendPrintPreviewLoadedNotification();
} else {
DCHECK_EQ(0, print_preview_loaded_page_count_);
print_preview_loaded_page_count_ = 1;
engine_->AppendBlankPages(print_preview_page_count_);
LoadNextPreviewPage();
}
OnGeometryChanged(0, 0);
if (!document_size_.IsEmpty())
paint_manager_.InvalidateRect(gfx::Rect(plugin_rect_.size()));
}
RecordDocumentMetrics();
SendAttachments();
SendBookmarks();
SendMetadata();
if (accessibility_state_ == AccessibilityState::kPending)
LoadAccessibility();
if (!full_frame_)
return;
DidStopLoading();
pdf_service_->UpdateContentRestrictions(GetContentRestrictions());
}
void PdfViewWebPlugin::DocumentLoadFailed() {
DCHECK_EQ(DocumentLoadState::kLoading, document_load_state_);
document_load_state_ = DocumentLoadState::kFailed;
client_->RecordComputedAction("PDF.LoadFailure");
// Send a progress value of -1 to indicate a failure.
SendLoadingProgress(-1);
DidStopLoading();
paint_manager_.InvalidateRect(gfx::Rect(plugin_rect_.size()));
}
void PdfViewWebPlugin::DocumentHasUnsupportedFeature(
const std::string& feature) {
DCHECK(!feature.empty());
@ -1127,6 +1209,22 @@ void PdfViewWebPlugin::SetIsSelecting(bool is_selecting) {
client_->PostMessage(std::move(message));
}
void PdfViewWebPlugin::SelectionChanged(const gfx::Rect& left,
const gfx::Rect& right) {
gfx::PointF left_point(left.x() + available_area_.x(), left.y());
gfx::PointF right_point(right.x() + available_area_.x(), right.y());
const float inverse_scale = 1.0f / device_scale_;
left_point.Scale(inverse_scale);
right_point.Scale(inverse_scale);
pdf_service_->SelectionChanged(left_point, left.height() * inverse_scale,
right_point, right.height() * inverse_scale);
if (accessibility_state_ == AccessibilityState::kLoaded)
PrepareAndSetAccessibilityViewportInfo();
}
void PdfViewWebPlugin::EnteredEditMode() {
edit_mode_ = true;
pdf_service_->SetPluginCanSave(true);
@ -1202,12 +1300,7 @@ PdfViewWebPlugin::CreateAssociatedURLLoader(
void PdfViewWebPlugin::OnMessage(const base::Value::Dict& message) {
using MessageHandler = void (PdfViewWebPlugin::*)(const base::Value::Dict&);
// Settings this as const instead of constexpr to workaround a bug
// in GCC, that will try to reinterpret_cast the method pointers.
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105996
// TODO(crbug.com/1302059): make it constexpr again when we get rid
// of PdfViewPluginBase
static const auto kMessageHandlers =
static constexpr auto kMessageHandlers =
base::MakeFixedFlatMap<base::StringPiece, MessageHandler>({
{"displayAnnotations",
&PdfViewWebPlugin::HandleDisplayAnnotationsMessage},
@ -1820,167 +1913,6 @@ void PdfViewWebPlugin::HandleAccessibilityAction(
engine_->HandleAccessibilityAction(action_data);
}
base::WeakPtr<PdfViewPluginBase> PdfViewWebPlugin::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
void PdfViewWebPlugin::OnPrintPreviewLoaded() {
// Scroll location is retained across document loads in Print Preview, so
// there's no need to override the scroll position by scrolling again.
if (IsPreviewingPDF(print_preview_page_count_)) {
SendPrintPreviewLoadedNotification();
} else {
DCHECK_EQ(0, print_preview_loaded_page_count_);
print_preview_loaded_page_count_ = 1;
engine_->AppendBlankPages(print_preview_page_count_);
LoadNextPreviewPage();
}
OnGeometryChanged(0, 0);
if (!document_size_.IsEmpty())
paint_manager_.InvalidateRect(gfx::Rect(plugin_rect_.size()));
}
void PdfViewWebPlugin::OnDocumentLoadComplete() {
RecordDocumentMetrics();
SendAttachments();
SendBookmarks();
SendMetadata();
if (accessibility_state_ == AccessibilityState::kPending)
LoadAccessibility();
}
void PdfViewWebPlugin::SendLoadingProgress(double percentage) {
DCHECK(percentage == -1 || (percentage >= 0 && percentage <= 100));
last_progress_sent_ = percentage;
base::Value::Dict message;
message.Set("type", "loadProgress");
message.Set("progress", percentage);
client_->PostMessage(std::move(message));
}
void PdfViewWebPlugin::SetAccessibilityDocInfo(AccessibilityDocInfo doc_info) {
pdf_accessibility_data_handler_->SetAccessibilityDocInfo(std::move(doc_info));
}
void PdfViewWebPlugin::SetAccessibilityPageInfo(
AccessibilityPageInfo page_info,
std::vector<AccessibilityTextRunInfo> text_runs,
std::vector<AccessibilityCharInfo> chars,
AccessibilityPageObjects page_objects) {
pdf_accessibility_data_handler_->SetAccessibilityPageInfo(
std::move(page_info), std::move(text_runs), std::move(chars),
std::move(page_objects));
}
void PdfViewWebPlugin::SetAccessibilityViewportInfo(
AccessibilityViewportInfo viewport_info) {
pdf_accessibility_data_handler_->SetAccessibilityViewportInfo(
std::move(viewport_info));
}
void PdfViewWebPlugin::SetContentRestrictions(int content_restrictions) {
pdf_service_->UpdateContentRestrictions(content_restrictions);
}
void PdfViewWebPlugin::DidStartLoading() {
if (did_call_start_loading_)
return;
client_->DidStartLoading();
did_call_start_loading_ = true;
}
void PdfViewWebPlugin::DidStopLoading() {
if (!did_call_start_loading_)
return;
client_->DidStopLoading();
did_call_start_loading_ = false;
}
void PdfViewWebPlugin::NotifySelectionChanged(const gfx::PointF& left,
int left_height,
const gfx::PointF& right,
int right_height) {
pdf_service_->SelectionChanged(left, left_height, right, right_height);
}
// TODO(crbug.com/1302059): Delete after merging with `PdfViewPluginBase`.
void PdfViewWebPlugin::UserMetricsRecordAction(const std::string& action) {
client_->RecordComputedAction(action);
}
// TODO(crbug.com/1302059): Delete after merging with `PdfViewPluginBase`.
PaintManager& PdfViewWebPlugin::paint_manager() {
return paint_manager_;
}
// TODO(crbug.com/1302059): Delete after merging with `PdfViewPluginBase`.
const gfx::Rect& PdfViewWebPlugin::available_area() const {
return available_area_;
}
// TODO(crbug.com/1302059): Delete after merging with `PdfViewPluginBase`.
double PdfViewWebPlugin::zoom() const {
return zoom_;
}
// TODO(crbug.com/1302059): Delete after merging with `PdfViewPluginBase`.
bool PdfViewWebPlugin::full_frame() const {
return full_frame_;
}
// TODO(crbug.com/1302059): Delete after merging with `PdfViewPluginBase`.
const gfx::Rect& PdfViewWebPlugin::plugin_rect() const {
return plugin_rect_;
}
// TODO(crbug.com/1302059): Delete after merging with `PdfViewPluginBase`.
float PdfViewWebPlugin::device_scale() const {
return device_scale_;
}
// TODO(crbug.com/1302059): Delete after merging with `PdfViewPluginBase`.
PdfViewPluginBase::DocumentLoadState PdfViewWebPlugin::document_load_state()
const {
return document_load_state_;
}
// TODO(crbug.com/1302059): Delete after merging with `PdfViewPluginBase`.
void PdfViewWebPlugin::set_document_load_state(DocumentLoadState state) {
document_load_state_ = state;
}
// TODO(crbug.com/1302059): Delete after merging with `PdfViewPluginBase`.
PdfViewPluginBase::AccessibilityState PdfViewWebPlugin::accessibility_state()
const {
return accessibility_state_;
}
// TODO(crbug.com/1302059): Delete after merging with `PdfViewPluginBase`.
void PdfViewWebPlugin::set_accessibility_state(AccessibilityState state) {
accessibility_state_ = state;
}
// TODO(crbug.com/1302059): Delete after merging with `PdfViewPluginBase`.
int32_t PdfViewWebPlugin::next_accessibility_page_index() const {
return next_accessibility_page_index_;
}
// TODO(crbug.com/1302059): Delete after merging with `PdfViewPluginBase`.
void PdfViewWebPlugin::increment_next_accessibility_page_index() {
++next_accessibility_page_index_;
}
// TODO(crbug.com/1302059): Delete after merging with `PdfViewPluginBase`.
void PdfViewWebPlugin::reset_next_accessibility_page_index() {
next_accessibility_page_index_ = 0;
}
void PdfViewWebPlugin::OnViewportChanged(
const gfx::Rect& new_plugin_rect_in_css_pixel,
float new_device_scale) {
@ -2222,6 +2154,16 @@ void PdfViewWebPlugin::SendMetadata() {
client_->PostMessage(std::move(message));
}
void PdfViewWebPlugin::SendLoadingProgress(double percentage) {
DCHECK(percentage == -1 || (percentage >= 0 && percentage <= 100));
last_progress_sent_ = percentage;
base::Value::Dict message;
message.Set("type", "loadProgress");
message.Set("progress", percentage);
client_->PostMessage(std::move(message));
}
void PdfViewWebPlugin::HandleResetPrintPreviewModeMessage(
const base::Value::Dict& message) {
const std::string& url = *message.FindString("url");
@ -2382,4 +2324,84 @@ gfx::Point PdfViewWebPlugin::FrameToPdfCoordinates(
gfx::Vector2d(available_area_.x(), 0);
}
AccessibilityDocInfo PdfViewWebPlugin::GetAccessibilityDocInfo() const {
AccessibilityDocInfo doc_info;
doc_info.page_count = engine_->GetNumberOfPages();
doc_info.text_accessible =
engine_->HasPermission(DocumentPermission::kCopyAccessible);
doc_info.text_copyable = engine_->HasPermission(DocumentPermission::kCopy);
return doc_info;
}
void PdfViewWebPlugin::PrepareAndSetAccessibilityPageInfo(int32_t page_index) {
// Outdated calls are ignored.
if (page_index != next_accessibility_page_index_)
return;
++next_accessibility_page_index_;
AccessibilityPageInfo page_info;
std::vector<AccessibilityTextRunInfo> text_runs;
std::vector<AccessibilityCharInfo> chars;
AccessibilityPageObjects page_objects;
if (!GetAccessibilityInfo(engine_.get(), page_index, page_info, text_runs,
chars, page_objects)) {
return;
}
pdf_accessibility_data_handler_->SetAccessibilityPageInfo(
std::move(page_info), std::move(text_runs), std::move(chars),
std::move(page_objects));
// Schedule loading the next page.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&PdfViewWebPlugin::PrepareAndSetAccessibilityPageInfo,
weak_factory_.GetWeakPtr(), page_index + 1),
kAccessibilityPageDelay);
}
void PdfViewWebPlugin::PrepareAndSetAccessibilityViewportInfo() {
AccessibilityViewportInfo viewport_info;
viewport_info.offset = gfx::ScaleToFlooredPoint(available_area_.origin(),
1 / (device_scale_ * zoom_));
viewport_info.zoom = zoom_;
viewport_info.scale = device_scale_;
viewport_info.focus_info = {FocusObjectType::kNone, 0, 0};
engine_->GetSelection(&viewport_info.selection_start_page_index,
&viewport_info.selection_start_char_index,
&viewport_info.selection_end_page_index,
&viewport_info.selection_end_char_index);
pdf_accessibility_data_handler_->SetAccessibilityViewportInfo(
std::move(viewport_info));
}
void PdfViewWebPlugin::LoadAccessibility() {
accessibility_state_ = AccessibilityState::kLoaded;
// A new document layout will trigger the creation of a new accessibility
// tree, so `next_accessibility_page_index_` should be reset to ignore
// outdated asynchronous calls of PrepareAndSetAccessibilityPageInfo().
next_accessibility_page_index_ = 0;
pdf_accessibility_data_handler_->SetAccessibilityDocInfo(
GetAccessibilityDocInfo());
// If the document contents isn't accessible, don't send anything more.
if (!(engine_->HasPermission(DocumentPermission::kCopy) ||
engine_->HasPermission(DocumentPermission::kCopyAccessible))) {
return;
}
PrepareAndSetAccessibilityViewportInfo();
// Schedule loading the first page.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&PdfViewWebPlugin::PrepareAndSetAccessibilityPageInfo,
weak_factory_.GetWeakPtr(), /*page_index=*/0),
kAccessibilityPageDelay);
}
} // namespace chrome_pdf

@ -22,11 +22,12 @@
#include "cc/paint/paint_image.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "pdf/accessibility_structs.h"
#include "pdf/loader/url_loader.h"
#include "pdf/mojom/pdf.mojom.h"
#include "pdf/paint_manager.h"
#include "pdf/pdf_accessibility_action_handler.h"
#include "pdf/pdf_engine.h"
#include "pdf/pdf_view_plugin_base.h"
#include "pdf/pdfium/pdfium_form_filler.h"
#include "pdf/post_message_receiver.h"
#include "pdf/preview_mode_client.h"
@ -37,6 +38,7 @@
#include "third_party/blink/public/web/web_plugin_container.h"
#include "third_party/blink/public/web/web_plugin_params.h"
#include "third_party/blink/public/web/web_print_params.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
#include "ui/gfx/geometry/rect.h"
@ -73,7 +75,7 @@ class PDFiumEngine;
class PdfAccessibilityDataHandler;
class Thumbnail;
class PdfViewWebPlugin final : public PdfViewPluginBase,
class PdfViewWebPlugin final : public PDFEngine::Client,
public blink::WebPlugin,
public pdf::mojom::PdfListener,
public UrlLoader::Client,
@ -86,6 +88,12 @@ class PdfViewWebPlugin final : public PdfViewPluginBase,
// and is also enforced in chrome/browser/resources/pdf/pdf_viewer.ts.
static constexpr size_t kMaximumSavedFileSize = 100 * 1000 * 1000;
enum class DocumentLoadState {
kLoading = 0,
kComplete,
kFailed,
};
// Must match `SaveRequestType` in chrome/browser/resources/pdf/constants.ts.
enum class SaveRequestType {
kAnnotation = 0,
@ -323,12 +331,15 @@ class PdfViewWebPlugin final : public PdfViewPluginBase,
std::vector<SearchStringResult> SearchString(const char16_t* string,
const char16_t* term,
bool case_sensitive) override;
void DocumentLoadComplete() override;
void DocumentLoadFailed() override;
void DocumentHasUnsupportedFeature(const std::string& feature) override;
void DocumentLoadProgress(uint32_t available, uint32_t doc_size) override;
void FormFieldFocusChange(PDFEngine::FocusFieldType type) override;
bool IsPrintPreview() const override;
SkColor GetBackgroundColor() const override;
void SetIsSelecting(bool is_selecting) override;
void SelectionChanged(const gfx::Rect& left, const gfx::Rect& right) override;
void CaretChanged(const gfx::Rect& caret_rect) override;
void EnteredEditMode() override;
void DocumentFocusChanged(bool document_has_focus) override;
@ -392,43 +403,6 @@ class PdfViewWebPlugin final : public PdfViewPluginBase,
return GetAccessibilityDocInfo();
}
protected:
// PdfViewPluginBase:
const PDFiumEngine* engine() const override;
PDFiumEngine* engine() override;
base::WeakPtr<PdfViewPluginBase> GetWeakPtr() override;
void OnPrintPreviewLoaded() override;
void OnDocumentLoadComplete() override;
void SendLoadingProgress(double percentage) override;
void SetAccessibilityDocInfo(AccessibilityDocInfo doc_info) override;
void SetAccessibilityPageInfo(AccessibilityPageInfo page_info,
std::vector<AccessibilityTextRunInfo> text_runs,
std::vector<AccessibilityCharInfo> chars,
AccessibilityPageObjects page_objects) override;
void SetAccessibilityViewportInfo(
AccessibilityViewportInfo viewport_info) override;
void SetContentRestrictions(int content_restrictions) override;
void DidStartLoading() override;
void DidStopLoading() override;
void NotifySelectionChanged(const gfx::PointF& left,
int left_height,
const gfx::PointF& right,
int right_height) override;
void UserMetricsRecordAction(const std::string& action) override;
PaintManager& paint_manager() override;
const gfx::Rect& available_area() const override;
double zoom() const override;
bool full_frame() const override;
const gfx::Rect& plugin_rect() const override;
float device_scale() const override;
DocumentLoadState document_load_state() const override;
void set_document_load_state(DocumentLoadState state) override;
AccessibilityState accessibility_state() const override;
void set_accessibility_state(AccessibilityState state) override;
int32_t next_accessibility_page_index() const override;
void increment_next_accessibility_page_index() override;
void reset_next_accessibility_page_index() override;
private:
// Callback that runs after `LoadUrl()`. The `loader` is the loader used to
// load the URL, and `result` is the result code for the load.
@ -436,6 +410,12 @@ class PdfViewWebPlugin final : public PdfViewPluginBase,
base::OnceCallback<void(std::unique_ptr<UrlLoader> loader,
int32_t result)>;
enum class AccessibilityState {
kOff = 0, // Off.
kPending, // Enabled but waiting for doc to load.
kLoaded, // Fully loaded.
};
struct BackgroundPart {
gfx::Rect location;
uint32_t color;
@ -471,6 +451,13 @@ class PdfViewWebPlugin final : public PdfViewPluginBase,
// Handles `Open()` result for `form_loader_`.
void DidFormOpen(int32_t result);
// Sends start/stop loading notifications to the plugin's render frame.
void DidStartLoading();
void DidStopLoading();
// Gets the content restrictions based on the permissions which `engine_` has.
int GetContentRestrictions() const;
// Message handlers.
void HandleDisplayAnnotationsMessage(const base::Value::Dict& message);
void HandleGetNamedDestinationMessage(const base::Value::Dict& message);
@ -572,6 +559,10 @@ class PdfViewWebPlugin final : public PdfViewPluginBase,
// Send document metadata data.
void SendMetadata();
// Sends the loading progress, where `percentage` represents the progress, or
// -1 for loading error.
void SendLoadingProgress(double percentage);
// Handles message for resetting Print Preview.
void HandleResetPrintPreviewModeMessage(const base::Value::Dict& message);
@ -596,6 +587,21 @@ class PdfViewWebPlugin final : public PdfViewPluginBase,
// Converts `frame_coordinates` to PDF coordinates.
gfx::Point FrameToPdfCoordinates(const gfx::PointF& frame_coordinates) const;
// Gets the accessibility doc info based on the information from `engine_`.
AccessibilityDocInfo GetAccessibilityDocInfo() const;
// Sets the accessibility information about the given `page_index` in the
// renderer.
void PrepareAndSetAccessibilityPageInfo(int32_t page_index);
// Prepares the accessibility information about the current viewport. This is
// done once when accessibility is first loaded and again when the geometry
// changes.
void PrepareAndSetAccessibilityViewportInfo();
// Starts loading accessibility information.
void LoadAccessibility();
blink::WebString selected_text_;
std::unique_ptr<Client> const client_;