OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "content/browser/browser_plugin/browser_plugin_guest.h" | 5 #include "content/browser/browser_plugin/browser_plugin_guest.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 | 48 |
49 #if defined(OS_MACOSX) | 49 #if defined(OS_MACOSX) |
50 #include "content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h" | 50 #include "content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h" |
51 #endif | 51 #endif |
52 | 52 |
53 namespace content { | 53 namespace content { |
54 | 54 |
55 // static | 55 // static |
56 BrowserPluginHostFactory* BrowserPluginGuest::factory_ = NULL; | 56 BrowserPluginHostFactory* BrowserPluginGuest::factory_ = NULL; |
57 | 57 |
58 // Parent class for the various types of permission requests, each of which | |
59 // should be able to handle the response to their permission request. | |
60 class BrowserPluginGuest::PermissionRequest : | |
61 public base::RefCounted<BrowserPluginGuest::PermissionRequest> { | |
62 public: | |
63 void Respond(bool should_allow, const std::string& user_input) { | |
64 if (!guest_) | |
65 return; | |
66 RespondImpl(should_allow, user_input); | |
67 } | |
68 virtual bool AllowedByDefault() const { | |
69 return false; | |
70 } | |
71 protected: | |
72 explicit PermissionRequest(const base::WeakPtr<BrowserPluginGuest>& guest) | |
73 : guest_(guest) { | |
74 RecordAction( | |
75 base::UserMetricsAction("BrowserPlugin.Guest.PermissionRequest")); | |
76 } | |
77 virtual ~PermissionRequest() {} | |
78 | |
79 virtual void RespondImpl(bool should_allow, | |
80 const std::string& user_input) = 0; | |
81 // Friend RefCounted so that the dtor can be non-public. | |
82 friend class base::RefCounted<BrowserPluginGuest::PermissionRequest>; | |
83 | |
84 base::WeakPtr<BrowserPluginGuest> guest_; | |
85 }; | |
86 | |
87 class BrowserPluginGuest::NewWindowRequest : public PermissionRequest { | |
88 public: | |
89 NewWindowRequest(const base::WeakPtr<BrowserPluginGuest>& guest, | |
90 int instance_id) | |
91 : PermissionRequest(guest), | |
92 instance_id_(instance_id) { | |
93 RecordAction( | |
94 base::UserMetricsAction("BrowserPlugin.Guest.PermissionRequest.NewWindow
")); | |
95 } | |
96 | |
97 virtual void RespondImpl(bool should_allow, | |
98 const std::string& user_input) OVERRIDE { | |
99 int embedder_render_process_id = | |
100 guest_->embedder_web_contents()->GetRenderProcessHost()->GetID(); | |
101 guest_->GetBrowserPluginGuestManager()-> | |
102 MaybeGetGuestByInstanceIDOrKill( | |
103 instance_id_, | |
104 embedder_render_process_id, | |
105 base::Bind(&BrowserPluginGuest::NewWindowRequest::RespondInternal, | |
106 base::Unretained(this), | |
107 should_allow)); | |
108 } | |
109 | |
110 private: | |
111 virtual ~NewWindowRequest() {} | |
112 | |
113 void RespondInternal(bool should_allow, | |
114 WebContents* guest_web_contents) { | |
115 if (!guest_web_contents) { | |
116 VLOG(0) << "Guest not found. Instance ID: " << instance_id_; | |
117 return; | |
118 } | |
119 | |
120 BrowserPluginGuest* guest = | |
121 static_cast<WebContentsImpl*>(guest_web_contents)-> | |
122 GetBrowserPluginGuest(); | |
123 DCHECK(guest); | |
124 // If we do not destroy the guest then we allow the new window. | |
125 if (!should_allow) | |
126 guest->Destroy(); | |
127 } | |
128 | |
129 int instance_id_; | |
130 }; | |
131 | |
132 namespace { | 58 namespace { |
133 std::string WindowOpenDispositionToString( | |
134 WindowOpenDisposition window_open_disposition) { | |
135 switch (window_open_disposition) { | |
136 case IGNORE_ACTION: | |
137 return "ignore"; | |
138 case SAVE_TO_DISK: | |
139 return "save_to_disk"; | |
140 case CURRENT_TAB: | |
141 return "current_tab"; | |
142 case NEW_BACKGROUND_TAB: | |
143 return "new_background_tab"; | |
144 case NEW_FOREGROUND_TAB: | |
145 return "new_foreground_tab"; | |
146 case NEW_WINDOW: | |
147 return "new_window"; | |
148 case NEW_POPUP: | |
149 return "new_popup"; | |
150 default: | |
151 NOTREACHED() << "Unknown Window Open Disposition"; | |
152 return "ignore"; | |
153 } | |
154 } | |
155 | 59 |
156 } // namespace | 60 } // namespace |
157 | 61 |
158 class BrowserPluginGuest::EmbedderWebContentsObserver | 62 class BrowserPluginGuest::EmbedderWebContentsObserver |
159 : public WebContentsObserver { | 63 : public WebContentsObserver { |
160 public: | 64 public: |
161 explicit EmbedderWebContentsObserver(BrowserPluginGuest* guest) | 65 explicit EmbedderWebContentsObserver(BrowserPluginGuest* guest) |
162 : WebContentsObserver(guest->embedder_web_contents()), | 66 : WebContentsObserver(guest->embedder_web_contents()), |
163 browser_plugin_guest_(guest) { | 67 browser_plugin_guest_(guest) { |
164 } | 68 } |
(...skipping 29 matching lines...) Expand all Loading... |
194 instance_id_(instance_id), | 98 instance_id_(instance_id), |
195 guest_device_scale_factor_(1.0f), | 99 guest_device_scale_factor_(1.0f), |
196 focused_(false), | 100 focused_(false), |
197 mouse_locked_(false), | 101 mouse_locked_(false), |
198 pending_lock_request_(false), | 102 pending_lock_request_(false), |
199 guest_visible_(false), | 103 guest_visible_(false), |
200 guest_opaque_(true), | 104 guest_opaque_(true), |
201 embedder_visible_(true), | 105 embedder_visible_(true), |
202 auto_size_enabled_(false), | 106 auto_size_enabled_(false), |
203 copy_request_id_(0), | 107 copy_request_id_(0), |
204 next_permission_request_id_(browser_plugin::kInvalidPermissionRequestID), | |
205 has_render_view_(has_render_view), | 108 has_render_view_(has_render_view), |
206 last_seen_auto_size_enabled_(false), | 109 last_seen_auto_size_enabled_(false), |
207 is_in_destruction_(false), | 110 is_in_destruction_(false), |
208 last_text_input_type_(ui::TEXT_INPUT_TYPE_NONE), | 111 last_text_input_type_(ui::TEXT_INPUT_TYPE_NONE), |
209 last_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT), | 112 last_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT), |
210 last_can_compose_inline_(true), | 113 last_can_compose_inline_(true), |
211 weak_ptr_factory_(this) { | 114 weak_ptr_factory_(this) { |
212 DCHECK(web_contents); | 115 DCHECK(web_contents); |
213 web_contents->SetDelegate(this); | 116 web_contents->SetDelegate(this); |
214 } | 117 } |
215 | 118 |
216 bool BrowserPluginGuest::AddMessageToConsole(WebContents* source, | 119 bool BrowserPluginGuest::AddMessageToConsole(WebContents* source, |
217 int32 level, | 120 int32 level, |
218 const base::string16& message, | 121 const base::string16& message, |
219 int32 line_no, | 122 int32 line_no, |
220 const base::string16& source_id) { | 123 const base::string16& source_id) { |
221 if (!delegate_) | 124 if (!delegate_) |
222 return false; | 125 return false; |
223 | 126 |
224 delegate_->AddMessageToConsole(level, message, line_no, source_id); | 127 delegate_->AddMessageToConsole(level, message, line_no, source_id); |
225 return true; | 128 return true; |
226 } | 129 } |
227 | 130 |
228 void BrowserPluginGuest::DestroyUnattachedWindows() { | 131 void BrowserPluginGuest::WillDestroy(WebContents* web_contents) { |
229 // Destroy() reaches in and removes the BrowserPluginGuest from its opener's | 132 DCHECK_EQ(web_contents, GetWebContents()); |
230 // pending_new_windows_ set. To avoid mutating the set while iterating, we | 133 is_in_destruction_ = true; |
231 // create a copy of the pending new windows set and iterate over the copy. | |
232 PendingWindowMap pending_new_windows(pending_new_windows_); | |
233 // Clean up unattached new windows opened by this guest. | |
234 for (PendingWindowMap::const_iterator it = pending_new_windows.begin(); | |
235 it != pending_new_windows.end(); ++it) { | |
236 it->first->Destroy(); | |
237 } | |
238 // All pending windows should be removed from the set after Destroy() is | |
239 // called on all of them. | |
240 DCHECK(pending_new_windows_.empty()); | |
241 } | |
242 | |
243 void BrowserPluginGuest::LoadURLWithParams(const GURL& url, | |
244 const Referrer& referrer, | |
245 PageTransition transition_type, | |
246 WebContents* web_contents) { | |
247 NavigationController::LoadURLParams load_url_params(url); | |
248 load_url_params.referrer = referrer; | |
249 load_url_params.transition_type = transition_type; | |
250 load_url_params.extra_headers = std::string(); | |
251 if (delegate_ && delegate_->IsOverridingUserAgent()) { | |
252 load_url_params.override_user_agent = | |
253 NavigationController::UA_OVERRIDE_TRUE; | |
254 } | |
255 web_contents->GetController().LoadURLWithParams(load_url_params); | |
256 } | |
257 | |
258 void BrowserPluginGuest::RespondToPermissionRequest( | |
259 int request_id, | |
260 bool should_allow, | |
261 const std::string& user_input) { | |
262 RequestMap::iterator request_itr = permission_request_map_.find(request_id); | |
263 if (request_itr == permission_request_map_.end()) { | |
264 VLOG(0) << "Not a valid request ID."; | |
265 return; | |
266 } | |
267 request_itr->second->Respond(should_allow, user_input); | |
268 permission_request_map_.erase(request_itr); | |
269 } | |
270 | |
271 void BrowserPluginGuest::RequestPermission( | |
272 BrowserPluginPermissionType permission_type, | |
273 scoped_refptr<BrowserPluginGuest::PermissionRequest> request, | |
274 const base::DictionaryValue& request_info) { | |
275 if (!delegate_) { | |
276 // Let the stack unwind before we deny the permission request so that | |
277 // objects held by the permission request are not destroyed immediately | |
278 // after creation. This is to allow those same objects to be accessed again | |
279 // in the same scope without fear of use after freeing. | |
280 base::MessageLoop::current()->PostTask( | |
281 FROM_HERE, | |
282 base::Bind(&BrowserPluginGuest::PermissionRequest::Respond, | |
283 request, false, "")); | |
284 } | |
285 | |
286 int request_id = ++next_permission_request_id_; | |
287 permission_request_map_[request_id] = request; | |
288 | |
289 BrowserPluginGuestDelegate::PermissionResponseCallback callback = | |
290 base::Bind(&BrowserPluginGuest::RespondToPermissionRequest, | |
291 AsWeakPtr(), | |
292 request_id); | |
293 delegate_->RequestPermission( | |
294 permission_type, request_info, callback, request->AllowedByDefault()); | |
295 } | |
296 | |
297 BrowserPluginGuest* BrowserPluginGuest::CreateNewGuestWindow( | |
298 const OpenURLParams& params) { | |
299 BrowserPluginGuestManager* guest_manager = | |
300 GetBrowserPluginGuestManager(); | |
301 | |
302 // Allocate a new instance ID for the new guest. | |
303 int instance_id = guest_manager->GetNextInstanceID(); | |
304 | |
305 // Set the attach params to use the same partition as the opener. | |
306 // We pull the partition information from the site's URL, which is of the form | |
307 // guest://site/{persist}?{partition_name}. | |
308 const GURL& site_url = GetWebContents()->GetSiteInstance()->GetSiteURL(); | |
309 | |
310 // The new guest gets a copy of this guest's extra params so that the content | |
311 // embedder exposes the same API for this guest as its opener. | |
312 scoped_ptr<base::DictionaryValue> extra_params( | |
313 extra_attach_params_->DeepCopy()); | |
314 const std::string& storage_partition_id = site_url.query(); | |
315 bool persist_storage = | |
316 site_url.path().find("persist") != std::string::npos; | |
317 WebContents* new_guest_web_contents = | |
318 guest_manager->CreateGuest(GetWebContents()->GetSiteInstance(), | |
319 instance_id, | |
320 storage_partition_id, | |
321 persist_storage, | |
322 extra_params.Pass()); | |
323 BrowserPluginGuest* new_guest = | |
324 static_cast<WebContentsImpl*>(new_guest_web_contents)-> | |
325 GetBrowserPluginGuest(); | |
326 if (new_guest->delegate_) | |
327 new_guest->delegate_->SetOpener(GetWebContents()); | |
328 | |
329 // Take ownership of |new_guest|. | |
330 pending_new_windows_.insert( | |
331 std::make_pair(new_guest, NewWindowInfo(params.url, std::string()))); | |
332 | |
333 // Request permission to show the new window. | |
334 RequestNewWindowPermission(params.disposition, gfx::Rect(), | |
335 params.user_gesture, new_guest->GetWebContents()); | |
336 | |
337 return new_guest; | |
338 } | 134 } |
339 | 135 |
340 base::WeakPtr<BrowserPluginGuest> BrowserPluginGuest::AsWeakPtr() { | 136 base::WeakPtr<BrowserPluginGuest> BrowserPluginGuest::AsWeakPtr() { |
341 return weak_ptr_factory_.GetWeakPtr(); | 137 return weak_ptr_factory_.GetWeakPtr(); |
342 } | 138 } |
343 | 139 |
344 bool BrowserPluginGuest::LockMouse(bool allowed) { | 140 bool BrowserPluginGuest::LockMouse(bool allowed) { |
345 if (!attached() || (mouse_locked_ == allowed)) | 141 if (!attached() || (mouse_locked_ == allowed)) |
346 return false; | 142 return false; |
347 | 143 |
348 return embedder_web_contents()->GotResponseToLockMouseRequest(allowed); | 144 return embedder_web_contents()->GotResponseToLockMouseRequest(allowed); |
349 } | 145 } |
350 | 146 |
351 void BrowserPluginGuest::EmbedderDestroyed() { | 147 void BrowserPluginGuest::EmbedderDestroyed() { |
352 embedder_web_contents_ = NULL; | 148 embedder_web_contents_ = NULL; |
353 if (delegate_) | 149 if (delegate_) |
354 delegate_->EmbedderDestroyed(); | 150 delegate_->EmbedderDestroyed(); |
355 Destroy(); | 151 Destroy(); |
356 } | 152 } |
357 | 153 |
358 void BrowserPluginGuest::Destroy() { | 154 void BrowserPluginGuest::Destroy() { |
359 is_in_destruction_ = true; | 155 if (!delegate_) |
360 if (!attached() && GetOpener()) | 156 return; |
361 GetOpener()->pending_new_windows_.erase(this); | 157 delegate_->Destroy(); |
362 DestroyUnattachedWindows(); | |
363 delete GetWebContents(); | |
364 } | 158 } |
365 | 159 |
366 bool BrowserPluginGuest::OnMessageReceivedFromEmbedder( | 160 bool BrowserPluginGuest::OnMessageReceivedFromEmbedder( |
367 const IPC::Message& message) { | 161 const IPC::Message& message) { |
368 bool handled = true; | 162 bool handled = true; |
369 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message) | 163 IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message) |
370 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameSwappedACK, | 164 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameSwappedACK, |
371 OnCompositorFrameSwappedACK) | 165 OnCompositorFrameSwappedACK) |
372 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CopyFromCompositingSurfaceAck, | 166 IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CopyFromCompositingSurfaceAck, |
373 OnCopyFromCompositingSurfaceAck) | 167 OnCopyFromCompositingSurfaceAck) |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 int guest_routing_id = | 251 int guest_routing_id = |
458 GetWebContents()->CreateSwappedOutRenderView( | 252 GetWebContents()->CreateSwappedOutRenderView( |
459 embedder_web_contents_->GetSiteInstance()); | 253 embedder_web_contents_->GetSiteInstance()); |
460 SendMessageToEmbedder( | 254 SendMessageToEmbedder( |
461 new BrowserPluginMsg_GuestContentWindowReady(instance_id_, | 255 new BrowserPluginMsg_GuestContentWindowReady(instance_id_, |
462 guest_routing_id)); | 256 guest_routing_id)); |
463 | 257 |
464 if (!params.src.empty()) { | 258 if (!params.src.empty()) { |
465 // params.src will be validated in BrowserPluginGuest::OnNavigateGuest. | 259 // params.src will be validated in BrowserPluginGuest::OnNavigateGuest. |
466 OnNavigateGuest(instance_id_, params.src); | 260 OnNavigateGuest(instance_id_, params.src); |
| 261 has_render_view_ = true; |
467 } | 262 } |
468 | 263 |
469 has_render_view_ = true; | |
470 | |
471 WebPreferences prefs = GetWebContents()->GetWebkitPrefs(); | 264 WebPreferences prefs = GetWebContents()->GetWebkitPrefs(); |
472 prefs.navigate_on_drag_drop = false; | 265 prefs.navigate_on_drag_drop = false; |
473 GetWebContents()->GetRenderViewHost()->UpdateWebkitPreferences(prefs); | 266 GetWebContents()->GetRenderViewHost()->UpdateWebkitPreferences(prefs); |
474 | 267 |
475 // Enable input method for guest if it's enabled for the embedder. | 268 // Enable input method for guest if it's enabled for the embedder. |
476 if (static_cast<RenderViewHostImpl*>( | 269 if (static_cast<RenderViewHostImpl*>( |
477 embedder_web_contents_->GetRenderViewHost())->input_method_active()) { | 270 embedder_web_contents_->GetRenderViewHost())->input_method_active()) { |
478 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>( | 271 RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>( |
479 GetWebContents()->GetRenderViewHost()); | 272 GetWebContents()->GetRenderViewHost()); |
480 guest_rvh->SetInputMethodActive(true); | 273 guest_rvh->SetInputMethodActive(true); |
(...skipping 20 matching lines...) Expand all Loading... |
501 delete pending_messages_.front(); | 294 delete pending_messages_.front(); |
502 pending_messages_.pop(); | 295 pending_messages_.pop(); |
503 } | 296 } |
504 } | 297 } |
505 | 298 |
506 // static | 299 // static |
507 BrowserPluginGuest* BrowserPluginGuest::Create( | 300 BrowserPluginGuest* BrowserPluginGuest::Create( |
508 int instance_id, | 301 int instance_id, |
509 SiteInstance* guest_site_instance, | 302 SiteInstance* guest_site_instance, |
510 WebContentsImpl* web_contents, | 303 WebContentsImpl* web_contents, |
511 scoped_ptr<base::DictionaryValue> extra_params) { | 304 scoped_ptr<base::DictionaryValue> extra_params, |
| 305 BrowserPluginGuest* opener) { |
512 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Create")); | 306 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Create")); |
513 BrowserPluginGuest* guest = NULL; | 307 BrowserPluginGuest* guest = NULL; |
514 if (factory_) { | 308 if (factory_) { |
515 guest = factory_->CreateBrowserPluginGuest(instance_id, web_contents); | 309 guest = factory_->CreateBrowserPluginGuest(instance_id, web_contents); |
516 } else { | 310 } else { |
517 guest = new BrowserPluginGuest(instance_id, false, web_contents); | 311 guest = new BrowserPluginGuest(instance_id, |
| 312 web_contents->opener() != NULL, |
| 313 web_contents); |
518 } | 314 } |
519 guest->extra_attach_params_.reset(extra_params->DeepCopy()); | |
520 web_contents->SetBrowserPluginGuest(guest); | 315 web_contents->SetBrowserPluginGuest(guest); |
| 316 WebContents* opener_web_contents = NULL; |
| 317 if (opener) { |
| 318 opener_web_contents = opener->GetWebContents(); |
| 319 guest_site_instance = opener_web_contents->GetSiteInstance(); |
| 320 } |
521 BrowserPluginGuestDelegate* delegate = NULL; | 321 BrowserPluginGuestDelegate* delegate = NULL; |
522 GetContentClient()->browser()->GuestWebContentsCreated( | 322 GetContentClient()->browser()->GuestWebContentsCreated( |
523 guest_site_instance, web_contents, NULL, &delegate, extra_params.Pass()); | 323 instance_id, |
524 guest->SetDelegate(delegate); | 324 guest_site_instance, |
| 325 web_contents, |
| 326 opener_web_contents, |
| 327 &delegate, |
| 328 extra_params.Pass()); |
| 329 if (delegate) { |
| 330 delegate->RegisterDestructionCallback( |
| 331 base::Bind(&BrowserPluginGuest::WillDestroy, |
| 332 base::Unretained(guest))); |
| 333 guest->SetDelegate(delegate); |
| 334 } |
525 return guest; | 335 return guest; |
526 } | 336 } |
527 | 337 |
528 // static | |
529 BrowserPluginGuest* BrowserPluginGuest::CreateWithOpener( | |
530 int instance_id, | |
531 bool has_render_view, | |
532 WebContentsImpl* web_contents, | |
533 BrowserPluginGuest* opener) { | |
534 BrowserPluginGuest* guest = | |
535 new BrowserPluginGuest( | |
536 instance_id, has_render_view, web_contents); | |
537 web_contents->SetBrowserPluginGuest(guest); | |
538 BrowserPluginGuestDelegate* delegate = NULL; | |
539 GetContentClient()->browser()->GuestWebContentsCreated( | |
540 opener->GetWebContents()->GetSiteInstance(), | |
541 web_contents, opener->GetWebContents(), &delegate, | |
542 scoped_ptr<base::DictionaryValue>()); | |
543 guest->SetDelegate(delegate); | |
544 return guest; | |
545 } | |
546 | |
547 RenderWidgetHostView* BrowserPluginGuest::GetEmbedderRenderWidgetHostView() { | 338 RenderWidgetHostView* BrowserPluginGuest::GetEmbedderRenderWidgetHostView() { |
548 if (!attached()) | 339 if (!attached()) |
549 return NULL; | 340 return NULL; |
550 return embedder_web_contents_->GetRenderWidgetHostView(); | 341 return embedder_web_contents_->GetRenderWidgetHostView(); |
551 } | 342 } |
552 | 343 |
553 BrowserPluginGuest* BrowserPluginGuest::GetOpener() const { | |
554 if (!delegate_) | |
555 return NULL; | |
556 | |
557 WebContents* opener = delegate_->GetOpener(); | |
558 if (!opener) | |
559 return NULL; | |
560 | |
561 return static_cast<WebContentsImpl*>(opener)->GetBrowserPluginGuest(); | |
562 } | |
563 | |
564 void BrowserPluginGuest::UpdateVisibility() { | 344 void BrowserPluginGuest::UpdateVisibility() { |
565 OnSetVisibility(instance_id_, visible()); | 345 OnSetVisibility(instance_id_, visible()); |
566 } | 346 } |
567 | 347 |
568 void BrowserPluginGuest::CopyFromCompositingSurface( | 348 void BrowserPluginGuest::CopyFromCompositingSurface( |
569 gfx::Rect src_subrect, | 349 gfx::Rect src_subrect, |
570 gfx::Size dst_size, | 350 gfx::Size dst_size, |
571 const base::Callback<void(bool, const SkBitmap&)>& callback) { | 351 const base::Callback<void(bool, const SkBitmap&)>& callback) { |
572 copy_request_callbacks_.insert(std::make_pair(++copy_request_id_, callback)); | 352 copy_request_callbacks_.insert(std::make_pair(++copy_request_id_, callback)); |
573 SendMessageToEmbedder( | 353 SendMessageToEmbedder( |
(...skipping 17 matching lines...) Expand all Loading... |
591 embedder_visible_ = visible; | 371 embedder_visible_ = visible; |
592 UpdateVisibility(); | 372 UpdateVisibility(); |
593 } | 373 } |
594 | 374 |
595 void BrowserPluginGuest::AddNewContents(WebContents* source, | 375 void BrowserPluginGuest::AddNewContents(WebContents* source, |
596 WebContents* new_contents, | 376 WebContents* new_contents, |
597 WindowOpenDisposition disposition, | 377 WindowOpenDisposition disposition, |
598 const gfx::Rect& initial_pos, | 378 const gfx::Rect& initial_pos, |
599 bool user_gesture, | 379 bool user_gesture, |
600 bool* was_blocked) { | 380 bool* was_blocked) { |
601 if (was_blocked) | 381 if (!delegate_) |
602 *was_blocked = false; | 382 return; |
603 RequestNewWindowPermission(disposition, initial_pos, user_gesture, | 383 |
604 static_cast<WebContentsImpl*>(new_contents)); | 384 delegate_->AddNewContents(source, new_contents, disposition, |
| 385 initial_pos, user_gesture, was_blocked); |
605 } | 386 } |
606 | 387 |
607 void BrowserPluginGuest::CanDownload( | 388 void BrowserPluginGuest::CanDownload( |
608 RenderViewHost* render_view_host, | 389 RenderViewHost* render_view_host, |
609 const GURL& url, | 390 const GURL& url, |
610 const std::string& request_method, | 391 const std::string& request_method, |
611 const base::Callback<void(bool)>& callback) { | 392 const base::Callback<void(bool)>& callback) { |
612 if (!delegate_ || !url.is_valid()) { | 393 if (!delegate_ || !url.is_valid()) { |
613 callback.Run(false); | 394 callback.Run(false); |
614 return; | 395 return; |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
688 return; | 469 return; |
689 | 470 |
690 // |selection_rect| is updated to incorporate embedder coordinates. | 471 // |selection_rect| is updated to incorporate embedder coordinates. |
691 delegate_->FindReply(request_id, number_of_matches, | 472 delegate_->FindReply(request_id, number_of_matches, |
692 ToGuestRect(selection_rect), | 473 ToGuestRect(selection_rect), |
693 active_match_ordinal, final_update); | 474 active_match_ordinal, final_update); |
694 } | 475 } |
695 | 476 |
696 WebContents* BrowserPluginGuest::OpenURLFromTab(WebContents* source, | 477 WebContents* BrowserPluginGuest::OpenURLFromTab(WebContents* source, |
697 const OpenURLParams& params) { | 478 const OpenURLParams& params) { |
698 // If the guest wishes to navigate away prior to attachment then we save the | 479 if (!delegate_) |
699 // navigation to perform upon attachment. Navigation initializes a lot of | |
700 // state that assumes an embedder exists, such as RenderWidgetHostViewGuest. | |
701 // Navigation also resumes resource loading which we don't want to allow | |
702 // until attachment. | |
703 if (!attached()) { | |
704 PendingWindowMap::iterator it = | |
705 GetOpener()->pending_new_windows_.find(this); | |
706 if (it == GetOpener()->pending_new_windows_.end()) | |
707 return NULL; | |
708 const NewWindowInfo& old_target_url = it->second; | |
709 NewWindowInfo new_window_info(params.url, old_target_url.name); | |
710 new_window_info.changed = new_window_info.url != old_target_url.url; | |
711 it->second = new_window_info; | |
712 return NULL; | 480 return NULL; |
713 } | 481 return delegate_->OpenURLFromTab(source, params); |
714 if (params.disposition == CURRENT_TAB) { | |
715 // This can happen for cross-site redirects. | |
716 LoadURLWithParams(params.url, params.referrer, params.transition, source); | |
717 return source; | |
718 } | |
719 | |
720 return CreateNewGuestWindow(params)->GetWebContents(); | |
721 } | 482 } |
722 | 483 |
723 void BrowserPluginGuest::WebContentsCreated(WebContents* source_contents, | 484 void BrowserPluginGuest::WebContentsCreated(WebContents* source_contents, |
724 int opener_render_frame_id, | 485 int opener_render_frame_id, |
725 const base::string16& frame_name, | 486 const base::string16& frame_name, |
726 const GURL& target_url, | 487 const GURL& target_url, |
727 WebContents* new_contents) { | 488 WebContents* new_contents) { |
728 WebContentsImpl* new_contents_impl = | 489 WebContentsImpl* new_contents_impl = |
729 static_cast<WebContentsImpl*>(new_contents); | 490 static_cast<WebContentsImpl*>(new_contents); |
730 BrowserPluginGuest* guest = new_contents_impl->GetBrowserPluginGuest(); | 491 BrowserPluginGuest* guest = new_contents_impl->GetBrowserPluginGuest(); |
731 if (guest->delegate_) | |
732 guest->delegate_->SetOpener(GetWebContents()); | |
733 std::string guest_name = base::UTF16ToUTF8(frame_name); | 492 std::string guest_name = base::UTF16ToUTF8(frame_name); |
734 guest->name_ = guest_name; | 493 guest->name_ = guest_name; |
735 // Take ownership of the new guest until it is attached to the embedder's DOM | 494 |
736 // tree to avoid leaking a guest if this guest is destroyed before attaching | 495 if (!delegate_) |
737 // the new guest. | 496 return; |
738 pending_new_windows_.insert( | 497 |
739 std::make_pair(guest, NewWindowInfo(target_url, guest_name))); | 498 delegate_->WebContentsCreated(source_contents, |
| 499 opener_render_frame_id, |
| 500 frame_name, |
| 501 target_url, |
| 502 new_contents); |
740 } | 503 } |
741 | 504 |
742 void BrowserPluginGuest::RendererUnresponsive(WebContents* source) { | 505 void BrowserPluginGuest::RendererUnresponsive(WebContents* source) { |
743 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Hung")); | 506 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Hung")); |
744 if (!delegate_) | 507 if (!delegate_) |
745 return; | 508 return; |
746 delegate_->RendererUnresponsive(); | 509 delegate_->RendererUnresponsive(); |
747 } | 510 } |
748 | 511 |
749 void BrowserPluginGuest::RendererResponsive(WebContents* source) { | 512 void BrowserPluginGuest::RendererResponsive(WebContents* source) { |
(...skipping 25 matching lines...) Expand all Loading... |
775 gfx::Point screen_pos(relative_position); | 538 gfx::Point screen_pos(relative_position); |
776 screen_pos += guest_window_rect_.OffsetFromOrigin(); | 539 screen_pos += guest_window_rect_.OffsetFromOrigin(); |
777 return screen_pos; | 540 return screen_pos; |
778 } | 541 } |
779 | 542 |
780 bool BrowserPluginGuest::InAutoSizeBounds(const gfx::Size& size) const { | 543 bool BrowserPluginGuest::InAutoSizeBounds(const gfx::Size& size) const { |
781 return size.width() <= max_auto_size_.width() && | 544 return size.width() <= max_auto_size_.width() && |
782 size.height() <= max_auto_size_.height(); | 545 size.height() <= max_auto_size_.height(); |
783 } | 546 } |
784 | 547 |
785 void BrowserPluginGuest::RequestNewWindowPermission( | |
786 WindowOpenDisposition disposition, | |
787 const gfx::Rect& initial_bounds, | |
788 bool user_gesture, | |
789 WebContentsImpl* new_contents) { | |
790 BrowserPluginGuest* guest = new_contents->GetBrowserPluginGuest(); | |
791 PendingWindowMap::iterator it = pending_new_windows_.find(guest); | |
792 if (it == pending_new_windows_.end()) | |
793 return; | |
794 const NewWindowInfo& new_window_info = it->second; | |
795 | |
796 base::DictionaryValue request_info; | |
797 request_info.Set(browser_plugin::kInitialHeight, | |
798 base::Value::CreateIntegerValue(initial_bounds.height())); | |
799 request_info.Set(browser_plugin::kInitialWidth, | |
800 base::Value::CreateIntegerValue(initial_bounds.width())); | |
801 request_info.Set(browser_plugin::kTargetURL, | |
802 base::Value::CreateStringValue(new_window_info.url.spec())); | |
803 request_info.Set(browser_plugin::kName, | |
804 base::Value::CreateStringValue(new_window_info.name)); | |
805 request_info.Set(browser_plugin::kWindowID, | |
806 base::Value::CreateIntegerValue(guest->instance_id())); | |
807 request_info.Set(browser_plugin::kWindowOpenDisposition, | |
808 base::Value::CreateStringValue( | |
809 WindowOpenDispositionToString(disposition))); | |
810 | |
811 RequestPermission(BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW, | |
812 new NewWindowRequest(weak_ptr_factory_.GetWeakPtr(), | |
813 guest->instance_id()), | |
814 request_info); | |
815 } | |
816 | |
817 void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) { | 548 void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) { |
818 if (!attached()) { | 549 if (!attached()) { |
819 // Some pages such as data URLs, javascript URLs, and about:blank | 550 // Some pages such as data URLs, javascript URLs, and about:blank |
820 // do not load external resources and so they load prior to attachment. | 551 // do not load external resources and so they load prior to attachment. |
821 // As a result, we must save all these IPCs until attachment and then | 552 // As a result, we must save all these IPCs until attachment and then |
822 // forward them so that the embedder gets a chance to see and process | 553 // forward them so that the embedder gets a chance to see and process |
823 // the load events. | 554 // the load events. |
824 pending_messages_.push(msg); | 555 pending_messages_.push(msg); |
825 return; | 556 return; |
826 } | 557 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
909 case base::TERMINATION_STATUS_PROCESS_CRASHED: | 640 case base::TERMINATION_STATUS_PROCESS_CRASHED: |
910 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Crashed")); | 641 RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Crashed")); |
911 break; | 642 break; |
912 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: | 643 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: |
913 RecordAction( | 644 RecordAction( |
914 base::UserMetricsAction("BrowserPlugin.Guest.AbnormalDeath")); | 645 base::UserMetricsAction("BrowserPlugin.Guest.AbnormalDeath")); |
915 break; | 646 break; |
916 default: | 647 default: |
917 break; | 648 break; |
918 } | 649 } |
919 // TODO(fsamuel): Consider whether we should be clearing | |
920 // |permission_request_map_| here. | |
921 if (delegate_) | 650 if (delegate_) |
922 delegate_->GuestProcessGone(status); | 651 delegate_->GuestProcessGone(status); |
923 } | 652 } |
924 | 653 |
925 // static | 654 // static |
926 bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest( | 655 bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest( |
927 const IPC::Message& message) { | 656 const IPC::Message& message) { |
928 switch (message.type()) { | 657 switch (message.type()) { |
929 case BrowserPluginHostMsg_CompositorFrameSwappedACK::ID: | 658 case BrowserPluginHostMsg_CompositorFrameSwappedACK::ID: |
930 case BrowserPluginHostMsg_CopyFromCompositingSurfaceAck::ID: | 659 case BrowserPluginHostMsg_CopyFromCompositingSurfaceAck::ID: |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
984 return handled; | 713 return handled; |
985 } | 714 } |
986 | 715 |
987 void BrowserPluginGuest::Attach( | 716 void BrowserPluginGuest::Attach( |
988 WebContentsImpl* embedder_web_contents, | 717 WebContentsImpl* embedder_web_contents, |
989 BrowserPluginHostMsg_Attach_Params params, | 718 BrowserPluginHostMsg_Attach_Params params, |
990 const base::DictionaryValue& extra_params) { | 719 const base::DictionaryValue& extra_params) { |
991 if (attached()) | 720 if (attached()) |
992 return; | 721 return; |
993 | 722 |
994 extra_attach_params_.reset(extra_params.DeepCopy()); | |
995 | |
996 // Clear parameters that get inherited from the opener. | 723 // Clear parameters that get inherited from the opener. |
997 params.storage_partition_id.clear(); | 724 params.storage_partition_id.clear(); |
998 params.persist_storage = false; | 725 params.persist_storage = false; |
999 params.src.clear(); | 726 params.src.clear(); |
1000 | 727 |
1001 // If a RenderView has already been created for this new window, then we need | 728 // If a RenderView has already been created for this new window, then we need |
1002 // to initialize the browser-side state now so that the RenderFrameHostManager | 729 // to initialize the browser-side state now so that the RenderFrameHostManager |
1003 // does not create a new RenderView on navigation. | 730 // does not create a new RenderView on navigation. |
1004 if (has_render_view_) { | 731 if (has_render_view_) { |
1005 static_cast<RenderViewHostImpl*>( | 732 static_cast<RenderViewHostImpl*>( |
1006 GetWebContents()->GetRenderViewHost())->Init(); | 733 GetWebContents()->GetRenderViewHost())->Init(); |
1007 WebContentsViewGuest* new_view = | 734 WebContentsViewGuest* new_view = |
1008 static_cast<WebContentsViewGuest*>(GetWebContents()->GetView()); | 735 static_cast<WebContentsViewGuest*>(GetWebContents()->GetView()); |
1009 new_view->CreateViewForWidget(web_contents()->GetRenderViewHost()); | 736 new_view->CreateViewForWidget(web_contents()->GetRenderViewHost()); |
1010 } | 737 } |
1011 | 738 |
1012 // We need to do a navigation here if the target URL has changed between | |
1013 // the time the WebContents was created and the time it was attached. | |
1014 // We also need to do an initial navigation if a RenderView was never | |
1015 // created for the new window in cases where there is no referrer. | |
1016 PendingWindowMap::iterator it = GetOpener()->pending_new_windows_.find(this); | |
1017 if (it != GetOpener()->pending_new_windows_.end()) { | |
1018 const NewWindowInfo& new_window_info = it->second; | |
1019 if (new_window_info.changed || !has_render_view_) | |
1020 params.src = it->second.url.spec(); | |
1021 } else { | |
1022 NOTREACHED(); | |
1023 } | |
1024 | |
1025 // Once a new guest is attached to the DOM of the embedder page, then the | |
1026 // lifetime of the new guest is no longer managed by the opener guest. | |
1027 GetOpener()->pending_new_windows_.erase(this); | |
1028 | |
1029 // The guest's frame name takes precedence over the BrowserPlugin's name. | 739 // The guest's frame name takes precedence over the BrowserPlugin's name. |
1030 // The guest's frame name is assigned in | 740 // The guest's frame name is assigned in |
1031 // BrowserPluginGuest::WebContentsCreated. | 741 // BrowserPluginGuest::WebContentsCreated. |
1032 if (!name_.empty()) | 742 if (!name_.empty()) |
1033 params.name.clear(); | 743 params.name.clear(); |
1034 | 744 |
1035 Initialize(params, embedder_web_contents); | 745 Initialize(params, embedder_web_contents); |
1036 | 746 |
1037 SendQueuedMessages(); | 747 SendQueuedMessages(); |
1038 | 748 |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1198 weak_ptr_factory_.GetWeakPtr())); | 908 weak_ptr_factory_.GetWeakPtr())); |
1199 } | 909 } |
1200 | 910 |
1201 void BrowserPluginGuest::OnLockMouseAck(int instance_id, bool succeeded) { | 911 void BrowserPluginGuest::OnLockMouseAck(int instance_id, bool succeeded) { |
1202 Send(new ViewMsg_LockMouse_ACK(routing_id(), succeeded)); | 912 Send(new ViewMsg_LockMouse_ACK(routing_id(), succeeded)); |
1203 pending_lock_request_ = false; | 913 pending_lock_request_ = false; |
1204 if (succeeded) | 914 if (succeeded) |
1205 mouse_locked_ = true; | 915 mouse_locked_ = true; |
1206 } | 916 } |
1207 | 917 |
1208 void BrowserPluginGuest::OnNavigateGuest( | 918 void BrowserPluginGuest::OnNavigateGuest(int instance_id, |
1209 int instance_id, | 919 const std::string& src) { |
1210 const std::string& src) { | 920 if (!delegate_) |
1211 GURL url = delegate_ ? delegate_->ResolveURL(src) : GURL(src); | |
1212 | |
1213 // Do not allow navigating a guest to schemes other than known safe schemes. | |
1214 // This will block the embedder trying to load unwanted schemes, e.g. | |
1215 // chrome://settings. | |
1216 bool scheme_is_blocked = | |
1217 (!ChildProcessSecurityPolicyImpl::GetInstance()->IsWebSafeScheme( | |
1218 url.scheme()) && | |
1219 !ChildProcessSecurityPolicyImpl::GetInstance()->IsPseudoScheme( | |
1220 url.scheme())) || | |
1221 url.SchemeIs(kJavaScriptScheme); | |
1222 if (scheme_is_blocked || !url.is_valid()) { | |
1223 if (delegate_) { | |
1224 std::string error_type; | |
1225 base::RemoveChars(net::ErrorToString(net::ERR_ABORTED), "net::", | |
1226 &error_type); | |
1227 delegate_->LoadAbort(true /* is_top_level */, url, error_type); | |
1228 } | |
1229 return; | 921 return; |
1230 } | 922 delegate_->NavigateGuest(src); |
1231 | |
1232 GURL validated_url(url); | |
1233 GetWebContents()->GetRenderProcessHost()->FilterURL(false, &validated_url); | |
1234 // As guests do not swap processes on navigation, only navigations to | |
1235 // normal web URLs are supported. No protocol handlers are installed for | |
1236 // other schemes (e.g., WebUI or extensions), and no permissions or bindings | |
1237 // can be granted to the guest process. | |
1238 LoadURLWithParams(validated_url, Referrer(), PAGE_TRANSITION_AUTO_TOPLEVEL, | |
1239 GetWebContents()); | |
1240 } | 923 } |
1241 | 924 |
1242 void BrowserPluginGuest::OnPluginDestroyed(int instance_id) { | 925 void BrowserPluginGuest::OnPluginDestroyed(int instance_id) { |
1243 Destroy(); | 926 Destroy(); |
1244 } | 927 } |
1245 | 928 |
1246 void BrowserPluginGuest::OnResizeGuest( | 929 void BrowserPluginGuest::OnResizeGuest( |
1247 int instance_id, | 930 int instance_id, |
1248 const BrowserPluginHostMsg_ResizeGuest_Params& params) { | 931 const BrowserPluginHostMsg_ResizeGuest_Params& params) { |
1249 if (!params.size_changed) | 932 if (!params.size_changed) |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1499 void BrowserPluginGuest::OnImeCompositionRangeChanged( | 1182 void BrowserPluginGuest::OnImeCompositionRangeChanged( |
1500 const gfx::Range& range, | 1183 const gfx::Range& range, |
1501 const std::vector<gfx::Rect>& character_bounds) { | 1184 const std::vector<gfx::Rect>& character_bounds) { |
1502 static_cast<RenderWidgetHostViewBase*>( | 1185 static_cast<RenderWidgetHostViewBase*>( |
1503 web_contents()->GetRenderWidgetHostView())->ImeCompositionRangeChanged( | 1186 web_contents()->GetRenderWidgetHostView())->ImeCompositionRangeChanged( |
1504 range, character_bounds); | 1187 range, character_bounds); |
1505 } | 1188 } |
1506 #endif | 1189 #endif |
1507 | 1190 |
1508 } // namespace content | 1191 } // namespace content |
OLD | NEW |