OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "chrome/browser/guest_view/web_view/web_view_guest.h" | 5 #include "chrome/browser/guest_view/web_view/web_view_guest.h" |
6 | 6 |
7 #include "base/message_loop/message_loop.h" | 7 #include "base/message_loop/message_loop.h" |
8 #include "base/strings/stringprintf.h" | 8 #include "base/strings/stringprintf.h" |
9 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
10 #include "chrome/browser/chrome_notification_types.h" | 10 #include "chrome/browser/chrome_notification_types.h" |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 #endif // defined(ENABLE_FULL_PRINTING) | 182 #endif // defined(ENABLE_FULL_PRINTING) |
183 #endif // defined(ENABLE_PRINTING) | 183 #endif // defined(ENABLE_PRINTING) |
184 PDFTabHelper::CreateForWebContents(contents); | 184 PDFTabHelper::CreateForWebContents(contents); |
185 } | 185 } |
186 | 186 |
187 } // namespace | 187 } // namespace |
188 | 188 |
189 WebViewGuest::WebViewGuest(int guest_instance_id, | 189 WebViewGuest::WebViewGuest(int guest_instance_id, |
190 WebContents* guest_web_contents, | 190 WebContents* guest_web_contents, |
191 const std::string& embedder_extension_id) | 191 const std::string& embedder_extension_id) |
192 : GuestView<WebViewGuest>(guest_instance_id, | 192 : GuestView<WebViewGuest>(guest_instance_id), |
193 guest_web_contents, | |
194 embedder_extension_id), | |
195 script_executor_(new extensions::ScriptExecutor(guest_web_contents, | 193 script_executor_(new extensions::ScriptExecutor(guest_web_contents, |
196 &script_observers_)), | 194 &script_observers_)), |
197 pending_context_menu_request_id_(0), | 195 pending_context_menu_request_id_(0), |
198 next_permission_request_id_(0), | 196 next_permission_request_id_(0), |
199 is_overriding_user_agent_(false), | 197 is_overriding_user_agent_(false), |
200 pending_reload_on_attachment_(false), | |
201 main_frame_id_(0), | 198 main_frame_id_(0), |
202 chromevox_injected_(false), | 199 chromevox_injected_(false), |
203 find_helper_(this), | 200 find_helper_(this), |
204 javascript_dialog_helper_(this) { | 201 javascript_dialog_helper_(this) { |
| 202 Init(guest_web_contents, embedder_extension_id); |
205 notification_registrar_.Add( | 203 notification_registrar_.Add( |
206 this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, | 204 this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, |
207 content::Source<WebContents>(guest_web_contents)); | 205 content::Source<WebContents>(guest_web_contents)); |
208 | 206 |
209 notification_registrar_.Add( | 207 notification_registrar_.Add( |
210 this, content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT, | 208 this, content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT, |
211 content::Source<WebContents>(guest_web_contents)); | 209 content::Source<WebContents>(guest_web_contents)); |
212 | 210 |
213 #if defined(OS_CHROMEOS) | 211 #if defined(OS_CHROMEOS) |
214 chromeos::AccessibilityManager* accessibility_manager = | 212 chromeos::AccessibilityManager* accessibility_manager = |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 // TODO(lazyboy): We need to expose some kind of enum equivalent of | 378 // TODO(lazyboy): We need to expose some kind of enum equivalent of |
381 // |command_id| instead of plain integers. | 379 // |command_id| instead of plain integers. |
382 item_value->SetInteger(webview::kMenuItemCommandId, | 380 item_value->SetInteger(webview::kMenuItemCommandId, |
383 menu_model.GetCommandIdAt(i)); | 381 menu_model.GetCommandIdAt(i)); |
384 item_value->SetString(webview::kMenuItemLabel, menu_model.GetLabelAt(i)); | 382 item_value->SetString(webview::kMenuItemLabel, menu_model.GetLabelAt(i)); |
385 items->Append(item_value); | 383 items->Append(item_value); |
386 } | 384 } |
387 return items.Pass(); | 385 return items.Pass(); |
388 } | 386 } |
389 | 387 |
390 void WebViewGuest::Attach(WebContents* embedder_web_contents, | 388 void WebViewGuest::DidAttachToEmbedder() { |
391 const base::DictionaryValue& args) { | |
392 std::string name; | 389 std::string name; |
393 args.GetString(webview::kName, &name); | 390 if (extra_params()->GetString(webview::kName, &name)) { |
394 // If the guest window's name is empty, then the WebView tag's name is | 391 // If the guest window's name is empty, then the WebView tag's name is |
395 // assigned. Otherwise, the guest window's name takes precedence over the | 392 // assigned. Otherwise, the guest window's name takes precedence over the |
396 // WebView tag's name. | 393 // WebView tag's name. |
397 if (name_.empty()) | 394 if (name_.empty()) |
398 name_ = name; | 395 name_ = name; |
| 396 } |
399 ReportFrameNameChange(name_); | 397 ReportFrameNameChange(name_); |
400 | 398 |
401 std::string user_agent_override; | 399 std::string user_agent_override; |
402 if (args.GetString(webview::kParameterUserAgentOverride, | 400 if (extra_params()->GetString(webview::kParameterUserAgentOverride, |
403 &user_agent_override)) { | 401 &user_agent_override)) { |
404 SetUserAgentOverride(user_agent_override); | 402 SetUserAgentOverride(user_agent_override); |
405 } else { | 403 } else { |
406 SetUserAgentOverride(""); | 404 SetUserAgentOverride(""); |
407 } | 405 } |
408 | 406 |
409 GuestViewBase::Attach(embedder_web_contents, args); | 407 std::string src; |
| 408 if (extra_params()->GetString("src", &src) && !src.empty()) |
| 409 NavigateGuest(src); |
410 | 410 |
411 AddWebViewToExtensionRendererState(); | 411 if (GetOpener()) { |
| 412 // We need to do a navigation here if the target URL has changed between |
| 413 // the time the WebContents was created and the time it was attached. |
| 414 // We also need to do an initial navigation if a RenderView was never |
| 415 // created for the new window in cases where there is no referrer. |
| 416 PendingWindowMap::iterator it = |
| 417 GetOpener()->pending_new_windows_.find(this); |
| 418 if (it != GetOpener()->pending_new_windows_.end()) { |
| 419 const NewWindowInfo& new_window_info = it->second; |
| 420 if (new_window_info.changed || !guest_web_contents()->HasOpener()) |
| 421 NavigateGuest(new_window_info.url.spec()); |
| 422 } else { |
| 423 NOTREACHED(); |
| 424 } |
| 425 |
| 426 // Once a new guest is attached to the DOM of the embedder page, then the |
| 427 // lifetime of the new guest is no longer managed by the opener guest. |
| 428 GetOpener()->pending_new_windows_.erase(this); |
| 429 } |
412 } | 430 } |
413 | 431 |
414 void WebViewGuest::DidStopLoading() { | 432 void WebViewGuest::DidStopLoading() { |
415 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue()); | 433 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue()); |
416 DispatchEvent(new GuestViewBase::Event(webview::kEventLoadStop, args.Pass())); | 434 DispatchEvent(new GuestViewBase::Event(webview::kEventLoadStop, args.Pass())); |
417 } | 435 } |
418 | 436 |
419 void WebViewGuest::EmbedderDestroyed() { | 437 void WebViewGuest::EmbedderDestroyed() { |
420 // TODO(fsamuel): WebRequest event listeners for <webview> should survive | 438 // TODO(fsamuel): WebRequest event listeners for <webview> should survive |
421 // reparenting of a <webview> within a single embedder. Right now, we keep | 439 // reparenting of a <webview> within a single embedder. Right now, we keep |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 DispatchEvent( | 486 DispatchEvent( |
469 new GuestViewBase::Event(webview::kEventConsoleMessage, args.Pass())); | 487 new GuestViewBase::Event(webview::kEventConsoleMessage, args.Pass())); |
470 return true; | 488 return true; |
471 } | 489 } |
472 | 490 |
473 void WebViewGuest::CloseContents(WebContents* source) { | 491 void WebViewGuest::CloseContents(WebContents* source) { |
474 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue()); | 492 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue()); |
475 DispatchEvent(new GuestViewBase::Event(webview::kEventClose, args.Pass())); | 493 DispatchEvent(new GuestViewBase::Event(webview::kEventClose, args.Pass())); |
476 } | 494 } |
477 | 495 |
478 void WebViewGuest::DidAttach(const base::DictionaryValue& extra_params) { | |
479 std::string src; | |
480 if (extra_params.GetString("src", &src) && !src.empty()) | |
481 NavigateGuest(src); | |
482 | |
483 if (GetOpener()) { | |
484 // We need to do a navigation here if the target URL has changed between | |
485 // the time the WebContents was created and the time it was attached. | |
486 // We also need to do an initial navigation if a RenderView was never | |
487 // created for the new window in cases where there is no referrer. | |
488 PendingWindowMap::iterator it = | |
489 GetOpener()->pending_new_windows_.find(this); | |
490 if (it != GetOpener()->pending_new_windows_.end()) { | |
491 const NewWindowInfo& new_window_info = it->second; | |
492 NavigateGuest(new_window_info.url.spec()); | |
493 } else { | |
494 NOTREACHED(); | |
495 } | |
496 | |
497 // Once a new guest is attached to the DOM of the embedder page, then the | |
498 // lifetime of the new guest is no longer managed by the opener guest. | |
499 GetOpener()->pending_new_windows_.erase(this); | |
500 } | |
501 | |
502 if (pending_reload_on_attachment_) { | |
503 pending_reload_on_attachment_ = false; | |
504 guest_web_contents()->GetController().Reload(false); | |
505 } | |
506 } | |
507 | |
508 void WebViewGuest::FindReply(WebContents* source, | 496 void WebViewGuest::FindReply(WebContents* source, |
509 int request_id, | 497 int request_id, |
510 int number_of_matches, | 498 int number_of_matches, |
511 const gfx::Rect& selection_rect, | 499 const gfx::Rect& selection_rect, |
512 int active_match_ordinal, | 500 int active_match_ordinal, |
513 bool final_update) { | 501 bool final_update) { |
514 find_helper_.FindReply(request_id, number_of_matches, selection_rect, | 502 find_helper_.FindReply(request_id, number_of_matches, selection_rect, |
515 active_match_ordinal, final_update); | 503 active_match_ordinal, final_update); |
516 } | 504 } |
517 | 505 |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
838 if (action != DEFAULT) | 826 if (action != DEFAULT) |
839 RecordUserInitiatedUMA(info, allow); | 827 RecordUserInitiatedUMA(info, allow); |
840 | 828 |
841 pending_permission_requests_.erase(request_itr); | 829 pending_permission_requests_.erase(request_itr); |
842 | 830 |
843 return allow ? SET_PERMISSION_ALLOWED : SET_PERMISSION_DENIED; | 831 return allow ? SET_PERMISSION_ALLOWED : SET_PERMISSION_DENIED; |
844 } | 832 } |
845 | 833 |
846 void WebViewGuest::SetUserAgentOverride( | 834 void WebViewGuest::SetUserAgentOverride( |
847 const std::string& user_agent_override) { | 835 const std::string& user_agent_override) { |
| 836 if (!attached()) |
| 837 return; |
848 is_overriding_user_agent_ = !user_agent_override.empty(); | 838 is_overriding_user_agent_ = !user_agent_override.empty(); |
849 if (is_overriding_user_agent_) { | 839 if (is_overriding_user_agent_) { |
850 content::RecordAction(UserMetricsAction("WebView.Guest.OverrideUA")); | 840 content::RecordAction(UserMetricsAction("WebView.Guest.OverrideUA")); |
851 } | 841 } |
852 guest_web_contents()->SetUserAgentOverride(user_agent_override); | 842 guest_web_contents()->SetUserAgentOverride(user_agent_override); |
853 } | 843 } |
854 | 844 |
855 void WebViewGuest::Stop() { | 845 void WebViewGuest::Stop() { |
856 guest_web_contents()->Stop(); | 846 guest_web_contents()->Stop(); |
857 } | 847 } |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1045 find_helper_.CancelAllFindSessions(); | 1035 find_helper_.CancelAllFindSessions(); |
1046 | 1036 |
1047 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue()); | 1037 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue()); |
1048 args->SetInteger(webview::kProcessId, | 1038 args->SetInteger(webview::kProcessId, |
1049 guest_web_contents()->GetRenderProcessHost()->GetID()); | 1039 guest_web_contents()->GetRenderProcessHost()->GetID()); |
1050 args->SetString(webview::kReason, TerminationStatusToString(status)); | 1040 args->SetString(webview::kReason, TerminationStatusToString(status)); |
1051 DispatchEvent(new GuestViewBase::Event(webview::kEventExit, args.Pass())); | 1041 DispatchEvent(new GuestViewBase::Event(webview::kEventExit, args.Pass())); |
1052 } | 1042 } |
1053 | 1043 |
1054 void WebViewGuest::UserAgentOverrideSet(const std::string& user_agent) { | 1044 void WebViewGuest::UserAgentOverrideSet(const std::string& user_agent) { |
| 1045 if (!attached()) |
| 1046 return; |
1055 content::NavigationController& controller = | 1047 content::NavigationController& controller = |
1056 guest_web_contents()->GetController(); | 1048 guest_web_contents()->GetController(); |
1057 content::NavigationEntry* entry = controller.GetVisibleEntry(); | 1049 content::NavigationEntry* entry = controller.GetVisibleEntry(); |
1058 if (!entry) | 1050 if (!entry) |
1059 return; | 1051 return; |
1060 entry->SetIsOverridingUserAgent(!user_agent.empty()); | 1052 entry->SetIsOverridingUserAgent(!user_agent.empty()); |
1061 if (!attached()) { | |
1062 // We cannot reload now because all resource loads are suspended until | |
1063 // attachment. | |
1064 pending_reload_on_attachment_ = true; | |
1065 return; | |
1066 } | |
1067 guest_web_contents()->GetController().Reload(false); | 1053 guest_web_contents()->GetController().Reload(false); |
1068 } | 1054 } |
1069 | 1055 |
1070 void WebViewGuest::RenderViewReady() { | 1056 void WebViewGuest::RenderViewReady() { |
1071 // The guest RenderView should always live in an isolated guest process. | 1057 // The guest RenderView should always live in an isolated guest process. |
1072 CHECK(guest_web_contents()->GetRenderProcessHost()->IsIsolatedGuest()); | 1058 CHECK(guest_web_contents()->GetRenderProcessHost()->IsIsolatedGuest()); |
1073 Send(new ChromeViewMsg_SetName(guest_web_contents()->GetRoutingID(), name_)); | 1059 Send(new ChromeViewMsg_SetName(guest_web_contents()->GetRoutingID(), name_)); |
1074 } | 1060 } |
1075 | 1061 |
1076 void WebViewGuest::ReportFrameNameChange(const std::string& name) { | 1062 void WebViewGuest::ReportFrameNameChange(const std::string& name) { |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1199 | 1185 |
1200 RequestPermission( | 1186 RequestPermission( |
1201 WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK, | 1187 WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK, |
1202 request_info, | 1188 request_info, |
1203 base::Bind(&WebViewGuest::OnWebViewPointerLockPermissionResponse, | 1189 base::Bind(&WebViewGuest::OnWebViewPointerLockPermissionResponse, |
1204 base::Unretained(this), | 1190 base::Unretained(this), |
1205 callback), | 1191 callback), |
1206 false /* allowed_by_default */); | 1192 false /* allowed_by_default */); |
1207 } | 1193 } |
1208 | 1194 |
| 1195 void WebViewGuest::WillAttachToEmbedder() { |
| 1196 // We must install the mapping from guests to WebViews prior to resuming |
| 1197 // suspended resource loads so that the WebRequest API will catch resource |
| 1198 // requests. |
| 1199 AddWebViewToExtensionRendererState(); |
| 1200 } |
| 1201 |
1209 content::JavaScriptDialogManager* | 1202 content::JavaScriptDialogManager* |
1210 WebViewGuest::GetJavaScriptDialogManager() { | 1203 WebViewGuest::GetJavaScriptDialogManager() { |
1211 return &javascript_dialog_helper_; | 1204 return &javascript_dialog_helper_; |
1212 } | 1205 } |
1213 | 1206 |
1214 content::ColorChooser* WebViewGuest::OpenColorChooser( | 1207 content::ColorChooser* WebViewGuest::OpenColorChooser( |
1215 WebContents* web_contents, | 1208 WebContents* web_contents, |
1216 SkColor color, | 1209 SkColor color, |
1217 const std::vector<content::ColorSuggestion>& suggestions) { | 1210 const std::vector<content::ColorSuggestion>& suggestions) { |
1218 if (!attached() || !embedder_web_contents()->GetDelegate()) | 1211 if (!attached() || !embedder_web_contents()->GetDelegate()) |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1465 // navigation to perform upon attachment. Navigation initializes a lot of | 1458 // navigation to perform upon attachment. Navigation initializes a lot of |
1466 // state that assumes an embedder exists, such as RenderWidgetHostViewGuest. | 1459 // state that assumes an embedder exists, such as RenderWidgetHostViewGuest. |
1467 // Navigation also resumes resource loading which we don't want to allow | 1460 // Navigation also resumes resource loading which we don't want to allow |
1468 // until attachment. | 1461 // until attachment. |
1469 if (!attached()) { | 1462 if (!attached()) { |
1470 WebViewGuest* opener = GetOpener(); | 1463 WebViewGuest* opener = GetOpener(); |
1471 PendingWindowMap::iterator it = | 1464 PendingWindowMap::iterator it = |
1472 opener->pending_new_windows_.find(this); | 1465 opener->pending_new_windows_.find(this); |
1473 if (it == opener->pending_new_windows_.end()) | 1466 if (it == opener->pending_new_windows_.end()) |
1474 return NULL; | 1467 return NULL; |
1475 const NewWindowInfo& old_target_url = it->second; | 1468 const NewWindowInfo& info = it->second; |
1476 NewWindowInfo new_window_info(params.url, old_target_url.name); | 1469 NewWindowInfo new_window_info(params.url, info.name); |
| 1470 new_window_info.changed = new_window_info.url != info.url; |
1477 it->second = new_window_info; | 1471 it->second = new_window_info; |
1478 return NULL; | 1472 return NULL; |
1479 } | 1473 } |
1480 if (params.disposition == CURRENT_TAB) { | 1474 if (params.disposition == CURRENT_TAB) { |
1481 // This can happen for cross-site redirects. | 1475 // This can happen for cross-site redirects. |
1482 LoadURLWithParams(params.url, params.referrer, params.transition, source); | 1476 LoadURLWithParams(params.url, params.referrer, params.transition, source); |
1483 return source; | 1477 return source; |
1484 } | 1478 } |
1485 | 1479 |
1486 return CreateNewGuestWindow(params)->guest_web_contents(); | 1480 return CreateNewGuestWindow(params)->guest_web_contents(); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1591 bool allow, | 1585 bool allow, |
1592 const std::string& user_input) { | 1586 const std::string& user_input) { |
1593 WebViewGuest* guest = | 1587 WebViewGuest* guest = |
1594 WebViewGuest::From(embedder_render_process_id(), new_window_instance_id); | 1588 WebViewGuest::From(embedder_render_process_id(), new_window_instance_id); |
1595 if (!guest) | 1589 if (!guest) |
1596 return; | 1590 return; |
1597 | 1591 |
1598 if (!allow) | 1592 if (!allow) |
1599 guest->Destroy(); | 1593 guest->Destroy(); |
1600 } | 1594 } |
OLD | NEW |