web_contents_impl.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file. 45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/web_contents/web_contents_impl.h" 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <utility> 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/command_line.h" 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/debug/trace_event.h" 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/lazy_instance.h" 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/logging.h" 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/metrics/histogram.h" 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/metrics/stats_counters.h" 156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/process/process.h" 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/strings/string16.h" 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/strings/string_util.h" 196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/time/time.h" 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/browser_plugin/browser_plugin_embedder.h" 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/browser_plugin/browser_plugin_guest.h" 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/browser_plugin/browser_plugin_guest_manager.h" 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/child_process_security_policy_impl.h" 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/devtools/render_view_devtools_agent_host.h" 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/dom_storage/dom_storage_context_wrapper.h" 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/dom_storage/session_storage_namespace_impl.h" 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/download/download_stats.h" 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/download/mhtml_generation_manager.h" 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/browser/download/save_package.h" 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/browser/frame_host/cross_process_frame_connector.h" 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/browser/frame_host/interstitial_page_impl.h" 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/frame_host/navigation_entry_impl.h" 346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "content/browser/frame_host/navigator_impl.h" 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/frame_host/render_frame_host_impl.h" 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/frame_host/render_widget_host_view_child_frame.h" 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/host_zoom_map_impl.h" 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/loader/resource_dispatcher_host_impl.h" 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/message_port_message_filter.h" 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/message_port_service.h" 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/power_save_blocker_impl.h" 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/renderer_host/render_process_host_impl.h" 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/renderer_host/render_view_host_impl.h" 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/renderer_host/render_widget_host_impl.h" 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/site_instance_impl.h" 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/web_contents/web_contents_view_guest.h" 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/webui/generic_handler.h" 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/webui/web_ui_controller_factory_registry.h" 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/webui/web_ui_impl.h" 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/common/browser_plugin/browser_plugin_constants.h" 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/common/browser_plugin/browser_plugin_messages.h" 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/common/frame_messages.h" 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/common/image_messages.h" 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/common/ssl_status_serialization.h" 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/common/view_messages.h" 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/port/browser/render_view_host_delegate_view.h" 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/port/browser/render_widget_host_view_port.h" 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/ax_event_notification_details.h" 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/browser_context.h" 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/color_chooser.h" 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/content_browser_client.h" 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/devtools_agent_host.h" 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/download_manager.h" 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/download_url_parameters.h" 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/invalidate_type.h" 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/javascript_dialog_manager.h" 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/load_from_memory_cache_details.h" 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/load_notification_details.h" 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/navigation_details.h" 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/notification_details.h" 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/notification_service.h" 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/resource_request_details.h" 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/storage_partition.h" 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/user_metrics.h" 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/web_contents_delegate.h" 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/web_contents_observer.h" 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/web_contents_view.h" 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/common/bindings_policy.h" 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/common/content_constants.h" 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/common/content_switches.h" 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/common/page_zoom.h" 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/common/result_codes.h" 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/common/url_constants.h" 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/common/url_utils.h" 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/base/mime_util.h" 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/base/net_util.h" 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/http/http_cache.h" 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/http/http_transaction_factory.h" 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/url_request/url_request_context.h" 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/url_request/url_request_context_getter.h" 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/base/layout.h" 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/gfx/display.h" 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/gfx/screen.h" 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/gl/gl_switches.h" 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "webkit/common/webpreferences.h" 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_ANDROID) 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/android/date_time_chooser_android.h" 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h" 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/web_contents/web_contents_android.h" 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/common/java_bridge_messages.h" 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/android/content_view_core.h" 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_MACOSX) 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/mac/foundation_util.h" 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/gl/io_surface_support_mac.h" 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Cross-Site Navigations 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// If a WebContentsImpl is told to navigate to a different web site (as 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// determined by SiteInstance), it will replace its current RenderViewHost with 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// a new RenderViewHost dedicated to the new SiteInstance. This works as 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// follows: 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// - RVHM::Navigate determines whether the destination is cross-site, and if so, 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// it creates a pending_render_view_host_. 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// - The pending RVH is "suspended," so that no navigation messages are sent to 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// its renderer until the beforeunload JavaScript handler has a chance to 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// run in the current RVH. 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// - The pending RVH tells CrossSiteRequestManager (a thread-safe singleton) 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// that it has a pending cross-site request. We will check this on the IO 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// thread when deciding how to handle the response. 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// - The current RVH runs its beforeunload handler. If it returns false, we 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// cancel all the pending logic. Otherwise we allow the pending RVH to send 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// the navigation request to its renderer. 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// - ResourceDispatcherHost receives a ResourceRequest on the IO thread for the 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// main resource load on the pending RVH. It creates a 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// CrossSiteResourceHandler to check whether a process swap is needed when 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// the request is ready to commit. 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// - When RDH receives a response, the BufferedResourceHandler determines 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// whether it is a download. If so, it sends a message to the new renderer 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// causing it to cancel the request, and the download proceeds. For now, the 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// pending RVH remains until the next DidNavigate event for this 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// WebContentsImpl. This isn't ideal, but it doesn't affect any functionality. 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// - After RDH receives a response and determines that it is safe and not a 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// download, the CrossSiteResourceHandler checks whether a process swap is 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// needed (either because CrossSiteRequestManager has state for it or because 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// a transfer was needed for a redirect). 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// - If so, CrossSiteResourceHandler pauses the response to first run the old 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// page's unload handler. It does this by asynchronously calling the 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// OnCrossSiteResponse method of RenderFrameHostManager on the UI thread, 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// which sends a SwapOut message to the current RVH. 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// - Once the unload handler is finished, RVHM::SwappedOut checks if a transfer 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// to a new process is needed, based on the stored pending_nav_params_. (This 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// is independent of whether we started out with a cross-process navigation.) 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// - If not, it just tells the ResourceDispatcherHost to resume the response 1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// to its current RenderViewHost. 1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// - If so, it cancels the current pending RenderViewHost and sets up a new 1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// navigation using RequestTransferURL. When the transferred request 1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// arrives in the ResourceDispatcherHost, we transfer the response and 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// resume it. 1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// - The pending renderer sends a FrameNavigate message that invokes the 1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// DidNavigate method. This replaces the current RVH with the 1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// pending RVH. 1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// - The previous renderer is kept swapped out in RenderFrameHostManager in case 1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// the user goes back. The process only stays live if another tab is using 1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// it, but if so, the existing frame relationships will be maintained. 1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace content { 1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace { 1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kDotGoogleDotCom[] = ".google.com"; 1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_ANDROID) 1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kWebContentsAndroidKey[] = "web_contents_android"; 1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif // OS_ANDROID 1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)base::LazyInstance<std::vector<WebContentsImpl::CreatedCallback> > 1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)g_created_callbacks = LAZY_INSTANCE_INITIALIZER; 1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static int StartDownload(content::RenderViewHost* rvh, 1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const GURL& url, 1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool is_favicon, 1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint32_t max_bitmap_size) { 1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) static int g_next_image_download_id = 0; 1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rvh->Send(new ImageMsg_DownloadImage(rvh->GetRoutingID(), 1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ++g_next_image_download_id, 1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) url, 1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_favicon, 1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) max_bitmap_size)); 1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return g_next_image_download_id; 1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void NotifyCacheOnIO( 1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<net::URLRequestContextGetter> request_context, 1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const GURL& url, 1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& http_method) { 1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) request_context->GetURLRequestContext()->http_transaction_factory()-> 1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) GetCache()->OnExternalCacheHit(url, http_method); 1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Helper function for retrieving all the sites in a frame tree. 1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool CollectSites(BrowserContext* context, 1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::set<GURL>* sites, 1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FrameTreeNode* node) { 1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sites->insert(SiteInstance::GetSiteForURL(context, node->current_url())); 1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool ForEachFrameInternal( 2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const base::Callback<void(RenderFrameHost*)>& on_frame, 2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FrameTreeNode* node) { 2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) on_frame.Run(node->current_frame_host()); 2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool ForEachPendingFrameInternal( 2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const base::Callback<void(RenderFrameHost*)>& on_frame, 2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FrameTreeNode* node) { 2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) RenderFrameHost* pending_frame_host = 2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node->render_manager()->pending_frame_host(); 2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (pending_frame_host) 2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) on_frame.Run(pending_frame_host); 2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SendToAllFramesInternal(IPC::Message* message, RenderFrameHost* rfh) { 2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC::Message* message_copy = new IPC::Message(*message); 2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) message_copy->set_routing_id(rfh->GetRoutingID()); 2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rfh->Send(message_copy); 2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void RunRenderFrameDeleted( 2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ObserverList<WebContentsObserver>* observer_list, 2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) RenderFrameHost* render_frame_host) { 2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FOR_EACH_OBSERVER(WebContentsObserver, 2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) *observer_list, 2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) RenderFrameDeleted(render_frame_host)); 2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} // namespace 2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)WebContents* WebContents::Create(const WebContents::CreateParams& params) { 2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return WebContentsImpl::CreateWithOpener( 2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) params, static_cast<WebContentsImpl*>(params.opener)); 2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)WebContents* WebContents::CreateWithSessionStorage( 2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const WebContents::CreateParams& params, 2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const SessionStorageNamespaceMap& session_storage_namespace_map) { 2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebContentsImpl* new_contents = new WebContentsImpl( 2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) params.browser_context, NULL); 2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (SessionStorageNamespaceMap::const_iterator it = 2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) session_storage_namespace_map.begin(); 2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) it != session_storage_namespace_map.end(); 2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ++it) { 2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new_contents->GetController() 2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) .SetSessionStorageNamespace(it->first, it->second.get()); 2525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new_contents->Init(params); 2555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return new_contents; 2565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void WebContentsImpl::AddCreatedCallback(const CreatedCallback& callback) { 2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) g_created_callbacks.Get().push_back(callback); 2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void WebContentsImpl::RemoveCreatedCallback(const CreatedCallback& callback) { 2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (size_t i = 0; i < g_created_callbacks.Get().size(); ++i) { 2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (g_created_callbacks.Get().at(i).Equals(callback)) { 2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) g_created_callbacks.Get().erase(g_created_callbacks.Get().begin() + i); 2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 2675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)WebContents* WebContents::FromRenderViewHost(const RenderViewHost* rvh) { 2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return rvh->GetDelegate()->GetAsWebContents(); 2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)WebContents* WebContents::FromRenderFrameHost(RenderFrameHost* rfh) { 2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) RenderFrameHostImpl* rfh_impl = static_cast<RenderFrameHostImpl*>(rfh); 2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!rfh_impl) 2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return NULL; 2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return rfh_impl->delegate()->GetAsWebContents(); 2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// WebContentsImpl::DestructionObserver ---------------------------------------- 2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class WebContentsImpl::DestructionObserver : public WebContentsObserver { 2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public: 2865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DestructionObserver(WebContentsImpl* owner, WebContents* watched_contents) 2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : WebContentsObserver(watched_contents), 2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) owner_(owner) { 2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // WebContentsObserver: 2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE { 2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) owner_->OnWebContentsDestroyed(static_cast<WebContentsImpl*>(web_contents)); 2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private: 2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebContentsImpl* owner_; 2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(DestructionObserver); 3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 3015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// WebContentsImpl ------------------------------------------------------------- 3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)WebContentsImpl::WebContentsImpl( 3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) BrowserContext* browser_context, 3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebContentsImpl* opener) 3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : delegate_(NULL), 3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) controller_(this, browser_context), 3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci render_view_host_delegate_view_(NULL), 3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) opener_(opener), 3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_WIN) 3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) accessible_parent_(NULL), 3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 3145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) frame_tree_(new NavigatorImpl(&controller_, this), 3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this, this, this, this), 3165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_loading_(false), 3175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING), 3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) crashed_error_code_(0), 3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) waiting_for_response_(false), 3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) load_state_(net::LOAD_STATE_IDLE, base::string16()), 3215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) upload_size_(0), 3225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) upload_position_(0), 3235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) displayed_insecure_content_(false), 3245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) capturer_count_(0), 3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) should_normally_be_visible_(true), 3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_being_destroyed_(false), 3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) notify_disconnection_(false), 3285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dialog_manager_(NULL), 3295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_showing_before_unload_dialog_(false), 3305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) last_active_time_(base::TimeTicks::Now()), 3315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) closed_by_user_gesture_(false), 3325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) minimum_zoom_percent_(static_cast<int>(kMinimumZoomFactor * 100)), 3335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) maximum_zoom_percent_(static_cast<int>(kMaximumZoomFactor * 100)), 3345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temporary_zoom_settings_(false), 3355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) color_chooser_identifier_(0), 3365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) render_view_message_source_(NULL), 3375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) fullscreen_widget_routing_id_(MSG_ROUTING_NONE), 3385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_subframe_(false) { 3395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (size_t i = 0; i < g_created_callbacks.Get().size(); i++) 3405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) g_created_callbacks.Get().at(i).Run(this); 3415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) frame_tree_.SetFrameRemoveListener( 3425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&WebContentsImpl::OnFrameRemoved, 3435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Unretained(this))); 3445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)WebContentsImpl::~WebContentsImpl() { 3475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_being_destroyed_ = true; 3485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Delete all RFH pending shutdown, which will lead the corresponding RVH to 3505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // shutdown and be deleted as well. 3515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) frame_tree_.ForEach( 3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&RenderFrameHostManager::ClearRFHsPendingShutdown)); 3535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ClearAllPowerSaveBlockers(); 3555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (std::set<RenderWidgetHostImpl*>::iterator iter = 3575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) created_widgets_.begin(); iter != created_widgets_.end(); ++iter) { 3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) (*iter)->DetachDelegate(); 3595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) created_widgets_.clear(); 3615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Clear out any JavaScript state. 3635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (dialog_manager_) 3645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dialog_manager_->WebContentsDestroyed(this); 3655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (color_chooser_) 3675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) color_chooser_->End(); 3685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NotifyDisconnected(); 3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Notify any observer that have a reference on this WebContents. 3725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NotificationService::current()->Notify( 3735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NOTIFICATION_WEB_CONTENTS_DESTROYED, 3745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Source<WebContents>(this), 3755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NotificationService::NoDetails()); 3765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Callback<void(RenderFrameHost*)> run_render_frame_deleted_callback = 3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&RunRenderFrameDeleted, base::Unretained(&observers_)); 3795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) frame_tree_.ForEach(base::Bind(&ForEachPendingFrameInternal, 3805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) run_render_frame_deleted_callback)); 3815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) RenderViewHost* pending_rvh = GetRenderManager()->pending_render_view_host(); 3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (pending_rvh) { 3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FOR_EACH_OBSERVER(WebContentsObserver, 3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) observers_, 3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) RenderViewDeleted(pending_rvh)); 3875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ForEachFrame(run_render_frame_deleted_callback); 3905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FOR_EACH_OBSERVER(WebContentsObserver, 3925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) observers_, 3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) RenderViewDeleted(GetRenderManager()->current_host())); 3945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FOR_EACH_OBSERVER(WebContentsObserver, 3965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) observers_, 3975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebContentsImplDestroyed()); 3985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SetDelegate(NULL); 4005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) STLDeleteContainerPairSecondPointers(destruction_observers_.begin(), 4021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci destruction_observers_.end()); 4035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 4045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)WebContentsImpl* WebContentsImpl::CreateWithOpener( 4065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const WebContents::CreateParams& params, 4075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebContentsImpl* opener) { 4085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) TRACE_EVENT0("browser", "WebContentsImpl::CreateWithOpener"); 4095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebContentsImpl* new_contents = new WebContentsImpl( 4105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) params.browser_context, opener); 4115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new_contents->Init(params); 4135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return new_contents; 4145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 4155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// static 4175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)BrowserPluginGuest* WebContentsImpl::CreateGuest( 4185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) BrowserContext* browser_context, 4195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SiteInstance* site_instance, 4205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int guest_instance_id, 4215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<base::DictionaryValue> extra_params) { 4225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebContentsImpl* new_contents = new WebContentsImpl(browser_context, NULL); 4235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // This makes |new_contents| act as a guest. 4255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // For more info, see comment above class BrowserPluginGuest. 4265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) BrowserPluginGuest::Create( 4275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) guest_instance_id, site_instance, new_contents, extra_params.Pass()); 4285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebContents::CreateParams create_params(browser_context, site_instance); 4305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new_contents->Init(create_params); 4315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // We are instantiating a WebContents for browser plugin. Set its subframe bit 4335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // to true. 4345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new_contents->is_subframe_ = true; 4355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return new_contents->browser_plugin_guest_.get(); 4375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 4385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)RenderFrameHostManager* WebContentsImpl::GetRenderManagerForTesting() { 4405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return GetRenderManager(); 4415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 4425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host, 4445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const IPC::Message& message) { 4455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return OnMessageReceived(render_view_host, NULL, message); 4465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 4475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host, 4495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) RenderFrameHost* render_frame_host, 4505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const IPC::Message& message) { 4515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(render_view_host || render_frame_host); 4525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (GetWebUI() && 4535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) static_cast<WebUIImpl*>(GetWebUI())->OnMessageReceived(message)) { 4545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 4555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ObserverListBase<WebContentsObserver>::Iterator it(observers_); 4585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebContentsObserver* observer; 4595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while ((observer = it.GetNext()) != NULL) 4605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (observer->OnMessageReceived(message)) 4615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 4625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Message handlers should be aware of which 4645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // RenderViewHost/RenderFrameHost sent the message, which is temporarily 4655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // stored in render_(view|frame)_message_source_. 4665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (render_frame_host) { 4675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (RenderViewDevToolsAgentHost::DispatchIPCMessage( 4685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) render_frame_host->GetRenderViewHost(), message)) 4695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 4705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) render_frame_message_source_ = render_frame_host; 4715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 4725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (RenderViewDevToolsAgentHost::DispatchIPCMessage( 4735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) render_view_host, message)) 4745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 4755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) render_view_message_source_ = render_view_host; 4765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool handled = true; 4795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool message_is_ok = true; 4805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_BEGIN_MESSAGE_MAP_EX(WebContentsImpl, message, message_is_ok) 4815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(FrameHostMsg_PepperPluginHung, OnPepperPluginHung) 4825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(FrameHostMsg_PluginCrashed, OnPluginCrashed) 4835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(FrameHostMsg_DomOperationResponse, 4845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnDomOperationResponse) 4855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache, 4865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnDidLoadResourceFromMemoryCache) 4875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(ViewHostMsg_DidDisplayInsecureContent, 4885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnDidDisplayInsecureContent) 4895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(ViewHostMsg_DidRunInsecureContent, 4905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnDidRunInsecureContent) 4915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(FrameHostMsg_DidFinishDocumentLoad, 4925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnDocumentLoadedInFrame) 4935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(FrameHostMsg_DidFinishLoad, OnDidFinishLoad) 4945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(ViewHostMsg_GoToEntryAtOffset, OnGoToEntryAtOffset) 4955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateZoomLimits, OnUpdateZoomLimits) 4965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(ViewHostMsg_EnumerateDirectory, OnEnumerateDirectory) 4975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(ViewHostMsg_RegisterProtocolHandler, 4985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnRegisterProtocolHandler) 4995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(ViewHostMsg_Find_Reply, OnFindReply) 5005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(ViewHostMsg_AppCacheAccessed, OnAppCacheAccessed) 5015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(ViewHostMsg_OpenColorChooser, OnOpenColorChooser) 5025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(ViewHostMsg_EndColorChooser, OnEndColorChooser) 50303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) IPC_MESSAGE_HANDLER(ViewHostMsg_SetSelectedColorInColorChooser, 5045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnSetSelectedColorInColorChooser) 5055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(ViewHostMsg_WebUISend, OnWebUISend) 5065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(ViewHostMsg_RequestPpapiBrokerPermission, 5075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnRequestPpapiBrokerPermission) 5085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginHostMsg_AllocateInstanceID, 5095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnBrowserPluginMessage(message)) 5105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginHostMsg_Attach, 51103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) OnBrowserPluginMessage(message)) 5125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(ImageHostMsg_DidDownloadImage, OnDidDownloadImage) 5135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFaviconURL, OnUpdateFaviconURL) 5145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_ANDROID) 5155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(ViewHostMsg_FindMatchRects_Reply, 5165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnFindMatchRectsReply) 5175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(ViewHostMsg_OpenDateTimeDialog, 5185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnOpenDateTimeDialog) 5195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER_DELAY_REPLY(JavaBridgeHostMsg_GetChannelHandle, 5205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnJavaBridgeGetChannelHandle) 5215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 5225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(ViewHostMsg_MediaPlayingNotification, 5235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnMediaPlayingNotification) 5245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(ViewHostMsg_MediaPausedNotification, 5255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnMediaPausedNotification) 5265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(ViewHostMsg_DidFirstVisuallyNonEmptyPaint, 5275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnFirstVisuallyNonEmptyPaint) 5285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC_MESSAGE_HANDLER(ViewHostMsg_ShowValidationMessage, 5295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnShowValidationMessage) 5301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_MESSAGE_HANDLER(ViewHostMsg_HideValidationMessage, 5315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnHideValidationMessage) 5321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_MESSAGE_HANDLER(ViewHostMsg_MoveValidationMessage, 5331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OnMoveValidationMessage) 5341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_MESSAGE_UNHANDLED(handled = false) 5351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPC_END_MESSAGE_MAP_EX() 5365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) render_view_message_source_ = NULL; 5375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) render_frame_message_source_ = NULL; 5385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 539 if (!message_is_ok) { 540 RecordAction(base::UserMetricsAction("BadMessageTerminate_RVD")); 541 GetRenderProcessHost()->ReceivedBadMessage(); 542 } 543 544 return handled; 545} 546 547void WebContentsImpl::RunFileChooser( 548 RenderViewHost* render_view_host, 549 const FileChooserParams& params) { 550 if (delegate_) 551 delegate_->RunFileChooser(this, params); 552} 553 554NavigationControllerImpl& WebContentsImpl::GetController() { 555 return controller_; 556} 557 558const NavigationControllerImpl& WebContentsImpl::GetController() const { 559 return controller_; 560} 561 562BrowserContext* WebContentsImpl::GetBrowserContext() const { 563 return controller_.GetBrowserContext(); 564} 565 566const GURL& WebContentsImpl::GetURL() const { 567 // We may not have a navigation entry yet. 568 NavigationEntry* entry = controller_.GetVisibleEntry(); 569 return entry ? entry->GetVirtualURL() : GURL::EmptyGURL(); 570} 571 572const GURL& WebContentsImpl::GetVisibleURL() const { 573 // We may not have a navigation entry yet. 574 NavigationEntry* entry = controller_.GetVisibleEntry(); 575 return entry ? entry->GetVirtualURL() : GURL::EmptyGURL(); 576} 577 578const GURL& WebContentsImpl::GetLastCommittedURL() const { 579 // We may not have a navigation entry yet. 580 NavigationEntry* entry = controller_.GetLastCommittedEntry(); 581 return entry ? entry->GetVirtualURL() : GURL::EmptyGURL(); 582} 583 584WebContentsDelegate* WebContentsImpl::GetDelegate() { 585 return delegate_; 586} 587 588void WebContentsImpl::SetDelegate(WebContentsDelegate* delegate) { 589 // TODO(cbentzel): remove this debugging code? 590 if (delegate == delegate_) 591 return; 592 if (delegate_) 593 delegate_->Detach(this); 594 delegate_ = delegate; 595 if (delegate_) { 596 delegate_->Attach(this); 597 // Ensure the visible RVH reflects the new delegate's preferences. 598 if (view_) 599 view_->SetOverscrollControllerEnabled(delegate->CanOverscrollContent()); 600 } 601} 602 603RenderProcessHost* WebContentsImpl::GetRenderProcessHost() const { 604 RenderViewHostImpl* host = GetRenderManager()->current_host(); 605 return host ? host->GetProcess() : NULL; 606} 607 608RenderFrameHost* WebContentsImpl::GetMainFrame() { 609 return frame_tree_.root()->current_frame_host(); 610} 611 612RenderFrameHost* WebContentsImpl::GetFocusedFrame() { 613 if (!frame_tree_.GetFocusedFrame()) 614 return NULL; 615 return frame_tree_.GetFocusedFrame()->current_frame_host(); 616} 617 618void WebContentsImpl::ForEachFrame( 619 const base::Callback<void(RenderFrameHost*)>& on_frame) { 620 frame_tree_.ForEach(base::Bind(&ForEachFrameInternal, on_frame)); 621} 622 623void WebContentsImpl::SendToAllFrames(IPC::Message* message) { 624 ForEachFrame(base::Bind(&SendToAllFramesInternal, message)); 625 delete message; 626} 627 628RenderViewHost* WebContentsImpl::GetRenderViewHost() const { 629 return GetRenderManager()->current_host(); 630} 631 632WebContents* WebContentsImpl::GetEmbedderWebContents() const { 633 BrowserPluginGuest* guest = GetBrowserPluginGuest(); 634 if (guest) 635 return guest->embedder_web_contents(); 636 return NULL; 637} 638 639int WebContentsImpl::GetEmbeddedInstanceID() const { 640 BrowserPluginGuest* guest = GetBrowserPluginGuest(); 641 if (guest) 642 return guest->instance_id(); 643 return 0; 644} 645 646int WebContentsImpl::GetRoutingID() const { 647 if (!GetRenderViewHost()) 648 return MSG_ROUTING_NONE; 649 650 return GetRenderViewHost()->GetRoutingID(); 651} 652 653int WebContentsImpl::GetFullscreenWidgetRoutingID() const { 654 return fullscreen_widget_routing_id_; 655} 656 657RenderWidgetHostView* WebContentsImpl::GetRenderWidgetHostView() const { 658 return GetRenderManager()->GetRenderWidgetHostView(); 659} 660 661RenderWidgetHostViewPort* WebContentsImpl::GetRenderWidgetHostViewPort() const { 662 BrowserPluginGuest* guest = GetBrowserPluginGuest(); 663 if (guest && guest->embedder_web_contents()) { 664 return guest->embedder_web_contents()->GetRenderWidgetHostViewPort(); 665 } 666 return RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView()); 667} 668 669RenderWidgetHostView* WebContentsImpl::GetFullscreenRenderWidgetHostView() 670 const { 671 RenderWidgetHost* const widget_host = 672 RenderWidgetHostImpl::FromID(GetRenderProcessHost()->GetID(), 673 GetFullscreenWidgetRoutingID()); 674 return widget_host ? widget_host->GetView() : NULL; 675} 676 677WebContentsView* WebContentsImpl::GetView() const { 678 return view_.get(); 679} 680 681WebUI* WebContentsImpl::CreateWebUI(const GURL& url) { 682 WebUIImpl* web_ui = new WebUIImpl(this); 683 WebUIController* controller = WebUIControllerFactoryRegistry::GetInstance()-> 684 CreateWebUIControllerForURL(web_ui, url); 685 if (controller) { 686 web_ui->AddMessageHandler(new GenericHandler()); 687 web_ui->SetController(controller); 688 return web_ui; 689 } 690 691 delete web_ui; 692 return NULL; 693} 694 695WebUI* WebContentsImpl::GetWebUI() const { 696 return GetRenderManager()->web_ui() ? GetRenderManager()->web_ui() 697 : GetRenderManager()->pending_web_ui(); 698} 699 700WebUI* WebContentsImpl::GetCommittedWebUI() const { 701 return GetRenderManager()->web_ui(); 702} 703 704void WebContentsImpl::SetUserAgentOverride(const std::string& override) { 705 if (GetUserAgentOverride() == override) 706 return; 707 708 renderer_preferences_.user_agent_override = override; 709 710 // Send the new override string to the renderer. 711 RenderViewHost* host = GetRenderViewHost(); 712 if (host) 713 host->SyncRendererPrefs(); 714 715 // Reload the page if a load is currently in progress to avoid having 716 // different parts of the page loaded using different user agents. 717 NavigationEntry* entry = controller_.GetVisibleEntry(); 718 if (is_loading_ && entry != NULL && entry->GetIsOverridingUserAgent()) 719 controller_.ReloadIgnoringCache(true); 720 721 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 722 UserAgentOverrideSet(override)); 723} 724 725const std::string& WebContentsImpl::GetUserAgentOverride() const { 726 return renderer_preferences_.user_agent_override; 727} 728 729#if defined(OS_WIN) 730void WebContentsImpl::SetParentNativeViewAccessible( 731gfx::NativeViewAccessible accessible_parent) { 732 accessible_parent_ = accessible_parent; 733 if (GetRenderViewHost()) 734 GetRenderViewHostImpl()->SetParentNativeViewAccessible(accessible_parent); 735} 736#endif 737 738const base::string16& WebContentsImpl::GetTitle() const { 739 // Transient entries take precedence. They are used for interstitial pages 740 // that are shown on top of existing pages. 741 NavigationEntry* entry = controller_.GetTransientEntry(); 742 std::string accept_languages = 743 GetContentClient()->browser()->GetAcceptLangs( 744 GetBrowserContext()); 745 if (entry) { 746 return entry->GetTitleForDisplay(accept_languages); 747 } 748 WebUI* our_web_ui = GetRenderManager()->pending_web_ui() ? 749 GetRenderManager()->pending_web_ui() : GetRenderManager()->web_ui(); 750 if (our_web_ui) { 751 // Don't override the title in view source mode. 752 entry = controller_.GetVisibleEntry(); 753 if (!(entry && entry->IsViewSourceMode())) { 754 // Give the Web UI the chance to override our title. 755 const base::string16& title = our_web_ui->GetOverriddenTitle(); 756 if (!title.empty()) 757 return title; 758 } 759 } 760 761 // We use the title for the last committed entry rather than a pending 762 // navigation entry. For example, when the user types in a URL, we want to 763 // keep the old page's title until the new load has committed and we get a new 764 // title. 765 entry = controller_.GetLastCommittedEntry(); 766 767 // We make an exception for initial navigations. 768 if (controller_.IsInitialNavigation()) { 769 // We only want to use the title from the visible entry in one of two cases: 770 // 1. There's already a committed entry for an initial navigation, in which 771 // case we are doing a history navigation in a new tab (e.g., Ctrl+Back). 772 // 2. The pending entry has been explicitly assigned a title to display. 773 // 774 // If there's no last committed entry and no assigned title, we should fall 775 // back to |page_title_when_no_navigation_entry_| rather than showing the 776 // URL. 777 if (entry || 778 (controller_.GetVisibleEntry() && 779 !controller_.GetVisibleEntry()->GetTitle().empty())) { 780 entry = controller_.GetVisibleEntry(); 781 } 782 } 783 784 if (entry) { 785 return entry->GetTitleForDisplay(accept_languages); 786 } 787 788 // |page_title_when_no_navigation_entry_| is finally used 789 // if no title cannot be retrieved. 790 return page_title_when_no_navigation_entry_; 791} 792 793int32 WebContentsImpl::GetMaxPageID() { 794 return GetMaxPageIDForSiteInstance(GetSiteInstance()); 795} 796 797int32 WebContentsImpl::GetMaxPageIDForSiteInstance( 798 SiteInstance* site_instance) { 799 if (max_page_ids_.find(site_instance->GetId()) == max_page_ids_.end()) 800 max_page_ids_[site_instance->GetId()] = -1; 801 802 return max_page_ids_[site_instance->GetId()]; 803} 804 805void WebContentsImpl::UpdateMaxPageID(int32 page_id) { 806 UpdateMaxPageIDForSiteInstance(GetSiteInstance(), page_id); 807} 808 809void WebContentsImpl::UpdateMaxPageIDForSiteInstance( 810 SiteInstance* site_instance, int32 page_id) { 811 if (GetMaxPageIDForSiteInstance(site_instance) < page_id) 812 max_page_ids_[site_instance->GetId()] = page_id; 813} 814 815void WebContentsImpl::CopyMaxPageIDsFrom(WebContents* web_contents) { 816 WebContentsImpl* contents = static_cast<WebContentsImpl*>(web_contents); 817 max_page_ids_ = contents->max_page_ids_; 818} 819 820SiteInstance* WebContentsImpl::GetSiteInstance() const { 821 return GetRenderManager()->current_host()->GetSiteInstance(); 822} 823 824SiteInstance* WebContentsImpl::GetPendingSiteInstance() const { 825 RenderViewHost* dest_rvh = GetRenderManager()->pending_render_view_host() ? 826 GetRenderManager()->pending_render_view_host() : 827 GetRenderManager()->current_host(); 828 return dest_rvh->GetSiteInstance(); 829} 830 831bool WebContentsImpl::IsLoading() const { 832 return is_loading_; 833} 834 835bool WebContentsImpl::IsWaitingForResponse() const { 836 return waiting_for_response_; 837} 838 839const net::LoadStateWithParam& WebContentsImpl::GetLoadState() const { 840 return load_state_; 841} 842 843const base::string16& WebContentsImpl::GetLoadStateHost() const { 844 return load_state_host_; 845} 846 847uint64 WebContentsImpl::GetUploadSize() const { 848 return upload_size_; 849} 850 851uint64 WebContentsImpl::GetUploadPosition() const { 852 return upload_position_; 853} 854 855std::set<GURL> WebContentsImpl::GetSitesInTab() const { 856 std::set<GURL> sites; 857 frame_tree_.ForEach(base::Bind(&CollectSites, 858 base::Unretained(GetBrowserContext()), 859 base::Unretained(&sites))); 860 return sites; 861} 862 863const std::string& WebContentsImpl::GetEncoding() const { 864 return encoding_; 865} 866 867bool WebContentsImpl::DisplayedInsecureContent() const { 868 return displayed_insecure_content_; 869} 870 871void WebContentsImpl::IncrementCapturerCount(const gfx::Size& capture_size) { 872 DCHECK(!is_being_destroyed_); 873 ++capturer_count_; 874 DVLOG(1) << "There are now " << capturer_count_ 875 << " capturing(s) of WebContentsImpl@" << this; 876 877 // Note: This provides a hint to upstream code to size the views optimally 878 // for quality (e.g., to avoid scaling). 879 if (!capture_size.IsEmpty() && preferred_size_for_capture_.IsEmpty()) { 880 preferred_size_for_capture_ = capture_size; 881 OnPreferredSizeChanged(preferred_size_); 882 } 883} 884 885void WebContentsImpl::DecrementCapturerCount() { 886 --capturer_count_; 887 DVLOG(1) << "There are now " << capturer_count_ 888 << " capturing(s) of WebContentsImpl@" << this; 889 DCHECK_LE(0, capturer_count_); 890 891 if (is_being_destroyed_) 892 return; 893 894 if (capturer_count_ == 0) { 895 const gfx::Size old_size = preferred_size_for_capture_; 896 preferred_size_for_capture_ = gfx::Size(); 897 OnPreferredSizeChanged(old_size); 898 } 899 900 if (IsHidden()) { 901 DVLOG(1) << "Executing delayed WasHidden()."; 902 WasHidden(); 903 } 904} 905 906int WebContentsImpl::GetCapturerCount() const { 907 return capturer_count_; 908} 909 910bool WebContentsImpl::IsCrashed() const { 911 return (crashed_status_ == base::TERMINATION_STATUS_PROCESS_CRASHED || 912 crashed_status_ == base::TERMINATION_STATUS_ABNORMAL_TERMINATION || 913 crashed_status_ == base::TERMINATION_STATUS_PROCESS_WAS_KILLED); 914} 915 916void WebContentsImpl::SetIsCrashed(base::TerminationStatus status, 917 int error_code) { 918 if (status == crashed_status_) 919 return; 920 921 crashed_status_ = status; 922 crashed_error_code_ = error_code; 923 NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB); 924} 925 926base::TerminationStatus WebContentsImpl::GetCrashedStatus() const { 927 return crashed_status_; 928} 929 930bool WebContentsImpl::IsBeingDestroyed() const { 931 return is_being_destroyed_; 932} 933 934void WebContentsImpl::NotifyNavigationStateChanged(unsigned changed_flags) { 935 if (delegate_) 936 delegate_->NavigationStateChanged(this, changed_flags); 937} 938 939base::TimeTicks WebContentsImpl::GetLastActiveTime() const { 940 return last_active_time_; 941} 942 943void WebContentsImpl::WasShown() { 944 controller_.SetActive(true); 945 RenderWidgetHostViewPort* rwhv = 946 RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView()); 947 if (rwhv) { 948 rwhv->Show(); 949#if defined(OS_MACOSX) 950 rwhv->SetActive(true); 951#endif 952 } 953 954 last_active_time_ = base::TimeTicks::Now(); 955 956 // The resize rect might have changed while this was inactive -- send the new 957 // one to make sure it's up to date. 958 RenderViewHostImpl* rvh = 959 static_cast<RenderViewHostImpl*>(GetRenderViewHost()); 960 if (rvh) { 961 rvh->ResizeRectChanged(GetRootWindowResizerRect()); 962 } 963 964 FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasShown()); 965 966 should_normally_be_visible_ = true; 967} 968 969void WebContentsImpl::WasHidden() { 970 // If there are entities capturing screenshots or video (e.g., mirroring), 971 // don't activate the "disable rendering" optimization. 972 if (capturer_count_ == 0) { 973 // |GetRenderViewHost()| can be NULL if the user middle clicks a link to 974 // open a tab in the background, then closes the tab before selecting it. 975 // This is because closing the tab calls WebContentsImpl::Destroy(), which 976 // removes the |GetRenderViewHost()|; then when we actually destroy the 977 // window, OnWindowPosChanged() notices and calls WasHidden() (which 978 // calls us). 979 RenderWidgetHostViewPort* rwhv = 980 RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView()); 981 if (rwhv) 982 rwhv->Hide(); 983 } 984 985 FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasHidden()); 986 987 should_normally_be_visible_ = false; 988} 989 990bool WebContentsImpl::NeedToFireBeforeUnload() { 991 // TODO(creis): Should we fire even for interstitial pages? 992 return WillNotifyDisconnection() && 993 !ShowingInterstitialPage() && 994 !static_cast<RenderViewHostImpl*>( 995 GetRenderViewHost())->SuddenTerminationAllowed(); 996} 997 998void WebContentsImpl::Stop() { 999 GetRenderManager()->Stop(); 1000 FOR_EACH_OBSERVER(WebContentsObserver, observers_, NavigationStopped()); 1001} 1002 1003WebContents* WebContentsImpl::Clone() { 1004 // We use our current SiteInstance since the cloned entry will use it anyway. 1005 // We pass our own opener so that the cloned page can access it if it was 1006 // before. 1007 CreateParams create_params(GetBrowserContext(), GetSiteInstance()); 1008 create_params.initial_size = view_->GetContainerSize(); 1009 WebContentsImpl* tc = CreateWithOpener(create_params, opener_); 1010 tc->GetController().CopyStateFrom(controller_); 1011 FOR_EACH_OBSERVER(WebContentsObserver, 1012 observers_, 1013 DidCloneToNewWebContents(this, tc)); 1014 return tc; 1015} 1016 1017void WebContentsImpl::Observe(int type, 1018 const NotificationSource& source, 1019 const NotificationDetails& details) { 1020 switch (type) { 1021 case NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED: { 1022 RenderWidgetHost* host = Source<RenderWidgetHost>(source).ptr(); 1023 for (PendingWidgetViews::iterator i = pending_widget_views_.begin(); 1024 i != pending_widget_views_.end(); ++i) { 1025 if (host->GetView() == i->second) { 1026 pending_widget_views_.erase(i); 1027 break; 1028 } 1029 } 1030 break; 1031 } 1032 default: 1033 NOTREACHED(); 1034 } 1035} 1036 1037WebContents* WebContentsImpl::GetWebContents() { 1038 return this; 1039} 1040 1041void WebContentsImpl::Init(const WebContents::CreateParams& params) { 1042 // This is set before initializing the render manager since 1043 // RenderFrameHostManager::Init calls back into us via its delegate to ask if 1044 // it should be hidden. 1045 should_normally_be_visible_ = !params.initially_hidden; 1046 1047 GetRenderManager()->Init( 1048 params.browser_context, params.site_instance, params.routing_id, 1049 params.main_frame_routing_id); 1050 1051 view_.reset(GetContentClient()->browser()-> 1052 OverrideCreateWebContentsView(this, &render_view_host_delegate_view_)); 1053 if (view_) { 1054 CHECK(render_view_host_delegate_view_); 1055 } else { 1056 WebContentsViewDelegate* delegate = 1057 GetContentClient()->browser()->GetWebContentsViewDelegate(this); 1058 1059 if (browser_plugin_guest_) { 1060 scoped_ptr<WebContentsViewPort> platform_view(CreateWebContentsView( 1061 this, delegate, &render_view_host_delegate_view_)); 1062 1063 WebContentsViewGuest* rv = new WebContentsViewGuest( 1064 this, browser_plugin_guest_.get(), platform_view.Pass(), 1065 render_view_host_delegate_view_); 1066 render_view_host_delegate_view_ = rv; 1067 view_.reset(rv); 1068 } else { 1069 // Regular WebContentsView. 1070 view_.reset(CreateWebContentsView( 1071 this, delegate, &render_view_host_delegate_view_)); 1072 } 1073 CHECK(render_view_host_delegate_view_); 1074 } 1075 CHECK(view_.get()); 1076 1077 gfx::Size initial_size = params.initial_size; 1078 view_->CreateView(initial_size, params.context); 1079 1080 // Listen for whether our opener gets destroyed. 1081 if (opener_) 1082 AddDestructionObserver(opener_); 1083 1084 registrar_.Add(this, 1085 NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED, 1086 NotificationService::AllBrowserContextsAndSources()); 1087#if defined(OS_ANDROID) 1088 java_bridge_dispatcher_host_manager_.reset( 1089 new JavaBridgeDispatcherHostManager(this)); 1090 date_time_chooser_.reset(new DateTimeChooserAndroid()); 1091#endif 1092} 1093 1094void WebContentsImpl::OnWebContentsDestroyed(WebContentsImpl* web_contents) { 1095 RemoveDestructionObserver(web_contents); 1096 1097 // Clear the opener if it has been closed. 1098 if (web_contents == opener_) { 1099 opener_ = NULL; 1100 return; 1101 } 1102 // Clear a pending contents that has been closed before being shown. 1103 for (PendingContents::iterator iter = pending_contents_.begin(); 1104 iter != pending_contents_.end(); 1105 ++iter) { 1106 if (iter->second != web_contents) 1107 continue; 1108 pending_contents_.erase(iter); 1109 return; 1110 } 1111 NOTREACHED(); 1112} 1113 1114void WebContentsImpl::AddDestructionObserver(WebContentsImpl* web_contents) { 1115 if (!ContainsKey(destruction_observers_, web_contents)) { 1116 destruction_observers_[web_contents] = 1117 new DestructionObserver(this, web_contents); 1118 } 1119} 1120 1121void WebContentsImpl::RemoveDestructionObserver(WebContentsImpl* web_contents) { 1122 DestructionObservers::iterator iter = 1123 destruction_observers_.find(web_contents); 1124 if (iter != destruction_observers_.end()) { 1125 delete destruction_observers_[web_contents]; 1126 destruction_observers_.erase(iter); 1127 } 1128} 1129 1130void WebContentsImpl::AddObserver(WebContentsObserver* observer) { 1131 observers_.AddObserver(observer); 1132} 1133 1134void WebContentsImpl::RemoveObserver(WebContentsObserver* observer) { 1135 observers_.RemoveObserver(observer); 1136} 1137 1138void WebContentsImpl::Activate() { 1139 if (delegate_) 1140 delegate_->ActivateContents(this); 1141} 1142 1143void WebContentsImpl::Deactivate() { 1144 if (delegate_) 1145 delegate_->DeactivateContents(this); 1146} 1147 1148void WebContentsImpl::LostCapture() { 1149 if (delegate_) 1150 delegate_->LostCapture(); 1151} 1152 1153void WebContentsImpl::RenderWidgetDeleted( 1154 RenderWidgetHostImpl* render_widget_host) { 1155 if (is_being_destroyed_) { 1156 // |created_widgets_| might have been destroyed. 1157 return; 1158 } 1159 1160 std::set<RenderWidgetHostImpl*>::iterator iter = 1161 created_widgets_.find(render_widget_host); 1162 if (iter != created_widgets_.end()) 1163 created_widgets_.erase(iter); 1164 1165 if (render_widget_host && 1166 render_widget_host->GetRoutingID() == fullscreen_widget_routing_id_) { 1167 if (delegate_ && delegate_->EmbedsFullscreenWidget()) 1168 delegate_->ToggleFullscreenModeForTab(this, false); 1169 FOR_EACH_OBSERVER(WebContentsObserver, 1170 observers_, 1171 DidDestroyFullscreenWidget( 1172 fullscreen_widget_routing_id_)); 1173 fullscreen_widget_routing_id_ = MSG_ROUTING_NONE; 1174 } 1175} 1176 1177bool WebContentsImpl::PreHandleKeyboardEvent( 1178 const NativeWebKeyboardEvent& event, 1179 bool* is_keyboard_shortcut) { 1180 return delegate_ && 1181 delegate_->PreHandleKeyboardEvent(this, event, is_keyboard_shortcut); 1182} 1183 1184void WebContentsImpl::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) { 1185 if (browser_plugin_embedder_ && 1186 browser_plugin_embedder_->HandleKeyboardEvent(event)) { 1187 return; 1188 } 1189 1190 if (delegate_) 1191 delegate_->HandleKeyboardEvent(this, event); 1192} 1193 1194bool WebContentsImpl::HandleWheelEvent( 1195 const blink::WebMouseWheelEvent& event) { 1196#if !defined(OS_MACOSX) 1197 // On platforms other than Mac, control+mousewheel changes zoom. On Mac, this 1198 // isn't done for two reasons: 1199 // -the OS already has a gesture to do this through pinch-zoom 1200 // -if a user starts an inertial scroll, let's go, and presses control 1201 // (i.e. control+tab) then the OS's buffered scroll events will come in 1202 // with control key set which isn't what the user wants 1203 if (delegate_ && 1204 event.wheelTicksY && 1205 (event.modifiers & blink::WebInputEvent::ControlKey)) { 1206 delegate_->ContentsZoomChange(event.wheelTicksY > 0); 1207 return true; 1208 } 1209#endif 1210 return false; 1211} 1212 1213bool WebContentsImpl::PreHandleGestureEvent( 1214 const blink::WebGestureEvent& event) { 1215 return delegate_ && delegate_->PreHandleGestureEvent(this, event); 1216} 1217 1218#if defined(OS_WIN) 1219gfx::NativeViewAccessible WebContentsImpl::GetParentNativeViewAccessible() { 1220 return accessible_parent_; 1221} 1222#endif 1223 1224void WebContentsImpl::HandleMouseDown() { 1225 if (delegate_) 1226 delegate_->HandleMouseDown(); 1227} 1228 1229void WebContentsImpl::HandleMouseUp() { 1230 if (delegate_) 1231 delegate_->HandleMouseUp(); 1232} 1233 1234void WebContentsImpl::HandlePointerActivate() { 1235 if (delegate_) 1236 delegate_->HandlePointerActivate(); 1237} 1238 1239void WebContentsImpl::HandleGestureBegin() { 1240 if (delegate_) 1241 delegate_->HandleGestureBegin(); 1242} 1243 1244void WebContentsImpl::HandleGestureEnd() { 1245 if (delegate_) 1246 delegate_->HandleGestureEnd(); 1247} 1248 1249void WebContentsImpl::ToggleFullscreenMode(bool enter_fullscreen) { 1250 // This method is being called to enter or leave renderer-initiated fullscreen 1251 // mode. Either way, make sure any existing fullscreen widget is shut down 1252 // first. 1253 RenderWidgetHostView* const widget_view = GetFullscreenRenderWidgetHostView(); 1254 if (widget_view) 1255 RenderWidgetHostImpl::From(widget_view->GetRenderWidgetHost())->Shutdown(); 1256 1257 if (delegate_) 1258 delegate_->ToggleFullscreenModeForTab(this, enter_fullscreen); 1259} 1260 1261bool WebContentsImpl::IsFullscreenForCurrentTab() const { 1262 return delegate_ ? delegate_->IsFullscreenForTabOrPending(this) : false; 1263} 1264 1265void WebContentsImpl::RequestToLockMouse(bool user_gesture, 1266 bool last_unlocked_by_target) { 1267 if (delegate_) { 1268 delegate_->RequestToLockMouse(this, user_gesture, last_unlocked_by_target); 1269 } else { 1270 GotResponseToLockMouseRequest(false); 1271 } 1272} 1273 1274void WebContentsImpl::LostMouseLock() { 1275 if (delegate_) 1276 delegate_->LostMouseLock(); 1277} 1278 1279void WebContentsImpl::CreateNewWindow( 1280 int render_process_id, 1281 int route_id, 1282 int main_frame_route_id, 1283 const ViewHostMsg_CreateWindow_Params& params, 1284 SessionStorageNamespace* session_storage_namespace) { 1285 // We usually create the new window in the same BrowsingInstance (group of 1286 // script-related windows), by passing in the current SiteInstance. However, 1287 // if the opener is being suppressed (in a non-guest), we create a new 1288 // SiteInstance in its own BrowsingInstance. 1289 bool is_guest = GetRenderProcessHost()->IsGuest(); 1290 1291 // If the opener is to be suppressed, the new window can be in any process. 1292 // Since routing ids are process specific, we must not have one passed in 1293 // as argument here. 1294 DCHECK(!params.opener_suppressed || route_id == MSG_ROUTING_NONE); 1295 1296 scoped_refptr<SiteInstance> site_instance = 1297 params.opener_suppressed && !is_guest ? 1298 SiteInstance::CreateForURL(GetBrowserContext(), params.target_url) : 1299 GetSiteInstance(); 1300 1301 // A message to create a new window can only come from the active process for 1302 // this WebContentsImpl instance. If any other process sends the request, 1303 // it is invalid and the process must be terminated. 1304 if (GetRenderProcessHost()->GetID() != render_process_id) { 1305 base::ProcessHandle process_handle = 1306 RenderProcessHost::FromID(render_process_id)->GetHandle(); 1307 if (process_handle != base::kNullProcessHandle) { 1308 RecordAction( 1309 base::UserMetricsAction("Terminate_ProcessMismatch_CreateNewWindow")); 1310 base::KillProcess(process_handle, content::RESULT_CODE_KILLED, false); 1311 } 1312 return; 1313 } 1314 1315 // We must assign the SessionStorageNamespace before calling Init(). 1316 // 1317 // http://crbug.com/142685 1318 const std::string& partition_id = 1319 GetContentClient()->browser()-> 1320 GetStoragePartitionIdForSite(GetBrowserContext(), 1321 site_instance->GetSiteURL()); 1322 StoragePartition* partition = BrowserContext::GetStoragePartition( 1323 GetBrowserContext(), site_instance.get()); 1324 DOMStorageContextWrapper* dom_storage_context = 1325 static_cast<DOMStorageContextWrapper*>(partition->GetDOMStorageContext()); 1326 SessionStorageNamespaceImpl* session_storage_namespace_impl = 1327 static_cast<SessionStorageNamespaceImpl*>(session_storage_namespace); 1328 CHECK(session_storage_namespace_impl->IsFromContext(dom_storage_context)); 1329 1330 if (delegate_ && 1331 !delegate_->ShouldCreateWebContents(this, 1332 route_id, 1333 params.window_container_type, 1334 params.frame_name, 1335 params.target_url, 1336 partition_id, 1337 session_storage_namespace)) { 1338 if (route_id != MSG_ROUTING_NONE && 1339 !RenderViewHost::FromID(render_process_id, route_id)) { 1340 // If the embedder didn't create a WebContents for this route, we need to 1341 // delete the RenderView that had already been created. 1342 Send(new ViewMsg_Close(route_id)); 1343 } 1344 GetRenderViewHost()->GetProcess()->ResumeRequestsForView(route_id); 1345 GetRenderViewHost()->GetProcess()->ResumeRequestsForView( 1346 main_frame_route_id); 1347 return; 1348 } 1349 1350 // Create the new web contents. This will automatically create the new 1351 // WebContentsView. In the future, we may want to create the view separately. 1352 WebContentsImpl* new_contents = 1353 new WebContentsImpl(GetBrowserContext(), 1354 params.opener_suppressed ? NULL : this); 1355 1356 new_contents->GetController().SetSessionStorageNamespace( 1357 partition_id, 1358 session_storage_namespace); 1359 CreateParams create_params(GetBrowserContext(), site_instance.get()); 1360 create_params.routing_id = route_id; 1361 create_params.main_frame_routing_id = main_frame_route_id; 1362 if (!is_guest) { 1363 create_params.context = view_->GetNativeView(); 1364 create_params.initial_size = view_->GetContainerSize(); 1365 } else { 1366 // This makes |new_contents| act as a guest. 1367 // For more info, see comment above class BrowserPluginGuest. 1368 int instance_id = GetBrowserPluginGuestManager()->get_next_instance_id(); 1369 WebContentsImpl* new_contents_impl = 1370 static_cast<WebContentsImpl*>(new_contents); 1371 BrowserPluginGuest::CreateWithOpener(instance_id, 1372 new_contents_impl->opener() != NULL, 1373 new_contents_impl, 1374 GetBrowserPluginGuest()); 1375 } 1376 if (params.disposition == NEW_BACKGROUND_TAB) 1377 create_params.initially_hidden = true; 1378 new_contents->Init(create_params); 1379 1380 // Save the window for later if we're not suppressing the opener (since it 1381 // will be shown immediately). 1382 if (!params.opener_suppressed) { 1383 if (!is_guest) { 1384 WebContentsViewPort* new_view = new_contents->view_.get(); 1385 1386 // TODO(brettw): It seems bogus that we have to call this function on the 1387 // newly created object and give it one of its own member variables. 1388 new_view->CreateViewForWidget(new_contents->GetRenderViewHost()); 1389 } 1390 // Save the created window associated with the route so we can show it 1391 // later. 1392 DCHECK_NE(MSG_ROUTING_NONE, route_id); 1393 pending_contents_[route_id] = new_contents; 1394 AddDestructionObserver(new_contents); 1395 } 1396 1397 if (delegate_) { 1398 delegate_->WebContentsCreated( 1399 this, params.opener_frame_id, params.frame_name, 1400 params.target_url, new_contents); 1401 } 1402 1403 if (params.opener_suppressed) { 1404 // When the opener is suppressed, the original renderer cannot access the 1405 // new window. As a result, we need to show and navigate the window here. 1406 bool was_blocked = false; 1407 if (delegate_) { 1408 gfx::Rect initial_pos; 1409 delegate_->AddNewContents( 1410 this, new_contents, params.disposition, initial_pos, 1411 params.user_gesture, &was_blocked); 1412 } 1413 if (!was_blocked) { 1414 OpenURLParams open_params(params.target_url, 1415 Referrer(), 1416 CURRENT_TAB, 1417 PAGE_TRANSITION_LINK, 1418 true /* is_renderer_initiated */); 1419 open_params.user_gesture = params.user_gesture; 1420 new_contents->OpenURL(open_params); 1421 } 1422 } 1423} 1424 1425void WebContentsImpl::CreateNewWidget(int render_process_id, 1426 int route_id, 1427 blink::WebPopupType popup_type) { 1428 CreateNewWidget(render_process_id, route_id, false, popup_type); 1429} 1430 1431void WebContentsImpl::CreateNewFullscreenWidget(int render_process_id, 1432 int route_id) { 1433 CreateNewWidget(render_process_id, route_id, true, blink::WebPopupTypeNone); 1434} 1435 1436void WebContentsImpl::CreateNewWidget(int render_process_id, 1437 int route_id, 1438 bool is_fullscreen, 1439 blink::WebPopupType popup_type) { 1440 RenderProcessHost* process = GetRenderProcessHost(); 1441 // A message to create a new widget can only come from the active process for 1442 // this WebContentsImpl instance. If any other process sends the request, 1443 // it is invalid and the process must be terminated. 1444 if (process->GetID() != render_process_id) { 1445 base::ProcessHandle process_handle = 1446 RenderProcessHost::FromID(render_process_id)->GetHandle(); 1447 if (process_handle != base::kNullProcessHandle) { 1448 RecordAction( 1449 base::UserMetricsAction("Terminate_ProcessMismatch_CreateNewWidget")); 1450 base::KillProcess(process_handle, content::RESULT_CODE_KILLED, false); 1451 } 1452 return; 1453 } 1454 1455 RenderWidgetHostImpl* widget_host = 1456 new RenderWidgetHostImpl(this, process, route_id, IsHidden()); 1457 created_widgets_.insert(widget_host); 1458 1459 RenderWidgetHostViewPort* widget_view = RenderWidgetHostViewPort::FromRWHV( 1460 view_->CreateViewForPopupWidget(widget_host)); 1461 if (!widget_view) 1462 return; 1463 if (!is_fullscreen) { 1464 // Popups should not get activated. 1465 widget_view->SetPopupType(popup_type); 1466 } 1467 // Save the created widget associated with the route so we can show it later. 1468 pending_widget_views_[route_id] = widget_view; 1469 1470#if defined(OS_MACOSX) 1471 // A RenderWidgetHostViewMac has lifetime scoped to the view. We'll retain it 1472 // to allow it to survive the trip without being hosted. 1473 base::mac::NSObjectRetain(widget_view->GetNativeView()); 1474#endif 1475} 1476 1477void WebContentsImpl::ShowCreatedWindow(int route_id, 1478 WindowOpenDisposition disposition, 1479 const gfx::Rect& initial_pos, 1480 bool user_gesture) { 1481 WebContentsImpl* contents = GetCreatedWindow(route_id); 1482 if (contents) { 1483 WebContentsDelegate* delegate = GetDelegate(); 1484 if (delegate) { 1485 delegate->AddNewContents( 1486 this, contents, disposition, initial_pos, user_gesture, NULL); 1487 } 1488 } 1489} 1490 1491void WebContentsImpl::ShowCreatedWidget(int route_id, 1492 const gfx::Rect& initial_pos) { 1493 ShowCreatedWidget(route_id, false, initial_pos); 1494} 1495 1496void WebContentsImpl::ShowCreatedFullscreenWidget(int route_id) { 1497 ShowCreatedWidget(route_id, true, gfx::Rect()); 1498} 1499 1500void WebContentsImpl::ShowCreatedWidget(int route_id, 1501 bool is_fullscreen, 1502 const gfx::Rect& initial_pos) { 1503 RenderWidgetHostViewPort* widget_host_view = 1504 RenderWidgetHostViewPort::FromRWHV(GetCreatedWidget(route_id)); 1505 if (!widget_host_view) 1506 return; 1507 if (is_fullscreen) { 1508 DCHECK_EQ(MSG_ROUTING_NONE, fullscreen_widget_routing_id_); 1509 fullscreen_widget_routing_id_ = route_id; 1510 if (delegate_ && delegate_->EmbedsFullscreenWidget()) { 1511 widget_host_view->InitAsChild(GetRenderWidgetHostView()->GetNativeView()); 1512 delegate_->ToggleFullscreenModeForTab(this, true); 1513 } else { 1514 widget_host_view->InitAsFullscreen(GetRenderWidgetHostViewPort()); 1515 } 1516 FOR_EACH_OBSERVER(WebContentsObserver, 1517 observers_, 1518 DidShowFullscreenWidget(route_id)); 1519 if (!widget_host_view->HasFocus()) 1520 widget_host_view->Focus(); 1521 } else { 1522 widget_host_view->InitAsPopup(GetRenderWidgetHostViewPort(), initial_pos); 1523 } 1524 1525 RenderWidgetHostImpl* render_widget_host_impl = 1526 RenderWidgetHostImpl::From(widget_host_view->GetRenderWidgetHost()); 1527 render_widget_host_impl->Init(); 1528 // Only allow privileged mouse lock for fullscreen render widget, which is 1529 // used to implement Pepper Flash fullscreen. 1530 render_widget_host_impl->set_allow_privileged_mouse_lock(is_fullscreen); 1531 1532#if defined(OS_MACOSX) 1533 // A RenderWidgetHostViewMac has lifetime scoped to the view. Now that it's 1534 // properly embedded (or purposefully ignored) we can release the retain we 1535 // took in CreateNewWidget(). 1536 base::mac::NSObjectRelease(widget_host_view->GetNativeView()); 1537#endif 1538} 1539 1540WebContentsImpl* WebContentsImpl::GetCreatedWindow(int route_id) { 1541 PendingContents::iterator iter = pending_contents_.find(route_id); 1542 1543 // Certain systems can block the creation of new windows. If we didn't succeed 1544 // in creating one, just return NULL. 1545 if (iter == pending_contents_.end()) { 1546 return NULL; 1547 } 1548 1549 WebContentsImpl* new_contents = iter->second; 1550 pending_contents_.erase(route_id); 1551 RemoveDestructionObserver(new_contents); 1552 1553 // Don't initialize the guest WebContents immediately. 1554 if (new_contents->GetRenderProcessHost()->IsGuest()) 1555 return new_contents; 1556 1557 if (!new_contents->GetRenderProcessHost()->HasConnection() || 1558 !new_contents->GetRenderViewHost()->GetView()) 1559 return NULL; 1560 1561 // TODO(brettw): It seems bogus to reach into here and initialize the host. 1562 static_cast<RenderViewHostImpl*>(new_contents->GetRenderViewHost())->Init(); 1563 return new_contents; 1564} 1565 1566RenderWidgetHostView* WebContentsImpl::GetCreatedWidget(int route_id) { 1567 PendingWidgetViews::iterator iter = pending_widget_views_.find(route_id); 1568 if (iter == pending_widget_views_.end()) { 1569 DCHECK(false); 1570 return NULL; 1571 } 1572 1573 RenderWidgetHostView* widget_host_view = iter->second; 1574 pending_widget_views_.erase(route_id); 1575 1576 RenderWidgetHost* widget_host = widget_host_view->GetRenderWidgetHost(); 1577 if (!widget_host->GetProcess()->HasConnection()) { 1578 // The view has gone away or the renderer crashed. Nothing to do. 1579 return NULL; 1580 } 1581 1582 return widget_host_view; 1583} 1584 1585void WebContentsImpl::RequestMediaAccessPermission( 1586 const MediaStreamRequest& request, 1587 const MediaResponseCallback& callback) { 1588 if (delegate_) { 1589 delegate_->RequestMediaAccessPermission(this, request, callback); 1590 } else { 1591 callback.Run(MediaStreamDevices(), 1592 MEDIA_DEVICE_INVALID_STATE, 1593 scoped_ptr<MediaStreamUI>()); 1594 } 1595} 1596 1597SessionStorageNamespace* WebContentsImpl::GetSessionStorageNamespace( 1598 SiteInstance* instance) { 1599 return controller_.GetSessionStorageNamespace(instance); 1600} 1601 1602FrameTree* WebContentsImpl::GetFrameTree() { 1603 return &frame_tree_; 1604} 1605 1606void WebContentsImpl::AccessibilityEventReceived( 1607 const std::vector<AXEventNotificationDetails>& details) { 1608 FOR_EACH_OBSERVER( 1609 WebContentsObserver, observers_, AccessibilityEventReceived(details)); 1610} 1611 1612void WebContentsImpl::OnShowValidationMessage( 1613 const gfx::Rect& anchor_in_root_view, 1614 const base::string16& main_text, 1615 const base::string16& sub_text) { 1616 if (delegate_) 1617 delegate_->ShowValidationMessage( 1618 this, anchor_in_root_view, main_text, sub_text); 1619} 1620 1621void WebContentsImpl::OnHideValidationMessage() { 1622 if (delegate_) 1623 delegate_->HideValidationMessage(this); 1624} 1625 1626void WebContentsImpl::OnMoveValidationMessage( 1627 const gfx::Rect& anchor_in_root_view) { 1628 if (delegate_) 1629 delegate_->MoveValidationMessage(this, anchor_in_root_view); 1630} 1631 1632void WebContentsImpl::DidSendScreenRects(RenderWidgetHostImpl* rwh) { 1633 if (browser_plugin_embedder_) 1634 browser_plugin_embedder_->DidSendScreenRects(); 1635} 1636 1637void WebContentsImpl::UpdatePreferredSize(const gfx::Size& pref_size) { 1638 const gfx::Size old_size = GetPreferredSize(); 1639 preferred_size_ = pref_size; 1640 OnPreferredSizeChanged(old_size); 1641} 1642 1643void WebContentsImpl::ResizeDueToAutoResize(const gfx::Size& new_size) { 1644 if (delegate_) 1645 delegate_->ResizeDueToAutoResize(this, new_size); 1646} 1647 1648WebContents* WebContentsImpl::OpenURL(const OpenURLParams& params) { 1649 if (!delegate_) 1650 return NULL; 1651 1652 WebContents* new_contents = delegate_->OpenURLFromTab(this, params); 1653 return new_contents; 1654} 1655 1656bool WebContentsImpl::Send(IPC::Message* message) { 1657 if (!GetRenderViewHost()) { 1658 delete message; 1659 return false; 1660 } 1661 1662 return GetRenderViewHost()->Send(message); 1663} 1664 1665bool WebContentsImpl::NavigateToPendingEntry( 1666 NavigationController::ReloadType reload_type) { 1667 return frame_tree_.root()->navigator()->NavigateToPendingEntry( 1668 frame_tree_.GetMainFrame(), reload_type); 1669} 1670 1671void WebContentsImpl::RenderFrameForInterstitialPageCreated( 1672 RenderFrameHost* render_frame_host) { 1673 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 1674 RenderFrameForInterstitialPageCreated(render_frame_host)); 1675} 1676 1677void WebContentsImpl::AttachInterstitialPage( 1678 InterstitialPageImpl* interstitial_page) { 1679 DCHECK(interstitial_page); 1680 GetRenderManager()->set_interstitial_page(interstitial_page); 1681 1682 // Cancel any visible dialogs so that they don't interfere with the 1683 // interstitial. 1684 if (dialog_manager_) 1685 dialog_manager_->CancelActiveAndPendingDialogs(this); 1686 1687 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 1688 DidAttachInterstitialPage()); 1689} 1690 1691void WebContentsImpl::DetachInterstitialPage() { 1692 if (GetInterstitialPage()) 1693 GetRenderManager()->remove_interstitial_page(); 1694 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 1695 DidDetachInterstitialPage()); 1696} 1697 1698void WebContentsImpl::SetHistoryLengthAndPrune( 1699 const SiteInstance* site_instance, 1700 int history_length, 1701 int32 minimum_page_id) { 1702 // SetHistoryLengthAndPrune doesn't work when there are pending cross-site 1703 // navigations. Callers should ensure that this is the case. 1704 if (GetRenderManager()->pending_render_view_host()) { 1705 NOTREACHED(); 1706 return; 1707 } 1708 RenderViewHostImpl* rvh = GetRenderViewHostImpl(); 1709 if (!rvh) { 1710 NOTREACHED(); 1711 return; 1712 } 1713 if (site_instance && rvh->GetSiteInstance() != site_instance) { 1714 NOTREACHED(); 1715 return; 1716 } 1717 Send(new ViewMsg_SetHistoryLengthAndPrune(GetRoutingID(), 1718 history_length, 1719 minimum_page_id)); 1720} 1721 1722void WebContentsImpl::FocusThroughTabTraversal(bool reverse) { 1723 if (ShowingInterstitialPage()) { 1724 GetRenderManager()->interstitial_page()->FocusThroughTabTraversal(reverse); 1725 return; 1726 } 1727 GetRenderViewHostImpl()->SetInitialFocus(reverse); 1728} 1729 1730bool WebContentsImpl::ShowingInterstitialPage() const { 1731 return GetRenderManager()->interstitial_page() != NULL; 1732} 1733 1734InterstitialPage* WebContentsImpl::GetInterstitialPage() const { 1735 return GetRenderManager()->interstitial_page(); 1736} 1737 1738bool WebContentsImpl::IsSavable() { 1739 // WebKit creates Document object when MIME type is application/xhtml+xml, 1740 // so we also support this MIME type. 1741 return contents_mime_type_ == "text/html" || 1742 contents_mime_type_ == "text/xml" || 1743 contents_mime_type_ == "application/xhtml+xml" || 1744 contents_mime_type_ == "text/plain" || 1745 contents_mime_type_ == "text/css" || 1746 net::IsSupportedJavascriptMimeType(contents_mime_type_.c_str()); 1747} 1748 1749void WebContentsImpl::OnSavePage() { 1750 // If we can not save the page, try to download it. 1751 if (!IsSavable()) { 1752 RecordDownloadSource(INITIATED_BY_SAVE_PACKAGE_ON_NON_HTML); 1753 SaveFrame(GetURL(), Referrer()); 1754 return; 1755 } 1756 1757 Stop(); 1758 1759 // Create the save package and possibly prompt the user for the name to save 1760 // the page as. The user prompt is an asynchronous operation that runs on 1761 // another thread. 1762 save_package_ = new SavePackage(this); 1763 save_package_->GetSaveInfo(); 1764} 1765 1766// Used in automated testing to bypass prompting the user for file names. 1767// Instead, the names and paths are hard coded rather than running them through 1768// file name sanitation and extension / mime checking. 1769bool WebContentsImpl::SavePage(const base::FilePath& main_file, 1770 const base::FilePath& dir_path, 1771 SavePageType save_type) { 1772 // Stop the page from navigating. 1773 Stop(); 1774 1775 save_package_ = new SavePackage(this, save_type, main_file, dir_path); 1776 return save_package_->Init(SavePackageDownloadCreatedCallback()); 1777} 1778 1779void WebContentsImpl::SaveFrame(const GURL& url, 1780 const Referrer& referrer) { 1781 if (!GetURL().is_valid()) 1782 return; 1783 bool is_main_frame = (url == GetURL()); 1784 1785 DownloadManager* dlm = 1786 BrowserContext::GetDownloadManager(GetBrowserContext()); 1787 if (!dlm) 1788 return; 1789 int64 post_id = -1; 1790 if (is_main_frame) { 1791 const NavigationEntry* entry = controller_.GetLastCommittedEntry(); 1792 if (entry) 1793 post_id = entry->GetPostID(); 1794 } 1795 scoped_ptr<DownloadUrlParameters> params( 1796 DownloadUrlParameters::FromWebContents(this, url)); 1797 params->set_referrer(referrer); 1798 params->set_post_id(post_id); 1799 params->set_prefer_cache(true); 1800 if (post_id >= 0) 1801 params->set_method("POST"); 1802 params->set_prompt(true); 1803 dlm->DownloadUrl(params.Pass()); 1804} 1805 1806void WebContentsImpl::GenerateMHTML( 1807 const base::FilePath& file, 1808 const base::Callback<void(int64)>& callback) { 1809 MHTMLGenerationManager::GetInstance()->SaveMHTML(this, file, callback); 1810} 1811 1812// TODO(nasko): Rename this method to IsVisibleEntry. 1813bool WebContentsImpl::IsActiveEntry(int32 page_id) { 1814 NavigationEntryImpl* visible_entry = 1815 NavigationEntryImpl::FromNavigationEntry(controller_.GetVisibleEntry()); 1816 return (visible_entry != NULL && 1817 visible_entry->site_instance() == GetSiteInstance() && 1818 visible_entry->GetPageID() == page_id); 1819} 1820 1821const std::string& WebContentsImpl::GetContentsMimeType() const { 1822 return contents_mime_type_; 1823} 1824 1825bool WebContentsImpl::WillNotifyDisconnection() const { 1826 return notify_disconnection_; 1827} 1828 1829void WebContentsImpl::SetOverrideEncoding(const std::string& encoding) { 1830 SetEncoding(encoding); 1831 Send(new ViewMsg_SetPageEncoding(GetRoutingID(), encoding)); 1832} 1833 1834void WebContentsImpl::ResetOverrideEncoding() { 1835 encoding_.clear(); 1836 Send(new ViewMsg_ResetPageEncodingToDefault(GetRoutingID())); 1837} 1838 1839RendererPreferences* WebContentsImpl::GetMutableRendererPrefs() { 1840 return &renderer_preferences_; 1841} 1842 1843void WebContentsImpl::Close() { 1844 Close(GetRenderViewHost()); 1845} 1846 1847void WebContentsImpl::DragSourceEndedAt(int client_x, int client_y, 1848 int screen_x, int screen_y, blink::WebDragOperation operation) { 1849 if (browser_plugin_embedder_.get()) 1850 browser_plugin_embedder_->DragSourceEndedAt(client_x, client_y, 1851 screen_x, screen_y, operation); 1852 if (GetRenderViewHost()) 1853 GetRenderViewHostImpl()->DragSourceEndedAt(client_x, client_y, 1854 screen_x, screen_y, operation); 1855} 1856 1857void WebContentsImpl::DragSourceMovedTo(int client_x, int client_y, 1858 int screen_x, int screen_y) { 1859 if (browser_plugin_embedder_.get()) 1860 browser_plugin_embedder_->DragSourceMovedTo(client_x, client_y, 1861 screen_x, screen_y); 1862 if (GetRenderViewHost()) 1863 GetRenderViewHostImpl()->DragSourceMovedTo(client_x, client_y, 1864 screen_x, screen_y); 1865} 1866 1867void WebContentsImpl::DidGetResourceResponseStart( 1868 const ResourceRequestDetails& details) { 1869 controller_.ssl_manager()->DidStartResourceResponse(details); 1870 1871 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 1872 DidGetResourceResponseStart(details)); 1873 1874 // TODO(avi): Remove. http://crbug.com/170921 1875 NotificationService::current()->Notify( 1876 NOTIFICATION_RESOURCE_RESPONSE_STARTED, 1877 Source<WebContents>(this), 1878 Details<const ResourceRequestDetails>(&details)); 1879} 1880 1881void WebContentsImpl::DidGetRedirectForResourceRequest( 1882 RenderViewHost* render_view_host, 1883 const ResourceRedirectDetails& details) { 1884 controller_.ssl_manager()->DidReceiveResourceRedirect(details); 1885 1886 FOR_EACH_OBSERVER( 1887 WebContentsObserver, 1888 observers_, 1889 DidGetRedirectForResourceRequest(render_view_host, details)); 1890 1891 // TODO(avi): Remove. http://crbug.com/170921 1892 NotificationService::current()->Notify( 1893 NOTIFICATION_RESOURCE_RECEIVED_REDIRECT, 1894 Source<WebContents>(this), 1895 Details<const ResourceRedirectDetails>(&details)); 1896} 1897 1898void WebContentsImpl::SystemDragEnded() { 1899 if (GetRenderViewHost()) 1900 GetRenderViewHostImpl()->DragSourceSystemDragEnded(); 1901 if (delegate_) 1902 delegate_->DragEnded(); 1903 if (browser_plugin_embedder_.get()) 1904 browser_plugin_embedder_->SystemDragEnded(); 1905} 1906 1907void WebContentsImpl::UserGestureDone() { 1908 OnUserGesture(); 1909} 1910 1911void WebContentsImpl::SetClosedByUserGesture(bool value) { 1912 closed_by_user_gesture_ = value; 1913} 1914 1915bool WebContentsImpl::GetClosedByUserGesture() const { 1916 return closed_by_user_gesture_; 1917} 1918 1919double WebContentsImpl::GetZoomLevel() const { 1920 HostZoomMapImpl* zoom_map = static_cast<HostZoomMapImpl*>( 1921 HostZoomMap::GetForBrowserContext(GetBrowserContext())); 1922 if (!zoom_map) 1923 return 0; 1924 1925 double zoom_level; 1926 if (temporary_zoom_settings_) { 1927 zoom_level = zoom_map->GetTemporaryZoomLevel( 1928 GetRenderProcessHost()->GetID(), GetRenderViewHost()->GetRoutingID()); 1929 } else { 1930 GURL url; 1931 NavigationEntry* entry = GetController().GetLastCommittedEntry(); 1932 // Since zoom map is updated using rewritten URL, use rewritten URL 1933 // to get the zoom level. 1934 url = entry ? entry->GetURL() : GURL::EmptyGURL(); 1935 zoom_level = zoom_map->GetZoomLevelForHostAndScheme(url.scheme(), 1936 net::GetHostOrSpecFromURL(url)); 1937 } 1938 return zoom_level; 1939} 1940 1941int WebContentsImpl::GetZoomPercent(bool* enable_increment, 1942 bool* enable_decrement) const { 1943 *enable_decrement = *enable_increment = false; 1944 // Calculate the zoom percent from the factor. Round up to the nearest whole 1945 // number. 1946 int percent = static_cast<int>( 1947 ZoomLevelToZoomFactor(GetZoomLevel()) * 100 + 0.5); 1948 *enable_decrement = percent > minimum_zoom_percent_; 1949 *enable_increment = percent < maximum_zoom_percent_; 1950 return percent; 1951} 1952 1953void WebContentsImpl::ViewSource() { 1954 if (!delegate_) 1955 return; 1956 1957 NavigationEntry* entry = GetController().GetLastCommittedEntry(); 1958 if (!entry) 1959 return; 1960 1961 delegate_->ViewSourceForTab(this, entry->GetURL()); 1962} 1963 1964void WebContentsImpl::ViewFrameSource(const GURL& url, 1965 const PageState& page_state) { 1966 if (!delegate_) 1967 return; 1968 1969 delegate_->ViewSourceForFrame(this, url, page_state); 1970} 1971 1972int WebContentsImpl::GetMinimumZoomPercent() const { 1973 return minimum_zoom_percent_; 1974} 1975 1976int WebContentsImpl::GetMaximumZoomPercent() const { 1977 return maximum_zoom_percent_; 1978} 1979 1980gfx::Size WebContentsImpl::GetPreferredSize() const { 1981 return capturer_count_ == 0 ? preferred_size_ : preferred_size_for_capture_; 1982} 1983 1984bool WebContentsImpl::GotResponseToLockMouseRequest(bool allowed) { 1985 return GetRenderViewHost() ? 1986 GetRenderViewHostImpl()->GotResponseToLockMouseRequest(allowed) : false; 1987} 1988 1989bool WebContentsImpl::HasOpener() const { 1990 return opener_ != NULL; 1991} 1992 1993void WebContentsImpl::DidChooseColorInColorChooser(SkColor color) { 1994 Send(new ViewMsg_DidChooseColorResponse( 1995 GetRoutingID(), color_chooser_identifier_, color)); 1996} 1997 1998void WebContentsImpl::DidEndColorChooser() { 1999 Send(new ViewMsg_DidEndColorChooser(GetRoutingID(), 2000 color_chooser_identifier_)); 2001 color_chooser_.reset(); 2002 color_chooser_identifier_ = 0; 2003} 2004 2005int WebContentsImpl::DownloadImage(const GURL& url, 2006 bool is_favicon, 2007 uint32_t max_bitmap_size, 2008 const ImageDownloadCallback& callback) { 2009 RenderViewHost* host = GetRenderViewHost(); 2010 int id = StartDownload(host, url, is_favicon, max_bitmap_size); 2011 image_download_map_[id] = callback; 2012 return id; 2013} 2014 2015bool WebContentsImpl::IsSubframe() const { 2016 return is_subframe_; 2017} 2018 2019void WebContentsImpl::SetZoomLevel(double level) { 2020 Send(new ViewMsg_SetZoomLevel(GetRoutingID(), level)); 2021 BrowserPluginEmbedder* embedder = GetBrowserPluginEmbedder(); 2022 if (embedder) 2023 embedder->SetZoomLevel(level); 2024} 2025 2026void WebContentsImpl::Find(int request_id, 2027 const base::string16& search_text, 2028 const blink::WebFindOptions& options) { 2029 Send(new ViewMsg_Find(GetRoutingID(), request_id, search_text, options)); 2030} 2031 2032void WebContentsImpl::StopFinding(StopFindAction action) { 2033 Send(new ViewMsg_StopFinding(GetRoutingID(), action)); 2034} 2035 2036bool WebContentsImpl::FocusLocationBarByDefault() { 2037 NavigationEntry* entry = controller_.GetVisibleEntry(); 2038 if (entry && entry->GetURL() == GURL(kAboutBlankURL)) 2039 return true; 2040 return delegate_ && delegate_->ShouldFocusLocationBarByDefault(this); 2041} 2042 2043void WebContentsImpl::SetFocusToLocationBar(bool select_all) { 2044 if (delegate_) 2045 delegate_->SetFocusToLocationBar(select_all); 2046} 2047 2048void WebContentsImpl::DidStartProvisionalLoad( 2049 RenderFrameHostImpl* render_frame_host, 2050 int parent_routing_id, 2051 bool is_main_frame, 2052 const GURL& validated_url, 2053 bool is_error_page, 2054 bool is_iframe_srcdoc) { 2055 if (is_main_frame) 2056 DidChangeLoadProgress(0); 2057 2058 // --site-per-process mode has a short-term hack allowing cross-process 2059 // subframe pages to commit thinking they are top-level. Correct it here to 2060 // avoid confusing the observers. 2061 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess) && 2062 render_frame_host != GetMainFrame()) { 2063 is_main_frame = false; 2064 } 2065 2066 // Notify observers about the start of the provisional load. 2067 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2068 DidStartProvisionalLoadForFrame( 2069 render_frame_host->GetRoutingID(), parent_routing_id, 2070 is_main_frame, validated_url, is_error_page, 2071 is_iframe_srcdoc, 2072 render_frame_host->render_view_host())); 2073 2074 if (is_main_frame) { 2075 FOR_EACH_OBSERVER( 2076 WebContentsObserver, 2077 observers_, 2078 ProvisionalChangeToMainFrameUrl(validated_url, 2079 render_frame_host)); 2080 } 2081} 2082 2083void WebContentsImpl::DidFailProvisionalLoadWithError( 2084 RenderFrameHostImpl* render_frame_host, 2085 const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params) { 2086 GURL validated_url(params.url); 2087 FOR_EACH_OBSERVER( 2088 WebContentsObserver, 2089 observers_, 2090 DidFailProvisionalLoad(render_frame_host->GetRoutingID(), 2091 params.frame_unique_name, 2092 params.is_main_frame, 2093 validated_url, 2094 params.error_code, 2095 params.error_description, 2096 render_frame_host->render_view_host())); 2097} 2098 2099void WebContentsImpl::DidFailLoadWithError( 2100 RenderFrameHostImpl* render_frame_host, 2101 const GURL& url, 2102 bool is_main_frame, 2103 int error_code, 2104 const base::string16& error_description) { 2105 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2106 DidFailLoad(render_frame_host->GetRoutingID(), 2107 url, is_main_frame, 2108 error_code, error_description, 2109 render_frame_host->render_view_host())); 2110} 2111 2112void WebContentsImpl::NotifyChangedNavigationState( 2113 InvalidateTypes changed_flags) { 2114 NotifyNavigationStateChanged(changed_flags); 2115} 2116 2117void WebContentsImpl::AboutToNavigateRenderFrame( 2118 RenderFrameHostImpl* render_frame_host) { 2119 // Notify observers that we will navigate in this RenderView. 2120 FOR_EACH_OBSERVER( 2121 WebContentsObserver, 2122 observers_, 2123 AboutToNavigateRenderView(render_frame_host->render_view_host())); 2124} 2125 2126void WebContentsImpl::DidStartNavigationToPendingEntry( 2127 RenderFrameHostImpl* render_frame_host, 2128 const GURL& url, 2129 NavigationController::ReloadType reload_type) { 2130 // Notify observers about navigation. 2131 FOR_EACH_OBSERVER( 2132 WebContentsObserver, 2133 observers_, 2134 DidStartNavigationToPendingEntry(url, reload_type)); 2135} 2136 2137void WebContentsImpl::RequestOpenURL(RenderFrameHostImpl* render_frame_host, 2138 const OpenURLParams& params) { 2139 int source_render_frame_id = render_frame_host->GetRoutingID(); 2140 WebContents* new_contents = OpenURL(params); 2141 2142 if (new_contents) { 2143 // Notify observers. 2144 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2145 DidOpenRequestedURL(new_contents, 2146 params.url, 2147 params.referrer, 2148 params.disposition, 2149 params.transition, 2150 source_render_frame_id)); 2151 } 2152} 2153 2154void WebContentsImpl::DidRedirectProvisionalLoad( 2155 RenderFrameHostImpl* render_frame_host, 2156 const GURL& validated_target_url) { 2157 // Notify observers about the provisional change in the main frame URL. 2158 FOR_EACH_OBSERVER( 2159 WebContentsObserver, 2160 observers_, 2161 ProvisionalChangeToMainFrameUrl(validated_target_url, 2162 render_frame_host)); 2163} 2164 2165void WebContentsImpl::DidCommitProvisionalLoad( 2166 RenderFrameHostImpl* render_frame_host, 2167 const base::string16& frame_unique_name, 2168 bool is_main_frame, 2169 const GURL& url, 2170 PageTransition transition_type) { 2171 RenderViewHost* render_view_host = render_frame_host->render_view_host(); 2172 int render_frame_id = render_frame_host->GetRoutingID(); 2173 // Notify observers about the commit of the provisional load. 2174 FOR_EACH_OBSERVER( 2175 WebContentsObserver, 2176 observers_, 2177 DidCommitProvisionalLoadForFrame(render_frame_id, 2178 frame_unique_name, 2179 is_main_frame, 2180 url, 2181 transition_type, 2182 render_view_host)); 2183} 2184 2185void WebContentsImpl::DidNavigateMainFramePostCommit( 2186 const LoadCommittedDetails& details, 2187 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) { 2188 if (details.is_navigation_to_different_page()) { 2189 // Clear the status bubble. This is a workaround for a bug where WebKit 2190 // doesn't let us know that the cursor left an element during a 2191 // transition (this is also why the mouse cursor remains as a hand after 2192 // clicking on a link); see bugs 1184641 and 980803. We don't want to 2193 // clear the bubble when a user navigates to a named anchor in the same 2194 // page. 2195 UpdateTargetURL(details.entry->GetPageID(), GURL()); 2196 } 2197 2198 if (!details.is_in_page) { 2199 // Once the main frame is navigated, we're no longer considered to have 2200 // displayed insecure content. 2201 displayed_insecure_content_ = false; 2202 SSLManager::NotifySSLInternalStateChanged( 2203 GetController().GetBrowserContext()); 2204 } 2205 2206 // Notify observers about navigation. 2207 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2208 DidNavigateMainFrame(details, params)); 2209 2210 if (delegate_) { 2211 delegate_->DidNavigateMainFramePostCommit(this); 2212 view_->SetOverscrollControllerEnabled(delegate_->CanOverscrollContent()); 2213 } 2214} 2215 2216void WebContentsImpl::DidNavigateAnyFramePostCommit( 2217 RenderFrameHostImpl* render_frame_host, 2218 const LoadCommittedDetails& details, 2219 const FrameHostMsg_DidCommitProvisionalLoad_Params& params) { 2220 // If we navigate off the page, close all JavaScript dialogs. 2221 if (dialog_manager_ && !details.is_in_page) 2222 dialog_manager_->CancelActiveAndPendingDialogs(this); 2223 2224 // Notify observers about navigation. 2225 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2226 DidNavigateAnyFrame(details, params)); 2227} 2228 2229void WebContentsImpl::SetMainFrameMimeType(const std::string& mime_type) { 2230 contents_mime_type_ = mime_type; 2231} 2232 2233bool WebContentsImpl::CanOverscrollContent() { 2234 if (delegate_) 2235 return delegate_->CanOverscrollContent(); 2236 2237 return false; 2238} 2239 2240void WebContentsImpl::OnDidLoadResourceFromMemoryCache( 2241 const GURL& url, 2242 const std::string& security_info, 2243 const std::string& http_method, 2244 const std::string& mime_type, 2245 ResourceType::Type resource_type) { 2246 base::StatsCounter cache("WebKit.CacheHit"); 2247 cache.Increment(); 2248 2249 // Send out a notification that we loaded a resource from our memory cache. 2250 int cert_id = 0; 2251 net::CertStatus cert_status = 0; 2252 int security_bits = -1; 2253 int connection_status = 0; 2254 SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids; 2255 DeserializeSecurityInfo(security_info, &cert_id, &cert_status, 2256 &security_bits, &connection_status, 2257 &signed_certificate_timestamp_ids); 2258 // TODO(alcutter,eranm): Pass signed_certificate_timestamp_ids into details 2259 LoadFromMemoryCacheDetails details( 2260 url, GetRenderProcessHost()->GetID(), cert_id, cert_status, http_method, 2261 mime_type, resource_type); 2262 2263 controller_.ssl_manager()->DidLoadFromMemoryCache(details); 2264 2265 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2266 DidLoadResourceFromMemoryCache(details)); 2267 2268 if (url.is_valid() && url.SchemeIsHTTPOrHTTPS()) { 2269 scoped_refptr<net::URLRequestContextGetter> request_context( 2270 resource_type == ResourceType::MEDIA ? 2271 GetBrowserContext()->GetMediaRequestContextForRenderProcess( 2272 GetRenderProcessHost()->GetID()) : 2273 GetBrowserContext()->GetRequestContextForRenderProcess( 2274 GetRenderProcessHost()->GetID())); 2275 BrowserThread::PostTask( 2276 BrowserThread::IO, 2277 FROM_HERE, 2278 base::Bind(&NotifyCacheOnIO, request_context, url, http_method)); 2279 } 2280} 2281 2282void WebContentsImpl::OnDidDisplayInsecureContent() { 2283 RecordAction(base::UserMetricsAction("SSL.DisplayedInsecureContent")); 2284 displayed_insecure_content_ = true; 2285 SSLManager::NotifySSLInternalStateChanged( 2286 GetController().GetBrowserContext()); 2287} 2288 2289void WebContentsImpl::OnDidRunInsecureContent( 2290 const std::string& security_origin, const GURL& target_url) { 2291 LOG(WARNING) << security_origin << " ran insecure content from " 2292 << target_url.possibly_invalid_spec(); 2293 RecordAction(base::UserMetricsAction("SSL.RanInsecureContent")); 2294 if (EndsWith(security_origin, kDotGoogleDotCom, false)) 2295 RecordAction(base::UserMetricsAction("SSL.RanInsecureContentGoogle")); 2296 controller_.ssl_manager()->DidRunInsecureContent(security_origin); 2297 displayed_insecure_content_ = true; 2298 SSLManager::NotifySSLInternalStateChanged( 2299 GetController().GetBrowserContext()); 2300} 2301 2302void WebContentsImpl::OnDocumentLoadedInFrame() { 2303 CHECK(render_frame_message_source_); 2304 CHECK(!render_view_message_source_); 2305 RenderFrameHostImpl* rfh = 2306 static_cast<RenderFrameHostImpl*>(render_frame_message_source_); 2307 2308 FOR_EACH_OBSERVER(WebContentsObserver, 2309 observers_, 2310 DocumentLoadedInFrame(rfh->GetRoutingID(), 2311 rfh->render_view_host())); 2312} 2313 2314void WebContentsImpl::OnDidFinishLoad( 2315 const GURL& url, 2316 bool is_main_frame) { 2317 if (!render_frame_message_source_) { 2318 RecordAction(base::UserMetricsAction("BadMessageTerminate_RVD2")); 2319 GetRenderProcessHost()->ReceivedBadMessage(); 2320 return; 2321 } 2322 2323 RenderFrameHostImpl* rfh = 2324 static_cast<RenderFrameHostImpl*>(render_frame_message_source_); 2325 2326 // --site-per-process mode has a short-term hack allowing cross-process 2327 // subframe pages to commit thinking they are top-level. Correct it here to 2328 // avoid confusing the observers. 2329 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess) && 2330 rfh != GetMainFrame()) { 2331 is_main_frame = false; 2332 } 2333 2334 GURL validated_url(url); 2335 RenderProcessHost* render_process_host = 2336 render_frame_message_source_->GetProcess(); 2337 render_process_host->FilterURL(false, &validated_url); 2338 2339 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2340 DidFinishLoad(rfh->GetRoutingID(), validated_url, 2341 is_main_frame, rfh->render_view_host())); 2342} 2343 2344void WebContentsImpl::OnGoToEntryAtOffset(int offset) { 2345 if (!delegate_ || delegate_->OnGoToEntryOffset(offset)) 2346 controller_.GoToOffset(offset); 2347} 2348 2349void WebContentsImpl::OnUpdateZoomLimits(int minimum_percent, 2350 int maximum_percent, 2351 bool remember) { 2352 minimum_zoom_percent_ = minimum_percent; 2353 maximum_zoom_percent_ = maximum_percent; 2354 temporary_zoom_settings_ = !remember; 2355} 2356 2357void WebContentsImpl::OnEnumerateDirectory(int request_id, 2358 const base::FilePath& path) { 2359 if (!delegate_) 2360 return; 2361 2362 ChildProcessSecurityPolicyImpl* policy = 2363 ChildProcessSecurityPolicyImpl::GetInstance(); 2364 if (policy->CanReadFile(GetRenderProcessHost()->GetID(), path)) 2365 delegate_->EnumerateDirectory(this, request_id, path); 2366} 2367 2368void WebContentsImpl::OnRegisterProtocolHandler(const std::string& protocol, 2369 const GURL& url, 2370 const base::string16& title, 2371 bool user_gesture) { 2372 if (!delegate_) 2373 return; 2374 2375 ChildProcessSecurityPolicyImpl* policy = 2376 ChildProcessSecurityPolicyImpl::GetInstance(); 2377 if (policy->IsPseudoScheme(protocol)) 2378 return; 2379 2380 delegate_->RegisterProtocolHandler(this, protocol, url, title, user_gesture); 2381} 2382 2383void WebContentsImpl::OnFindReply(int request_id, 2384 int number_of_matches, 2385 const gfx::Rect& selection_rect, 2386 int active_match_ordinal, 2387 bool final_update) { 2388 if (delegate_) { 2389 delegate_->FindReply(this, request_id, number_of_matches, selection_rect, 2390 active_match_ordinal, final_update); 2391 } 2392} 2393 2394#if defined(OS_ANDROID) 2395void WebContentsImpl::OnFindMatchRectsReply( 2396 int version, 2397 const std::vector<gfx::RectF>& rects, 2398 const gfx::RectF& active_rect) { 2399 if (delegate_) 2400 delegate_->FindMatchRectsReply(this, version, rects, active_rect); 2401} 2402 2403void WebContentsImpl::OnOpenDateTimeDialog( 2404 const ViewHostMsg_DateTimeDialogValue_Params& value) { 2405 date_time_chooser_->ShowDialog(ContentViewCore::FromWebContents(this), 2406 GetRenderViewHost(), 2407 value.dialog_type, 2408 value.dialog_value, 2409 value.minimum, 2410 value.maximum, 2411 value.step, 2412 value.suggestions); 2413} 2414 2415void WebContentsImpl::OnJavaBridgeGetChannelHandle(IPC::Message* reply_msg) { 2416 java_bridge_dispatcher_host_manager_->OnGetChannelHandle( 2417 render_frame_message_source_, reply_msg); 2418} 2419 2420#endif 2421 2422void WebContentsImpl::OnPepperPluginHung(int plugin_child_id, 2423 const base::FilePath& path, 2424 bool is_hung) { 2425 UMA_HISTOGRAM_COUNTS("Pepper.PluginHung", 1); 2426 2427 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2428 PluginHungStatusChanged(plugin_child_id, path, is_hung)); 2429} 2430 2431void WebContentsImpl::OnPluginCrashed(const base::FilePath& plugin_path, 2432 base::ProcessId plugin_pid) { 2433 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2434 PluginCrashed(plugin_path, plugin_pid)); 2435} 2436 2437void WebContentsImpl::OnDomOperationResponse(const std::string& json_string, 2438 int automation_id) { 2439 DomOperationNotificationDetails details(json_string, automation_id); 2440 NotificationService::current()->Notify( 2441 NOTIFICATION_DOM_OPERATION_RESPONSE, 2442 Source<WebContents>(this), 2443 Details<DomOperationNotificationDetails>(&details)); 2444} 2445 2446void WebContentsImpl::OnAppCacheAccessed(const GURL& manifest_url, 2447 bool blocked_by_policy) { 2448 // Notify observers about navigation. 2449 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2450 AppCacheAccessed(manifest_url, blocked_by_policy)); 2451} 2452 2453void WebContentsImpl::OnOpenColorChooser( 2454 int color_chooser_id, 2455 SkColor color, 2456 const std::vector<ColorSuggestion>& suggestions) { 2457 ColorChooser* new_color_chooser = 2458 delegate_->OpenColorChooser(this, color, suggestions); 2459 if (!new_color_chooser) 2460 return; 2461 if (color_chooser_) 2462 color_chooser_->End(); 2463 color_chooser_.reset(new_color_chooser); 2464 color_chooser_identifier_ = color_chooser_id; 2465} 2466 2467void WebContentsImpl::OnEndColorChooser(int color_chooser_id) { 2468 if (color_chooser_ && 2469 color_chooser_id == color_chooser_identifier_) 2470 color_chooser_->End(); 2471} 2472 2473void WebContentsImpl::OnSetSelectedColorInColorChooser(int color_chooser_id, 2474 SkColor color) { 2475 if (color_chooser_ && 2476 color_chooser_id == color_chooser_identifier_) 2477 color_chooser_->SetSelectedColor(color); 2478} 2479 2480// This exists for render views that don't have a WebUI, but do have WebUI 2481// bindings enabled. 2482void WebContentsImpl::OnWebUISend(const GURL& source_url, 2483 const std::string& name, 2484 const base::ListValue& args) { 2485 if (delegate_) 2486 delegate_->WebUISend(this, source_url, name, args); 2487} 2488 2489void WebContentsImpl::OnRequestPpapiBrokerPermission( 2490 int routing_id, 2491 const GURL& url, 2492 const base::FilePath& plugin_path) { 2493 if (!delegate_) { 2494 OnPpapiBrokerPermissionResult(routing_id, false); 2495 return; 2496 } 2497 2498 if (!delegate_->RequestPpapiBrokerPermission( 2499 this, url, plugin_path, 2500 base::Bind(&WebContentsImpl::OnPpapiBrokerPermissionResult, 2501 base::Unretained(this), routing_id))) { 2502 NOTIMPLEMENTED(); 2503 OnPpapiBrokerPermissionResult(routing_id, false); 2504 } 2505} 2506 2507void WebContentsImpl::OnPpapiBrokerPermissionResult(int routing_id, 2508 bool result) { 2509 Send(new ViewMsg_PpapiBrokerPermissionResult(routing_id, result)); 2510} 2511 2512void WebContentsImpl::OnBrowserPluginMessage(const IPC::Message& message) { 2513 // This creates a BrowserPluginEmbedder, which handles all the BrowserPlugin 2514 // specific messages for this WebContents. This means that any message from 2515 // a BrowserPlugin prior to this will be ignored. 2516 // For more info, see comment above classes BrowserPluginEmbedder and 2517 // BrowserPluginGuest. 2518 CHECK(!browser_plugin_embedder_.get()); 2519 browser_plugin_embedder_.reset(BrowserPluginEmbedder::Create(this)); 2520 browser_plugin_embedder_->OnMessageReceived(message); 2521} 2522 2523void WebContentsImpl::OnDidDownloadImage( 2524 int id, 2525 int http_status_code, 2526 const GURL& image_url, 2527 const std::vector<SkBitmap>& bitmaps, 2528 const std::vector<gfx::Size>& original_bitmap_sizes) { 2529 if (bitmaps.size() != original_bitmap_sizes.size()) 2530 return; 2531 2532 ImageDownloadMap::iterator iter = image_download_map_.find(id); 2533 if (iter == image_download_map_.end()) { 2534 // Currently WebContents notifies us of ANY downloads so that it is 2535 // possible to get here. 2536 return; 2537 } 2538 if (!iter->second.is_null()) { 2539 iter->second.Run( 2540 id, http_status_code, image_url, bitmaps, original_bitmap_sizes); 2541 } 2542 image_download_map_.erase(id); 2543} 2544 2545void WebContentsImpl::OnUpdateFaviconURL( 2546 int32 page_id, 2547 const std::vector<FaviconURL>& candidates) { 2548 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2549 DidUpdateFaviconURL(page_id, candidates)); 2550} 2551 2552void WebContentsImpl::OnMediaPlayingNotification(int64 player_cookie, 2553 bool has_video, 2554 bool has_audio) { 2555// Chrome OS does its own detection of audio and video. 2556#if !defined(OS_CHROMEOS) 2557 scoped_ptr<PowerSaveBlocker> blocker; 2558 if (has_video) { 2559 blocker = PowerSaveBlocker::Create( 2560 PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, "Playing video"); 2561#if defined(OS_ANDROID) 2562 static_cast<PowerSaveBlockerImpl*>(blocker.get()) 2563 ->InitDisplaySleepBlocker(GetView()->GetNativeView()); 2564#endif 2565 } else if (has_audio) { 2566 blocker = PowerSaveBlocker::Create( 2567 PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, "Playing audio"); 2568 } 2569 2570 if (blocker) { 2571 power_save_blockers_[render_view_message_source_][player_cookie] = 2572 blocker.release(); 2573 } 2574#endif // !defined(OS_CHROMEOS) 2575} 2576 2577void WebContentsImpl::OnMediaPausedNotification(int64 player_cookie) { 2578 // Chrome OS does its own detection of audio and video. 2579#if !defined(OS_CHROMEOS) 2580 delete power_save_blockers_[render_view_message_source_][player_cookie]; 2581 power_save_blockers_[render_view_message_source_].erase(player_cookie); 2582#endif // !defined(OS_CHROMEOS) 2583} 2584 2585void WebContentsImpl::OnFirstVisuallyNonEmptyPaint(int32 page_id) { 2586 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2587 DidFirstVisuallyNonEmptyPaint(page_id)); 2588} 2589 2590void WebContentsImpl::DidChangeVisibleSSLState() { 2591 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2592 DidChangeVisibleSSLState()); 2593} 2594 2595void WebContentsImpl::NotifyBeforeFormRepostWarningShow() { 2596 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2597 BeforeFormRepostWarningShow()); 2598} 2599 2600 2601void WebContentsImpl::ActivateAndShowRepostFormWarningDialog() { 2602 Activate(); 2603 if (delegate_) 2604 delegate_->ShowRepostFormWarningDialog(this); 2605} 2606 2607// Notifies the RenderWidgetHost instance about the fact that the page is 2608// loading, or done loading. 2609void WebContentsImpl::SetIsLoading(RenderViewHost* render_view_host, 2610 bool is_loading, 2611 LoadNotificationDetails* details) { 2612 if (is_loading == is_loading_) 2613 return; 2614 2615 if (!is_loading) { 2616 load_state_ = net::LoadStateWithParam(net::LOAD_STATE_IDLE, 2617 base::string16()); 2618 load_state_host_.clear(); 2619 upload_size_ = 0; 2620 upload_position_ = 0; 2621 } 2622 2623 GetRenderManager()->SetIsLoading(is_loading); 2624 2625 is_loading_ = is_loading; 2626 waiting_for_response_ = is_loading; 2627 2628 if (delegate_) 2629 delegate_->LoadingStateChanged(this); 2630 NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD); 2631 2632 std::string url = (details ? details->url.possibly_invalid_spec() : "NULL"); 2633 if (is_loading) { 2634 TRACE_EVENT_ASYNC_BEGIN1("browser", "WebContentsImpl Loading", this, 2635 "URL", url); 2636 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2637 DidStartLoading(render_view_host)); 2638 } else { 2639 TRACE_EVENT_ASYNC_END1("browser", "WebContentsImpl Loading", this, 2640 "URL", url); 2641 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2642 DidStopLoading(render_view_host)); 2643 } 2644 2645 // TODO(avi): Remove. http://crbug.com/170921 2646 int type = is_loading ? NOTIFICATION_LOAD_START : NOTIFICATION_LOAD_STOP; 2647 NotificationDetails det = NotificationService::NoDetails(); 2648 if (details) 2649 det = Details<LoadNotificationDetails>(details); 2650 NotificationService::current()->Notify( 2651 type, Source<NavigationController>(&controller_), det); 2652} 2653 2654void WebContentsImpl::UpdateMaxPageIDIfNecessary(RenderViewHost* rvh) { 2655 // If we are creating a RVH for a restored controller, then we need to make 2656 // sure the RenderView starts with a next_page_id_ larger than the number 2657 // of restored entries. This must be called before the RenderView starts 2658 // navigating (to avoid a race between the browser updating max_page_id and 2659 // the renderer updating next_page_id_). Because of this, we only call this 2660 // from CreateRenderView and allow that to notify the RenderView for us. 2661 int max_restored_page_id = controller_.GetMaxRestoredPageID(); 2662 if (max_restored_page_id > 2663 GetMaxPageIDForSiteInstance(rvh->GetSiteInstance())) 2664 UpdateMaxPageIDForSiteInstance(rvh->GetSiteInstance(), 2665 max_restored_page_id); 2666} 2667 2668bool WebContentsImpl::UpdateTitleForEntry(NavigationEntryImpl* entry, 2669 const base::string16& title) { 2670 // For file URLs without a title, use the pathname instead. In the case of a 2671 // synthesized title, we don't want the update to count toward the "one set 2672 // per page of the title to history." 2673 base::string16 final_title; 2674 bool explicit_set; 2675 if (entry && entry->GetURL().SchemeIsFile() && title.empty()) { 2676 final_title = base::UTF8ToUTF16(entry->GetURL().ExtractFileName()); 2677 explicit_set = false; // Don't count synthetic titles toward the set limit. 2678 } else { 2679 base::TrimWhitespace(title, base::TRIM_ALL, &final_title); 2680 explicit_set = true; 2681 } 2682 2683 // If a page is created via window.open and never navigated, 2684 // there will be no navigation entry. In this situation, 2685 // |page_title_when_no_navigation_entry_| will be used for page title. 2686 if (entry) { 2687 if (final_title == entry->GetTitle()) 2688 return false; // Nothing changed, don't bother. 2689 2690 entry->SetTitle(final_title); 2691 } else { 2692 if (page_title_when_no_navigation_entry_ == final_title) 2693 return false; // Nothing changed, don't bother. 2694 2695 page_title_when_no_navigation_entry_ = final_title; 2696 } 2697 2698 // Lastly, set the title for the view. 2699 view_->SetPageTitle(final_title); 2700 2701 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2702 TitleWasSet(entry, explicit_set)); 2703 2704 // TODO(avi): Remove. http://crbug.com/170921 2705 std::pair<NavigationEntry*, bool> details = 2706 std::make_pair(entry, explicit_set); 2707 NotificationService::current()->Notify( 2708 NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED, 2709 Source<WebContents>(this), 2710 Details<std::pair<NavigationEntry*, bool> >(&details)); 2711 2712 return true; 2713} 2714 2715void WebContentsImpl::NotifySwapped(RenderViewHost* old_host, 2716 RenderViewHost* new_host) { 2717 // After sending out a swap notification, we need to send a disconnect 2718 // notification so that clients that pick up a pointer to |this| can NULL the 2719 // pointer. See Bug 1230284. 2720 notify_disconnection_ = true; 2721 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2722 RenderViewHostChanged(old_host, new_host)); 2723 2724 // TODO(avi): Remove. http://crbug.com/170921 2725 std::pair<RenderViewHost*, RenderViewHost*> details = 2726 std::make_pair(old_host, new_host); 2727 NotificationService::current()->Notify( 2728 NOTIFICATION_RENDER_VIEW_HOST_CHANGED, 2729 Source<WebContents>(this), 2730 Details<std::pair<RenderViewHost*, RenderViewHost*> >(&details)); 2731 2732 // Ensure that the associated embedder gets cleared after a RenderViewHost 2733 // gets swapped, so we don't reuse the same embedder next time a 2734 // RenderViewHost is attached to this WebContents. 2735 RemoveBrowserPluginEmbedder(); 2736} 2737 2738// TODO(avi): Remove this entire function because this notification is already 2739// covered by two observer functions. http://crbug.com/170921 2740void WebContentsImpl::NotifyDisconnected() { 2741 if (!notify_disconnection_) 2742 return; 2743 2744 notify_disconnection_ = false; 2745 NotificationService::current()->Notify( 2746 NOTIFICATION_WEB_CONTENTS_DISCONNECTED, 2747 Source<WebContents>(this), 2748 NotificationService::NoDetails()); 2749} 2750 2751void WebContentsImpl::NotifyNavigationEntryCommitted( 2752 const LoadCommittedDetails& load_details) { 2753 FOR_EACH_OBSERVER( 2754 WebContentsObserver, observers_, NavigationEntryCommitted(load_details)); 2755} 2756 2757bool WebContentsImpl::OnMessageReceived(RenderFrameHost* render_frame_host, 2758 const IPC::Message& message) { 2759 return OnMessageReceived(NULL, render_frame_host, message); 2760} 2761 2762void WebContentsImpl::RenderFrameCreated(RenderFrameHost* render_frame_host) { 2763 // Note this is only for subframes, the notification for the main frame 2764 // happens in RenderViewCreated. 2765 FOR_EACH_OBSERVER(WebContentsObserver, 2766 observers_, 2767 RenderFrameCreated(render_frame_host)); 2768} 2769 2770void WebContentsImpl::RenderFrameDeleted(RenderFrameHost* render_frame_host) { 2771 FOR_EACH_OBSERVER(WebContentsObserver, 2772 observers_, 2773 RenderFrameDeleted(render_frame_host)); 2774} 2775 2776void WebContentsImpl::WorkerCrashed(RenderFrameHost* render_frame_host) { 2777 if (delegate_) 2778 delegate_->WorkerCrashed(this); 2779} 2780 2781void WebContentsImpl::ShowContextMenu(RenderFrameHost* render_frame_host, 2782 const ContextMenuParams& params) { 2783 // Allow WebContentsDelegates to handle the context menu operation first. 2784 if (delegate_ && delegate_->HandleContextMenu(params)) 2785 return; 2786 2787 render_view_host_delegate_view_->ShowContextMenu(render_frame_host, params); 2788} 2789 2790WebContents* WebContentsImpl::GetAsWebContents() { 2791 return this; 2792} 2793 2794RenderViewHostDelegateView* WebContentsImpl::GetDelegateView() { 2795 return render_view_host_delegate_view_; 2796} 2797 2798RendererPreferences WebContentsImpl::GetRendererPrefs( 2799 BrowserContext* browser_context) const { 2800 return renderer_preferences_; 2801} 2802 2803gfx::Rect WebContentsImpl::GetRootWindowResizerRect() const { 2804 if (delegate_) 2805 return delegate_->GetRootWindowResizerRect(); 2806 return gfx::Rect(); 2807} 2808 2809void WebContentsImpl::RemoveBrowserPluginEmbedder() { 2810 if (browser_plugin_embedder_) 2811 browser_plugin_embedder_.reset(); 2812} 2813 2814void WebContentsImpl::RenderViewCreated(RenderViewHost* render_view_host) { 2815 // Don't send notifications if we are just creating a swapped-out RVH for 2816 // the opener chain. These won't be used for view-source or WebUI, so it's 2817 // ok to return early. 2818 if (static_cast<RenderViewHostImpl*>(render_view_host)->IsSwappedOut()) 2819 return; 2820 2821 if (delegate_) 2822 view_->SetOverscrollControllerEnabled(delegate_->CanOverscrollContent()); 2823 2824 NotificationService::current()->Notify( 2825 NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED, 2826 Source<WebContents>(this), 2827 Details<RenderViewHost>(render_view_host)); 2828 2829 // When we're creating views, we're still doing initial setup, so we always 2830 // use the pending Web UI rather than any possibly existing committed one. 2831 if (GetRenderManager()->pending_web_ui()) 2832 GetRenderManager()->pending_web_ui()->RenderViewCreated(render_view_host); 2833 2834 NavigationEntry* entry = controller_.GetPendingEntry(); 2835 if (entry && entry->IsViewSourceMode()) { 2836 // Put the renderer in view source mode. 2837 render_view_host->Send( 2838 new ViewMsg_EnableViewSourceMode(render_view_host->GetRoutingID())); 2839 } 2840 2841 view_->RenderViewCreated(render_view_host); 2842 2843 FOR_EACH_OBSERVER( 2844 WebContentsObserver, observers_, RenderViewCreated(render_view_host)); 2845 2846 // We tell the observers now instead of when the main RenderFrameHostImpl is 2847 // constructed because otherwise it would be too early (i.e. IPCs sent to the 2848 // frame would be dropped because it's not created yet). 2849 RenderFrameHost* main_frame = render_view_host->GetMainFrame(); 2850 FOR_EACH_OBSERVER( 2851 WebContentsObserver, observers_, RenderFrameCreated(main_frame)); 2852} 2853 2854void WebContentsImpl::RenderViewReady(RenderViewHost* rvh) { 2855 if (rvh != GetRenderViewHost()) { 2856 // Don't notify the world, since this came from a renderer in the 2857 // background. 2858 return; 2859 } 2860 2861 notify_disconnection_ = true; 2862 // TODO(avi): Remove. http://crbug.com/170921 2863 NotificationService::current()->Notify( 2864 NOTIFICATION_WEB_CONTENTS_CONNECTED, 2865 Source<WebContents>(this), 2866 NotificationService::NoDetails()); 2867 2868 bool was_crashed = IsCrashed(); 2869 SetIsCrashed(base::TERMINATION_STATUS_STILL_RUNNING, 0); 2870 2871 // Restore the focus to the tab (otherwise the focus will be on the top 2872 // window). 2873 if (was_crashed && !FocusLocationBarByDefault() && 2874 (!delegate_ || delegate_->ShouldFocusPageAfterCrash())) { 2875 view_->Focus(); 2876 } 2877 2878 FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewReady()); 2879} 2880 2881void WebContentsImpl::RenderViewTerminated(RenderViewHost* rvh, 2882 base::TerminationStatus status, 2883 int error_code) { 2884 if (rvh != GetRenderViewHost()) { 2885 // The pending page's RenderViewHost is gone. 2886 return; 2887 } 2888 2889 // Ensure fullscreen mode is exited in the |delegate_| since a crashed 2890 // renderer may not have made a clean exit. 2891 if (IsFullscreenForCurrentTab()) 2892 ToggleFullscreenMode(false); 2893 2894 // Cancel any visible dialogs so they are not left dangling over the sad tab. 2895 if (dialog_manager_) 2896 dialog_manager_->CancelActiveAndPendingDialogs(this); 2897 2898 ClearPowerSaveBlockers(rvh); 2899 SetIsLoading(rvh, false, NULL); 2900 NotifyDisconnected(); 2901 SetIsCrashed(status, error_code); 2902 GetView()->OnTabCrashed(GetCrashedStatus(), crashed_error_code_); 2903 2904 FOR_EACH_OBSERVER(WebContentsObserver, 2905 observers_, 2906 RenderProcessGone(GetCrashedStatus())); 2907} 2908 2909void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) { 2910 ClearPowerSaveBlockers(rvh); 2911 GetRenderManager()->RenderViewDeleted(rvh); 2912 FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewDeleted(rvh)); 2913} 2914 2915void WebContentsImpl::UpdateState(RenderViewHost* rvh, 2916 int32 page_id, 2917 const PageState& page_state) { 2918 // Ensure that this state update comes from either the active RVH or one of 2919 // the swapped out RVHs. We don't expect to hear from any other RVHs. 2920 // TODO(nasko): This should go through RenderFrameHost. 2921 // TODO(creis): We can't update state for cross-process subframes until we 2922 // have FrameNavigationEntries. Once we do, this should be a DCHECK. 2923 if (rvh != GetRenderViewHost() && 2924 !GetRenderManager()->IsRVHOnSwappedOutList( 2925 static_cast<RenderViewHostImpl*>(rvh))) 2926 return; 2927 2928 // We must be prepared to handle state updates for any page, these occur 2929 // when the user is scrolling and entering form data, as well as when we're 2930 // leaving a page, in which case our state may have already been moved to 2931 // the next page. The navigation controller will look up the appropriate 2932 // NavigationEntry and update it when it is notified via the delegate. 2933 2934 int entry_index = controller_.GetEntryIndexWithPageID( 2935 rvh->GetSiteInstance(), page_id); 2936 if (entry_index < 0) 2937 return; 2938 NavigationEntry* entry = controller_.GetEntryAtIndex(entry_index); 2939 2940 if (page_state == entry->GetPageState()) 2941 return; // Nothing to update. 2942 entry->SetPageState(page_state); 2943 controller_.NotifyEntryChanged(entry, entry_index); 2944} 2945 2946void WebContentsImpl::UpdateTitle(RenderViewHost* rvh, 2947 int32 page_id, 2948 const base::string16& title, 2949 base::i18n::TextDirection title_direction) { 2950 // If we have a title, that's a pretty good indication that we've started 2951 // getting useful data. 2952 SetNotWaitingForResponse(); 2953 2954 // Try to find the navigation entry, which might not be the current one. 2955 // For example, it might be from a pending RVH for the pending entry. 2956 NavigationEntryImpl* entry = controller_.GetEntryWithPageID( 2957 rvh->GetSiteInstance(), page_id); 2958 2959 // We can handle title updates when we don't have an entry in 2960 // UpdateTitleForEntry, but only if the update is from the current RVH. 2961 if (!entry && rvh != GetRenderViewHost()) 2962 return; 2963 2964 // TODO(evan): make use of title_direction. 2965 // http://code.google.com/p/chromium/issues/detail?id=27094 2966 if (!UpdateTitleForEntry(entry, title)) 2967 return; 2968 2969 // Broadcast notifications when the UI should be updated. 2970 if (entry == controller_.GetEntryAtOffset(0)) 2971 NotifyNavigationStateChanged(INVALIDATE_TYPE_TITLE); 2972} 2973 2974void WebContentsImpl::UpdateEncoding(RenderViewHost* render_view_host, 2975 const std::string& encoding) { 2976 SetEncoding(encoding); 2977} 2978 2979void WebContentsImpl::UpdateTargetURL(int32 page_id, const GURL& url) { 2980 if (delegate_) 2981 delegate_->UpdateTargetURL(this, page_id, url); 2982} 2983 2984void WebContentsImpl::Close(RenderViewHost* rvh) { 2985#if defined(OS_MACOSX) 2986 // The UI may be in an event-tracking loop, such as between the 2987 // mouse-down and mouse-up in text selection or a button click. 2988 // Defer the close until after tracking is complete, so that we 2989 // don't free objects out from under the UI. 2990 // TODO(shess): This could get more fine-grained. For instance, 2991 // closing a tab in another window while selecting text in the 2992 // current window's Omnibox should be just fine. 2993 if (view_->IsEventTracking()) { 2994 view_->CloseTabAfterEventTracking(); 2995 return; 2996 } 2997#endif 2998 2999 // Ignore this if it comes from a RenderViewHost that we aren't showing. 3000 if (delegate_ && rvh == GetRenderViewHost()) 3001 delegate_->CloseContents(this); 3002} 3003 3004void WebContentsImpl::SwappedOut(RenderViewHost* rvh) { 3005 if (rvh == GetRenderViewHost()) { 3006 // Exit fullscreen mode before the current RVH is swapped out. For numerous 3007 // cases, there is no guarantee the renderer would/could initiate an exit. 3008 // Example: http://crbug.com/347232 3009 if (IsFullscreenForCurrentTab()) { 3010 if (rvh) 3011 rvh->ExitFullscreen(); 3012 DCHECK(!IsFullscreenForCurrentTab()); 3013 } 3014 3015 if (delegate_) 3016 delegate_->SwappedOut(this); 3017 } 3018 3019 // Allow the navigation to proceed. 3020 GetRenderManager()->SwappedOut(rvh); 3021} 3022 3023void WebContentsImpl::RequestMove(const gfx::Rect& new_bounds) { 3024 if (delegate_ && delegate_->IsPopupOrPanel(this)) 3025 delegate_->MoveContents(this, new_bounds); 3026} 3027 3028void WebContentsImpl::DidStartLoading(RenderFrameHost* render_frame_host) { 3029 SetIsLoading(render_frame_host->GetRenderViewHost(), true, NULL); 3030} 3031 3032void WebContentsImpl::DidStopLoading(RenderFrameHost* render_frame_host) { 3033 scoped_ptr<LoadNotificationDetails> details; 3034 3035 // Use the last committed entry rather than the active one, in case a 3036 // pending entry has been created. 3037 NavigationEntry* entry = controller_.GetLastCommittedEntry(); 3038 Navigator* navigator = frame_tree_.root()->navigator(); 3039 3040 // An entry may not exist for a stop when loading an initial blank page or 3041 // if an iframe injected by script into a blank page finishes loading. 3042 if (entry) { 3043 base::TimeDelta elapsed = 3044 base::TimeTicks::Now() - navigator->GetCurrentLoadStart(); 3045 3046 details.reset(new LoadNotificationDetails( 3047 entry->GetVirtualURL(), 3048 entry->GetTransitionType(), 3049 elapsed, 3050 &controller_, 3051 controller_.GetCurrentEntryIndex())); 3052 } 3053 3054 SetIsLoading(render_frame_host->GetRenderViewHost(), false, details.get()); 3055} 3056 3057void WebContentsImpl::DidCancelLoading() { 3058 controller_.DiscardNonCommittedEntries(); 3059 3060 // Update the URL display. 3061 NotifyNavigationStateChanged(INVALIDATE_TYPE_URL); 3062} 3063 3064void WebContentsImpl::DidChangeLoadProgress(double progress) { 3065 if (delegate_) 3066 delegate_->LoadProgressChanged(this, progress); 3067} 3068 3069void WebContentsImpl::DidDisownOpener(RenderViewHost* rvh) { 3070 if (opener_) { 3071 // Clear our opener so that future cross-process navigations don't have an 3072 // opener assigned. 3073 RemoveDestructionObserver(opener_); 3074 opener_ = NULL; 3075 } 3076 3077 // Notify all swapped out RenderViewHosts for this tab. This is important 3078 // in case we go back to them, or if another window in those processes tries 3079 // to access window.opener. 3080 GetRenderManager()->DidDisownOpener(rvh); 3081} 3082 3083void WebContentsImpl::DidAccessInitialDocument() { 3084 // Update the URL display. 3085 NotifyNavigationStateChanged(content::INVALIDATE_TYPE_URL); 3086} 3087 3088void WebContentsImpl::DocumentAvailableInMainFrame( 3089 RenderViewHost* render_view_host) { 3090 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3091 DocumentAvailableInMainFrame()); 3092} 3093 3094void WebContentsImpl::DocumentOnLoadCompletedInMainFrame( 3095 RenderViewHost* render_view_host, 3096 int32 page_id) { 3097 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3098 DocumentOnLoadCompletedInMainFrame(page_id)); 3099 3100 // TODO(avi): Remove. http://crbug.com/170921 3101 NotificationService::current()->Notify( 3102 NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, 3103 Source<WebContents>(this), 3104 Details<int>(&page_id)); 3105} 3106 3107void WebContentsImpl::RouteCloseEvent(RenderViewHost* rvh) { 3108 // Tell the active RenderViewHost to run unload handlers and close, as long 3109 // as the request came from a RenderViewHost in the same BrowsingInstance. 3110 // In most cases, we receive this from a swapped out RenderViewHost. 3111 // It is possible to receive it from one that has just been swapped in, 3112 // in which case we might as well deliver the message anyway. 3113 if (rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance())) 3114 GetRenderViewHost()->ClosePage(); 3115} 3116 3117void WebContentsImpl::RouteMessageEvent( 3118 RenderViewHost* rvh, 3119 const ViewMsg_PostMessage_Params& params) { 3120 // Only deliver the message to the active RenderViewHost if the request 3121 // came from a RenderViewHost in the same BrowsingInstance or if this 3122 // WebContents is dedicated to a browser plugin guest. 3123 // Note: This check means that an embedder could theoretically receive a 3124 // postMessage from anyone (not just its own guests). However, this is 3125 // probably not a risk for apps since other pages won't have references 3126 // to App windows. 3127 if (!rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance()) && 3128 !GetBrowserPluginGuest() && !GetBrowserPluginEmbedder()) 3129 return; 3130 3131 ViewMsg_PostMessage_Params new_params(params); 3132 3133 if (!params.message_port_ids.empty()) { 3134 MessagePortMessageFilter* message_port_message_filter = 3135 static_cast<RenderProcessHostImpl*>(GetRenderProcessHost()) 3136 ->message_port_message_filter(); 3137 std::vector<int> new_routing_ids(params.message_port_ids.size()); 3138 for (size_t i = 0; i < params.message_port_ids.size(); ++i) { 3139 new_routing_ids[i] = message_port_message_filter->GetNextRoutingID(); 3140 MessagePortService::GetInstance()->UpdateMessagePort( 3141 params.message_port_ids[i], 3142 message_port_message_filter, 3143 new_routing_ids[i]); 3144 } 3145 new_params.new_routing_ids = new_routing_ids; 3146 } 3147 3148 // If there is a source_routing_id, translate it to the routing ID for 3149 // the equivalent swapped out RVH in the target process. If we need 3150 // to create a swapped out RVH for the source tab, we create its opener 3151 // chain as well, since those will also be accessible to the target page. 3152 if (new_params.source_routing_id != MSG_ROUTING_NONE) { 3153 // Try to look up the WebContents for the source page. 3154 WebContentsImpl* source_contents = NULL; 3155 RenderViewHostImpl* source_rvh = RenderViewHostImpl::FromID( 3156 rvh->GetProcess()->GetID(), params.source_routing_id); 3157 if (source_rvh) { 3158 source_contents = static_cast<WebContentsImpl*>( 3159 source_rvh->GetDelegate()->GetAsWebContents()); 3160 } 3161 3162 if (source_contents) { 3163 if (GetBrowserPluginGuest()) { 3164 // We create a swapped out RenderView for the embedder in the guest's 3165 // render process but we intentionally do not expose the embedder's 3166 // opener chain to it. 3167 new_params.source_routing_id = 3168 source_contents->CreateSwappedOutRenderView(GetSiteInstance()); 3169 } else { 3170 new_params.source_routing_id = 3171 source_contents->CreateOpenerRenderViews(GetSiteInstance()); 3172 } 3173 } else { 3174 // We couldn't find it, so don't pass a source frame. 3175 new_params.source_routing_id = MSG_ROUTING_NONE; 3176 } 3177 } 3178 3179 // In most cases, we receive this from a swapped out RenderViewHost. 3180 // It is possible to receive it from one that has just been swapped in, 3181 // in which case we might as well deliver the message anyway. 3182 Send(new ViewMsg_PostMessageEvent(GetRoutingID(), new_params)); 3183} 3184 3185void WebContentsImpl::RunJavaScriptMessage( 3186 RenderViewHost* rvh, 3187 const base::string16& message, 3188 const base::string16& default_prompt, 3189 const GURL& frame_url, 3190 JavaScriptMessageType javascript_message_type, 3191 IPC::Message* reply_msg, 3192 bool* did_suppress_message) { 3193 // Suppress JavaScript dialogs when requested. Also suppress messages when 3194 // showing an interstitial as it's shown over the previous page and we don't 3195 // want the hidden page's dialogs to interfere with the interstitial. 3196 bool suppress_this_message = 3197 static_cast<RenderViewHostImpl*>(rvh)->IsSwappedOut() || 3198 ShowingInterstitialPage() || 3199 !delegate_ || 3200 delegate_->ShouldSuppressDialogs() || 3201 !delegate_->GetJavaScriptDialogManager(); 3202 3203 if (!suppress_this_message) { 3204 std::string accept_lang = GetContentClient()->browser()-> 3205 GetAcceptLangs(GetBrowserContext()); 3206 dialog_manager_ = delegate_->GetJavaScriptDialogManager(); 3207 dialog_manager_->RunJavaScriptDialog( 3208 this, 3209 frame_url.GetOrigin(), 3210 accept_lang, 3211 javascript_message_type, 3212 message, 3213 default_prompt, 3214 base::Bind(&WebContentsImpl::OnDialogClosed, 3215 base::Unretained(this), 3216 rvh, 3217 reply_msg), 3218 &suppress_this_message); 3219 } 3220 3221 *did_suppress_message = suppress_this_message; 3222 3223 if (suppress_this_message) { 3224 // If we are suppressing messages, just reply as if the user immediately 3225 // pressed "Cancel". 3226 OnDialogClosed(rvh, reply_msg, false, base::string16()); 3227 } 3228 3229 // OnDialogClosed (two lines up) may have caused deletion of this object (see 3230 // http://crbug.com/288961 ). The only safe thing to do here is return. 3231} 3232 3233void WebContentsImpl::RunBeforeUnloadConfirm(RenderViewHost* rvh, 3234 const base::string16& message, 3235 bool is_reload, 3236 IPC::Message* reply_msg) { 3237 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(rvh); 3238 if (delegate_) 3239 delegate_->WillRunBeforeUnloadConfirm(); 3240 3241 bool suppress_this_message = 3242 rvhi->rvh_state() != RenderViewHostImpl::STATE_DEFAULT || 3243 !delegate_ || 3244 delegate_->ShouldSuppressDialogs() || 3245 !delegate_->GetJavaScriptDialogManager(); 3246 if (suppress_this_message) { 3247 // The reply must be sent to the RVH that sent the request. 3248 rvhi->JavaScriptDialogClosed(reply_msg, true, base::string16()); 3249 return; 3250 } 3251 3252 is_showing_before_unload_dialog_ = true; 3253 dialog_manager_ = delegate_->GetJavaScriptDialogManager(); 3254 dialog_manager_->RunBeforeUnloadDialog( 3255 this, message, is_reload, 3256 base::Bind(&WebContentsImpl::OnDialogClosed, base::Unretained(this), rvh, 3257 reply_msg)); 3258} 3259 3260bool WebContentsImpl::AddMessageToConsole(int32 level, 3261 const base::string16& message, 3262 int32 line_no, 3263 const base::string16& source_id) { 3264 if (!delegate_) 3265 return false; 3266 return delegate_->AddMessageToConsole(this, level, message, line_no, 3267 source_id); 3268} 3269 3270WebPreferences WebContentsImpl::GetWebkitPrefs() { 3271 // We want to base the page config off of the actual URL, rather than the 3272 // virtual URL. 3273 // TODO(nasko): Investigate how to remove the GetActiveEntry usage here, 3274 // as it is deprecated and can be out of sync with GetRenderViewHost(). 3275 GURL url = controller_.GetActiveEntry() 3276 ? controller_.GetActiveEntry()->GetURL() : GURL::EmptyGURL(); 3277 3278 return GetRenderManager()->current_host()->GetWebkitPrefs(url); 3279} 3280 3281int WebContentsImpl::CreateSwappedOutRenderView( 3282 SiteInstance* instance) { 3283 return GetRenderManager()->CreateRenderFrame(instance, MSG_ROUTING_NONE, 3284 true, true); 3285} 3286 3287void WebContentsImpl::OnUserGesture() { 3288 // Notify observers. 3289 FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetUserGesture()); 3290 3291 ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get(); 3292 if (rdh) // NULL in unittests. 3293 rdh->OnUserGesture(this); 3294} 3295 3296void WebContentsImpl::OnIgnoredUIEvent() { 3297 // Notify observers. 3298 FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetIgnoredUIEvent()); 3299} 3300 3301void WebContentsImpl::RendererUnresponsive(RenderViewHost* rvh, 3302 bool is_during_beforeunload, 3303 bool is_during_unload) { 3304 // Don't show hung renderer dialog for a swapped out RVH. 3305 if (rvh != GetRenderViewHost()) 3306 return; 3307 3308 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(rvh); 3309 3310 // Ignore renderer unresponsive event if debugger is attached to the tab 3311 // since the event may be a result of the renderer sitting on a breakpoint. 3312 // See http://crbug.com/65458 3313 if (DevToolsAgentHost::IsDebuggerAttached(this)) 3314 return; 3315 3316 if (is_during_beforeunload || is_during_unload) { 3317 // Hang occurred while firing the beforeunload/unload handler. 3318 // Pretend the handler fired so tab closing continues as if it had. 3319 rvhi->set_sudden_termination_allowed(true); 3320 3321 if (!GetRenderManager()->ShouldCloseTabOnUnresponsiveRenderer()) 3322 return; 3323 3324 // If the tab hangs in the beforeunload/unload handler there's really 3325 // nothing we can do to recover. If the hang is in the beforeunload handler, 3326 // pretend the beforeunload listeners have all fired and allow the delegate 3327 // to continue closing; the user will not have the option of cancelling the 3328 // close. Otherwise, pretend the unload listeners have all fired and close 3329 // the tab. 3330 bool close = true; 3331 if (is_during_beforeunload) { 3332 delegate_->BeforeUnloadFired(this, true, &close); 3333 } 3334 if (close) 3335 Close(rvh); 3336 return; 3337 } 3338 3339 if (!GetRenderViewHostImpl() || !GetRenderViewHostImpl()->IsRenderViewLive()) 3340 return; 3341 3342 if (delegate_) 3343 delegate_->RendererUnresponsive(this); 3344} 3345 3346void WebContentsImpl::RendererResponsive(RenderViewHost* render_view_host) { 3347 if (delegate_) 3348 delegate_->RendererResponsive(this); 3349} 3350 3351void WebContentsImpl::LoadStateChanged( 3352 const GURL& url, 3353 const net::LoadStateWithParam& load_state, 3354 uint64 upload_position, 3355 uint64 upload_size) { 3356 load_state_ = load_state; 3357 upload_position_ = upload_position; 3358 upload_size_ = upload_size; 3359 load_state_host_ = net::IDNToUnicode(url.host(), 3360 GetContentClient()->browser()->GetAcceptLangs( 3361 GetBrowserContext())); 3362 if (load_state_.state == net::LOAD_STATE_READING_RESPONSE) 3363 SetNotWaitingForResponse(); 3364 if (IsLoading()) { 3365 NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD | INVALIDATE_TYPE_TAB); 3366 } 3367} 3368 3369void WebContentsImpl::BeforeUnloadFiredFromRenderManager( 3370 bool proceed, const base::TimeTicks& proceed_time, 3371 bool* proceed_to_fire_unload) { 3372 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3373 BeforeUnloadFired(proceed_time)); 3374 if (delegate_) 3375 delegate_->BeforeUnloadFired(this, proceed, proceed_to_fire_unload); 3376 // Note: |this| might be deleted at this point. 3377} 3378 3379void WebContentsImpl::RenderProcessGoneFromRenderManager( 3380 RenderViewHost* render_view_host) { 3381 DCHECK(crashed_status_ != base::TERMINATION_STATUS_STILL_RUNNING); 3382 RenderViewTerminated(render_view_host, crashed_status_, crashed_error_code_); 3383} 3384 3385void WebContentsImpl::UpdateRenderViewSizeForRenderManager() { 3386 // TODO(brettw) this is a hack. See WebContentsView::SizeContents. 3387 gfx::Size size = GetSizeForNewRenderView(); 3388 // 0x0 isn't a valid window size (minimal window size is 1x1) but it may be 3389 // here during container initialization and normal window size will be set 3390 // later. In case of tab duplication this resizing to 0x0 prevents setting 3391 // normal size later so just ignore it. 3392 if (!size.IsEmpty()) 3393 view_->SizeContents(size); 3394} 3395 3396void WebContentsImpl::CancelModalDialogsForRenderManager() { 3397 // We need to cancel modal dialogs when doing a process swap, since the load 3398 // deferrer would prevent us from swapping out. 3399 if (dialog_manager_) 3400 dialog_manager_->CancelActiveAndPendingDialogs(this); 3401} 3402 3403void WebContentsImpl::NotifySwappedFromRenderManager(RenderViewHost* old_host, 3404 RenderViewHost* new_host) { 3405 NotifySwapped(old_host, new_host); 3406 3407 // Make sure the visible RVH reflects the new delegate's preferences. 3408 if (delegate_) 3409 view_->SetOverscrollControllerEnabled(delegate_->CanOverscrollContent()); 3410 3411 view_->RenderViewSwappedIn(new_host); 3412} 3413 3414int WebContentsImpl::CreateOpenerRenderViewsForRenderManager( 3415 SiteInstance* instance) { 3416 if (!opener_) 3417 return MSG_ROUTING_NONE; 3418 3419 // Recursively create RenderViews for anything else in the opener chain. 3420 return opener_->CreateOpenerRenderViews(instance); 3421} 3422 3423int WebContentsImpl::CreateOpenerRenderViews(SiteInstance* instance) { 3424 int opener_route_id = MSG_ROUTING_NONE; 3425 3426 // If this tab has an opener, ensure it has a RenderView in the given 3427 // SiteInstance as well. 3428 if (opener_) 3429 opener_route_id = opener_->CreateOpenerRenderViews(instance); 3430 3431 // If any of the renderers (current, pending, or swapped out) for this 3432 // WebContents has the same SiteInstance, use it. 3433 if (GetRenderManager()->current_host()->GetSiteInstance() == instance) 3434 return GetRenderManager()->current_host()->GetRoutingID(); 3435 3436 if (GetRenderManager()->pending_render_view_host() && 3437 GetRenderManager()->pending_render_view_host()->GetSiteInstance() == 3438 instance) 3439 return GetRenderManager()->pending_render_view_host()->GetRoutingID(); 3440 3441 RenderViewHostImpl* rvh = GetRenderManager()->GetSwappedOutRenderViewHost( 3442 instance); 3443 if (rvh) 3444 return rvh->GetRoutingID(); 3445 3446 // Create a swapped out RenderView in the given SiteInstance if none exists, 3447 // setting its opener to the given route_id. Return the new view's route_id. 3448 return GetRenderManager()->CreateRenderFrame(instance, opener_route_id, 3449 true, true); 3450} 3451 3452NavigationControllerImpl& WebContentsImpl::GetControllerForRenderManager() { 3453 return GetController(); 3454} 3455 3456WebUIImpl* WebContentsImpl::CreateWebUIForRenderManager(const GURL& url) { 3457 return static_cast<WebUIImpl*>(CreateWebUI(url)); 3458} 3459 3460NavigationEntry* 3461 WebContentsImpl::GetLastCommittedNavigationEntryForRenderManager() { 3462 return controller_.GetLastCommittedEntry(); 3463} 3464 3465bool WebContentsImpl::CreateRenderViewForRenderManager( 3466 RenderViewHost* render_view_host, 3467 int opener_route_id, 3468 CrossProcessFrameConnector* frame_connector) { 3469 TRACE_EVENT0("browser", "WebContentsImpl::CreateRenderViewForRenderManager"); 3470 // Can be NULL during tests. 3471 RenderWidgetHostView* rwh_view; 3472 // TODO(kenrb): RenderWidgetHostViewChildFrame special casing is temporary 3473 // until RenderWidgetHost is attached to RenderFrameHost. We need to special 3474 // case this because RWH is still a base class of RenderViewHost, and child 3475 // frame RWHVs are unique in that they do not have their own WebContents. 3476 if (frame_connector) { 3477 RenderWidgetHostViewChildFrame* rwh_view_child = 3478 new RenderWidgetHostViewChildFrame(render_view_host); 3479 frame_connector->set_view(rwh_view_child); 3480 rwh_view = rwh_view_child; 3481 } else { 3482 rwh_view = view_->CreateViewForWidget(render_view_host); 3483 } 3484 3485 // Now that the RenderView has been created, we need to tell it its size. 3486 if (rwh_view) 3487 rwh_view->SetSize(GetSizeForNewRenderView()); 3488 3489 // Make sure we use the correct starting page_id in the new RenderView. 3490 UpdateMaxPageIDIfNecessary(render_view_host); 3491 int32 max_page_id = 3492 GetMaxPageIDForSiteInstance(render_view_host->GetSiteInstance()); 3493 3494 if (!static_cast<RenderViewHostImpl*>( 3495 render_view_host)->CreateRenderView(base::string16(), 3496 opener_route_id, 3497 max_page_id)) { 3498 return false; 3499 } 3500 3501#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 3502 // Force a ViewMsg_Resize to be sent, needed to make plugins show up on 3503 // linux. See crbug.com/83941. 3504 if (rwh_view) { 3505 if (RenderWidgetHost* render_widget_host = rwh_view->GetRenderWidgetHost()) 3506 render_widget_host->WasResized(); 3507 } 3508#endif 3509 3510 return true; 3511} 3512 3513#if defined(OS_ANDROID) 3514base::android::ScopedJavaLocalRef<jobject> 3515WebContentsImpl::GetJavaWebContents() { 3516 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 3517 3518 WebContentsAndroid* web_contents_android = 3519 static_cast<WebContentsAndroid*>(GetUserData(kWebContentsAndroidKey)); 3520 if (!web_contents_android) { 3521 web_contents_android = new WebContentsAndroid(this); 3522 SetUserData(kWebContentsAndroidKey, web_contents_android); 3523 } 3524 return web_contents_android->GetJavaObject(); 3525} 3526 3527bool WebContentsImpl::CreateRenderViewForInitialEmptyDocument() { 3528 return CreateRenderViewForRenderManager(GetRenderViewHost(), 3529 MSG_ROUTING_NONE, 3530 NULL); 3531} 3532#endif 3533 3534void WebContentsImpl::OnDialogClosed(RenderViewHost* rvh, 3535 IPC::Message* reply_msg, 3536 bool success, 3537 const base::string16& user_input) { 3538 if (is_showing_before_unload_dialog_ && !success) { 3539 // If a beforeunload dialog is canceled, we need to stop the throbber from 3540 // spinning, since we forced it to start spinning in Navigate. 3541 DidStopLoading(rvh->GetMainFrame()); 3542 controller_.DiscardNonCommittedEntries(); 3543 3544 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3545 BeforeUnloadDialogCancelled()); 3546 } 3547 is_showing_before_unload_dialog_ = false; 3548 static_cast<RenderViewHostImpl*>( 3549 rvh)->JavaScriptDialogClosed(reply_msg, success, user_input); 3550} 3551 3552void WebContentsImpl::SetEncoding(const std::string& encoding) { 3553 encoding_ = GetContentClient()->browser()-> 3554 GetCanonicalEncodingNameByAliasName(encoding); 3555} 3556 3557void WebContentsImpl::CreateViewAndSetSizeForRVH(RenderViewHost* rvh) { 3558 RenderWidgetHostView* rwh_view = view_->CreateViewForWidget(rvh); 3559 // Can be NULL during tests. 3560 if (rwh_view) 3561 rwh_view->SetSize(GetView()->GetContainerSize()); 3562} 3563 3564bool WebContentsImpl::IsHidden() { 3565 return capturer_count_ == 0 && !should_normally_be_visible_; 3566} 3567 3568RenderFrameHostManager* WebContentsImpl::GetRenderManager() const { 3569 return frame_tree_.root()->render_manager(); 3570} 3571 3572RenderViewHostImpl* WebContentsImpl::GetRenderViewHostImpl() { 3573 return static_cast<RenderViewHostImpl*>(GetRenderViewHost()); 3574} 3575 3576BrowserPluginGuest* WebContentsImpl::GetBrowserPluginGuest() const { 3577 return browser_plugin_guest_.get(); 3578} 3579 3580void WebContentsImpl::SetBrowserPluginGuest(BrowserPluginGuest* guest) { 3581 CHECK(!browser_plugin_guest_); 3582 browser_plugin_guest_.reset(guest); 3583} 3584 3585BrowserPluginEmbedder* WebContentsImpl::GetBrowserPluginEmbedder() const { 3586 return browser_plugin_embedder_.get(); 3587} 3588 3589BrowserPluginGuestManager* 3590 WebContentsImpl::GetBrowserPluginGuestManager() const { 3591 return static_cast<BrowserPluginGuestManager*>( 3592 GetBrowserContext()->GetUserData( 3593 browser_plugin::kBrowserPluginGuestManagerKeyName)); 3594} 3595 3596void WebContentsImpl::ClearPowerSaveBlockers( 3597 RenderViewHost* render_view_host) { 3598 STLDeleteValues(&power_save_blockers_[render_view_host]); 3599 power_save_blockers_.erase(render_view_host); 3600} 3601 3602void WebContentsImpl::ClearAllPowerSaveBlockers() { 3603 for (PowerSaveBlockerMap::iterator i(power_save_blockers_.begin()); 3604 i != power_save_blockers_.end(); ++i) 3605 STLDeleteValues(&power_save_blockers_[i->first]); 3606 power_save_blockers_.clear(); 3607} 3608 3609gfx::Size WebContentsImpl::GetSizeForNewRenderView() const { 3610 gfx::Size size; 3611 if (delegate_) 3612 size = delegate_->GetSizeForNewRenderView(this); 3613 if (size.IsEmpty()) 3614 size = view_->GetContainerSize(); 3615 return size; 3616} 3617 3618void WebContentsImpl::OnFrameRemoved( 3619 RenderViewHostImpl* render_view_host, 3620 int frame_routing_id) { 3621 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3622 FrameDetached(render_view_host, frame_routing_id)); 3623} 3624 3625void WebContentsImpl::OnPreferredSizeChanged(const gfx::Size& old_size) { 3626 if (!delegate_) 3627 return; 3628 const gfx::Size new_size = GetPreferredSize(); 3629 if (new_size != old_size) 3630 delegate_->UpdatePreferredSize(this, new_size); 3631} 3632 3633} // namespace content 3634