OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/plugins/renderer/webview_plugin.h" | 5 #include "components/plugins/renderer/webview_plugin.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 using blink::WebVector; | 46 using blink::WebVector; |
47 using blink::WebView; | 47 using blink::WebView; |
48 using content::WebPreferences; | 48 using content::WebPreferences; |
49 | 49 |
50 WebViewPlugin::WebViewPlugin(content::RenderView* render_view, | 50 WebViewPlugin::WebViewPlugin(content::RenderView* render_view, |
51 WebViewPlugin::Delegate* delegate, | 51 WebViewPlugin::Delegate* delegate, |
52 const WebPreferences& preferences) | 52 const WebPreferences& preferences) |
53 : content::RenderViewObserver(render_view), | 53 : content::RenderViewObserver(render_view), |
54 delegate_(delegate), | 54 delegate_(delegate), |
55 container_(nullptr), | 55 container_(nullptr), |
56 web_view_(WebView::create(this, blink::WebPageVisibilityStateVisible)), | 56 finished_loading_(false), |
57 focused_(false), | 57 focused_(false), |
58 is_painting_(false), | 58 is_painting_(false), |
59 is_resizing_(false), | 59 is_resizing_(false), |
60 web_frame_client_(this), | 60 web_view_helper_(this, preferences), |
61 weak_factory_(this) { | 61 weak_factory_(this) { |
62 // ApplyWebPreferences before making a WebLocalFrame so that the frame sees a | |
63 // consistent view of our preferences. | |
64 content::RenderView::ApplyWebPreferences(preferences, web_view_); | |
65 WebLocalFrame* web_frame = WebLocalFrame::create( | |
66 blink::WebTreeScopeType::Document, &web_frame_client_); | |
67 web_view_->setMainFrame(web_frame); | |
68 // TODO(dcheng): The main frame widget currently has a special case. | |
69 // Eliminate this once WebView is no longer a WebWidget. | |
70 WebFrameWidget::create(this, web_view_, web_frame); | |
71 } | 62 } |
72 | 63 |
73 // static | 64 // static |
74 WebViewPlugin* WebViewPlugin::Create(content::RenderView* render_view, | 65 WebViewPlugin* WebViewPlugin::Create(content::RenderView* render_view, |
75 WebViewPlugin::Delegate* delegate, | 66 WebViewPlugin::Delegate* delegate, |
76 const WebPreferences& preferences, | 67 const WebPreferences& preferences, |
77 const std::string& html_data, | 68 const std::string& html_data, |
78 const GURL& url) { | 69 const GURL& url) { |
79 DCHECK(url.is_valid()) << "Blink requires the WebView to have a valid URL."; | 70 DCHECK(url.is_valid()) << "Blink requires the WebView to have a valid URL."; |
80 WebViewPlugin* plugin = new WebViewPlugin(render_view, delegate, preferences); | 71 WebViewPlugin* plugin = new WebViewPlugin(render_view, delegate, preferences); |
81 plugin->web_view()->mainFrame()->loadHTMLString(html_data, url); | 72 plugin->web_view()->mainFrame()->loadHTMLString(html_data, url); |
82 return plugin; | 73 return plugin; |
83 } | 74 } |
84 | 75 |
85 WebViewPlugin::~WebViewPlugin() { | 76 WebViewPlugin::~WebViewPlugin() { |
86 DCHECK(!weak_factory_.HasWeakPtrs()); | 77 DCHECK(!weak_factory_.HasWeakPtrs()); |
87 web_view_->close(); | 78 } |
| 79 |
| 80 void WebViewPlugin::ReplayReceivedData(WebPlugin* plugin) { |
| 81 if (!response_.isNull()) { |
| 82 plugin->didReceiveResponse(response_); |
| 83 size_t total_bytes = 0; |
| 84 for (std::list<std::string>::iterator it = data_.begin(); it != data_.end(); |
| 85 ++it) { |
| 86 plugin->didReceiveData( |
| 87 it->c_str(), base::checked_cast<int>(it->length())); |
| 88 total_bytes += it->length(); |
| 89 } |
| 90 } |
| 91 // We need to transfer the |focused_| to new plugin after it loaded. |
| 92 if (focused_) |
| 93 plugin->updateFocus(true, blink::WebFocusTypeNone); |
| 94 if (finished_loading_) |
| 95 plugin->didFinishLoading(); |
| 96 if (error_) |
| 97 plugin->didFailLoading(*error_); |
88 } | 98 } |
89 | 99 |
90 WebPluginContainer* WebViewPlugin::container() const { return container_; } | 100 WebPluginContainer* WebViewPlugin::container() const { return container_; } |
91 | 101 |
92 bool WebViewPlugin::initialize(WebPluginContainer* container) { | 102 bool WebViewPlugin::initialize(WebPluginContainer* container) { |
93 DCHECK(container); | 103 DCHECK(container); |
94 DCHECK_EQ(this, container->plugin()); | 104 DCHECK_EQ(this, container->plugin()); |
95 container_ = container; | 105 container_ = container; |
96 | 106 |
97 // We must call layout again here to ensure that the container is laid | 107 // We must call layout again here to ensure that the container is laid |
98 // out before we next try to paint it, which is a requirement of the | 108 // out before we next try to paint it, which is a requirement of the |
99 // document life cycle in Blink. In most cases, needsLayout is set by | 109 // document life cycle in Blink. In most cases, needsLayout is set by |
100 // scheduleAnimation, but due to timers controlling widget update, | 110 // scheduleAnimation, but due to timers controlling widget update, |
101 // scheduleAnimation may be invoked before this initialize call (which | 111 // scheduleAnimation may be invoked before this initialize call (which |
102 // comes through the widget update process). It doesn't hurt to mark | 112 // comes through the widget update process). It doesn't hurt to mark |
103 // for animation again, and it does help us in the race-condition situation. | 113 // for animation again, and it does help us in the race-condition situation. |
104 container_->scheduleAnimation(); | 114 container_->scheduleAnimation(); |
105 | 115 |
106 old_title_ = container_->element().getAttribute("title"); | 116 old_title_ = container_->element().getAttribute("title"); |
107 | 117 |
108 // Propagate device scale and zoom level to inner webview. | 118 // Propagate device scale and zoom level to inner webview. |
109 web_view_->setDeviceScaleFactor(container_->deviceScaleFactor()); | 119 web_view()->setDeviceScaleFactor(container_->deviceScaleFactor()); |
110 web_view_->setZoomLevel( | 120 web_view()->setZoomLevel( |
111 blink::WebView::zoomFactorToZoomLevel(container_->pageZoomFactor())); | 121 blink::WebView::zoomFactorToZoomLevel(container_->pageZoomFactor())); |
112 | 122 |
113 return true; | 123 return true; |
114 } | 124 } |
115 | 125 |
116 void WebViewPlugin::destroy() { | 126 void WebViewPlugin::destroy() { |
117 weak_factory_.InvalidateWeakPtrs(); | 127 weak_factory_.InvalidateWeakPtrs(); |
118 | 128 |
119 if (delegate_) { | 129 if (delegate_) { |
120 delegate_->PluginDestroyed(); | 130 delegate_->PluginDestroyed(); |
121 delegate_ = nullptr; | 131 delegate_ = nullptr; |
122 } | 132 } |
123 container_ = nullptr; | 133 container_ = nullptr; |
124 content::RenderViewObserver::Observe(nullptr); | 134 content::RenderViewObserver::Observe(nullptr); |
125 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); | 135 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); |
126 } | 136 } |
127 | 137 |
128 v8::Local<v8::Object> WebViewPlugin::v8ScriptableObject(v8::Isolate* isolate) { | 138 v8::Local<v8::Object> WebViewPlugin::v8ScriptableObject(v8::Isolate* isolate) { |
129 if (!delegate_) | 139 if (!delegate_) |
130 return v8::Local<v8::Object>(); | 140 return v8::Local<v8::Object>(); |
131 | 141 |
132 return delegate_->GetV8ScriptableObject(isolate); | 142 return delegate_->GetV8ScriptableObject(isolate); |
133 } | 143 } |
134 | 144 |
135 void WebViewPlugin::updateAllLifecyclePhases() { | 145 void WebViewPlugin::updateAllLifecyclePhases() { |
136 web_view_->updateAllLifecyclePhases(); | 146 web_view()->updateAllLifecyclePhases(); |
137 } | 147 } |
138 | 148 |
139 void WebViewPlugin::paint(WebCanvas* canvas, const WebRect& rect) { | 149 void WebViewPlugin::paint(WebCanvas* canvas, const WebRect& rect) { |
140 gfx::Rect paint_rect = gfx::IntersectRects(rect_, rect); | 150 gfx::Rect paint_rect = gfx::IntersectRects(rect_, rect); |
141 if (paint_rect.IsEmpty()) | 151 if (paint_rect.IsEmpty()) |
142 return; | 152 return; |
143 | 153 |
144 base::AutoReset<bool> is_painting( | 154 base::AutoReset<bool> is_painting( |
145 &is_painting_, true); | 155 &is_painting_, true); |
146 | 156 |
147 paint_rect.Offset(-rect_.x(), -rect_.y()); | 157 paint_rect.Offset(-rect_.x(), -rect_.y()); |
148 | 158 |
149 canvas->save(); | 159 canvas->save(); |
150 canvas->translate(SkIntToScalar(rect_.x()), SkIntToScalar(rect_.y())); | 160 canvas->translate(SkIntToScalar(rect_.x()), SkIntToScalar(rect_.y())); |
151 | 161 |
152 // Apply inverse device scale factor, as the outer webview has already | 162 // Apply inverse device scale factor, as the outer webview has already |
153 // applied it, and the inner webview will apply it again. | 163 // applied it, and the inner webview will apply it again. |
154 SkScalar inverse_scale = | 164 SkScalar inverse_scale = |
155 SkFloatToScalar(1.0 / container_->deviceScaleFactor()); | 165 SkFloatToScalar(1.0 / container_->deviceScaleFactor()); |
156 canvas->scale(inverse_scale, inverse_scale); | 166 canvas->scale(inverse_scale, inverse_scale); |
157 | 167 |
158 web_view_->paint(canvas, paint_rect); | 168 web_view()->paint(canvas, paint_rect); |
159 | 169 |
160 canvas->restore(); | 170 canvas->restore(); |
161 } | 171 } |
162 | 172 |
163 // Coordinates are relative to the containing window. | 173 // Coordinates are relative to the containing window. |
164 void WebViewPlugin::updateGeometry(const WebRect& window_rect, | 174 void WebViewPlugin::updateGeometry(const WebRect& window_rect, |
165 const WebRect& clip_rect, | 175 const WebRect& clip_rect, |
166 const WebRect& unobscured_rect, | 176 const WebRect& unobscured_rect, |
167 const WebVector<WebRect>& cut_outs_rects, | 177 const WebVector<WebRect>& cut_outs_rects, |
168 bool is_visible) { | 178 bool is_visible) { |
169 DCHECK(container_); | 179 DCHECK(container_); |
170 | 180 |
171 base::AutoReset<bool> is_resizing(&is_resizing_, true); | 181 base::AutoReset<bool> is_resizing(&is_resizing_, true); |
172 | 182 |
173 if (static_cast<gfx::Rect>(window_rect) != rect_) { | 183 if (static_cast<gfx::Rect>(window_rect) != rect_) { |
174 rect_ = window_rect; | 184 rect_ = window_rect; |
175 web_view_->resize(rect_.size()); | 185 web_view()->resize(rect_.size()); |
176 } | 186 } |
177 | 187 |
178 // Plugin updates are forbidden during Blink layout. Therefore, | 188 // Plugin updates are forbidden during Blink layout. Therefore, |
179 // UpdatePluginForNewGeometry must be posted to a task to run asynchronously. | 189 // UpdatePluginForNewGeometry must be posted to a task to run asynchronously. |
180 base::ThreadTaskRunnerHandle::Get()->PostTask( | 190 base::ThreadTaskRunnerHandle::Get()->PostTask( |
181 FROM_HERE, | 191 FROM_HERE, |
182 base::Bind(&WebViewPlugin::UpdatePluginForNewGeometry, | 192 base::Bind(&WebViewPlugin::UpdatePluginForNewGeometry, |
183 weak_factory_.GetWeakPtr(), window_rect, unobscured_rect)); | 193 weak_factory_.GetWeakPtr(), window_rect, unobscured_rect)); |
184 } | 194 } |
185 | 195 |
(...skipping 16 matching lines...) Expand all Loading... |
202 | 212 |
203 if (event.type == WebInputEvent::ContextMenu) { | 213 if (event.type == WebInputEvent::ContextMenu) { |
204 if (delegate_) { | 214 if (delegate_) { |
205 const WebMouseEvent& mouse_event = | 215 const WebMouseEvent& mouse_event = |
206 reinterpret_cast<const WebMouseEvent&>(event); | 216 reinterpret_cast<const WebMouseEvent&>(event); |
207 delegate_->ShowContextMenu(mouse_event); | 217 delegate_->ShowContextMenu(mouse_event); |
208 } | 218 } |
209 return blink::WebInputEventResult::HandledSuppressed; | 219 return blink::WebInputEventResult::HandledSuppressed; |
210 } | 220 } |
211 current_cursor_ = cursor; | 221 current_cursor_ = cursor; |
212 blink::WebInputEventResult handled = web_view_->handleInputEvent(event); | 222 blink::WebInputEventResult handled = web_view()->handleInputEvent(event); |
213 cursor = current_cursor_; | 223 cursor = current_cursor_; |
214 | 224 |
215 return handled; | 225 return handled; |
216 } | 226 } |
217 | 227 |
218 void WebViewPlugin::didReceiveResponse(const WebURLResponse& response) { | 228 void WebViewPlugin::didReceiveResponse(const WebURLResponse& response) { |
219 NOTREACHED(); | 229 DCHECK(response_.isNull()); |
| 230 response_ = response; |
220 } | 231 } |
221 | 232 |
222 void WebViewPlugin::didReceiveData(const char* data, int data_length) { | 233 void WebViewPlugin::didReceiveData(const char* data, int data_length) { |
223 NOTREACHED(); | 234 data_.push_back(std::string(data, data_length)); |
224 } | 235 } |
225 | 236 |
226 void WebViewPlugin::didFinishLoading() { | 237 void WebViewPlugin::didFinishLoading() { |
227 NOTREACHED(); | 238 DCHECK(!finished_loading_); |
| 239 finished_loading_ = true; |
228 } | 240 } |
229 | 241 |
230 void WebViewPlugin::didFailLoading(const WebURLError& error) { | 242 void WebViewPlugin::didFailLoading(const WebURLError& error) { |
231 NOTREACHED(); | 243 DCHECK(!error_.get()); |
| 244 error_.reset(new WebURLError(error)); |
232 } | 245 } |
233 | 246 |
234 bool WebViewPlugin::acceptsLoadDrops() { return false; } | 247 WebViewPlugin::WebViewHelper::WebViewHelper( |
235 | 248 WebViewPlugin* plugin, |
236 void WebViewPlugin::setToolTipText(const WebString& text, | 249 const WebPreferences& preferences) : plugin_(plugin) { |
237 blink::WebTextDirection hint) { | 250 web_view_ = |
238 if (container_) | 251 WebView::create(this, blink::WebPageVisibilityStateVisible); |
239 container_->element().setAttribute("title", text); | 252 // ApplyWebPreferences before making a WebLocalFrame so that the frame sees a |
| 253 // consistent view of our preferences. |
| 254 content::RenderView::ApplyWebPreferences(preferences, web_view_); |
| 255 WebLocalFrame* web_frame = WebLocalFrame::create( |
| 256 blink::WebTreeScopeType::Document, this); |
| 257 web_view_->setMainFrame(web_frame); |
| 258 // TODO(dcheng): The main frame widget currently has a special case. |
| 259 // Eliminate this once WebView is no longer a WebWidget. |
| 260 WebFrameWidget::create(this, web_view_, web_frame); |
240 } | 261 } |
241 | 262 |
242 void WebViewPlugin::startDragging(blink::WebReferrerPolicy, | 263 WebViewPlugin::WebViewHelper::~WebViewHelper() { |
243 const WebDragData&, | 264 web_view_->close(); |
244 WebDragOperationsMask, | 265 } |
245 const WebImage&, | 266 |
246 const WebPoint&) { | 267 bool WebViewPlugin::WebViewHelper::acceptsLoadDrops() { return false; } |
| 268 |
| 269 void WebViewPlugin::WebViewHelper::setToolTipText( |
| 270 const WebString& text, |
| 271 blink::WebTextDirection hint) { |
| 272 if (plugin_->container_) |
| 273 plugin_->container_->element().setAttribute("title", text); |
| 274 } |
| 275 |
| 276 void WebViewPlugin::WebViewHelper::startDragging(blink::WebReferrerPolicy, |
| 277 const WebDragData&, |
| 278 WebDragOperationsMask, |
| 279 const WebImage&, |
| 280 const WebPoint&) { |
247 // Immediately stop dragging. | 281 // Immediately stop dragging. |
248 DCHECK(web_view_->mainFrame()->isWebLocalFrame()); | 282 DCHECK(web_view_->mainFrame()->isWebLocalFrame()); |
249 web_view_->mainFrame()->toWebLocalFrame()->frameWidget()-> | 283 web_view_->mainFrame()->toWebLocalFrame()->frameWidget()-> |
250 dragSourceSystemDragEnded(); | 284 dragSourceSystemDragEnded(); |
251 } | 285 } |
252 | 286 |
253 bool WebViewPlugin::allowsBrokenNullLayerTreeView() const { | 287 bool WebViewPlugin::WebViewHelper::allowsBrokenNullLayerTreeView() const { |
254 return true; | 288 return true; |
255 } | 289 } |
256 | 290 |
257 void WebViewPlugin::didInvalidateRect(const WebRect& rect) { | 291 void WebViewPlugin::WebViewHelper::didInvalidateRect(const WebRect& rect) { |
258 if (container_) | 292 if (plugin_->container_) |
259 container_->invalidateRect(rect); | 293 plugin_->container_->invalidateRect(rect); |
260 } | 294 } |
261 | 295 |
262 void WebViewPlugin::didChangeCursor(const WebCursorInfo& cursor) { | 296 void WebViewPlugin::WebViewHelper::didChangeCursor( |
263 current_cursor_ = cursor; | 297 const WebCursorInfo& cursor) { |
| 298 plugin_->current_cursor_ = cursor; |
264 } | 299 } |
265 | 300 |
266 void WebViewPlugin::scheduleAnimation() { | 301 void WebViewPlugin::WebViewHelper::scheduleAnimation() { |
267 // Resizes must be self-contained: any lifecycle updating must | 302 // Resizes must be self-contained: any lifecycle updating must |
268 // be triggerd from within the WebView or this WebViewPlugin. | 303 // be triggerd from within the WebView or this WebViewPlugin. |
269 // This is because this WebViewPlugin is contained in another | 304 // This is because this WebViewPlugin is contained in another |
270 // Web View which may be in the middle of updating its lifecycle, | 305 // Web View which may be in the middle of updating its lifecycle, |
271 // but after layout is done, and it is illegal to dirty earlier | 306 // but after layout is done, and it is illegal to dirty earlier |
272 // lifecycle stages during later ones. | 307 // lifecycle stages during later ones. |
273 if (is_resizing_) | 308 if (plugin_->is_resizing_) |
274 return; | 309 return; |
275 if (container_) { | 310 if (plugin_->container_) { |
276 // This should never happen; see also crbug.com/545039 for context. | 311 // This should never happen; see also crbug.com/545039 for context. |
277 CHECK(!is_painting_); | 312 DCHECK(!plugin_->is_painting_); |
278 container_->scheduleAnimation(); | 313 plugin_->container_->scheduleAnimation(); |
279 } | 314 } |
280 } | 315 } |
281 | 316 |
282 void WebViewPlugin::PluginWebFrameClient::didClearWindowObject( | 317 void WebViewPlugin::WebViewHelper::didClearWindowObject( |
283 WebLocalFrame* frame) { | 318 WebLocalFrame* frame) { |
284 if (!plugin_->delegate_) | 319 if (!plugin_->delegate_) |
285 return; | 320 return; |
286 | 321 |
287 v8::Isolate* isolate = blink::mainThreadIsolate(); | 322 v8::Isolate* isolate = blink::mainThreadIsolate(); |
288 v8::HandleScope handle_scope(isolate); | 323 v8::HandleScope handle_scope(isolate); |
289 v8::Local<v8::Context> context = frame->mainWorldScriptContext(); | 324 v8::Local<v8::Context> context = frame->mainWorldScriptContext(); |
290 DCHECK(!context.IsEmpty()); | 325 DCHECK(!context.IsEmpty()); |
291 | 326 |
292 v8::Context::Scope context_scope(context); | 327 v8::Context::Scope context_scope(context); |
293 v8::Local<v8::Object> global = context->Global(); | 328 v8::Local<v8::Object> global = context->Global(); |
294 | 329 |
295 global->Set(gin::StringToV8(isolate, "plugin"), | 330 global->Set(gin::StringToV8(isolate, "plugin"), |
296 plugin_->delegate_->GetV8Handle(isolate)); | 331 plugin_->delegate_->GetV8Handle(isolate)); |
297 } | 332 } |
298 | 333 |
299 void WebViewPlugin::OnDestruct() {} | |
300 | |
301 void WebViewPlugin::OnZoomLevelChanged() { | 334 void WebViewPlugin::OnZoomLevelChanged() { |
302 if (container_) { | 335 if (container_) { |
303 web_view_->setZoomLevel( | 336 web_view()->setZoomLevel( |
304 blink::WebView::zoomFactorToZoomLevel(container_->pageZoomFactor())); | 337 blink::WebView::zoomFactorToZoomLevel(container_->pageZoomFactor())); |
305 } | 338 } |
306 } | 339 } |
307 | 340 |
308 void WebViewPlugin::UpdatePluginForNewGeometry( | 341 void WebViewPlugin::UpdatePluginForNewGeometry( |
309 const blink::WebRect& window_rect, | 342 const blink::WebRect& window_rect, |
310 const blink::WebRect& unobscured_rect) { | 343 const blink::WebRect& unobscured_rect) { |
311 DCHECK(container_); | 344 DCHECK(container_); |
312 if (!delegate_) | 345 if (!delegate_) |
313 return; | 346 return; |
314 | 347 |
315 // The delegate may instantiate a new plugin. | 348 // The delegate may instantiate a new plugin. |
316 delegate_->OnUnobscuredRectUpdate(gfx::Rect(unobscured_rect)); | 349 delegate_->OnUnobscuredRectUpdate(gfx::Rect(unobscured_rect)); |
317 // The delegate may have dirtied style and layout of the WebView. | 350 // The delegate may have dirtied style and layout of the WebView. |
318 // See for example the resizePoster function in plugin_poster.html. | 351 // See for example the resizePoster function in plugin_poster.html. |
319 // Run the lifecycle now so that it is clean. | 352 // Run the lifecycle now so that it is clean. |
320 web_view_->updateAllLifecyclePhases(); | 353 web_view()->updateAllLifecyclePhases(); |
321 } | 354 } |
OLD | NEW |