[M108 Migration][HBBTV] Implement ewk_context_register_jsplugin_mime_types API
[platform/framework/web/chromium-efl.git] / pdf / pdf_view_plugin_base.cc
1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "pdf/pdf_view_plugin_base.h"
6
7 #include <algorithm>
8 #include <cmath>
9 #include <iterator>
10 #include <memory>
11 #include <sstream>
12 #include <string>
13 #include <utility>
14
15 #include "base/bind.h"
16 #include "base/callback.h"
17 #include "base/check.h"
18 #include "base/check_op.h"
19 #include "base/containers/span.h"
20 #include "base/cxx17_backports.h"
21 #include "base/feature_list.h"
22 #include "base/location.h"
23 #include "base/memory/weak_ptr.h"
24 #include "base/notreached.h"
25 #include "base/numerics/safe_conversions.h"
26 #include "base/strings/string_piece.h"
27 #include "base/strings/string_util.h"
28 #include "base/threading/thread_task_runner_handle.h"
29 #include "base/time/time.h"
30 #include "base/values.h"
31 #include "pdf/accessibility.h"
32 #include "pdf/accessibility_structs.h"
33 #include "pdf/buildflags.h"
34 #include "pdf/content_restriction.h"
35 #include "pdf/document_layout.h"
36 #include "pdf/document_metadata.h"
37 #include "pdf/paint_ready_rect.h"
38 #include "pdf/pdf_engine.h"
39 #include "pdf/pdf_features.h"
40 #include "pdf/pdfium/pdfium_engine.h"
41 #include "pdf/pdfium/pdfium_form_filler.h"
42 #include "pdf/ui/file_name.h"
43 #include "third_party/abseil-cpp/absl/types/optional.h"
44 #include "third_party/blink/public/common/input/web_input_event.h"
45 #include "third_party/blink/public/common/input/web_mouse_event.h"
46 #include "third_party/blink/public/common/input/web_touch_event.h"
47 #include "third_party/skia/include/core/SkBitmap.h"
48 #include "third_party/skia/include/core/SkImage.h"
49 #include "third_party/skia/include/core/SkRefCnt.h"
50 #include "ui/events/blink/blink_event_util.h"
51 #include "ui/gfx/geometry/point.h"
52 #include "ui/gfx/geometry/point_f.h"
53 #include "ui/gfx/geometry/rect.h"
54 #include "ui/gfx/geometry/size.h"
55 #include "ui/gfx/geometry/skia_conversions.h"
56 #include "ui/gfx/geometry/vector2d.h"
57 #include "ui/gfx/geometry/vector2d_f.h"
58 #include "url/gurl.h"
59
60 namespace chrome_pdf {
61
62 namespace {
63
64 // A delay to wait between each accessibility page to keep the system
65 // responsive.
66 constexpr base::TimeDelta kAccessibilityPageDelay = base::Milliseconds(100);
67
68 }  // namespace
69
70 PdfViewPluginBase::PdfViewPluginBase() = default;
71
72 PdfViewPluginBase::~PdfViewPluginBase() = default;
73
74 void PdfViewPluginBase::DocumentLoadComplete() {
75   DCHECK_EQ(DocumentLoadState::kLoading, document_load_state());
76   set_document_load_state(DocumentLoadState::kComplete);
77
78   UserMetricsRecordAction("PDF.LoadSuccess");
79
80   // Clear the focus state for on-screen keyboards.
81   FormFieldFocusChange(PDFEngine::FocusFieldType::kNoFocus);
82
83   if (IsPrintPreview())
84     OnPrintPreviewLoaded();
85
86   OnDocumentLoadComplete();
87
88   if (!full_frame())
89     return;
90
91   DidStopLoading();
92   SetContentRestrictions(GetContentRestrictions());
93 }
94
95 void PdfViewPluginBase::DocumentLoadFailed() {
96   DCHECK_EQ(DocumentLoadState::kLoading, document_load_state());
97   set_document_load_state(DocumentLoadState::kFailed);
98
99   UserMetricsRecordAction("PDF.LoadFailure");
100
101   // Send a progress value of -1 to indicate a failure.
102   SendLoadingProgress(-1);
103
104   DidStopLoading();
105
106   paint_manager().InvalidateRect(gfx::Rect(plugin_rect().size()));
107 }
108
109 void PdfViewPluginBase::SelectionChanged(const gfx::Rect& left,
110                                          const gfx::Rect& right) {
111   gfx::PointF left_point(left.x() + available_area().x(), left.y());
112   gfx::PointF right_point(right.x() + available_area().x(), right.y());
113
114   const float inverse_scale = 1.0f / device_scale();
115   left_point.Scale(inverse_scale);
116   right_point.Scale(inverse_scale);
117
118   NotifySelectionChanged(left_point, left.height() * inverse_scale, right_point,
119                          right.height() * inverse_scale);
120
121   if (accessibility_state() == AccessibilityState::kLoaded)
122     PrepareAndSetAccessibilityViewportInfo();
123 }
124
125 int PdfViewPluginBase::GetContentRestrictions() const {
126   int content_restrictions = kContentRestrictionCut | kContentRestrictionPaste;
127   if (!engine()->HasPermission(DocumentPermission::kCopy))
128     content_restrictions |= kContentRestrictionCopy;
129
130   if (!engine()->HasPermission(DocumentPermission::kPrintLowQuality) &&
131       !engine()->HasPermission(DocumentPermission::kPrintHighQuality)) {
132     content_restrictions |= kContentRestrictionPrint;
133   }
134
135   return content_restrictions;
136 }
137
138 AccessibilityDocInfo PdfViewPluginBase::GetAccessibilityDocInfo() const {
139   AccessibilityDocInfo doc_info;
140   doc_info.page_count = engine()->GetNumberOfPages();
141   doc_info.text_accessible =
142       engine()->HasPermission(DocumentPermission::kCopyAccessible);
143   doc_info.text_copyable = engine()->HasPermission(DocumentPermission::kCopy);
144   return doc_info;
145 }
146
147 void PdfViewPluginBase::PrepareAndSetAccessibilityPageInfo(int32_t page_index) {
148   // Outdated calls are ignored.
149   if (page_index != next_accessibility_page_index())
150     return;
151   increment_next_accessibility_page_index();
152
153   AccessibilityPageInfo page_info;
154   std::vector<AccessibilityTextRunInfo> text_runs;
155   std::vector<AccessibilityCharInfo> chars;
156   AccessibilityPageObjects page_objects;
157
158   if (!GetAccessibilityInfo(engine(), page_index, page_info, text_runs, chars,
159                             page_objects)) {
160     return;
161   }
162
163   SetAccessibilityPageInfo(std::move(page_info), std::move(text_runs),
164                            std::move(chars), std::move(page_objects));
165
166   // Schedule loading the next page.
167   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
168       FROM_HERE,
169       base::BindOnce(&PdfViewPluginBase::PrepareAndSetAccessibilityPageInfo,
170                      GetWeakPtr(), page_index + 1),
171       kAccessibilityPageDelay);
172 }
173
174 void PdfViewPluginBase::PrepareAndSetAccessibilityViewportInfo() {
175   AccessibilityViewportInfo viewport_info;
176   viewport_info.offset = gfx::ScaleToFlooredPoint(
177       available_area().origin(), 1 / (device_scale() * zoom()));
178   viewport_info.zoom = zoom();
179   viewport_info.scale = device_scale();
180   viewport_info.focus_info = {FocusObjectType::kNone, 0, 0};
181
182   engine()->GetSelection(&viewport_info.selection_start_page_index,
183                          &viewport_info.selection_start_char_index,
184                          &viewport_info.selection_end_page_index,
185                          &viewport_info.selection_end_char_index);
186
187   SetAccessibilityViewportInfo(std::move(viewport_info));
188 }
189
190 void PdfViewPluginBase::LoadAccessibility() {
191   set_accessibility_state(AccessibilityState::kLoaded);
192
193   // A new document layout will trigger the creation of a new accessibility
194   // tree, so `next_accessibility_page_index_` should be reset to ignore
195   // outdated asynchronous calls of PrepareAndSetAccessibilityPageInfo().
196   reset_next_accessibility_page_index();
197   SetAccessibilityDocInfo(GetAccessibilityDocInfo());
198
199   // If the document contents isn't accessible, don't send anything more.
200   if (!(engine()->HasPermission(DocumentPermission::kCopy) ||
201         engine()->HasPermission(DocumentPermission::kCopyAccessible))) {
202     return;
203   }
204
205   PrepareAndSetAccessibilityViewportInfo();
206
207   // Schedule loading the first page.
208   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
209       FROM_HERE,
210       base::BindOnce(&PdfViewPluginBase::PrepareAndSetAccessibilityPageInfo,
211                      GetWeakPtr(), /*page_index=*/0),
212       kAccessibilityPageDelay);
213 }
214
215 }  // namespace chrome_pdf