| 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 |