Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(613)

Side by Side Diff: content/renderer/browser_plugin/browser_plugin.cc

Issue 11826005: Browser Plugin: Implement BrowserPluginObserver. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Merge with ToT Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
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 "content/renderer/browser_plugin/browser_plugin.h"
6
7 #include "base/json/json_string_value_serializer.h"
8 #include "base/message_loop.h"
9 #include "base/string_number_conversions.h"
10 #include "base/string_util.h"
11 #include "base/utf_string_conversions.h"
12 #include "content/common/browser_plugin_messages.h"
13 #include "content/common/view_messages.h"
14 #include "content/public/common/content_client.h"
15 #include "content/public/renderer/content_renderer_client.h"
16 #include "content/renderer/browser_plugin/browser_plugin_bindings.h"
17 #include "content/renderer/browser_plugin/browser_plugin_compositing_helper.h"
18 #include "content/renderer/browser_plugin/browser_plugin_constants.h"
19 #include "content/renderer/browser_plugin/browser_plugin_manager.h"
20 #include "content/renderer/render_process_impl.h"
21 #include "content/renderer/render_thread_impl.h"
22 #include "content/renderer/v8_value_converter_impl.h"
23 #include "skia/ext/platform_canvas.h"
24 #include "third_party/WebKit/Source/Platform/chromium/public/WebRect.h"
25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h"
26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDOMCustomEvent.h"
27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
28 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
29 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
30 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
31 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h"
32 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginParams.h"
33 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h"
34 #include "webkit/plugins/sad_plugin.h"
35
36 #if defined (OS_WIN)
37 #include "base/sys_info.h"
38 #endif
39
40 using WebKit::WebCanvas;
41 using WebKit::WebPluginContainer;
42 using WebKit::WebPluginParams;
43 using WebKit::WebPoint;
44 using WebKit::WebRect;
45 using WebKit::WebURL;
46 using WebKit::WebVector;
47
48 namespace content {
49
50 namespace {
51
52 static std::string TerminationStatusToString(base::TerminationStatus status) {
53 switch (status) {
54 case base::TERMINATION_STATUS_NORMAL_TERMINATION:
55 return "normal";
56 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
57 return "abnormal";
58 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
59 return "killed";
60 case base::TERMINATION_STATUS_PROCESS_CRASHED:
61 return "crashed";
62 case base::TERMINATION_STATUS_STILL_RUNNING:
63 case base::TERMINATION_STATUS_MAX_ENUM:
64 break;
65 }
66 NOTREACHED() << "Unknown Termination Status.";
67 return "unknown";
68 }
69
70 static std::string GetInternalEventName(const char* event_name) {
71 return base::StringPrintf("-internal-%s", event_name);
72 }
73 } // namespace
74
75 BrowserPlugin::BrowserPlugin(
76 RenderViewImpl* render_view,
77 WebKit::WebFrame* frame,
78 const WebPluginParams& params)
79 : instance_id_(browser_plugin::kInstanceIDNone),
80 render_view_(render_view->AsWeakPtr()),
81 render_view_routing_id_(render_view->GetRoutingID()),
82 container_(NULL),
83 damage_buffer_sequence_id_(0),
84 resize_ack_received_(true),
85 sad_guest_(NULL),
86 guest_crashed_(false),
87 navigate_src_sent_(false),
88 auto_size_ack_pending_(false),
89 guest_process_id_(-1),
90 guest_route_id_(-1),
91 persist_storage_(false),
92 valid_partition_id_(true),
93 content_window_routing_id_(MSG_ROUTING_NONE),
94 plugin_focused_(false),
95 visible_(true),
96 size_changed_in_flight_(false),
97 allocate_instance_id_sent_(false),
98 browser_plugin_manager_(render_view->browser_plugin_manager()),
99 current_nav_entry_index_(0),
100 nav_entry_count_(0),
101 compositing_enabled_(false),
102 ALLOW_THIS_IN_INITIALIZER_LIST(
103 weak_ptr_factory_(this)) {
104 }
105
106 BrowserPlugin::~BrowserPlugin() {
107 // If the BrowserPlugin has never navigated then the browser process and
108 // BrowserPluginManager don't know about it and so there is nothing to do
109 // here.
110 if (!navigate_src_sent_)
111 return;
112 browser_plugin_manager()->RemoveBrowserPlugin(instance_id_);
113 browser_plugin_manager()->Send(
114 new BrowserPluginHostMsg_PluginDestroyed(render_view_routing_id_,
115 instance_id_));
116 }
117
118 bool BrowserPlugin::OnMessageReceived(const IPC::Message& message) {
119 bool handled = true;
120 IPC_BEGIN_MESSAGE_MAP(BrowserPlugin, message)
121 IPC_MESSAGE_HANDLER(BrowserPluginMsg_AdvanceFocus, OnAdvanceFocus)
122 IPC_MESSAGE_HANDLER(BrowserPluginMsg_BuffersSwapped, OnBuffersSwapped)
123 IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestContentWindowReady,
124 OnGuestContentWindowReady)
125 IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestGone, OnGuestGone)
126 IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestResponsive, OnGuestResponsive)
127 IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestUnresponsive, OnGuestUnresponsive)
128 IPC_MESSAGE_HANDLER(BrowserPluginMsg_LoadAbort, OnLoadAbort)
129 IPC_MESSAGE_HANDLER(BrowserPluginMsg_LoadCommit, OnLoadCommit)
130 IPC_MESSAGE_HANDLER(BrowserPluginMsg_LoadRedirect, OnLoadRedirect)
131 IPC_MESSAGE_HANDLER(BrowserPluginMsg_LoadStart, OnLoadStart)
132 IPC_MESSAGE_HANDLER(BrowserPluginMsg_LoadStop, OnLoadStop)
133 IPC_MESSAGE_HANDLER(BrowserPluginMsg_RequestPermission, OnRequestPermission)
134 IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetCursor, OnSetCursor)
135 IPC_MESSAGE_HANDLER(BrowserPluginMsg_ShouldAcceptTouchEvents,
136 OnShouldAcceptTouchEvents)
137 IPC_MESSAGE_HANDLER(BrowserPluginMsg_UpdatedName, OnUpdatedName)
138 IPC_MESSAGE_HANDLER(BrowserPluginMsg_UpdateRect, OnUpdateRect)
139 IPC_MESSAGE_UNHANDLED(handled = false)
140 IPC_END_MESSAGE_MAP()
141 return handled;
142 }
143
144 void BrowserPlugin::UpdateDOMAttribute(const std::string& attribute_name,
145 const std::string& attribute_value) {
146 if (!container())
147 return;
148
149 WebKit::WebElement element = container()->element();
150 WebKit::WebString web_attribute_name =
151 WebKit::WebString::fromUTF8(attribute_name);
152 if (!HasDOMAttribute(attribute_name) ||
153 (std::string(element.getAttribute(web_attribute_name).utf8()) !=
154 attribute_value)) {
155 element.setAttribute(web_attribute_name,
156 WebKit::WebString::fromUTF8(attribute_value));
157 }
158 }
159
160 void BrowserPlugin::RemoveDOMAttribute(const std::string& attribute_name) {
161 if (!container())
162 return;
163
164 container()->element().removeAttribute(
165 WebKit::WebString::fromUTF8(attribute_name));
166 }
167
168 std::string BrowserPlugin::GetDOMAttributeValue(
169 const std::string& attribute_name) const {
170 if (!container())
171 return "";
172
173 return container()->element().getAttribute(
174 WebKit::WebString::fromUTF8(attribute_name)).utf8();
175 }
176
177 bool BrowserPlugin::HasDOMAttribute(const std::string& attribute_name) const {
178 if (!container())
179 return false;
180
181 return container()->element().hasAttribute(
182 WebKit::WebString::fromUTF8(attribute_name));
183 }
184
185 std::string BrowserPlugin::GetNameAttribute() const {
186 return GetDOMAttributeValue(browser_plugin::kAttributeName);
187 }
188
189 std::string BrowserPlugin::GetSrcAttribute() const {
190 return GetDOMAttributeValue(browser_plugin::kAttributeSrc);
191 }
192
193 bool BrowserPlugin::GetAutoSizeAttribute() const {
194 return HasDOMAttribute(browser_plugin::kAttributeAutoSize);
195 }
196
197 int BrowserPlugin::GetMaxHeightAttribute() const {
198 int max_height;
199 base::StringToInt(GetDOMAttributeValue(browser_plugin::kAttributeMaxHeight),
200 &max_height);
201 return max_height;
202 }
203
204 int BrowserPlugin::GetMaxWidthAttribute() const {
205 int max_width;
206 base::StringToInt(GetDOMAttributeValue(browser_plugin::kAttributeMaxWidth),
207 &max_width);
208 return max_width;
209 }
210
211 int BrowserPlugin::GetMinHeightAttribute() const {
212 int min_height;
213 base::StringToInt(GetDOMAttributeValue(browser_plugin::kAttributeMinHeight),
214 &min_height);
215 return min_height;
216 }
217
218 int BrowserPlugin::GetMinWidthAttribute() const {
219 int min_width;
220 base::StringToInt(GetDOMAttributeValue(browser_plugin::kAttributeMinWidth),
221 &min_width);
222 return min_width;
223 }
224
225 int BrowserPlugin::GetAdjustedMaxHeight() const {
226 int max_height = GetMaxHeightAttribute();
227 return max_height ? max_height : height();
228 }
229
230 int BrowserPlugin::GetAdjustedMaxWidth() const {
231 int max_width = GetMaxWidthAttribute();
232 return max_width ? max_width : width();
233 }
234
235 int BrowserPlugin::GetAdjustedMinHeight() const {
236 int min_height = GetMinHeightAttribute();
237 // FrameView.cpp does not allow this value to be <= 0, so when the value is
238 // unset (or set to 0), we set it to the container size.
239 min_height = min_height ? min_height : height();
240 // For autosize, minHeight should not be bigger than maxHeight.
241 return std::min(min_height, GetAdjustedMaxHeight());
242 }
243
244 int BrowserPlugin::GetAdjustedMinWidth() const {
245 int min_width = GetMinWidthAttribute();
246 // FrameView.cpp does not allow this value to be <= 0, so when the value is
247 // unset (or set to 0), we set it to the container size.
248 min_width = min_width ? min_width : width();
249 // For autosize, minWidth should not be bigger than maxWidth.
250 return std::min(min_width, GetAdjustedMaxWidth());
251 }
252
253 std::string BrowserPlugin::GetPartitionAttribute() const {
254 return GetDOMAttributeValue(browser_plugin::kAttributePartition);
255 }
256
257 void BrowserPlugin::ParseNameAttribute() {
258 if (!navigate_src_sent_)
259 return;
260 browser_plugin_manager()->Send(
261 new BrowserPluginHostMsg_SetName(render_view_routing_id_,
262 instance_id_,
263 GetNameAttribute()));
264 }
265
266 bool BrowserPlugin::ParseSrcAttribute(std::string* error_message) {
267 if (!valid_partition_id_) {
268 *error_message = browser_plugin::kErrorInvalidPartition;
269 return false;
270 }
271 std::string src = GetSrcAttribute();
272 if (src.empty())
273 return true;
274
275 // If we haven't created the guest yet, do so now. We will navigate it right
276 // after creation. If |src| is empty, we can delay the creation until we
277 // actually need it.
278 if (!navigate_src_sent_) {
279 // On initial navigation, we request an instance ID from the browser
280 // process. We essentially ignore all subsequent calls to SetSrcAttribute
281 // until we receive an instance ID. |allocate_instance_id_sent_|
282 // prevents BrowserPlugin from allocating more than one instance ID.
283 // Upon receiving an instance ID from the browser process, we continue
284 // the process of navigation by populating the
285 // BrowserPluginHostMsg_CreateGuest_Params with the current state of
286 // BrowserPlugin and sending a BrowserPluginHostMsg_CreateGuest to the
287 // browser process in order to create a new guest.
288 if (!allocate_instance_id_sent_) {
289 browser_plugin_manager()->AllocateInstanceID(this);
290 allocate_instance_id_sent_ = true;
291 }
292 return true;
293 }
294
295 browser_plugin_manager()->Send(
296 new BrowserPluginHostMsg_NavigateGuest(render_view_routing_id_,
297 instance_id_,
298 src));
299 return true;
300 }
301
302 void BrowserPlugin::ParseAutoSizeAttribute() {
303 auto_size_ack_pending_ = true;
304 last_view_size_ = plugin_rect_.size();
305 UpdateGuestAutoSizeState(GetAutoSizeAttribute());
306 }
307
308 void BrowserPlugin::PopulateAutoSizeParameters(
309 BrowserPluginHostMsg_AutoSize_Params* params, bool current_auto_size) {
310 params->enable = current_auto_size;
311 // No need to populate the params if autosize is off.
312 if (current_auto_size) {
313 params->max_size = gfx::Size(GetAdjustedMaxWidth(), GetAdjustedMaxHeight());
314 params->min_size = gfx::Size(GetAdjustedMinWidth(), GetAdjustedMinHeight());
315 }
316 }
317
318 void BrowserPlugin::UpdateGuestAutoSizeState(bool current_auto_size) {
319 // If we haven't yet heard back from the guest about the last resize request,
320 // then we don't issue another request until we do in
321 // BrowserPlugin::UpdateRect.
322 if (!navigate_src_sent_ || !resize_ack_received_)
323 return;
324 BrowserPluginHostMsg_AutoSize_Params auto_size_params;
325 BrowserPluginHostMsg_ResizeGuest_Params resize_guest_params;
326 if (current_auto_size) {
327 GetDamageBufferWithSizeParams(&auto_size_params, &resize_guest_params);
328 } else {
329 GetDamageBufferWithSizeParams(NULL, &resize_guest_params);
330 }
331 resize_ack_received_ = false;
332 browser_plugin_manager()->Send(
333 new BrowserPluginHostMsg_SetAutoSize(render_view_routing_id_,
334 instance_id_,
335 auto_size_params,
336 resize_guest_params));
337 }
338
339 void BrowserPlugin::SizeChangedDueToAutoSize(const gfx::Size& old_view_size) {
340 size_changed_in_flight_ = false;
341
342 std::map<std::string, base::Value*> props;
343 props[browser_plugin::kOldHeight] =
344 new base::FundamentalValue(old_view_size.height());
345 props[browser_plugin::kOldWidth] =
346 new base::FundamentalValue(old_view_size.width());
347 props[browser_plugin::kNewHeight] =
348 new base::FundamentalValue(last_view_size_.height());
349 props[browser_plugin::kNewWidth] =
350 new base::FundamentalValue(last_view_size_.width());
351 TriggerEvent(browser_plugin::kEventSizeChanged, &props);
352 }
353
354 // static
355 bool BrowserPlugin::UsesDamageBuffer(
356 const BrowserPluginMsg_UpdateRect_Params& params) {
357 return params.damage_buffer_sequence_id != 0 || params.needs_ack;
358 }
359
360 bool BrowserPlugin::UsesPendingDamageBuffer(
361 const BrowserPluginMsg_UpdateRect_Params& params) {
362 if (!pending_damage_buffer_.get())
363 return false;
364 return damage_buffer_sequence_id_ == params.damage_buffer_sequence_id;
365 }
366
367 void BrowserPlugin::SetInstanceID(int instance_id) {
368 CHECK(instance_id != browser_plugin::kInstanceIDNone);
369 instance_id_ = instance_id;
370 browser_plugin_manager()->AddBrowserPlugin(instance_id, this);
371
372 BrowserPluginHostMsg_CreateGuest_Params create_guest_params;
373 create_guest_params.storage_partition_id = storage_partition_id_;
374 create_guest_params.persist_storage = persist_storage_;
375 create_guest_params.focused = ShouldGuestBeFocused();
376 create_guest_params.visible = visible_;
377 create_guest_params.name = GetNameAttribute();
378 create_guest_params.src = GetSrcAttribute();
379 GetDamageBufferWithSizeParams(&create_guest_params.auto_size_params,
380 &create_guest_params.resize_guest_params);
381 browser_plugin_manager()->Send(
382 new BrowserPluginHostMsg_CreateGuest(render_view_routing_id_,
383 instance_id_,
384 create_guest_params));
385
386 // Record that we sent a navigation request to the browser process.
387 // Once this instance has navigated, the storage partition cannot be changed,
388 // so this value is used for enforcing this.
389 navigate_src_sent_ = true;
390 }
391
392 void BrowserPlugin::OnAdvanceFocus(int instance_id, bool reverse) {
393 DCHECK(render_view_);
394 render_view_->GetWebView()->advanceFocus(reverse);
395 }
396
397 void BrowserPlugin::OnBuffersSwapped(int instance_id,
398 const gfx::Size& size,
399 std::string mailbox_name,
400 int gpu_route_id,
401 int gpu_host_id) {
402 DCHECK(instance_id == instance_id_);
403 EnableCompositing(true);
404
405 compositing_helper_->OnBuffersSwapped(size,
406 mailbox_name,
407 gpu_route_id,
408 gpu_host_id);
409 }
410
411 void BrowserPlugin::OnGuestContentWindowReady(int instance_id,
412 int content_window_routing_id) {
413 DCHECK(content_window_routing_id != MSG_ROUTING_NONE);
414 content_window_routing_id_ = content_window_routing_id;
415 }
416
417 void BrowserPlugin::OnGuestGone(int instance_id, int process_id, int status) {
418 // Set the BrowserPlugin in a crashed state before firing event listeners so
419 // that operations on the BrowserPlugin within listeners are aware that
420 // BrowserPlugin is in a crashed state.
421 guest_crashed_ = true;
422
423 // We fire the event listeners before painting the sad graphic to give the
424 // developer an opportunity to display an alternative overlay image on crash.
425 std::string termination_status = TerminationStatusToString(
426 static_cast<base::TerminationStatus>(status));
427 std::map<std::string, base::Value*> props;
428 props[browser_plugin::kProcessId] = new base::FundamentalValue(process_id);
429 props[browser_plugin::kReason] = new base::StringValue(termination_status);
430
431 // Event listeners may remove the BrowserPlugin from the document. If that
432 // happens, the BrowserPlugin will be scheduled for later deletion (see
433 // BrowserPlugin::destroy()). That will clear the container_ reference,
434 // but leave other member variables valid below.
435 TriggerEvent(browser_plugin::kEventExit, &props);
436
437 // We won't paint the contents of the current backing store again so we might
438 // as well toss it out and save memory.
439 backing_store_.reset();
440 // If the BrowserPlugin is scheduled to be deleted, then container_ will be
441 // NULL so we shouldn't attempt to access it.
442 if (container_)
443 container_->invalidate();
444 // Turn off compositing so we can display the sad graphic.
445 EnableCompositing(false);
446 }
447
448 void BrowserPlugin::OnGuestResponsive(int instance_id, int process_id) {
449 std::map<std::string, base::Value*> props;
450 props[browser_plugin::kProcessId] = new base::FundamentalValue(process_id);
451 TriggerEvent(browser_plugin::kEventResponsive, &props);
452 }
453
454 void BrowserPlugin::OnGuestUnresponsive(int instance_id, int process_id) {
455 std::map<std::string, base::Value*> props;
456 props[browser_plugin::kProcessId] = new base::FundamentalValue(process_id);
457 TriggerEvent(browser_plugin::kEventUnresponsive, &props);
458 }
459
460 void BrowserPlugin::OnLoadAbort(int instance_id,
461 const GURL& url,
462 bool is_top_level,
463 const std::string& type) {
464 std::map<std::string, base::Value*> props;
465 props[browser_plugin::kURL] = new base::StringValue(url.spec());
466 props[browser_plugin::kIsTopLevel] = new base::FundamentalValue(is_top_level);
467 props[browser_plugin::kReason] = new base::StringValue(type);
468 TriggerEvent(browser_plugin::kEventLoadAbort, &props);
469 }
470
471 void BrowserPlugin::OnLoadCommit(
472 int instance_id,
473 const BrowserPluginMsg_LoadCommit_Params& params) {
474 // If the guest has just committed a new navigation then it is no longer
475 // crashed.
476 guest_crashed_ = false;
477 if (params.is_top_level)
478 UpdateDOMAttribute(browser_plugin::kAttributeSrc, params.url.spec());
479
480 guest_process_id_ = params.process_id;
481 guest_route_id_ = params.route_id;
482 current_nav_entry_index_ = params.current_entry_index;
483 nav_entry_count_ = params.entry_count;
484
485 std::map<std::string, base::Value*> props;
486 props[browser_plugin::kURL] = new base::StringValue(params.url.spec());
487 props[browser_plugin::kIsTopLevel] =
488 new base::FundamentalValue(params.is_top_level);
489 TriggerEvent(browser_plugin::kEventLoadCommit, &props);
490 }
491
492 void BrowserPlugin::OnLoadRedirect(int instance_id,
493 const GURL& old_url,
494 const GURL& new_url,
495 bool is_top_level) {
496 std::map<std::string, base::Value*> props;
497 props[browser_plugin::kOldURL] = new base::StringValue(old_url.spec());
498 props[browser_plugin::kNewURL] = new base::StringValue(new_url.spec());
499 props[browser_plugin::kIsTopLevel] = new base::FundamentalValue(is_top_level);
500 TriggerEvent(browser_plugin::kEventLoadRedirect, &props);
501 }
502
503 void BrowserPlugin::OnLoadStart(int instance_id,
504 const GURL& url,
505 bool is_top_level) {
506 std::map<std::string, base::Value*> props;
507 props[browser_plugin::kURL] = new base::StringValue(url.spec());
508 props[browser_plugin::kIsTopLevel] = new base::FundamentalValue(is_top_level);
509
510 TriggerEvent(browser_plugin::kEventLoadStart, &props);
511 }
512
513 void BrowserPlugin::OnLoadStop(int instance_id) {
514 TriggerEvent(browser_plugin::kEventLoadStop, NULL);
515 }
516
517 void BrowserPlugin::OnRequestPermission(
518 int instance_id,
519 BrowserPluginPermissionType permission_type,
520 int request_id,
521 const base::DictionaryValue& request_info) {
522 if (permission_type == BrowserPluginPermissionTypeMedia)
523 RequestMediaPermission(request_id, request_info);
524 }
525
526 void BrowserPlugin::OnSetCursor(int instance_id, const WebCursor& cursor) {
527 cursor_ = cursor;
528 }
529
530 void BrowserPlugin::OnShouldAcceptTouchEvents(int instance_id, bool accept) {
531 if (container()) {
532 container()->requestTouchEventType(accept ?
533 WebKit::WebPluginContainer::TouchEventRequestTypeRaw :
534 WebKit::WebPluginContainer::TouchEventRequestTypeNone);
535 }
536 }
537
538 void BrowserPlugin::OnUpdatedName(int instance_id, const std::string& name) {
539 UpdateDOMAttribute(browser_plugin::kAttributeName, name);
540 }
541
542 void BrowserPlugin::RequestMediaPermission(
543 int request_id, const base::DictionaryValue& request_info) {
544 if (!HasEventListeners(browser_plugin::kEventRequestPermission)) {
545 // Automatically deny the request if there are no event listeners for
546 // permissionrequest.
547 RespondPermission(
548 BrowserPluginPermissionTypeMedia, request_id, false /* allow */);
549 return;
550 }
551 DCHECK(!pending_permission_requests_.count(request_id));
552 pending_permission_requests_.insert(
553 std::make_pair(request_id,
554 std::make_pair(request_id,
555 BrowserPluginPermissionTypeMedia)));
556
557 std::map<std::string, base::Value*> props;
558 props[browser_plugin::kPermission] =
559 base::Value::CreateStringValue(browser_plugin::kPermissionTypeMedia);
560 props[browser_plugin::kRequestId] =
561 base::Value::CreateIntegerValue(request_id);
562
563 // Fill in the info provided by the browser.
564 for (DictionaryValue::Iterator iter(request_info); !iter.IsAtEnd();
565 iter.Advance()) {
566 props[iter.key()] = iter.value().DeepCopy();
567 }
568 TriggerEvent(browser_plugin::kEventRequestPermission, &props);
569 }
570
571 bool BrowserPlugin::HasEventListeners(const std::string& event_name) {
572 if (!container())
573 return false;
574
575 WebKit::WebNode node = container()->element();
576 // Escape the <webview> shim if this BrowserPlugin has one.
577 WebKit::WebElement shim = node.shadowHost();
578 if (!shim.isNull())
579 node = shim;
580
581 const WebKit::WebString& web_event_name =
582 WebKit::WebString::fromUTF8(event_name);
583 while (!node.isNull()) {
584 if (node.hasEventListeners(web_event_name))
585 return true;
586 node = node.parentNode();
587 }
588 return false;
589 }
590
591 void BrowserPlugin::OnUpdateRect(
592 int instance_id,
593 const BrowserPluginMsg_UpdateRect_Params& params) {
594 bool use_new_damage_buffer = !backing_store_;
595 BrowserPluginHostMsg_AutoSize_Params auto_size_params;
596 BrowserPluginHostMsg_ResizeGuest_Params resize_guest_params;
597 // If we have a pending damage buffer, and the guest has begun to use the
598 // damage buffer then we know the guest will no longer use the current
599 // damage buffer. At this point, we drop the current damage buffer, and
600 // mark the pending damage buffer as the current damage buffer.
601 if (UsesPendingDamageBuffer(params)) {
602 SwapDamageBuffers();
603 use_new_damage_buffer = true;
604 }
605
606 bool auto_size = GetAutoSizeAttribute();
607 // We receive a resize ACK in regular mode, but not in autosize.
608 // In SW, |resize_ack_received_| is reset in SwapDamageBuffers().
609 // In HW mode, we need to do it here so we can continue sending
610 // resize messages when needed.
611 if (params.is_resize_ack ||
612 (!params.needs_ack && (auto_size || auto_size_ack_pending_)))
613 resize_ack_received_ = true;
614
615 auto_size_ack_pending_ = false;
616
617 if ((!auto_size && (width() != params.view_size.width() ||
618 height() != params.view_size.height())) ||
619 (auto_size && (!InAutoSizeBounds(params.view_size)))) {
620 // We are HW accelerated, render widget does not expect an ack,
621 // but we still need to update the size.
622 if (!params.needs_ack) {
623 UpdateGuestAutoSizeState(auto_size);
624 return;
625 }
626
627 if (!resize_ack_received_) {
628 // The guest has not yet responded to the last resize request, and
629 // so we don't want to do anything at this point other than ACK the guest.
630 if (auto_size)
631 PopulateAutoSizeParameters(&auto_size_params, auto_size);
632 } else {
633 // If we have no pending damage buffer, then the guest has not caught up
634 // with the BrowserPlugin container. We now tell the guest about the new
635 // container size.
636 if (auto_size) {
637 GetDamageBufferWithSizeParams(&auto_size_params,
638 &resize_guest_params);
639 } else {
640 GetDamageBufferWithSizeParams(NULL, &resize_guest_params);
641 }
642 }
643 browser_plugin_manager()->Send(new BrowserPluginHostMsg_UpdateRect_ACK(
644 render_view_routing_id_,
645 instance_id_,
646 auto_size_params,
647 resize_guest_params));
648 return;
649 }
650
651 if (auto_size && (params.view_size != last_view_size_)) {
652 if (backing_store_)
653 backing_store_->Clear(SK_ColorWHITE);
654 gfx::Size old_view_size = last_view_size_;
655 last_view_size_ = params.view_size;
656 // Schedule a SizeChanged instead of calling it directly to ensure that
657 // the backing store has been updated before the developer attempts to
658 // resize to avoid flicker. |size_changed_in_flight_| acts as a form of
659 // flow control for SizeChanged events. If the guest's view size is changing
660 // rapidly before a SizeChanged event fires, then we avoid scheduling
661 // another SizeChanged event. SizeChanged reads the new size from
662 // |last_view_size_| so we can be sure that it always fires an event
663 // with the last seen view size.
664 if (container_ && !size_changed_in_flight_) {
665 size_changed_in_flight_ = true;
666 MessageLoop::current()->PostTask(
667 FROM_HERE,
668 base::Bind(&BrowserPlugin::SizeChangedDueToAutoSize,
669 base::Unretained(this),
670 old_view_size));
671 }
672 }
673
674 // No more work to do since the guest is no longer using a damage buffer.
675 if (!UsesDamageBuffer(params))
676 return;
677
678 // If we are seeing damage buffers, HW compositing should be turned off.
679 EnableCompositing(false);
680
681 // If we are now using a new damage buffer, then that means that the guest
682 // has updated its size state in response to a resize request. We change
683 // the backing store's size to accomodate the new damage buffer size.
684 if (use_new_damage_buffer) {
685 int backing_store_width = auto_size ? GetAdjustedMaxWidth() : width();
686 int backing_store_height = auto_size ? GetAdjustedMaxHeight(): height();
687 backing_store_.reset(
688 new BrowserPluginBackingStore(
689 gfx::Size(backing_store_width, backing_store_height),
690 params.scale_factor));
691 }
692
693 // Update the backing store.
694 if (!params.scroll_rect.IsEmpty()) {
695 backing_store_->ScrollBackingStore(params.scroll_delta,
696 params.scroll_rect,
697 params.view_size);
698 }
699 for (unsigned i = 0; i < params.copy_rects.size(); i++) {
700 backing_store_->PaintToBackingStore(params.bitmap_rect,
701 params.copy_rects,
702 current_damage_buffer_->memory());
703 }
704
705 // Invalidate the container.
706 // If the BrowserPlugin is scheduled to be deleted, then container_ will be
707 // NULL so we shouldn't attempt to access it.
708 if (container_)
709 container_->invalidate();
710 if (auto_size)
711 PopulateAutoSizeParameters(&auto_size_params, auto_size);
712 browser_plugin_manager()->Send(new BrowserPluginHostMsg_UpdateRect_ACK(
713 render_view_routing_id_,
714 instance_id_,
715 auto_size_params,
716 resize_guest_params));
717 }
718
719 void BrowserPlugin::ParseSizeContraintsChanged() {
720 bool auto_size = GetAutoSizeAttribute();
721 if (auto_size)
722 UpdateGuestAutoSizeState(true);
723 }
724
725 bool BrowserPlugin::InAutoSizeBounds(const gfx::Size& size) const {
726 return size.width() <= GetAdjustedMaxWidth() &&
727 size.height() <= GetAdjustedMaxHeight();
728 }
729
730 NPObject* BrowserPlugin::GetContentWindow() const {
731 if (content_window_routing_id_ == MSG_ROUTING_NONE)
732 return NULL;
733 RenderViewImpl* guest_render_view = static_cast<RenderViewImpl*>(
734 ChildThread::current()->ResolveRoute(content_window_routing_id_));
735 if (!guest_render_view)
736 return NULL;
737 WebKit::WebFrame* guest_frame = guest_render_view->GetWebView()->mainFrame();
738 return guest_frame->windowObject();
739 }
740
741 bool BrowserPlugin::CanGoBack() const {
742 return nav_entry_count_ > 1 && current_nav_entry_index_ > 0;
743 }
744
745 bool BrowserPlugin::CanGoForward() const {
746 return current_nav_entry_index_ >= 0 &&
747 current_nav_entry_index_ < (nav_entry_count_ - 1);
748 }
749
750 bool BrowserPlugin::ParsePartitionAttribute(std::string* error_message) {
751 if (allocate_instance_id_sent_) {
752 *error_message = browser_plugin::kErrorAlreadyNavigated;
753 return false;
754 }
755
756 std::string input = GetPartitionAttribute();
757
758 // Since the "persist:" prefix is in ASCII, StartsWith will work fine on
759 // UTF-8 encoded |partition_id|. If the prefix is a match, we can safely
760 // remove the prefix without splicing in the middle of a multi-byte codepoint.
761 // We can use the rest of the string as UTF-8 encoded one.
762 if (StartsWithASCII(input, browser_plugin::kPersistPrefix, true)) {
763 size_t index = input.find(":");
764 CHECK(index != std::string::npos);
765 // It is safe to do index + 1, since we tested for the full prefix above.
766 input = input.substr(index + 1);
767 if (input.empty()) {
768 valid_partition_id_ = false;
769 *error_message = browser_plugin::kErrorInvalidPartition;
770 return false;
771 }
772 persist_storage_ = true;
773 } else {
774 persist_storage_ = false;
775 }
776
777 valid_partition_id_ = true;
778 storage_partition_id_ = input;
779 return true;
780 }
781
782 bool BrowserPlugin::CanRemovePartitionAttribute(std::string* error_message) {
783 if (navigate_src_sent_)
784 *error_message = browser_plugin::kErrorCannotRemovePartition;
785 return !navigate_src_sent_;
786 }
787
788 void BrowserPlugin::ParseAttributes() {
789 // TODO(mthiesse): Handle errors here?
790 std::string error;
791 ParsePartitionAttribute(&error);
792
793 // Parse the 'src' attribute last, as it will set the has_navigated_ flag to
794 // true, which prevents changing the 'partition' attribute.
795 ParseSrcAttribute(&error);
796 }
797
798 float BrowserPlugin::GetDeviceScaleFactor() const {
799 if (!render_view_)
800 return 1.0f;
801 return render_view_->GetWebView()->deviceScaleFactor();
802 }
803
804 void BrowserPlugin::TriggerEvent(const std::string& event_name,
805 std::map<std::string, base::Value*>* props) {
806 if (!container() || !container()->element().document().frame())
807 return;
808 v8::HandleScope handle_scope;
809 std::string json_string;
810 if (props) {
811 base::DictionaryValue dict;
812 for (std::map<std::string, base::Value*>::iterator iter = props->begin(),
813 end = props->end(); iter != end; ++iter) {
814 dict.Set(iter->first, iter->second);
815 }
816
817 JSONStringValueSerializer serializer(&json_string);
818 if (!serializer.Serialize(dict))
819 return;
820 }
821
822 WebKit::WebFrame* frame = container()->element().document().frame();
823 WebKit::WebDOMEvent dom_event = frame->document().createEvent("CustomEvent");
824 WebKit::WebDOMCustomEvent event = dom_event.to<WebKit::WebDOMCustomEvent>();
825
826 // The events triggered directly from the plugin <object> are internal events
827 // whose implementation details can (and likely will) change over time. The
828 // wrapper/shim (e.g. <webview> tag) should receive these events, and expose a
829 // more appropriate (and stable) event to the consumers as part of the API.
830 event.initCustomEvent(
831 WebKit::WebString::fromUTF8(GetInternalEventName(event_name.c_str())),
832 false, false,
833 WebKit::WebSerializedScriptValue::serialize(
834 v8::String::New(json_string.c_str(), json_string.size())));
835 container()->element().dispatchEvent(event);
836 }
837
838 void BrowserPlugin::OnRequestObjectGarbageCollected(int request_id) {
839 // Remove from alive objects.
840 std::map<int, AliveV8PermissionRequestItem*>::iterator iter =
841 alive_v8_permission_request_objects_.find(request_id);
842 if (iter != alive_v8_permission_request_objects_.end())
843 alive_v8_permission_request_objects_.erase(iter);
844
845 // If a decision has not been made for this request yet, deny it.
846 RespondPermissionIfRequestIsPending(request_id, false /*allow*/);
847 }
848
849 void BrowserPlugin::PersistRequestObject(
850 const NPVariant* request, const std::string& type, int id) {
851 CHECK(alive_v8_permission_request_objects_.find(id) ==
852 alive_v8_permission_request_objects_.end());
853 if (pending_permission_requests_.find(id) ==
854 pending_permission_requests_.end()) {
855 return;
856 }
857
858 v8::Persistent<v8::Value> weak_request =
859 v8::Persistent<v8::Value>::New(WebKit::WebBindings::toV8Value(request));
860
861 AliveV8PermissionRequestItem* new_item =
862 new std::pair<int, base::WeakPtr<BrowserPlugin> >(
863 id, weak_ptr_factory_.GetWeakPtr());
864
865 std::pair<std::map<int, AliveV8PermissionRequestItem*>::iterator, bool>
866 result = alive_v8_permission_request_objects_.insert(
867 std::make_pair(id, new_item));
868 CHECK(result.second); // Inserted in the map.
869 AliveV8PermissionRequestItem* request_item = result.first->second;
870 weak_request.MakeWeak(request_item, WeakCallbackForPersistObject);
871 }
872
873 // static
874 void BrowserPlugin::WeakCallbackForPersistObject(
875 v8::Persistent<v8::Value> object, void* param) {
876 v8::Persistent<v8::Object> persistent_object =
877 v8::Persistent<v8::Object>::Cast(object);
878
879 AliveV8PermissionRequestItem* item_ptr =
880 static_cast<AliveV8PermissionRequestItem*>(param);
881 int request_id = item_ptr->first;
882 base::WeakPtr<BrowserPlugin> plugin = item_ptr->second;
883 delete item_ptr;
884
885 persistent_object.Dispose();
886 persistent_object.Clear();
887
888 if (plugin) {
889 // Asynchronously remove item from |alive_v8_permission_request_objects_|.
890 // Note that we are using weak pointer for the following PostTask, so we
891 // don't need to worry about BrowserPlugin going away.
892 MessageLoop::current()->PostTask(
893 FROM_HERE,
894 base::Bind(&BrowserPlugin::OnRequestObjectGarbageCollected,
895 plugin, request_id));
896 }
897 }
898
899 void BrowserPlugin::Back() {
900 if (!navigate_src_sent_)
901 return;
902 browser_plugin_manager()->Send(
903 new BrowserPluginHostMsg_Go(render_view_routing_id_,
904 instance_id_, -1));
905 }
906
907 void BrowserPlugin::Forward() {
908 if (!navigate_src_sent_)
909 return;
910 browser_plugin_manager()->Send(
911 new BrowserPluginHostMsg_Go(render_view_routing_id_,
912 instance_id_, 1));
913 }
914
915 void BrowserPlugin::Go(int relative_index) {
916 if (!navigate_src_sent_)
917 return;
918 browser_plugin_manager()->Send(
919 new BrowserPluginHostMsg_Go(render_view_routing_id_,
920 instance_id_,
921 relative_index));
922 }
923
924 void BrowserPlugin::TerminateGuest() {
925 if (!navigate_src_sent_ || guest_crashed_)
926 return;
927 browser_plugin_manager()->Send(
928 new BrowserPluginHostMsg_TerminateGuest(render_view_routing_id_,
929 instance_id_));
930 }
931
932 void BrowserPlugin::Stop() {
933 if (!navigate_src_sent_)
934 return;
935 browser_plugin_manager()->Send(
936 new BrowserPluginHostMsg_Stop(render_view_routing_id_,
937 instance_id_));
938 }
939
940 void BrowserPlugin::Reload() {
941 if (!navigate_src_sent_)
942 return;
943 browser_plugin_manager()->Send(
944 new BrowserPluginHostMsg_Reload(render_view_routing_id_,
945 instance_id_));
946 }
947
948 void BrowserPlugin::UpdateGuestFocusState() {
949 if (!navigate_src_sent_)
950 return;
951 bool should_be_focused = ShouldGuestBeFocused();
952 browser_plugin_manager()->Send(new BrowserPluginHostMsg_SetFocus(
953 render_view_routing_id_,
954 instance_id_,
955 should_be_focused));
956 }
957
958 bool BrowserPlugin::ShouldGuestBeFocused() const {
959 bool embedder_focused = false;
960 if (render_view_)
961 embedder_focused = render_view_->has_focus();
962 return plugin_focused_ && embedder_focused;
963 }
964
965 WebKit::WebPluginContainer* BrowserPlugin::container() const {
966 return container_;
967 }
968
969 void BrowserPlugin::RespondPermission(
970 BrowserPluginPermissionType permission_type, int request_id, bool allow) {
971 switch (permission_type) {
972 case BrowserPluginPermissionTypeMedia:
973 browser_plugin_manager()->Send(
974 new BrowserPluginHostMsg_RespondPermission(
975 render_view_->GetRoutingID(), instance_id_,
976 BrowserPluginPermissionTypeMedia, request_id, allow));
977 break;
978 case BrowserPluginPermissionTypeUnknown:
979 default:
980 // Not a valid permission type.
981 NOTREACHED();
982 break;
983 }
984 }
985
986 void BrowserPlugin::RespondPermissionIfRequestIsPending(
987 int request_id, bool allow) {
988 PendingPermissionRequests::iterator iter =
989 pending_permission_requests_.find(request_id);
990 if (iter == pending_permission_requests_.end())
991 return;
992
993 BrowserPluginPermissionType permission_type = iter->second.second;
994 pending_permission_requests_.erase(iter);
995 RespondPermission(permission_type, request_id, allow);
996 }
997
998 void BrowserPlugin::OnEmbedderDecidedPermission(int request_id, bool allow) {
999 RespondPermissionIfRequestIsPending(request_id, allow);
1000 }
1001
1002 bool BrowserPlugin::initialize(WebPluginContainer* container) {
1003 if (!container)
1004 return false;
1005
1006 if (!GetContentClient()->renderer()->AllowBrowserPlugin(container))
1007 return false;
1008
1009 bindings_.reset(new BrowserPluginBindings(this));
1010 container_ = container;
1011 container_->setWantsWheelEvents(true);
1012 ParseAttributes();
1013 return true;
1014 }
1015
1016 void BrowserPlugin::EnableCompositing(bool enable) {
1017 if (compositing_enabled_ == enable)
1018 return;
1019
1020 compositing_enabled_ = enable;
1021 if (enable) {
1022 // No need to keep the backing store and damage buffer around if we're now
1023 // compositing.
1024 backing_store_.reset();
1025 current_damage_buffer_.reset();
1026 if (!compositing_helper_) {
1027 compositing_helper_ = new BrowserPluginCompositingHelper(
1028 container_,
1029 browser_plugin_manager(),
1030 instance_id_,
1031 render_view_routing_id_);
1032 }
1033 } else {
1034 // We're switching back to the software path. We create a new damage
1035 // buffer that can accommodate the current size of the container.
1036 BrowserPluginHostMsg_ResizeGuest_Params params;
1037 PopulateResizeGuestParameters(&params, gfx::Size(width(), height()));
1038 // Request a full repaint from the guest even if its size is not actually
1039 // changing.
1040 params.repaint = true;
1041 resize_ack_received_ = false;
1042 browser_plugin_manager()->Send(new BrowserPluginHostMsg_ResizeGuest(
1043 render_view_routing_id_,
1044 instance_id_,
1045 params));
1046 }
1047 compositing_helper_->EnableCompositing(enable);
1048 }
1049
1050 void BrowserPlugin::destroy() {
1051 // The BrowserPlugin's WebPluginContainer is deleted immediately after this
1052 // call returns, so let's not keep a reference to it around.
1053 container_ = NULL;
1054 if (compositing_helper_)
1055 compositing_helper_->OnContainerDestroy();
1056 MessageLoop::current()->DeleteSoon(FROM_HERE, this);
1057 }
1058
1059 NPObject* BrowserPlugin::scriptableObject() {
1060 if (!bindings_.get())
1061 return NULL;
1062
1063 NPObject* browser_plugin_np_object(bindings_->np_object());
1064 // The object is expected to be retained before it is returned.
1065 WebKit::WebBindings::retainObject(browser_plugin_np_object);
1066 return browser_plugin_np_object;
1067 }
1068
1069 bool BrowserPlugin::supportsKeyboardFocus() const {
1070 return true;
1071 }
1072
1073 bool BrowserPlugin::canProcessDrag() const {
1074 return true;
1075 }
1076
1077 void BrowserPlugin::paint(WebCanvas* canvas, const WebRect& rect) {
1078 if (guest_crashed_) {
1079 if (!sad_guest_) // Lazily initialize bitmap.
1080 sad_guest_ = content::GetContentClient()->renderer()->
1081 GetSadWebViewBitmap();
1082 // content_shell does not have the sad plugin bitmap, so we'll paint black
1083 // instead to make it clear that something went wrong.
1084 if (sad_guest_) {
1085 webkit::PaintSadPlugin(canvas, plugin_rect_, *sad_guest_);
1086 return;
1087 }
1088 }
1089 SkAutoCanvasRestore auto_restore(canvas, true);
1090 canvas->translate(plugin_rect_.x(), plugin_rect_.y());
1091 SkRect image_data_rect = SkRect::MakeXYWH(
1092 SkIntToScalar(0),
1093 SkIntToScalar(0),
1094 SkIntToScalar(plugin_rect_.width()),
1095 SkIntToScalar(plugin_rect_.height()));
1096 canvas->clipRect(image_data_rect);
1097 // Paint black or white in case we have nothing in our backing store or we
1098 // need to show a gutter.
1099 SkPaint paint;
1100 paint.setStyle(SkPaint::kFill_Style);
1101 paint.setColor(guest_crashed_ ? SK_ColorBLACK : SK_ColorWHITE);
1102 canvas->drawRect(image_data_rect, paint);
1103 // Stay a solid color if we have never set a non-empty src, or we don't have a
1104 // backing store.
1105 if (!backing_store_.get() || !navigate_src_sent_)
1106 return;
1107 float inverse_scale_factor = 1.0f / backing_store_->GetScaleFactor();
1108 canvas->scale(inverse_scale_factor, inverse_scale_factor);
1109 canvas->drawBitmap(backing_store_->GetBitmap(), 0, 0);
1110 }
1111
1112 bool BrowserPlugin::InBounds(const gfx::Point& position) const {
1113 // Note that even for plugins that are rotated using rotate transformations,
1114 // we use the the |plugin_rect_| provided by updateGeometry, which means we
1115 // will be off if |position| is within the plugin rect but does not fall
1116 // within the actual plugin boundary. Not supporting such edge case is OK
1117 // since this function should not be used for making security-sensitive
1118 // decisions.
1119 // This also does not take overlapping plugins into account.
1120 bool result = position.x() >= plugin_rect_.x() &&
1121 position.x() < plugin_rect_.x() + plugin_rect_.width() &&
1122 position.y() >= plugin_rect_.y() &&
1123 position.y() < plugin_rect_.y() + plugin_rect_.height();
1124 return result;
1125 }
1126
1127 gfx::Point BrowserPlugin::ToLocalCoordinates(const gfx::Point& point) const {
1128 if (container_)
1129 return container_->windowToLocalPoint(WebKit::WebPoint(point));
1130 return gfx::Point(point.x() - plugin_rect_.x(), point.y() - plugin_rect_.y());
1131 }
1132
1133 void BrowserPlugin::updateGeometry(
1134 const WebRect& window_rect,
1135 const WebRect& clip_rect,
1136 const WebVector<WebRect>& cut_outs_rects,
1137 bool is_visible) {
1138 int old_width = width();
1139 int old_height = height();
1140 plugin_rect_ = window_rect;
1141 // In AutoSize mode, guests don't care when the BrowserPlugin container is
1142 // resized. If |!resize_ack_received_|, then we are still waiting on a
1143 // previous resize to be ACK'ed and so we don't issue additional resizes
1144 // until the previous one is ACK'ed.
1145 // TODO(mthiesse): Assess the performance of calling GetAutoSizeAttribute() on
1146 // resize.
1147 if (!navigate_src_sent_ ||
1148 !resize_ack_received_ ||
1149 (old_width == window_rect.width && old_height == window_rect.height) ||
1150 GetAutoSizeAttribute()) {
1151 return;
1152 }
1153
1154 BrowserPluginHostMsg_ResizeGuest_Params params;
1155 PopulateResizeGuestParameters(&params, gfx::Size(width(), height()));
1156 resize_ack_received_ = false;
1157 browser_plugin_manager()->Send(new BrowserPluginHostMsg_ResizeGuest(
1158 render_view_routing_id_,
1159 instance_id_,
1160 params));
1161 }
1162
1163 void BrowserPlugin::SwapDamageBuffers() {
1164 current_damage_buffer_.reset(pending_damage_buffer_.release());
1165 resize_ack_received_ = true;
1166 }
1167
1168 void BrowserPlugin::PopulateResizeGuestParameters(
1169 BrowserPluginHostMsg_ResizeGuest_Params* params,
1170 const gfx::Size& view_size) {
1171 params->view_size = view_size;
1172 params->scale_factor = GetDeviceScaleFactor();
1173
1174 // In HW compositing mode, we do not need a damage buffer.
1175 if (compositing_enabled_)
1176 return;
1177
1178 const size_t stride = skia::PlatformCanvasStrideForWidth(view_size.width());
1179 // Make sure the size of the damage buffer is at least four bytes so that we
1180 // can fit in a magic word to verify that the memory is shared correctly.
1181 size_t size =
1182 std::max(sizeof(unsigned int),
1183 static_cast<size_t>(view_size.height() *
1184 stride *
1185 GetDeviceScaleFactor() *
1186 GetDeviceScaleFactor()));
1187
1188 params->damage_buffer_size = size;
1189 pending_damage_buffer_.reset(
1190 CreateDamageBuffer(size, &params->damage_buffer_handle));
1191 if (!pending_damage_buffer_.get())
1192 NOTREACHED();
1193 params->damage_buffer_sequence_id = ++damage_buffer_sequence_id_;
1194 }
1195
1196 void BrowserPlugin::GetDamageBufferWithSizeParams(
1197 BrowserPluginHostMsg_AutoSize_Params* auto_size_params,
1198 BrowserPluginHostMsg_ResizeGuest_Params* resize_guest_params) {
1199 if (auto_size_params)
1200 PopulateAutoSizeParameters(auto_size_params, GetAutoSizeAttribute());
1201 gfx::Size view_size = (auto_size_params && auto_size_params->enable) ?
1202 auto_size_params->max_size : gfx::Size(width(), height());
1203 if (view_size.IsEmpty())
1204 return;
1205 resize_ack_received_ = false;
1206 PopulateResizeGuestParameters(resize_guest_params, view_size);
1207 }
1208
1209 #if defined(OS_POSIX)
1210 base::SharedMemory* BrowserPlugin::CreateDamageBuffer(
1211 const size_t size,
1212 base::SharedMemoryHandle* damage_buffer_handle) {
1213 scoped_ptr<base::SharedMemory> shared_buf(
1214 content::RenderThread::Get()->HostAllocateSharedMemoryBuffer(
1215 size).release());
1216
1217 if (shared_buf.get()) {
1218 if (shared_buf->Map(size)) {
1219 // Insert the magic word.
1220 *static_cast<unsigned int*>(shared_buf->memory()) = 0xdeadbeef;
1221 shared_buf->ShareToProcess(base::GetCurrentProcessHandle(),
1222 damage_buffer_handle);
1223 return shared_buf.release();
1224 }
1225 }
1226 NOTREACHED();
1227 return NULL;
1228 }
1229 #elif defined(OS_WIN)
1230 base::SharedMemory* BrowserPlugin::CreateDamageBuffer(
1231 const size_t size,
1232 base::SharedMemoryHandle* damage_buffer_handle) {
1233 scoped_ptr<base::SharedMemory> shared_buf(new base::SharedMemory());
1234
1235 if (!shared_buf->CreateAndMapAnonymous(size)) {
1236 NOTREACHED() << "Buffer allocation failed";
1237 return NULL;
1238 }
1239
1240 // Insert the magic word.
1241 *static_cast<unsigned int*>(shared_buf->memory()) = 0xdeadbeef;
1242 if (shared_buf->ShareToProcess(base::GetCurrentProcessHandle(),
1243 damage_buffer_handle))
1244 return shared_buf.release();
1245 NOTREACHED();
1246 return NULL;
1247 }
1248 #endif
1249
1250 void BrowserPlugin::updateFocus(bool focused) {
1251 if (plugin_focused_ == focused)
1252 return;
1253
1254 bool old_guest_focus_state = ShouldGuestBeFocused();
1255 plugin_focused_ = focused;
1256
1257 if (ShouldGuestBeFocused() != old_guest_focus_state)
1258 UpdateGuestFocusState();
1259 }
1260
1261 void BrowserPlugin::updateVisibility(bool visible) {
1262 if (visible_ == visible)
1263 return;
1264
1265 visible_ = visible;
1266 if (!navigate_src_sent_)
1267 return;
1268
1269 if (compositing_helper_)
1270 compositing_helper_->UpdateVisibility(visible);
1271
1272 browser_plugin_manager()->Send(new BrowserPluginHostMsg_SetVisibility(
1273 render_view_routing_id_,
1274 instance_id_,
1275 visible));
1276 }
1277
1278 bool BrowserPlugin::acceptsInputEvents() {
1279 return true;
1280 }
1281
1282 bool BrowserPlugin::handleInputEvent(const WebKit::WebInputEvent& event,
1283 WebKit::WebCursorInfo& cursor_info) {
1284 if (guest_crashed_ || !navigate_src_sent_ ||
1285 event.type == WebKit::WebInputEvent::ContextMenu)
1286 return false;
1287 browser_plugin_manager()->Send(
1288 new BrowserPluginHostMsg_HandleInputEvent(render_view_routing_id_,
1289 instance_id_,
1290 plugin_rect_,
1291 &event));
1292 cursor_.GetCursorInfo(&cursor_info);
1293 return true;
1294 }
1295
1296 bool BrowserPlugin::handleDragStatusUpdate(WebKit::WebDragStatus drag_status,
1297 const WebKit::WebDragData& drag_data,
1298 WebKit::WebDragOperationsMask mask,
1299 const WebKit::WebPoint& position,
1300 const WebKit::WebPoint& screen) {
1301 if (guest_crashed_ || !navigate_src_sent_)
1302 return false;
1303 browser_plugin_manager()->Send(
1304 new BrowserPluginHostMsg_DragStatusUpdate(
1305 render_view_routing_id_,
1306 instance_id_,
1307 drag_status,
1308 WebDropData(drag_data),
1309 mask,
1310 position));
1311 return false;
1312 }
1313
1314 void BrowserPlugin::didReceiveResponse(
1315 const WebKit::WebURLResponse& response) {
1316 }
1317
1318 void BrowserPlugin::didReceiveData(const char* data, int data_length) {
1319 }
1320
1321 void BrowserPlugin::didFinishLoading() {
1322 }
1323
1324 void BrowserPlugin::didFailLoading(const WebKit::WebURLError& error) {
1325 }
1326
1327 void BrowserPlugin::didFinishLoadingFrameRequest(const WebKit::WebURL& url,
1328 void* notify_data) {
1329 }
1330
1331 void BrowserPlugin::didFailLoadingFrameRequest(
1332 const WebKit::WebURL& url,
1333 void* notify_data,
1334 const WebKit::WebURLError& error) {
1335 }
1336
1337 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/browser_plugin/browser_plugin.h ('k') | content/renderer/browser_plugin/browser_plugin_bindings.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698