web_contents_impl.cc revision 58537e28ecd584eab876aee8be7156509866d23a
146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/web_contents/web_contents_impl.h" 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility> 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/command_line.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/metrics/stats_counters.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string16.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string_util.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sys_info.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/time/time.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "cc/base/switches.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/browser_plugin/browser_plugin_embedder.h" 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/browser_plugin/browser_plugin_guest.h" 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/browser_plugin/browser_plugin_guest_manager.h" 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/child_process_security_policy_impl.h" 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/devtools/devtools_manager_impl.h" 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/dom_storage/dom_storage_context_wrapper.h" 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/dom_storage/session_storage_namespace_impl.h" 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/download/download_stats.h" 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/download/mhtml_generation_manager.h" 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/download/save_package.h" 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/gpu/compositor_util.h" 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/gpu/gpu_data_manager_impl.h" 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/gpu/gpu_process_host.h" 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/host_zoom_map_impl.h" 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/loader/resource_dispatcher_host_impl.h" 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/power_save_blocker_impl.h" 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/renderer_host/render_process_host_impl.h" 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/renderer_host/render_view_host_impl.h" 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/renderer_host/render_widget_host_impl.h" 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/site_instance_impl.h" 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/web_contents/interstitial_page_impl.h" 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/web_contents/navigation_entry_impl.h" 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/web_contents/web_contents_view_guest.h" 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/webui/generic_handler.h" 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/webui/web_ui_controller_factory_registry.h" 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/webui/web_ui_impl.h" 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/common/browser_plugin/browser_plugin_constants.h" 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/common/browser_plugin/browser_plugin_messages.h" 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/common/image_messages.h" 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/common/ssl_status_serialization.h" 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/common/view_messages.h" 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/port/browser/render_view_host_delegate_view.h" 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/port/browser/render_widget_host_view_port.h" 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/browser_context.h" 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/color_chooser.h" 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/content_browser_client.h" 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/devtools_agent_host.h" 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/download_manager.h" 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/download_url_parameters.h" 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/invalidate_type.h" 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/javascript_dialog_manager.h" 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/load_from_memory_cache_details.h" 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/load_notification_details.h" 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/navigation_details.h" 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/notification_details.h" 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h" 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/resource_request_details.h" 697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/public/browser/storage_partition.h" 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/user_metrics.h" 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/web_contents_delegate.h" 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/web_contents_observer.h" 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/web_contents_view.h" 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/bindings_policy.h" 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/content_constants.h" 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/content_switches.h" 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/page_zoom.h" 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/common/url_constants.h" 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/base/mime_util.h" 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/base/net_util.h" 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/base/network_change_notifier.h" 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_cache.h" 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_transaction_factory.h" 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context.h" 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h" 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/layout.h" 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/touch/touch_device.h" 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/touch/touch_enabled.h" 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/ui_base_switches.h" 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/display.h" 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/screen.h" 927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ui/gl/gl_switches.h" 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "webkit/common/webpreferences.h" 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/android/date_time_chooser_android.h" 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/android/content_view_core.h" 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_MACOSX) 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/mac/foundation_util.h" 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gl/io_surface_support_mac.h" 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_ANDROID) 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h" 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Cross-Site Navigations 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// If a WebContentsImpl is told to navigate to a different web site (as 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// determined by SiteInstance), it will replace its current RenderViewHost with 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// a new RenderViewHost dedicated to the new SiteInstance. This works as 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// follows: 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Navigate determines whether the destination is cross-site, and if so, 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it creates a pending_render_view_host_. 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - The pending RVH is "suspended," so that no navigation messages are sent to 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// its renderer until the onbeforeunload JavaScript handler has a chance to 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// run in the current RVH. 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// - The pending RVH tells CrossSiteRequestManager (a thread-safe singleton) 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// that it has a pending cross-site request. ResourceDispatcherHost will 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// check for this when the response arrives. 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// - The current RVH runs its onbeforeunload handler. If it returns false, we 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// cancel all the pending logic. Otherwise we allow the pending RVH to send 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// the navigation request to its renderer. 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// - ResourceDispatcherHost receives a ResourceRequest on the IO thread for the 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// main resource load on the pending RVH. It checks CrossSiteRequestManager 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// to see that it is a cross-site request, and installs a 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// CrossSiteResourceHandler. 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// - When RDH receives a response, the BufferedResourceHandler determines 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// whether it is a download. If so, it sends a message to the new renderer 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// causing it to cancel the request, and the download proceeds. For now, the 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// pending RVH remains until the next DidNavigate event for this 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// WebContentsImpl. This isn't ideal, but it doesn't affect any functionality. 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// - After RDH receives a response and determines that it is safe and not a 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// download, it pauses the response to first run the old page's onunload 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// handler. It does this by asynchronously calling the OnCrossSiteResponse 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// method of WebContentsImpl on the UI thread, which sends a SwapOut message 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// to the current RVH. 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// - Once the onunload handler is finished, a SwapOut_ACK message is sent to 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// the ResourceDispatcherHost, who unpauses the response. Data is then sent 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// to the pending RVH. 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// - The pending renderer sends a FrameNavigate message that invokes the 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// DidNavigate method. This replaces the current RVH with the 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// pending RVH. 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// - The previous renderer is kept swapped out in RenderViewHostManager in case 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// the user goes back. The process only stays live if another tab is using 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// it, but if so, the existing frame relationships will be maintained. 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace content { 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Amount of time we wait between when a key event is received and the renderer 1550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// is queried for its state and pushed to the NavigationEntry. 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int kQueryStateDelay = 5000; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kSyncWaitDelay = 40; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kDotGoogleDotCom[] = ".google.com"; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::LazyInstance<std::vector<WebContents::CreatedCallback> > 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)g_created_callbacks = LAZY_INSTANCE_INITIALIZER; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int StartDownload(content::RenderViewHost* rvh, 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_favicon, 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t preferred_image_size, 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t max_image_size) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int g_next_image_download_id = 0; 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rvh->Send(new ImageMsg_DownloadImage(rvh->GetRoutingID(), 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++g_next_image_download_id, 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url, 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_favicon, 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) preferred_image_size, 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) max_image_size)); 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return g_next_image_download_id; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ViewMsg_Navigate_Type::Value GetNavigationType( 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserContext* browser_context, const NavigationEntryImpl& entry, 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NavigationController::ReloadType reload_type) { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (reload_type) { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case NavigationControllerImpl::RELOAD: 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ViewMsg_Navigate_Type::RELOAD; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case NavigationControllerImpl::RELOAD_IGNORING_CACHE: 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ViewMsg_Navigate_Type::RELOAD_IGNORING_CACHE; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case NavigationControllerImpl::RELOAD_ORIGINAL_REQUEST_URL: 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ViewMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case NavigationControllerImpl::NO_RELOAD: 191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; // Fall through to rest of function. 192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // |RenderViewImpl::PopulateStateFromPendingNavigationParams| differentiates 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // between |RESTORE_WITH_POST| and |RESTORE|. 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (entry.restore_type() == 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NavigationEntryImpl::RESTORE_LAST_SESSION_EXITED_CLEANLY) { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry.GetHasPostData()) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ViewMsg_Navigate_Type::RESTORE_WITH_POST; 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return ViewMsg_Navigate_Type::RESTORE; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ViewMsg_Navigate_Type::NORMAL; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid MakeNavigateParams(const NavigationEntryImpl& entry, 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const NavigationControllerImpl& controller, 208 WebContentsDelegate* delegate, 209 NavigationController::ReloadType reload_type, 210 ViewMsg_Navigate_Params* params) { 211 params->page_id = entry.GetPageID(); 212 params->should_clear_history_list = entry.should_clear_history_list(); 213 if (entry.should_clear_history_list()) { 214 // Set the history list related parameters to the same values a 215 // NavigationController would return before its first navigation. This will 216 // fully clear the RenderView's view of the session history. 217 params->pending_history_list_offset = -1; 218 params->current_history_list_offset = -1; 219 params->current_history_list_length = 0; 220 } else { 221 params->pending_history_list_offset = controller.GetIndexOfEntry(&entry); 222 params->current_history_list_offset = 223 controller.GetLastCommittedEntryIndex(); 224 params->current_history_list_length = controller.GetEntryCount(); 225 } 226 if (!entry.GetBaseURLForDataURL().is_empty()) { 227 params->base_url_for_data_url = entry.GetBaseURLForDataURL(); 228 params->history_url_for_data_url = entry.GetVirtualURL(); 229 } 230 params->referrer = entry.GetReferrer(); 231 params->transition = entry.GetTransitionType(); 232 params->page_state = entry.GetPageState(); 233 params->navigation_type = 234 GetNavigationType(controller.GetBrowserContext(), entry, reload_type); 235 params->request_time = base::Time::Now(); 236 params->extra_headers = entry.extra_headers(); 237 params->transferred_request_child_id = 238 entry.transferred_global_request_id().child_id; 239 params->transferred_request_request_id = 240 entry.transferred_global_request_id().request_id; 241 params->is_overriding_user_agent = entry.GetIsOverridingUserAgent(); 242 // Avoid downloading when in view-source mode. 243 params->allow_download = !entry.IsViewSourceMode(); 244 params->is_post = entry.GetHasPostData(); 245 if(entry.GetBrowserInitiatedPostData()) { 246 params->browser_initiated_post_data.assign( 247 entry.GetBrowserInitiatedPostData()->front(), 248 entry.GetBrowserInitiatedPostData()->front() + 249 entry.GetBrowserInitiatedPostData()->size()); 250 251 } 252 253 if (reload_type == NavigationControllerImpl::RELOAD_ORIGINAL_REQUEST_URL && 254 entry.GetOriginalRequestURL().is_valid() && !entry.GetHasPostData()) { 255 // We may have been redirected when navigating to the current URL. 256 // Use the URL the user originally intended to visit, if it's valid and if a 257 // POST wasn't involved; the latter case avoids issues with sending data to 258 // the wrong page. 259 params->url = entry.GetOriginalRequestURL(); 260 } else { 261 params->url = entry.GetURL(); 262 } 263 264 params->can_load_local_resources = entry.GetCanLoadLocalResources(); 265 params->frame_to_navigate = entry.GetFrameToNavigate(); 266 267 if (delegate) 268 delegate->AddNavigationHeaders(params->url, ¶ms->extra_headers); 269} 270 271void NotifyCacheOnIO( 272 scoped_refptr<net::URLRequestContextGetter> request_context, 273 const GURL& url, 274 const std::string& http_method) { 275 request_context->GetURLRequestContext()->http_transaction_factory()-> 276 GetCache()->OnExternalCacheHit(url, http_method); 277} 278 279} // namespace 280 281WebContents* WebContents::Create(const WebContents::CreateParams& params) { 282 return WebContentsImpl::CreateWithOpener( 283 params, static_cast<WebContentsImpl*>(params.opener)); 284} 285 286WebContents* WebContents::CreateWithSessionStorage( 287 const WebContents::CreateParams& params, 288 const SessionStorageNamespaceMap& session_storage_namespace_map) { 289 WebContentsImpl* new_contents = new WebContentsImpl( 290 params.browser_context, NULL); 291 292 for (SessionStorageNamespaceMap::const_iterator it = 293 session_storage_namespace_map.begin(); 294 it != session_storage_namespace_map.end(); 295 ++it) { 296 new_contents->GetController() 297 .SetSessionStorageNamespace(it->first, it->second.get()); 298 } 299 300 new_contents->Init(params); 301 return new_contents; 302} 303 304void WebContents::AddCreatedCallback(const CreatedCallback& callback) { 305 g_created_callbacks.Get().push_back(callback); 306} 307 308void WebContents::RemoveCreatedCallback(const CreatedCallback& callback) { 309 for (size_t i = 0; i < g_created_callbacks.Get().size(); ++i) { 310 if (g_created_callbacks.Get().at(i).Equals(callback)) { 311 g_created_callbacks.Get().erase(g_created_callbacks.Get().begin() + i); 312 return; 313 } 314 } 315} 316 317WebContents* WebContents::FromRenderViewHost(const RenderViewHost* rvh) { 318 return rvh->GetDelegate()->GetAsWebContents(); 319} 320 321// WebContentsImpl::DestructionObserver ---------------------------------------- 322 323class WebContentsImpl::DestructionObserver : public WebContentsObserver { 324 public: 325 DestructionObserver(WebContentsImpl* owner, WebContents* watched_contents) 326 : WebContentsObserver(watched_contents), 327 owner_(owner) { 328 } 329 330 // WebContentsObserver: 331 virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE { 332 owner_->OnWebContentsDestroyed(static_cast<WebContentsImpl*>(web_contents)); 333 } 334 335 private: 336 WebContentsImpl* owner_; 337 338 DISALLOW_COPY_AND_ASSIGN(DestructionObserver); 339}; 340 341// WebContentsImpl ------------------------------------------------------------- 342 343WebContentsImpl::WebContentsImpl( 344 BrowserContext* browser_context, 345 WebContentsImpl* opener) 346 : delegate_(NULL), 347 controller_(this, browser_context), 348 render_view_host_delegate_view_(NULL), 349 opener_(opener), 350#if defined(OS_WIN) && defined(USE_AURA) 351 accessible_parent_(NULL), 352#endif 353 render_manager_(this, this, this), 354 is_loading_(false), 355 crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING), 356 crashed_error_code_(0), 357 waiting_for_response_(false), 358 load_state_(net::LOAD_STATE_IDLE, string16()), 359 upload_size_(0), 360 upload_position_(0), 361 displayed_insecure_content_(false), 362 capturer_count_(0), 363 should_normally_be_visible_(true), 364 is_being_destroyed_(false), 365 notify_disconnection_(false), 366 dialog_manager_(NULL), 367 is_showing_before_unload_dialog_(false), 368 closed_by_user_gesture_(false), 369 minimum_zoom_percent_(static_cast<int>(kMinimumZoomFactor * 100)), 370 maximum_zoom_percent_(static_cast<int>(kMaximumZoomFactor * 100)), 371 temporary_zoom_settings_(false), 372 color_chooser_identifier_(0), 373 message_source_(NULL), 374 fullscreen_widget_routing_id_(MSG_ROUTING_NONE) { 375 for (size_t i = 0; i < g_created_callbacks.Get().size(); i++) 376 g_created_callbacks.Get().at(i).Run(this); 377} 378 379WebContentsImpl::~WebContentsImpl() { 380 is_being_destroyed_ = true; 381 382 ClearAllPowerSaveBlockers(); 383 384 for (std::set<RenderWidgetHostImpl*>::iterator iter = 385 created_widgets_.begin(); iter != created_widgets_.end(); ++iter) { 386 (*iter)->DetachDelegate(); 387 } 388 created_widgets_.clear(); 389 390 // Clear out any JavaScript state. 391 if (dialog_manager_) 392 dialog_manager_->WebContentsDestroyed(this); 393 394 if (color_chooser_) 395 color_chooser_->End(); 396 397 NotifyDisconnected(); 398 399 // Notify any observer that have a reference on this WebContents. 400 NotificationService::current()->Notify( 401 NOTIFICATION_WEB_CONTENTS_DESTROYED, 402 Source<WebContents>(this), 403 NotificationService::NoDetails()); 404 405 // TODO(brettw) this should be moved to the view. 406#if defined(OS_WIN) && !defined(USE_AURA) 407 // If we still have a window handle, destroy it. GetNativeView can return 408 // NULL if this contents was part of a window that closed. 409 if (view_->GetNativeView()) { 410 RenderViewHost* host = GetRenderViewHost(); 411 if (host && host->GetView()) 412 RenderWidgetHostViewPort::FromRWHV(host->GetView())->WillWmDestroy(); 413 } 414#endif 415 416 FOR_EACH_OBSERVER(WebContentsObserver, 417 observers_, 418 WebContentsImplDestroyed()); 419 420 SetDelegate(NULL); 421 422 STLDeleteContainerPairSecondPointers(destruction_observers_.begin(), 423 destruction_observers_.end()); 424} 425 426WebContentsImpl* WebContentsImpl::CreateWithOpener( 427 const WebContents::CreateParams& params, 428 WebContentsImpl* opener) { 429 TRACE_EVENT0("browser", "WebContentsImpl::CreateWithOpener"); 430 WebContentsImpl* new_contents = new WebContentsImpl( 431 params.browser_context, opener); 432 433 new_contents->Init(params); 434 return new_contents; 435} 436 437// static 438BrowserPluginGuest* WebContentsImpl::CreateGuest( 439 BrowserContext* browser_context, 440 SiteInstance* site_instance, 441 int guest_instance_id, 442 scoped_ptr<base::DictionaryValue> extra_params) { 443 WebContentsImpl* new_contents = new WebContentsImpl(browser_context, NULL); 444 445 // This makes |new_contents| act as a guest. 446 // For more info, see comment above class BrowserPluginGuest. 447 BrowserPluginGuest::Create( 448 guest_instance_id, new_contents, extra_params.Pass()); 449 450 WebContents::CreateParams create_params(browser_context, site_instance); 451 new_contents->Init(create_params); 452 453 // We are instantiating a WebContents for browser plugin. Set its subframe bit 454 // to true. 455 static_cast<RenderViewHostImpl*>( 456 new_contents->GetRenderViewHost())->set_is_subframe(true); 457 458 return new_contents->browser_plugin_guest_.get(); 459} 460 461WebPreferences WebContentsImpl::GetWebkitPrefs(RenderViewHost* rvh, 462 const GURL& url) { 463 TRACE_EVENT0("browser", "WebContentsImpl::GetWebkitPrefs"); 464 WebPreferences prefs; 465 466 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 467 468 prefs.javascript_enabled = 469 !command_line.HasSwitch(switches::kDisableJavaScript); 470 prefs.web_security_enabled = 471 !command_line.HasSwitch(switches::kDisableWebSecurity); 472 prefs.plugins_enabled = 473 !command_line.HasSwitch(switches::kDisablePlugins); 474 prefs.java_enabled = 475 !command_line.HasSwitch(switches::kDisableJava); 476 477 prefs.remote_fonts_enabled = 478 !command_line.HasSwitch(switches::kDisableRemoteFonts); 479 prefs.xss_auditor_enabled = 480 !command_line.HasSwitch(switches::kDisableXSSAuditor); 481 prefs.application_cache_enabled = 482 !command_line.HasSwitch(switches::kDisableApplicationCache); 483 484 prefs.local_storage_enabled = 485 !command_line.HasSwitch(switches::kDisableLocalStorage); 486 prefs.databases_enabled = 487 !command_line.HasSwitch(switches::kDisableDatabases); 488 prefs.webaudio_enabled = 489 !command_line.HasSwitch(switches::kDisableWebAudio); 490 491 prefs.experimental_webgl_enabled = 492 GpuProcessHost::gpu_enabled() && 493 !command_line.HasSwitch(switches::kDisable3DAPIs) && 494 !command_line.HasSwitch(switches::kDisableExperimentalWebGL); 495 496 prefs.flash_3d_enabled = 497 GpuProcessHost::gpu_enabled() && 498 !command_line.HasSwitch(switches::kDisableFlash3d); 499 prefs.flash_stage3d_enabled = 500 GpuProcessHost::gpu_enabled() && 501 !command_line.HasSwitch(switches::kDisableFlashStage3d); 502 prefs.flash_stage3d_baseline_enabled = 503 GpuProcessHost::gpu_enabled() && 504 !command_line.HasSwitch(switches::kDisableFlashStage3d); 505 506 prefs.gl_multisampling_enabled = 507 !command_line.HasSwitch(switches::kDisableGLMultisampling); 508 prefs.privileged_webgl_extensions_enabled = 509 command_line.HasSwitch(switches::kEnablePrivilegedWebGLExtensions); 510 prefs.site_specific_quirks_enabled = 511 !command_line.HasSwitch(switches::kDisableSiteSpecificQuirks); 512 prefs.allow_file_access_from_file_urls = 513 command_line.HasSwitch(switches::kAllowFileAccessFromFiles); 514 515 prefs.accelerated_compositing_for_overflow_scroll_enabled = false; 516 if (command_line.HasSwitch(switches::kEnableAcceleratedOverflowScroll)) 517 prefs.accelerated_compositing_for_overflow_scroll_enabled = true; 518 if (command_line.HasSwitch(switches::kDisableAcceleratedOverflowScroll)) 519 prefs.accelerated_compositing_for_overflow_scroll_enabled = false; 520 521 prefs.accelerated_compositing_for_scrollable_frames_enabled = 522 command_line.HasSwitch(switches::kEnableAcceleratedScrollableFrames); 523 prefs.composited_scrolling_for_frames_enabled = 524 command_line.HasSwitch(switches::kEnableCompositedScrollingForFrames); 525 prefs.show_paint_rects = 526 command_line.HasSwitch(switches::kShowPaintRects); 527 prefs.accelerated_compositing_enabled = 528 GpuProcessHost::gpu_enabled() && 529 !command_line.HasSwitch(switches::kDisableAcceleratedCompositing); 530 prefs.force_compositing_mode = 531 content::IsForceCompositingModeEnabled() && 532 !command_line.HasSwitch(switches::kDisableForceCompositingMode); 533 prefs.accelerated_2d_canvas_enabled = 534 GpuProcessHost::gpu_enabled() && 535 !command_line.HasSwitch(switches::kDisableAccelerated2dCanvas); 536 prefs.antialiased_2d_canvas_disabled = 537 command_line.HasSwitch(switches::kDisable2dCanvasAntialiasing); 538 prefs.accelerated_filters_enabled = 539 GpuProcessHost::gpu_enabled() && 540 command_line.HasSwitch(switches::kEnableAcceleratedFilters); 541 prefs.accelerated_compositing_for_3d_transforms_enabled = 542 prefs.accelerated_compositing_for_animation_enabled = 543 !command_line.HasSwitch(switches::kDisableAcceleratedLayers); 544 prefs.accelerated_compositing_for_plugins_enabled = 545 !command_line.HasSwitch(switches::kDisableAcceleratedPlugins); 546 prefs.accelerated_compositing_for_video_enabled = 547 !command_line.HasSwitch(switches::kDisableAcceleratedVideo); 548 prefs.fullscreen_enabled = 549 !command_line.HasSwitch(switches::kDisableFullScreen); 550 prefs.css_sticky_position_enabled = 551 command_line.HasSwitch(switches::kEnableExperimentalWebPlatformFeatures); 552 prefs.css_shaders_enabled = 553 command_line.HasSwitch(switches::kEnableCssShaders); 554 prefs.lazy_layout_enabled = 555 command_line.HasSwitch(switches::kEnableExperimentalWebPlatformFeatures); 556 prefs.region_based_columns_enabled = 557 command_line.HasSwitch(switches::kEnableRegionBasedColumns); 558 prefs.threaded_html_parser = 559 !command_line.HasSwitch(switches::kDisableThreadedHTMLParser); 560 prefs.experimental_websocket_enabled = 561 command_line.HasSwitch(switches::kEnableExperimentalWebSocket); 562 if (command_line.HasSwitch(cc::switches::kEnablePinchVirtualViewport)) { 563 prefs.pinch_virtual_viewport_enabled = true; 564 prefs.pinch_overlay_scrollbar_thickness = 10; 565 } 566 567#if defined(OS_ANDROID) 568 prefs.use_solid_color_scrollbars = true; 569 prefs.user_gesture_required_for_media_playback = !command_line.HasSwitch( 570 switches::kDisableGestureRequirementForMediaPlayback); 571#endif 572 573 prefs.touch_enabled = ui::AreTouchEventsEnabled(); 574 prefs.device_supports_touch = prefs.touch_enabled && 575 ui::IsTouchDevicePresent(); 576#if defined(OS_ANDROID) 577 prefs.device_supports_mouse = false; 578#endif 579 580 prefs.touch_adjustment_enabled = 581 !command_line.HasSwitch(switches::kDisableTouchAdjustment); 582 583#if defined(OS_MACOSX) || defined(OS_CHROMEOS) 584 bool default_enable_scroll_animator = true; 585#else 586 bool default_enable_scroll_animator = false; 587#endif 588 prefs.enable_scroll_animator = default_enable_scroll_animator; 589 if (command_line.HasSwitch(switches::kEnableSmoothScrolling)) 590 prefs.enable_scroll_animator = true; 591 if (command_line.HasSwitch(switches::kDisableSmoothScrolling)) 592 prefs.enable_scroll_animator = false; 593 594 prefs.visual_word_movement_enabled = 595 command_line.HasSwitch(switches::kEnableVisualWordMovement); 596 597 // Certain GPU features might have been blacklisted. 598 GpuDataManagerImpl::GetInstance()->UpdateRendererWebPrefs(&prefs); 599 600 if (ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( 601 rvh->GetProcess()->GetID())) { 602 prefs.loads_images_automatically = true; 603 prefs.javascript_enabled = true; 604 } 605 606 prefs.is_online = !net::NetworkChangeNotifier::IsOffline(); 607 608#if !defined(USE_AURA) 609 // Force accelerated compositing and 2d canvas off for chrome: and about: 610 // pages (unless it's specifically allowed). 611 if ((url.SchemeIs(chrome::kChromeUIScheme) || 612 (url.SchemeIs(chrome::kAboutScheme) && 613 url.spec() != kAboutBlankURL)) && 614 !command_line.HasSwitch(switches::kAllowWebUICompositing)) { 615 prefs.accelerated_compositing_enabled = false; 616 prefs.accelerated_2d_canvas_enabled = false; 617 } 618#endif 619 620 prefs.fixed_position_creates_stacking_context = !command_line.HasSwitch( 621 switches::kDisableFixedPositionCreatesStackingContext); 622 623#if defined(OS_CHROMEOS) 624 prefs.gesture_tap_highlight_enabled = !command_line.HasSwitch( 625 switches::kDisableGestureTapHighlight); 626#else 627 prefs.gesture_tap_highlight_enabled = command_line.HasSwitch( 628 switches::kEnableGestureTapHighlight); 629#endif 630 631 prefs.number_of_cpu_cores = base::SysInfo::NumberOfProcessors(); 632 633 prefs.viewport_enabled = command_line.HasSwitch(switches::kEnableViewport); 634 635 prefs.deferred_image_decoding_enabled = 636 command_line.HasSwitch(switches::kEnableDeferredImageDecoding) || 637 cc::switches::IsImplSidePaintingEnabled(); 638 639 prefs.spatial_navigation_enabled = command_line.HasSwitch( 640 switches::kEnableSpatialNavigation); 641 642 GetContentClient()->browser()->OverrideWebkitPrefs(rvh, url, &prefs); 643 644 // Disable compositing in guests until we have compositing path implemented 645 // for guests. 646 bool guest_compositing_enabled = !command_line.HasSwitch( 647 switches::kDisableBrowserPluginCompositing); 648 if (rvh->GetProcess()->IsGuest() && !guest_compositing_enabled) { 649 prefs.force_compositing_mode = false; 650 prefs.accelerated_compositing_enabled = false; 651 } 652 653 return prefs; 654} 655 656RenderViewHostManager* WebContentsImpl::GetRenderManagerForTesting() { 657 return &render_manager_; 658} 659 660bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host, 661 const IPC::Message& message) { 662 if (GetWebUI() && 663 static_cast<WebUIImpl*>(GetWebUI())->OnMessageReceived(message)) { 664 return true; 665 } 666 667 ObserverListBase<WebContentsObserver>::Iterator it(observers_); 668 WebContentsObserver* observer; 669 while ((observer = it.GetNext()) != NULL) 670 if (observer->OnMessageReceived(message)) 671 return true; 672 673 // Message handlers should be aware of which RenderViewHost sent the 674 // message, which is temporarily stored in message_source_. 675 message_source_ = render_view_host; 676 bool handled = true; 677 bool message_is_ok = true; 678 IPC_BEGIN_MESSAGE_MAP_EX(WebContentsImpl, message, message_is_ok) 679 IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache, 680 OnDidLoadResourceFromMemoryCache) 681 IPC_MESSAGE_HANDLER(ViewHostMsg_DidDisplayInsecureContent, 682 OnDidDisplayInsecureContent) 683 IPC_MESSAGE_HANDLER(ViewHostMsg_DidRunInsecureContent, 684 OnDidRunInsecureContent) 685 IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentLoadedInFrame, 686 OnDocumentLoadedInFrame) 687 IPC_MESSAGE_HANDLER(ViewHostMsg_DidFinishLoad, OnDidFinishLoad) 688 IPC_MESSAGE_HANDLER(ViewHostMsg_DidFailLoadWithError, 689 OnDidFailLoadWithError) 690 IPC_MESSAGE_HANDLER(ViewHostMsg_GoToEntryAtOffset, OnGoToEntryAtOffset) 691 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateZoomLimits, OnUpdateZoomLimits) 692 IPC_MESSAGE_HANDLER(ViewHostMsg_EnumerateDirectory, OnEnumerateDirectory) 693 IPC_MESSAGE_HANDLER(ViewHostMsg_JSOutOfMemory, OnJSOutOfMemory) 694 IPC_MESSAGE_HANDLER(ViewHostMsg_RegisterProtocolHandler, 695 OnRegisterProtocolHandler) 696 IPC_MESSAGE_HANDLER(ViewHostMsg_Find_Reply, OnFindReply) 697 IPC_MESSAGE_HANDLER(ViewHostMsg_DidProgrammaticallyScroll, 698 OnDidProgrammaticallyScroll) 699 IPC_MESSAGE_HANDLER(ViewHostMsg_CrashedPlugin, OnCrashedPlugin) 700 IPC_MESSAGE_HANDLER(ViewHostMsg_AppCacheAccessed, OnAppCacheAccessed) 701 IPC_MESSAGE_HANDLER(ViewHostMsg_OpenColorChooser, OnOpenColorChooser) 702 IPC_MESSAGE_HANDLER(ViewHostMsg_EndColorChooser, OnEndColorChooser) 703 IPC_MESSAGE_HANDLER(ViewHostMsg_SetSelectedColorInColorChooser, 704 OnSetSelectedColorInColorChooser) 705 IPC_MESSAGE_HANDLER(ViewHostMsg_PepperPluginHung, OnPepperPluginHung) 706 IPC_MESSAGE_HANDLER(ViewHostMsg_WebUISend, OnWebUISend) 707 IPC_MESSAGE_HANDLER(ViewHostMsg_RequestPpapiBrokerPermission, 708 OnRequestPpapiBrokerPermission) 709 IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginHostMsg_AllocateInstanceID, 710 OnBrowserPluginMessage(message)) 711 IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginHostMsg_Attach, 712 OnBrowserPluginMessage(message)) 713 IPC_MESSAGE_HANDLER(ImageHostMsg_DidDownloadImage, OnDidDownloadImage) 714 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFaviconURL, OnUpdateFaviconURL) 715#if defined(OS_ANDROID) 716 IPC_MESSAGE_HANDLER(ViewHostMsg_FindMatchRects_Reply, 717 OnFindMatchRectsReply) 718 IPC_MESSAGE_HANDLER(ViewHostMsg_OpenDateTimeDialog, 719 OnOpenDateTimeDialog) 720#endif 721 IPC_MESSAGE_HANDLER(ViewHostMsg_FrameAttached, OnFrameAttached) 722 IPC_MESSAGE_HANDLER(ViewHostMsg_FrameDetached, OnFrameDetached) 723 IPC_MESSAGE_HANDLER(ViewHostMsg_MediaNotification, OnMediaNotification) 724 IPC_MESSAGE_UNHANDLED(handled = false) 725 IPC_END_MESSAGE_MAP_EX() 726 message_source_ = NULL; 727 728 if (!message_is_ok) { 729 RecordAction(UserMetricsAction("BadMessageTerminate_RVD")); 730 GetRenderProcessHost()->ReceivedBadMessage(); 731 } 732 733 return handled; 734} 735 736void WebContentsImpl::RunFileChooser( 737 RenderViewHost* render_view_host, 738 const FileChooserParams& params) { 739 if (delegate_) 740 delegate_->RunFileChooser(this, params); 741} 742 743NavigationControllerImpl& WebContentsImpl::GetController() { 744 return controller_; 745} 746 747const NavigationControllerImpl& WebContentsImpl::GetController() const { 748 return controller_; 749} 750 751BrowserContext* WebContentsImpl::GetBrowserContext() const { 752 return controller_.GetBrowserContext(); 753} 754 755const GURL& WebContentsImpl::GetURL() const { 756 // We may not have a navigation entry yet. 757 NavigationEntry* entry = controller_.GetVisibleEntry(); 758 return entry ? entry->GetVirtualURL() : GURL::EmptyGURL(); 759} 760 761const GURL& WebContentsImpl::GetVisibleURL() const { 762 // We may not have a navigation entry yet. 763 NavigationEntry* entry = controller_.GetVisibleEntry(); 764 return entry ? entry->GetVirtualURL() : GURL::EmptyGURL(); 765} 766 767const GURL& WebContentsImpl::GetLastCommittedURL() const { 768 // We may not have a navigation entry yet. 769 NavigationEntry* entry = controller_.GetLastCommittedEntry(); 770 return entry ? entry->GetVirtualURL() : GURL::EmptyGURL(); 771} 772 773WebContentsDelegate* WebContentsImpl::GetDelegate() { 774 return delegate_; 775} 776 777void WebContentsImpl::SetDelegate(WebContentsDelegate* delegate) { 778 // TODO(cbentzel): remove this debugging code? 779 if (delegate == delegate_) 780 return; 781 if (delegate_) 782 delegate_->Detach(this); 783 delegate_ = delegate; 784 if (delegate_) { 785 delegate_->Attach(this); 786 // Ensure the visible RVH reflects the new delegate's preferences. 787 if (view_) 788 view_->SetOverscrollControllerEnabled(delegate->CanOverscrollContent()); 789 } 790} 791 792RenderProcessHost* WebContentsImpl::GetRenderProcessHost() const { 793 RenderViewHostImpl* host = render_manager_.current_host(); 794 return host ? host->GetProcess() : NULL; 795} 796 797RenderViewHost* WebContentsImpl::GetRenderViewHost() const { 798 return render_manager_.current_host(); 799} 800 801void WebContentsImpl::GetRenderViewHostAtPosition( 802 int x, 803 int y, 804 const base::Callback<void(RenderViewHost*, int, int)>& callback) { 805 BrowserPluginEmbedder* embedder = GetBrowserPluginEmbedder(); 806 if (embedder) 807 embedder->GetRenderViewHostAtPosition(x, y, callback); 808 else 809 callback.Run(GetRenderViewHost(), x, y); 810} 811 812WebContents* WebContentsImpl::GetEmbedderWebContents() const { 813 BrowserPluginGuest* guest = GetBrowserPluginGuest(); 814 if (guest) 815 return guest->embedder_web_contents(); 816 return NULL; 817} 818 819int WebContentsImpl::GetEmbeddedInstanceID() const { 820 BrowserPluginGuest* guest = GetBrowserPluginGuest(); 821 if (guest) 822 return guest->instance_id(); 823 return 0; 824} 825 826int WebContentsImpl::GetRoutingID() const { 827 if (!GetRenderViewHost()) 828 return MSG_ROUTING_NONE; 829 830 return GetRenderViewHost()->GetRoutingID(); 831} 832 833int WebContentsImpl::GetFullscreenWidgetRoutingID() const { 834 return fullscreen_widget_routing_id_; 835} 836 837RenderWidgetHostView* WebContentsImpl::GetRenderWidgetHostView() const { 838 return render_manager_.GetRenderWidgetHostView(); 839} 840 841RenderWidgetHostViewPort* WebContentsImpl::GetRenderWidgetHostViewPort() const { 842 BrowserPluginGuest* guest = GetBrowserPluginGuest(); 843 if (guest && guest->embedder_web_contents()) { 844 return guest->embedder_web_contents()->GetRenderWidgetHostViewPort(); 845 } 846 return RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView()); 847} 848 849WebContentsView* WebContentsImpl::GetView() const { 850 return view_.get(); 851} 852 853WebUI* WebContentsImpl::CreateWebUI(const GURL& url) { 854 WebUIImpl* web_ui = new WebUIImpl(this); 855 WebUIController* controller = WebUIControllerFactoryRegistry::GetInstance()-> 856 CreateWebUIControllerForURL(web_ui, url); 857 if (controller) { 858 web_ui->AddMessageHandler(new GenericHandler()); 859 web_ui->SetController(controller); 860 return web_ui; 861 } 862 863 delete web_ui; 864 return NULL; 865} 866 867WebUI* WebContentsImpl::GetWebUI() const { 868 return render_manager_.web_ui() ? render_manager_.web_ui() 869 : render_manager_.pending_web_ui(); 870} 871 872WebUI* WebContentsImpl::GetCommittedWebUI() const { 873 return render_manager_.web_ui(); 874} 875 876void WebContentsImpl::SetUserAgentOverride(const std::string& override) { 877 if (GetUserAgentOverride() == override) 878 return; 879 880 renderer_preferences_.user_agent_override = override; 881 882 // Send the new override string to the renderer. 883 RenderViewHost* host = GetRenderViewHost(); 884 if (host) 885 host->SyncRendererPrefs(); 886 887 // Reload the page if a load is currently in progress to avoid having 888 // different parts of the page loaded using different user agents. 889 NavigationEntry* entry = controller_.GetActiveEntry(); 890 if (is_loading_ && entry != NULL && entry->GetIsOverridingUserAgent()) 891 controller_.ReloadIgnoringCache(true); 892 893 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 894 UserAgentOverrideSet(override)); 895} 896 897const std::string& WebContentsImpl::GetUserAgentOverride() const { 898 return renderer_preferences_.user_agent_override; 899} 900 901#if defined(OS_WIN) && defined(USE_AURA) 902void WebContentsImpl::SetParentNativeViewAccessible( 903gfx::NativeViewAccessible accessible_parent) { 904 accessible_parent_ = accessible_parent; 905 if (GetRenderViewHost()) 906 GetRenderViewHostImpl()->SetParentNativeViewAccessible(accessible_parent); 907} 908#endif 909 910const string16& WebContentsImpl::GetTitle() const { 911 // Transient entries take precedence. They are used for interstitial pages 912 // that are shown on top of existing pages. 913 NavigationEntry* entry = controller_.GetTransientEntry(); 914 std::string accept_languages = 915 GetContentClient()->browser()->GetAcceptLangs( 916 GetBrowserContext()); 917 if (entry) { 918 return entry->GetTitleForDisplay(accept_languages); 919 } 920 WebUI* our_web_ui = render_manager_.pending_web_ui() ? 921 render_manager_.pending_web_ui() : render_manager_.web_ui(); 922 if (our_web_ui) { 923 // Don't override the title in view source mode. 924 entry = controller_.GetVisibleEntry(); 925 if (!(entry && entry->IsViewSourceMode())) { 926 // Give the Web UI the chance to override our title. 927 const string16& title = our_web_ui->GetOverriddenTitle(); 928 if (!title.empty()) 929 return title; 930 } 931 } 932 933 // We use the title for the last committed entry rather than a pending 934 // navigation entry. For example, when the user types in a URL, we want to 935 // keep the old page's title until the new load has committed and we get a new 936 // title. 937 entry = controller_.GetLastCommittedEntry(); 938 939 // We make an exception for initial navigations, because we can have a 940 // committed entry for an initial navigation when doing a history navigation 941 // in a new tab, such as Ctrl+Back. 942 if (entry && controller_.IsInitialNavigation()) 943 entry = controller_.GetVisibleEntry(); 944 945 if (entry) { 946 return entry->GetTitleForDisplay(accept_languages); 947 } 948 949 // |page_title_when_no_navigation_entry_| is finally used 950 // if no title cannot be retrieved. 951 return page_title_when_no_navigation_entry_; 952} 953 954int32 WebContentsImpl::GetMaxPageID() { 955 return GetMaxPageIDForSiteInstance(GetSiteInstance()); 956} 957 958int32 WebContentsImpl::GetMaxPageIDForSiteInstance( 959 SiteInstance* site_instance) { 960 if (max_page_ids_.find(site_instance->GetId()) == max_page_ids_.end()) 961 max_page_ids_[site_instance->GetId()] = -1; 962 963 return max_page_ids_[site_instance->GetId()]; 964} 965 966void WebContentsImpl::UpdateMaxPageID(int32 page_id) { 967 UpdateMaxPageIDForSiteInstance(GetSiteInstance(), page_id); 968} 969 970void WebContentsImpl::UpdateMaxPageIDForSiteInstance( 971 SiteInstance* site_instance, int32 page_id) { 972 if (GetMaxPageIDForSiteInstance(site_instance) < page_id) 973 max_page_ids_[site_instance->GetId()] = page_id; 974} 975 976void WebContentsImpl::CopyMaxPageIDsFrom(WebContentsImpl* web_contents) { 977 max_page_ids_ = web_contents->max_page_ids_; 978} 979 980SiteInstance* WebContentsImpl::GetSiteInstance() const { 981 return render_manager_.current_host()->GetSiteInstance(); 982} 983 984SiteInstance* WebContentsImpl::GetPendingSiteInstance() const { 985 RenderViewHost* dest_rvh = render_manager_.pending_render_view_host() ? 986 render_manager_.pending_render_view_host() : 987 render_manager_.current_host(); 988 return dest_rvh->GetSiteInstance(); 989} 990 991bool WebContentsImpl::IsLoading() const { 992 return is_loading_; 993} 994 995bool WebContentsImpl::IsWaitingForResponse() const { 996 return waiting_for_response_; 997} 998 999const net::LoadStateWithParam& WebContentsImpl::GetLoadState() const { 1000 return load_state_; 1001} 1002 1003const string16& WebContentsImpl::GetLoadStateHost() const { 1004 return load_state_host_; 1005} 1006 1007uint64 WebContentsImpl::GetUploadSize() const { 1008 return upload_size_; 1009} 1010 1011uint64 WebContentsImpl::GetUploadPosition() const { 1012 return upload_position_; 1013} 1014 1015std::set<GURL> WebContentsImpl::GetSitesInTab() const { 1016 BrowserContext* browser_context = GetBrowserContext(); 1017 std::set<GURL> sites; 1018 if (!frame_tree_root_.get()) 1019 return sites; 1020 1021 // Iterates over the FrameTreeNodes to find each unique site URL that is 1022 // currently committed. 1023 FrameTreeNode* node = NULL; 1024 std::queue<FrameTreeNode*> queue; 1025 queue.push(frame_tree_root_.get()); 1026 1027 while (!queue.empty()) { 1028 node = queue.front(); 1029 queue.pop(); 1030 sites.insert(SiteInstance::GetSiteForURL(browser_context, 1031 node->current_url())); 1032 1033 for (size_t i = 0; i < node->child_count(); ++i) 1034 queue.push(node->child_at(i)); 1035 } 1036 1037 return sites; 1038} 1039 1040const std::string& WebContentsImpl::GetEncoding() const { 1041 return encoding_; 1042} 1043 1044bool WebContentsImpl::DisplayedInsecureContent() const { 1045 return displayed_insecure_content_; 1046} 1047 1048void WebContentsImpl::IncrementCapturerCount() { 1049 DCHECK(!is_being_destroyed_); 1050 ++capturer_count_; 1051 DVLOG(1) << "There are now " << capturer_count_ 1052 << " capturing(s) of WebContentsImpl@" << this; 1053} 1054 1055void WebContentsImpl::DecrementCapturerCount() { 1056 --capturer_count_; 1057 DVLOG(1) << "There are now " << capturer_count_ 1058 << " capturing(s) of WebContentsImpl@" << this; 1059 DCHECK_LE(0, capturer_count_); 1060 1061 if (is_being_destroyed_) 1062 return; 1063 1064 if (IsHidden()) { 1065 DVLOG(1) << "Executing delayed WasHidden()."; 1066 WasHidden(); 1067 } 1068} 1069 1070int WebContentsImpl::GetCapturerCount() const { 1071 return capturer_count_; 1072} 1073 1074bool WebContentsImpl::IsCrashed() const { 1075 return (crashed_status_ == base::TERMINATION_STATUS_PROCESS_CRASHED || 1076 crashed_status_ == base::TERMINATION_STATUS_ABNORMAL_TERMINATION || 1077 crashed_status_ == base::TERMINATION_STATUS_PROCESS_WAS_KILLED); 1078} 1079 1080void WebContentsImpl::SetIsCrashed(base::TerminationStatus status, 1081 int error_code) { 1082 if (status == crashed_status_) 1083 return; 1084 1085 crashed_status_ = status; 1086 crashed_error_code_ = error_code; 1087 NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB); 1088} 1089 1090base::TerminationStatus WebContentsImpl::GetCrashedStatus() const { 1091 return crashed_status_; 1092} 1093 1094bool WebContentsImpl::IsBeingDestroyed() const { 1095 return is_being_destroyed_; 1096} 1097 1098void WebContentsImpl::NotifyNavigationStateChanged(unsigned changed_flags) { 1099 if (delegate_) 1100 delegate_->NavigationStateChanged(this, changed_flags); 1101} 1102 1103base::TimeTicks WebContentsImpl::GetLastSelectedTime() const { 1104 return last_selected_time_; 1105} 1106 1107void WebContentsImpl::WasShown() { 1108 controller_.SetActive(true); 1109 RenderWidgetHostViewPort* rwhv = 1110 RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView()); 1111 if (rwhv) { 1112 rwhv->WasShown(); 1113#if defined(OS_MACOSX) 1114 rwhv->SetActive(true); 1115#endif 1116 } 1117 1118 last_selected_time_ = base::TimeTicks::Now(); 1119 1120 FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasShown()); 1121 1122 // The resize rect might have changed while this was inactive -- send the new 1123 // one to make sure it's up to date. 1124 RenderViewHostImpl* rvh = 1125 static_cast<RenderViewHostImpl*>(GetRenderViewHost()); 1126 if (rvh) { 1127 rvh->ResizeRectChanged(GetRootWindowResizerRect()); 1128 } 1129 1130 should_normally_be_visible_ = true; 1131 NotificationService::current()->Notify( 1132 NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED, 1133 Source<WebContents>(this), 1134 Details<const bool>(&should_normally_be_visible_)); 1135} 1136 1137void WebContentsImpl::WasHidden() { 1138 // If there are entities capturing screenshots or video (e.g., mirroring), 1139 // don't activate the "disable rendering" optimization. 1140 if (capturer_count_ == 0) { 1141 // |GetRenderViewHost()| can be NULL if the user middle clicks a link to 1142 // open a tab in the background, then closes the tab before selecting it. 1143 // This is because closing the tab calls WebContentsImpl::Destroy(), which 1144 // removes the |GetRenderViewHost()|; then when we actually destroy the 1145 // window, OnWindowPosChanged() notices and calls WasHidden() (which 1146 // calls us). 1147 RenderWidgetHostViewPort* rwhv = 1148 RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView()); 1149 if (rwhv) 1150 rwhv->WasHidden(); 1151 } 1152 1153 should_normally_be_visible_ = false; 1154 NotificationService::current()->Notify( 1155 NOTIFICATION_WEB_CONTENTS_VISIBILITY_CHANGED, 1156 Source<WebContents>(this), 1157 Details<const bool>(&should_normally_be_visible_)); 1158} 1159 1160bool WebContentsImpl::NeedToFireBeforeUnload() { 1161 // TODO(creis): Should we fire even for interstitial pages? 1162 return WillNotifyDisconnection() && 1163 !ShowingInterstitialPage() && 1164 !static_cast<RenderViewHostImpl*>( 1165 GetRenderViewHost())->SuddenTerminationAllowed(); 1166} 1167 1168void WebContentsImpl::Stop() { 1169 render_manager_.Stop(); 1170 FOR_EACH_OBSERVER(WebContentsObserver, observers_, NavigationStopped()); 1171} 1172 1173WebContents* WebContentsImpl::Clone() { 1174 // We use our current SiteInstance since the cloned entry will use it anyway. 1175 // We pass our own opener so that the cloned page can access it if it was 1176 // before. 1177 CreateParams create_params(GetBrowserContext(), GetSiteInstance()); 1178 create_params.initial_size = view_->GetContainerSize(); 1179 WebContentsImpl* tc = CreateWithOpener(create_params, opener_); 1180 tc->GetController().CopyStateFrom(controller_); 1181 FOR_EACH_OBSERVER(WebContentsObserver, 1182 observers_, 1183 DidCloneToNewWebContents(this, tc)); 1184 return tc; 1185} 1186 1187void WebContentsImpl::Observe(int type, 1188 const NotificationSource& source, 1189 const NotificationDetails& details) { 1190 switch (type) { 1191 case NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED: { 1192 RenderWidgetHost* host = Source<RenderWidgetHost>(source).ptr(); 1193 for (PendingWidgetViews::iterator i = pending_widget_views_.begin(); 1194 i != pending_widget_views_.end(); ++i) { 1195 if (host->GetView() == i->second) { 1196 pending_widget_views_.erase(i); 1197 break; 1198 } 1199 } 1200 break; 1201 } 1202 default: 1203 NOTREACHED(); 1204 } 1205} 1206 1207void WebContentsImpl::Init(const WebContents::CreateParams& params) { 1208 render_manager_.Init( 1209 params.browser_context, params.site_instance, params.routing_id, 1210 params.main_frame_routing_id); 1211 1212 view_.reset(GetContentClient()->browser()-> 1213 OverrideCreateWebContentsView(this, &render_view_host_delegate_view_)); 1214 if (view_) { 1215 CHECK(render_view_host_delegate_view_); 1216 } else { 1217 WebContentsViewDelegate* delegate = 1218 GetContentClient()->browser()->GetWebContentsViewDelegate(this); 1219 1220 if (browser_plugin_guest_) { 1221 scoped_ptr<WebContentsViewPort> platform_view(CreateWebContentsView( 1222 this, delegate, &render_view_host_delegate_view_)); 1223 1224 WebContentsViewGuest* rv = new WebContentsViewGuest( 1225 this, browser_plugin_guest_.get(), platform_view.Pass(), 1226 render_view_host_delegate_view_); 1227 render_view_host_delegate_view_ = rv; 1228 view_.reset(rv); 1229 } else { 1230 // Regular WebContentsView. 1231 view_.reset(CreateWebContentsView( 1232 this, delegate, &render_view_host_delegate_view_)); 1233 } 1234 CHECK(render_view_host_delegate_view_); 1235 } 1236 CHECK(view_.get()); 1237 1238 gfx::Size initial_size = params.initial_size; 1239 view_->CreateView(initial_size, params.context); 1240 1241 // Listen for whether our opener gets destroyed. 1242 if (opener_) 1243 AddDestructionObserver(opener_); 1244 1245 registrar_.Add(this, 1246 NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED, 1247 NotificationService::AllBrowserContextsAndSources()); 1248#if defined(OS_ANDROID) 1249 java_bridge_dispatcher_host_manager_.reset( 1250 new JavaBridgeDispatcherHostManager(this)); 1251#endif 1252 1253#if defined(OS_ANDROID) 1254 date_time_chooser_.reset(new DateTimeChooserAndroid()); 1255#endif 1256} 1257 1258void WebContentsImpl::OnWebContentsDestroyed(WebContentsImpl* web_contents) { 1259 RemoveDestructionObserver(web_contents); 1260 1261 // Clear the opener if it has been closed. 1262 if (web_contents == opener_) { 1263 opener_ = NULL; 1264 return; 1265 } 1266 // Clear a pending contents that has been closed before being shown. 1267 for (PendingContents::iterator iter = pending_contents_.begin(); 1268 iter != pending_contents_.end(); 1269 ++iter) { 1270 if (iter->second != web_contents) 1271 continue; 1272 pending_contents_.erase(iter); 1273 return; 1274 } 1275 NOTREACHED(); 1276} 1277 1278void WebContentsImpl::AddDestructionObserver(WebContentsImpl* web_contents) { 1279 if (!ContainsKey(destruction_observers_, web_contents)) { 1280 destruction_observers_[web_contents] = 1281 new DestructionObserver(this, web_contents); 1282 } 1283} 1284 1285void WebContentsImpl::RemoveDestructionObserver(WebContentsImpl* web_contents) { 1286 DestructionObservers::iterator iter = 1287 destruction_observers_.find(web_contents); 1288 if (iter != destruction_observers_.end()) { 1289 delete destruction_observers_[web_contents]; 1290 destruction_observers_.erase(iter); 1291 } 1292} 1293 1294void WebContentsImpl::AddObserver(WebContentsObserver* observer) { 1295 observers_.AddObserver(observer); 1296} 1297 1298void WebContentsImpl::RemoveObserver(WebContentsObserver* observer) { 1299 observers_.RemoveObserver(observer); 1300} 1301 1302void WebContentsImpl::Activate() { 1303 if (delegate_) 1304 delegate_->ActivateContents(this); 1305} 1306 1307void WebContentsImpl::Deactivate() { 1308 if (delegate_) 1309 delegate_->DeactivateContents(this); 1310} 1311 1312void WebContentsImpl::LostCapture() { 1313 if (delegate_) 1314 delegate_->LostCapture(); 1315} 1316 1317void WebContentsImpl::RenderWidgetDeleted( 1318 RenderWidgetHostImpl* render_widget_host) { 1319 if (is_being_destroyed_) { 1320 // |created_widgets_| might have been destroyed. 1321 return; 1322 } 1323 1324 std::set<RenderWidgetHostImpl*>::iterator iter = 1325 created_widgets_.find(render_widget_host); 1326 if (iter != created_widgets_.end()) 1327 created_widgets_.erase(iter); 1328 1329 if (render_widget_host && 1330 render_widget_host->GetRoutingID() == fullscreen_widget_routing_id_) { 1331 FOR_EACH_OBSERVER(WebContentsObserver, 1332 observers_, 1333 DidDestroyFullscreenWidget( 1334 fullscreen_widget_routing_id_)); 1335 fullscreen_widget_routing_id_ = MSG_ROUTING_NONE; 1336 } 1337} 1338 1339bool WebContentsImpl::PreHandleKeyboardEvent( 1340 const NativeWebKeyboardEvent& event, 1341 bool* is_keyboard_shortcut) { 1342 return delegate_ && 1343 delegate_->PreHandleKeyboardEvent(this, event, is_keyboard_shortcut); 1344} 1345 1346void WebContentsImpl::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) { 1347 if (browser_plugin_embedder_ && 1348 browser_plugin_embedder_->HandleKeyboardEvent(event)) { 1349 return; 1350 } 1351 1352 if (delegate_) 1353 delegate_->HandleKeyboardEvent(this, event); 1354} 1355 1356bool WebContentsImpl::PreHandleWheelEvent( 1357 const WebKit::WebMouseWheelEvent& event) { 1358#if !defined(OS_MACOSX) 1359 // On platforms other than Mac, control+mousewheel changes zoom. On Mac, this 1360 // isn't done for two reasons: 1361 // -the OS already has a gesture to do this through pinch-zoom 1362 // -if a user starts an inertial scroll, let's go, and presses control 1363 // (i.e. control+tab) then the OS's buffered scroll events will come in 1364 // with control key set which isn't what the user wants 1365 if (delegate_ && 1366 event.wheelTicksY && 1367 (event.modifiers & WebKit::WebInputEvent::ControlKey)) { 1368 delegate_->ContentsZoomChange(event.wheelTicksY > 0); 1369 return true; 1370 } 1371#endif 1372 1373 return false; 1374} 1375 1376#if defined(OS_WIN) && defined(USE_AURA) 1377gfx::NativeViewAccessible WebContentsImpl::GetParentNativeViewAccessible() { 1378 return accessible_parent_; 1379} 1380#endif 1381 1382void WebContentsImpl::HandleMouseDown() { 1383 if (delegate_) 1384 delegate_->HandleMouseDown(); 1385} 1386 1387void WebContentsImpl::HandleMouseUp() { 1388 if (delegate_) 1389 delegate_->HandleMouseUp(); 1390} 1391 1392void WebContentsImpl::HandlePointerActivate() { 1393 if (delegate_) 1394 delegate_->HandlePointerActivate(); 1395} 1396 1397void WebContentsImpl::HandleGestureBegin() { 1398 if (delegate_) 1399 delegate_->HandleGestureBegin(); 1400} 1401 1402void WebContentsImpl::HandleGestureEnd() { 1403 if (delegate_) 1404 delegate_->HandleGestureEnd(); 1405} 1406 1407void WebContentsImpl::ToggleFullscreenMode(bool enter_fullscreen) { 1408 if (delegate_) 1409 delegate_->ToggleFullscreenModeForTab(this, enter_fullscreen); 1410} 1411 1412bool WebContentsImpl::IsFullscreenForCurrentTab() const { 1413 return delegate_ ? delegate_->IsFullscreenForTabOrPending(this) : false; 1414} 1415 1416void WebContentsImpl::RequestToLockMouse(bool user_gesture, 1417 bool last_unlocked_by_target) { 1418 if (delegate_) { 1419 delegate_->RequestToLockMouse(this, user_gesture, last_unlocked_by_target); 1420 } else { 1421 GotResponseToLockMouseRequest(false); 1422 } 1423} 1424 1425void WebContentsImpl::LostMouseLock() { 1426 if (delegate_) 1427 delegate_->LostMouseLock(); 1428} 1429 1430void WebContentsImpl::CreateNewWindow( 1431 int route_id, 1432 int main_frame_route_id, 1433 const ViewHostMsg_CreateWindow_Params& params, 1434 SessionStorageNamespace* session_storage_namespace) { 1435 // We usually create the new window in the same BrowsingInstance (group of 1436 // script-related windows), by passing in the current SiteInstance. However, 1437 // if the opener is being suppressed (in a non-guest), we create a new 1438 // SiteInstance in its own BrowsingInstance. 1439 bool is_guest = GetRenderProcessHost()->IsGuest(); 1440 1441 scoped_refptr<SiteInstance> site_instance = 1442 params.opener_suppressed && !is_guest ? 1443 SiteInstance::CreateForURL(GetBrowserContext(), params.target_url) : 1444 GetSiteInstance(); 1445 1446 // We must assign the SessionStorageNamespace before calling Init(). 1447 // 1448 // http://crbug.com/142685 1449 const std::string& partition_id = 1450 GetContentClient()->browser()-> 1451 GetStoragePartitionIdForSite(GetBrowserContext(), 1452 site_instance->GetSiteURL()); 1453 StoragePartition* partition = BrowserContext::GetStoragePartition( 1454 GetBrowserContext(), site_instance.get()); 1455 DOMStorageContextWrapper* dom_storage_context = 1456 static_cast<DOMStorageContextWrapper*>(partition->GetDOMStorageContext()); 1457 SessionStorageNamespaceImpl* session_storage_namespace_impl = 1458 static_cast<SessionStorageNamespaceImpl*>(session_storage_namespace); 1459 CHECK(session_storage_namespace_impl->IsFromContext(dom_storage_context)); 1460 1461 if (delegate_ && 1462 !delegate_->ShouldCreateWebContents(this, 1463 route_id, 1464 params.window_container_type, 1465 params.frame_name, 1466 params.target_url, 1467 partition_id, 1468 session_storage_namespace)) { 1469 GetRenderViewHost()->GetProcess()->ResumeRequestsForView(route_id); 1470 GetRenderViewHost()->GetProcess()->ResumeRequestsForView( 1471 main_frame_route_id); 1472 return; 1473 } 1474 1475 // Create the new web contents. This will automatically create the new 1476 // WebContentsView. In the future, we may want to create the view separately. 1477 WebContentsImpl* new_contents = 1478 new WebContentsImpl(GetBrowserContext(), 1479 params.opener_suppressed ? NULL : this); 1480 1481 new_contents->GetController().SetSessionStorageNamespace( 1482 partition_id, 1483 session_storage_namespace); 1484 CreateParams create_params(GetBrowserContext(), site_instance.get()); 1485 create_params.routing_id = route_id; 1486 create_params.main_frame_routing_id = main_frame_route_id; 1487 if (!is_guest) { 1488 create_params.context = view_->GetNativeView(); 1489 create_params.initial_size = view_->GetContainerSize(); 1490 } else { 1491 // This makes |new_contents| act as a guest. 1492 // For more info, see comment above class BrowserPluginGuest. 1493 int instance_id = GetBrowserPluginGuestManager()->get_next_instance_id(); 1494 WebContentsImpl* new_contents_impl = 1495 static_cast<WebContentsImpl*>(new_contents); 1496 BrowserPluginGuest::CreateWithOpener(instance_id, new_contents_impl, 1497 GetBrowserPluginGuest(), !!new_contents_impl->opener()); 1498 } 1499 if (params.disposition == NEW_BACKGROUND_TAB) 1500 create_params.initially_hidden = true; 1501 new_contents->Init(create_params); 1502 1503 // Save the window for later if we're not suppressing the opener (since it 1504 // will be shown immediately). 1505 if (!params.opener_suppressed) { 1506 if (!is_guest) { 1507 WebContentsViewPort* new_view = new_contents->view_.get(); 1508 1509 // TODO(brettw): It seems bogus that we have to call this function on the 1510 // newly created object and give it one of its own member variables. 1511 new_view->CreateViewForWidget(new_contents->GetRenderViewHost()); 1512 } 1513 // Save the created window associated with the route so we can show it 1514 // later. 1515 DCHECK_NE(MSG_ROUTING_NONE, route_id); 1516 pending_contents_[route_id] = new_contents; 1517 AddDestructionObserver(new_contents); 1518 } 1519 1520 if (delegate_) { 1521 delegate_->WebContentsCreated( 1522 this, params.opener_frame_id, params.frame_name, 1523 params.target_url, new_contents); 1524 } 1525 1526 if (params.opener_suppressed) { 1527 // When the opener is suppressed, the original renderer cannot access the 1528 // new window. As a result, we need to show and navigate the window here. 1529 bool was_blocked = false; 1530 if (delegate_) { 1531 gfx::Rect initial_pos; 1532 delegate_->AddNewContents( 1533 this, new_contents, params.disposition, initial_pos, 1534 params.user_gesture, &was_blocked); 1535 } 1536 if (!was_blocked) { 1537 OpenURLParams open_params(params.target_url, 1538 Referrer(), 1539 CURRENT_TAB, 1540 PAGE_TRANSITION_LINK, 1541 true /* is_renderer_initiated */); 1542 open_params.user_gesture = params.user_gesture; 1543 new_contents->OpenURL(open_params); 1544 } 1545 } 1546} 1547 1548void WebContentsImpl::CreateNewWidget(int route_id, 1549 WebKit::WebPopupType popup_type) { 1550 CreateNewWidget(route_id, false, popup_type); 1551} 1552 1553void WebContentsImpl::CreateNewFullscreenWidget(int route_id) { 1554 CreateNewWidget(route_id, true, WebKit::WebPopupTypeNone); 1555} 1556 1557void WebContentsImpl::CreateNewWidget(int route_id, 1558 bool is_fullscreen, 1559 WebKit::WebPopupType popup_type) { 1560 RenderProcessHost* process = GetRenderProcessHost(); 1561 RenderWidgetHostImpl* widget_host = 1562 new RenderWidgetHostImpl(this, process, route_id, IsHidden()); 1563 created_widgets_.insert(widget_host); 1564 1565 RenderWidgetHostViewPort* widget_view = RenderWidgetHostViewPort::FromRWHV( 1566 view_->CreateViewForPopupWidget(widget_host)); 1567 if (!widget_view) 1568 return; 1569 if (!is_fullscreen) { 1570 // Popups should not get activated. 1571 widget_view->SetPopupType(popup_type); 1572 } 1573 // Save the created widget associated with the route so we can show it later. 1574 pending_widget_views_[route_id] = widget_view; 1575 1576#if defined(OS_MACOSX) 1577 // A RenderWidgetHostViewMac has lifetime scoped to the view. We'll retain it 1578 // to allow it to survive the trip without being hosted. 1579 base::mac::NSObjectRetain(widget_view->GetNativeView()); 1580#endif 1581} 1582 1583void WebContentsImpl::ShowCreatedWindow(int route_id, 1584 WindowOpenDisposition disposition, 1585 const gfx::Rect& initial_pos, 1586 bool user_gesture) { 1587 WebContentsImpl* contents = GetCreatedWindow(route_id); 1588 if (contents) { 1589 WebContentsDelegate* delegate = GetDelegate(); 1590 if (delegate) { 1591 delegate->AddNewContents( 1592 this, contents, disposition, initial_pos, user_gesture, NULL); 1593 } 1594 } 1595} 1596 1597void WebContentsImpl::ShowCreatedWidget(int route_id, 1598 const gfx::Rect& initial_pos) { 1599 ShowCreatedWidget(route_id, false, initial_pos); 1600} 1601 1602void WebContentsImpl::ShowCreatedFullscreenWidget(int route_id) { 1603 ShowCreatedWidget(route_id, true, gfx::Rect()); 1604 1605 DCHECK_EQ(MSG_ROUTING_NONE, fullscreen_widget_routing_id_); 1606 fullscreen_widget_routing_id_ = route_id; 1607 FOR_EACH_OBSERVER(WebContentsObserver, 1608 observers_, 1609 DidShowFullscreenWidget(route_id)); 1610} 1611 1612void WebContentsImpl::ShowCreatedWidget(int route_id, 1613 bool is_fullscreen, 1614 const gfx::Rect& initial_pos) { 1615 if (delegate_) 1616 delegate_->RenderWidgetShowing(); 1617 1618 RenderWidgetHostViewPort* widget_host_view = 1619 RenderWidgetHostViewPort::FromRWHV(GetCreatedWidget(route_id)); 1620 if (!widget_host_view) 1621 return; 1622 if (is_fullscreen) 1623 widget_host_view->InitAsFullscreen(GetRenderWidgetHostViewPort()); 1624 else 1625 widget_host_view->InitAsPopup(GetRenderWidgetHostViewPort(), initial_pos); 1626 1627 RenderWidgetHostImpl* render_widget_host_impl = 1628 RenderWidgetHostImpl::From(widget_host_view->GetRenderWidgetHost()); 1629 render_widget_host_impl->Init(); 1630 // Only allow privileged mouse lock for fullscreen render widget, which is 1631 // used to implement Pepper Flash fullscreen. 1632 render_widget_host_impl->set_allow_privileged_mouse_lock(is_fullscreen); 1633 1634#if defined(OS_MACOSX) 1635 // A RenderWidgetHostViewMac has lifetime scoped to the view. Now that it's 1636 // properly embedded (or purposefully ignored) we can release the retain we 1637 // took in CreateNewWidget(). 1638 base::mac::NSObjectRelease(widget_host_view->GetNativeView()); 1639#endif 1640} 1641 1642WebContentsImpl* WebContentsImpl::GetCreatedWindow(int route_id) { 1643 PendingContents::iterator iter = pending_contents_.find(route_id); 1644 1645 // Certain systems can block the creation of new windows. If we didn't succeed 1646 // in creating one, just return NULL. 1647 if (iter == pending_contents_.end()) { 1648 return NULL; 1649 } 1650 1651 WebContentsImpl* new_contents = iter->second; 1652 pending_contents_.erase(route_id); 1653 RemoveDestructionObserver(new_contents); 1654 1655 // Don't initialize the guest WebContents immediately. 1656 if (new_contents->GetRenderProcessHost()->IsGuest()) 1657 return new_contents; 1658 1659 if (!new_contents->GetRenderProcessHost()->HasConnection() || 1660 !new_contents->GetRenderViewHost()->GetView()) 1661 return NULL; 1662 1663 // TODO(brettw): It seems bogus to reach into here and initialize the host. 1664 static_cast<RenderViewHostImpl*>(new_contents->GetRenderViewHost())->Init(); 1665 return new_contents; 1666} 1667 1668RenderWidgetHostView* WebContentsImpl::GetCreatedWidget(int route_id) { 1669 PendingWidgetViews::iterator iter = pending_widget_views_.find(route_id); 1670 if (iter == pending_widget_views_.end()) { 1671 DCHECK(false); 1672 return NULL; 1673 } 1674 1675 RenderWidgetHostView* widget_host_view = iter->second; 1676 pending_widget_views_.erase(route_id); 1677 1678 RenderWidgetHost* widget_host = widget_host_view->GetRenderWidgetHost(); 1679 if (!widget_host->GetProcess()->HasConnection()) { 1680 // The view has gone away or the renderer crashed. Nothing to do. 1681 return NULL; 1682 } 1683 1684 return widget_host_view; 1685} 1686 1687void WebContentsImpl::ShowContextMenu(const ContextMenuParams& params) { 1688 // Allow WebContentsDelegates to handle the context menu operation first. 1689 if (delegate_ && delegate_->HandleContextMenu(params)) 1690 return; 1691 1692 render_view_host_delegate_view_->ShowContextMenu(params); 1693} 1694 1695void WebContentsImpl::RequestMediaAccessPermission( 1696 const MediaStreamRequest& request, 1697 const MediaResponseCallback& callback) { 1698 if (delegate_) 1699 delegate_->RequestMediaAccessPermission(this, request, callback); 1700 else 1701 callback.Run(MediaStreamDevices(), scoped_ptr<MediaStreamUI>()); 1702} 1703 1704SessionStorageNamespace* WebContentsImpl::GetSessionStorageNamespace( 1705 SiteInstance* instance) { 1706 return controller_.GetSessionStorageNamespace(instance); 1707} 1708 1709void WebContentsImpl::DidSendScreenRects(RenderWidgetHostImpl* rwh) { 1710 if (browser_plugin_embedder_) 1711 browser_plugin_embedder_->DidSendScreenRects(); 1712} 1713 1714void WebContentsImpl::UpdatePreferredSize(const gfx::Size& pref_size) { 1715 preferred_size_ = pref_size; 1716 if (delegate_) 1717 delegate_->UpdatePreferredSize(this, pref_size); 1718} 1719 1720void WebContentsImpl::ResizeDueToAutoResize(const gfx::Size& new_size) { 1721 if (delegate_) 1722 delegate_->ResizeDueToAutoResize(this, new_size); 1723} 1724 1725WebContents* WebContentsImpl::OpenURL(const OpenURLParams& params) { 1726 if (!delegate_) 1727 return NULL; 1728 1729 WebContents* new_contents = delegate_->OpenURLFromTab(this, params); 1730 return new_contents; 1731} 1732 1733bool WebContentsImpl::Send(IPC::Message* message) { 1734 if (!GetRenderViewHost()) { 1735 delete message; 1736 return false; 1737 } 1738 1739 return GetRenderViewHost()->Send(message); 1740} 1741 1742bool WebContentsImpl::NavigateToPendingEntry( 1743 NavigationController::ReloadType reload_type) { 1744 return NavigateToEntry( 1745 *NavigationEntryImpl::FromNavigationEntry(controller_.GetPendingEntry()), 1746 reload_type); 1747} 1748 1749void WebContentsImpl::RenderViewForInterstitialPageCreated( 1750 RenderViewHost* render_view_host) { 1751 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 1752 RenderViewForInterstitialPageCreated(render_view_host)); 1753} 1754 1755void WebContentsImpl::AttachInterstitialPage( 1756 InterstitialPageImpl* interstitial_page) { 1757 DCHECK(interstitial_page); 1758 render_manager_.set_interstitial_page(interstitial_page); 1759 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 1760 DidAttachInterstitialPage()); 1761} 1762 1763void WebContentsImpl::DetachInterstitialPage() { 1764 if (GetInterstitialPage()) 1765 render_manager_.remove_interstitial_page(); 1766 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 1767 DidDetachInterstitialPage()); 1768} 1769 1770bool WebContentsImpl::NavigateToEntry( 1771 const NavigationEntryImpl& entry, 1772 NavigationController::ReloadType reload_type) { 1773 TRACE_EVENT0("browser", "WebContentsImpl::NavigateToEntry"); 1774 1775 // The renderer will reject IPC messages with URLs longer than 1776 // this limit, so don't attempt to navigate with a longer URL. 1777 if (entry.GetURL().spec().size() > kMaxURLChars) { 1778 LOG(WARNING) << "Refusing to load URL as it exceeds " << kMaxURLChars 1779 << " characters."; 1780 return false; 1781 } 1782 1783 RenderViewHostImpl* dest_render_view_host = 1784 static_cast<RenderViewHostImpl*>(render_manager_.Navigate(entry)); 1785 if (!dest_render_view_host) 1786 return false; // Unable to create the desired render view host. 1787 1788 // For security, we should never send non-Web-UI URLs to a Web UI renderer. 1789 // Double check that here. 1790 int enabled_bindings = dest_render_view_host->GetEnabledBindings(); 1791 bool data_urls_allowed = delegate_ && delegate_->CanLoadDataURLsInWebUI(); 1792 bool is_allowed_in_web_ui_renderer = 1793 WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI( 1794 GetBrowserContext(), entry.GetURL(), data_urls_allowed); 1795 if ((enabled_bindings & BINDINGS_POLICY_WEB_UI) && 1796 !is_allowed_in_web_ui_renderer) { 1797 // Log the URL to help us diagnose any future failures of this CHECK. 1798 GetContentClient()->SetActiveURL(entry.GetURL()); 1799 CHECK(0); 1800 } 1801 1802 // Notify observers that we will navigate in this RV. 1803 FOR_EACH_OBSERVER(WebContentsObserver, 1804 observers_, 1805 AboutToNavigateRenderView(dest_render_view_host)); 1806 1807 // Used for page load time metrics. 1808 current_load_start_ = base::TimeTicks::Now(); 1809 1810 // Navigate in the desired RenderViewHost. 1811 ViewMsg_Navigate_Params navigate_params; 1812 MakeNavigateParams(entry, controller_, delegate_, reload_type, 1813 &navigate_params); 1814 dest_render_view_host->Navigate(navigate_params); 1815 1816 if (entry.GetPageID() == -1) { 1817 // HACK!! This code suppresses javascript: URLs from being added to 1818 // session history, which is what we want to do for javascript: URLs that 1819 // do not generate content. What we really need is a message from the 1820 // renderer telling us that a new page was not created. The same message 1821 // could be used for mailto: URLs and the like. 1822 if (entry.GetURL().SchemeIs(kJavaScriptScheme)) 1823 return false; 1824 } 1825 1826 // Notify observers about navigation. 1827 FOR_EACH_OBSERVER(WebContentsObserver, 1828 observers_, 1829 NavigateToPendingEntry(entry.GetURL(), reload_type)); 1830 1831 if (delegate_) 1832 delegate_->DidNavigateToPendingEntry(this); 1833 1834 return true; 1835} 1836 1837void WebContentsImpl::SetHistoryLengthAndPrune( 1838 const SiteInstance* site_instance, 1839 int history_length, 1840 int32 minimum_page_id) { 1841 // SetHistoryLengthAndPrune doesn't work when there are pending cross-site 1842 // navigations. Callers should ensure that this is the case. 1843 if (render_manager_.pending_render_view_host()) { 1844 NOTREACHED(); 1845 return; 1846 } 1847 RenderViewHostImpl* rvh = GetRenderViewHostImpl(); 1848 if (!rvh) { 1849 NOTREACHED(); 1850 return; 1851 } 1852 if (site_instance && rvh->GetSiteInstance() != site_instance) { 1853 NOTREACHED(); 1854 return; 1855 } 1856 Send(new ViewMsg_SetHistoryLengthAndPrune(GetRoutingID(), 1857 history_length, 1858 minimum_page_id)); 1859} 1860 1861void WebContentsImpl::FocusThroughTabTraversal(bool reverse) { 1862 if (ShowingInterstitialPage()) { 1863 render_manager_.interstitial_page()->FocusThroughTabTraversal(reverse); 1864 return; 1865 } 1866 GetRenderViewHostImpl()->SetInitialFocus(reverse); 1867} 1868 1869bool WebContentsImpl::ShowingInterstitialPage() const { 1870 return render_manager_.interstitial_page() != NULL; 1871} 1872 1873InterstitialPage* WebContentsImpl::GetInterstitialPage() const { 1874 return render_manager_.interstitial_page(); 1875} 1876 1877bool WebContentsImpl::IsSavable() { 1878 // WebKit creates Document object when MIME type is application/xhtml+xml, 1879 // so we also support this MIME type. 1880 return contents_mime_type_ == "text/html" || 1881 contents_mime_type_ == "text/xml" || 1882 contents_mime_type_ == "application/xhtml+xml" || 1883 contents_mime_type_ == "text/plain" || 1884 contents_mime_type_ == "text/css" || 1885 net::IsSupportedJavascriptMimeType(contents_mime_type_.c_str()); 1886} 1887 1888void WebContentsImpl::OnSavePage() { 1889 // If we can not save the page, try to download it. 1890 if (!IsSavable()) { 1891 RecordDownloadSource(INITIATED_BY_SAVE_PACKAGE_ON_NON_HTML); 1892 SaveFrame(GetURL(), Referrer()); 1893 return; 1894 } 1895 1896 Stop(); 1897 1898 // Create the save package and possibly prompt the user for the name to save 1899 // the page as. The user prompt is an asynchronous operation that runs on 1900 // another thread. 1901 save_package_ = new SavePackage(this); 1902 save_package_->GetSaveInfo(); 1903} 1904 1905// Used in automated testing to bypass prompting the user for file names. 1906// Instead, the names and paths are hard coded rather than running them through 1907// file name sanitation and extension / mime checking. 1908bool WebContentsImpl::SavePage(const base::FilePath& main_file, 1909 const base::FilePath& dir_path, 1910 SavePageType save_type) { 1911 // Stop the page from navigating. 1912 Stop(); 1913 1914 save_package_ = new SavePackage(this, save_type, main_file, dir_path); 1915 return save_package_->Init(SavePackageDownloadCreatedCallback()); 1916} 1917 1918void WebContentsImpl::SaveFrame(const GURL& url, 1919 const Referrer& referrer) { 1920 if (!GetURL().is_valid()) 1921 return; 1922 bool is_main_frame = (url == GetURL()); 1923 1924 DownloadManager* dlm = 1925 BrowserContext::GetDownloadManager(GetBrowserContext()); 1926 if (!dlm) 1927 return; 1928 int64 post_id = -1; 1929 if (is_main_frame) { 1930 const NavigationEntry* entry = controller_.GetActiveEntry(); 1931 if (entry) 1932 post_id = entry->GetPostID(); 1933 } 1934 scoped_ptr<DownloadUrlParameters> params( 1935 DownloadUrlParameters::FromWebContents(this, url)); 1936 params->set_referrer(referrer); 1937 params->set_post_id(post_id); 1938 params->set_prefer_cache(true); 1939 if (post_id >= 0) 1940 params->set_method("POST"); 1941 params->set_prompt(true); 1942 dlm->DownloadUrl(params.Pass()); 1943} 1944 1945void WebContentsImpl::GenerateMHTML( 1946 const base::FilePath& file, 1947 const base::Callback<void(int64)>& callback) { 1948 MHTMLGenerationManager::GetInstance()->SaveMHTML(this, file, callback); 1949} 1950 1951bool WebContentsImpl::IsActiveEntry(int32 page_id) { 1952 NavigationEntryImpl* active_entry = 1953 NavigationEntryImpl::FromNavigationEntry(controller_.GetActiveEntry()); 1954 return (active_entry != NULL && 1955 active_entry->site_instance() == GetSiteInstance() && 1956 active_entry->GetPageID() == page_id); 1957} 1958 1959const std::string& WebContentsImpl::GetContentsMimeType() const { 1960 return contents_mime_type_; 1961} 1962 1963bool WebContentsImpl::WillNotifyDisconnection() const { 1964 return notify_disconnection_; 1965} 1966 1967void WebContentsImpl::SetOverrideEncoding(const std::string& encoding) { 1968 SetEncoding(encoding); 1969 Send(new ViewMsg_SetPageEncoding(GetRoutingID(), encoding)); 1970} 1971 1972void WebContentsImpl::ResetOverrideEncoding() { 1973 encoding_.clear(); 1974 Send(new ViewMsg_ResetPageEncodingToDefault(GetRoutingID())); 1975} 1976 1977RendererPreferences* WebContentsImpl::GetMutableRendererPrefs() { 1978 return &renderer_preferences_; 1979} 1980 1981void WebContentsImpl::Close() { 1982 Close(GetRenderViewHost()); 1983} 1984 1985void WebContentsImpl::DragSourceEndedAt(int client_x, int client_y, 1986 int screen_x, int screen_y, WebKit::WebDragOperation operation) { 1987 if (browser_plugin_embedder_.get()) 1988 browser_plugin_embedder_->DragSourceEndedAt(client_x, client_y, 1989 screen_x, screen_y, operation); 1990 if (GetRenderViewHost()) 1991 GetRenderViewHostImpl()->DragSourceEndedAt(client_x, client_y, 1992 screen_x, screen_y, operation); 1993} 1994 1995void WebContentsImpl::DragSourceMovedTo(int client_x, int client_y, 1996 int screen_x, int screen_y) { 1997 if (browser_plugin_embedder_.get()) 1998 browser_plugin_embedder_->DragSourceMovedTo(client_x, client_y, 1999 screen_x, screen_y); 2000 if (GetRenderViewHost()) 2001 GetRenderViewHostImpl()->DragSourceMovedTo(client_x, client_y, 2002 screen_x, screen_y); 2003} 2004 2005void WebContentsImpl::SystemDragEnded() { 2006 if (GetRenderViewHost()) 2007 GetRenderViewHostImpl()->DragSourceSystemDragEnded(); 2008 if (delegate_) 2009 delegate_->DragEnded(); 2010 if (browser_plugin_embedder_.get()) 2011 browser_plugin_embedder_->SystemDragEnded(); 2012} 2013 2014void WebContentsImpl::UserGestureDone() { 2015 OnUserGesture(); 2016} 2017 2018void WebContentsImpl::SetClosedByUserGesture(bool value) { 2019 closed_by_user_gesture_ = value; 2020} 2021 2022bool WebContentsImpl::GetClosedByUserGesture() const { 2023 return closed_by_user_gesture_; 2024} 2025 2026double WebContentsImpl::GetZoomLevel() const { 2027 HostZoomMapImpl* zoom_map = static_cast<HostZoomMapImpl*>( 2028 HostZoomMap::GetForBrowserContext(GetBrowserContext())); 2029 if (!zoom_map) 2030 return 0; 2031 2032 double zoom_level; 2033 if (temporary_zoom_settings_) { 2034 zoom_level = zoom_map->GetTemporaryZoomLevel( 2035 GetRenderProcessHost()->GetID(), GetRenderViewHost()->GetRoutingID()); 2036 } else { 2037 GURL url; 2038 NavigationEntry* active_entry = GetController().GetActiveEntry(); 2039 // Since zoom map is updated using rewritten URL, use rewritten URL 2040 // to get the zoom level. 2041 url = active_entry ? active_entry->GetURL() : GURL::EmptyGURL(); 2042 zoom_level = zoom_map->GetZoomLevelForHostAndScheme(url.scheme(), 2043 net::GetHostOrSpecFromURL(url)); 2044 } 2045 return zoom_level; 2046} 2047 2048int WebContentsImpl::GetZoomPercent(bool* enable_increment, 2049 bool* enable_decrement) const { 2050 *enable_decrement = *enable_increment = false; 2051 // Calculate the zoom percent from the factor. Round up to the nearest whole 2052 // number. 2053 int percent = static_cast<int>( 2054 ZoomLevelToZoomFactor(GetZoomLevel()) * 100 + 0.5); 2055 *enable_decrement = percent > minimum_zoom_percent_; 2056 *enable_increment = percent < maximum_zoom_percent_; 2057 return percent; 2058} 2059 2060void WebContentsImpl::ViewSource() { 2061 if (!delegate_) 2062 return; 2063 2064 NavigationEntry* active_entry = GetController().GetActiveEntry(); 2065 if (!active_entry) 2066 return; 2067 2068 delegate_->ViewSourceForTab(this, active_entry->GetURL()); 2069} 2070 2071void WebContentsImpl::ViewFrameSource(const GURL& url, 2072 const PageState& page_state) { 2073 if (!delegate_) 2074 return; 2075 2076 delegate_->ViewSourceForFrame(this, url, page_state); 2077} 2078 2079int WebContentsImpl::GetMinimumZoomPercent() const { 2080 return minimum_zoom_percent_; 2081} 2082 2083int WebContentsImpl::GetMaximumZoomPercent() const { 2084 return maximum_zoom_percent_; 2085} 2086 2087gfx::Size WebContentsImpl::GetPreferredSize() const { 2088 return preferred_size_; 2089} 2090 2091bool WebContentsImpl::GotResponseToLockMouseRequest(bool allowed) { 2092 return GetRenderViewHost() ? 2093 GetRenderViewHostImpl()->GotResponseToLockMouseRequest(allowed) : false; 2094} 2095 2096bool WebContentsImpl::HasOpener() const { 2097 return opener_ != NULL; 2098} 2099 2100void WebContentsImpl::DidChooseColorInColorChooser(SkColor color) { 2101 Send(new ViewMsg_DidChooseColorResponse( 2102 GetRoutingID(), color_chooser_identifier_, color)); 2103} 2104 2105void WebContentsImpl::DidEndColorChooser() { 2106 Send(new ViewMsg_DidEndColorChooser(GetRoutingID(), 2107 color_chooser_identifier_)); 2108 color_chooser_.reset(); 2109 color_chooser_identifier_ = 0; 2110} 2111 2112int WebContentsImpl::DownloadImage(const GURL& url, 2113 bool is_favicon, 2114 uint32_t preferred_image_size, 2115 uint32_t max_image_size, 2116 const ImageDownloadCallback& callback) { 2117 RenderViewHost* host = GetRenderViewHost(); 2118 int id = StartDownload( 2119 host, url, is_favicon, preferred_image_size, max_image_size); 2120 image_download_map_[id] = callback; 2121 return id; 2122} 2123 2124bool WebContentsImpl::FocusLocationBarByDefault() { 2125 NavigationEntry* entry = controller_.GetActiveEntry(); 2126 if (entry && entry->GetURL() == GURL(kAboutBlankURL)) 2127 return true; 2128 return delegate_ && delegate_->ShouldFocusLocationBarByDefault(this); 2129} 2130 2131void WebContentsImpl::SetFocusToLocationBar(bool select_all) { 2132 if (delegate_) 2133 delegate_->SetFocusToLocationBar(select_all); 2134} 2135 2136void WebContentsImpl::DidStartProvisionalLoadForFrame( 2137 RenderViewHost* render_view_host, 2138 int64 frame_id, 2139 int64 parent_frame_id, 2140 bool is_main_frame, 2141 const GURL& url) { 2142 bool is_error_page = (url.spec() == kUnreachableWebDataURL); 2143 bool is_iframe_srcdoc = (url.spec() == kAboutSrcDocURL); 2144 GURL validated_url(url); 2145 RenderProcessHost* render_process_host = 2146 render_view_host->GetProcess(); 2147 RenderViewHost::FilterURL(render_process_host, false, &validated_url); 2148 2149 if (is_main_frame) { 2150 DidChangeLoadProgress(0); 2151 2152 // If there is no browser-initiated pending entry for this navigation and it 2153 // is not for the error URL, create a pending entry using the current 2154 // SiteInstance, and ensure the address bar updates accordingly. We don't 2155 // know the referrer or extra headers at this point, but the referrer will 2156 // be set properly upon commit. 2157 NavigationEntry* pending_entry = controller_.GetPendingEntry(); 2158 bool has_browser_initiated_pending_entry = pending_entry && 2159 !NavigationEntryImpl::FromNavigationEntry(pending_entry)-> 2160 is_renderer_initiated(); 2161 if (!has_browser_initiated_pending_entry && !is_error_page) { 2162 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( 2163 controller_.CreateNavigationEntry(validated_url, 2164 content::Referrer(), 2165 content::PAGE_TRANSITION_LINK, 2166 true /* is_renderer_initiated */, 2167 std::string(), 2168 GetBrowserContext())); 2169 entry->set_site_instance( 2170 static_cast<SiteInstanceImpl*>(GetSiteInstance())); 2171 controller_.SetPendingEntry(entry); 2172 NotifyNavigationStateChanged(content::INVALIDATE_TYPE_URL); 2173 } 2174 } 2175 2176 // Notify observers about the start of the provisional load. 2177 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2178 DidStartProvisionalLoadForFrame(frame_id, parent_frame_id, 2179 is_main_frame, validated_url, is_error_page, 2180 is_iframe_srcdoc, render_view_host)); 2181 2182 if (is_main_frame) { 2183 // Notify observers about the provisional change in the main frame URL. 2184 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2185 ProvisionalChangeToMainFrameUrl(validated_url, 2186 render_view_host)); 2187 } 2188} 2189 2190void WebContentsImpl::DidRedirectProvisionalLoad( 2191 RenderViewHost* render_view_host, 2192 int32 page_id, 2193 const GURL& source_url, 2194 const GURL& target_url) { 2195 // TODO(creis): Remove this method and have the pre-rendering code listen to 2196 // WebContentsObserver::DidGetRedirectForResourceRequest instead. 2197 // See http://crbug.com/78512. 2198 GURL validated_source_url(source_url); 2199 GURL validated_target_url(target_url); 2200 RenderProcessHost* render_process_host = 2201 render_view_host->GetProcess(); 2202 RenderViewHost::FilterURL(render_process_host, false, &validated_source_url); 2203 RenderViewHost::FilterURL(render_process_host, false, &validated_target_url); 2204 NavigationEntry* entry; 2205 if (page_id == -1) { 2206 entry = controller_.GetPendingEntry(); 2207 } else { 2208 entry = controller_.GetEntryWithPageID(render_view_host->GetSiteInstance(), 2209 page_id); 2210 } 2211 if (!entry || entry->GetURL() != validated_source_url) 2212 return; 2213 2214 // Notify observers about the provisional change in the main frame URL. 2215 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2216 ProvisionalChangeToMainFrameUrl(validated_target_url, 2217 render_view_host)); 2218} 2219 2220void WebContentsImpl::DidFailProvisionalLoadWithError( 2221 RenderViewHost* render_view_host, 2222 const ViewHostMsg_DidFailProvisionalLoadWithError_Params& params) { 2223 VLOG(1) << "Failed Provisional Load: " << params.url.possibly_invalid_spec() 2224 << ", error_code: " << params.error_code 2225 << ", error_description: " << params.error_description 2226 << ", is_main_frame: " << params.is_main_frame 2227 << ", showing_repost_interstitial: " << 2228 params.showing_repost_interstitial 2229 << ", frame_id: " << params.frame_id; 2230 GURL validated_url(params.url); 2231 RenderProcessHost* render_process_host = 2232 render_view_host->GetProcess(); 2233 RenderViewHost::FilterURL(render_process_host, false, &validated_url); 2234 2235 if (net::ERR_ABORTED == params.error_code) { 2236 // EVIL HACK ALERT! Ignore failed loads when we're showing interstitials. 2237 // This means that the interstitial won't be torn down properly, which is 2238 // bad. But if we have an interstitial, go back to another tab type, and 2239 // then load the same interstitial again, we could end up getting the first 2240 // interstitial's "failed" message (as a result of the cancel) when we're on 2241 // the second one. 2242 // 2243 // We can't tell this apart, so we think we're tearing down the current page 2244 // which will cause a crash later one. There is also some code in 2245 // RenderViewHostManager::RendererAbortedProvisionalLoad that is commented 2246 // out because of this problem. 2247 // 2248 // http://code.google.com/p/chromium/issues/detail?id=2855 2249 // Because this will not tear down the interstitial properly, if "back" is 2250 // back to another tab type, the interstitial will still be somewhat alive 2251 // in the previous tab type. If you navigate somewhere that activates the 2252 // tab with the interstitial again, you'll see a flash before the new load 2253 // commits of the interstitial page. 2254 if (ShowingInterstitialPage()) { 2255 LOG(WARNING) << "Discarding message during interstitial."; 2256 return; 2257 } 2258 2259 render_manager_.RendererAbortedProvisionalLoad(render_view_host); 2260 } 2261 2262 // Do not usually clear the pending entry if one exists, so that the user's 2263 // typed URL is not lost when a navigation fails or is aborted. However, in 2264 // cases that we don't show the pending entry (e.g., renderer-initiated 2265 // navigations in an existing tab), we don't keep it around. That prevents 2266 // spoofs on in-page navigations that don't go through 2267 // DidStartProvisionalLoadForFrame. 2268 // In general, we allow the view to clear the pending entry and typed URL if 2269 // the user requests (e.g., hitting Escape with focus in the address bar). 2270 // Note: don't touch the transient entry, since an interstitial may exist. 2271 if (controller_.GetPendingEntry() != controller_.GetVisibleEntry()) 2272 controller_.DiscardPendingEntry(); 2273 2274 FOR_EACH_OBSERVER(WebContentsObserver, 2275 observers_, 2276 DidFailProvisionalLoad(params.frame_id, 2277 params.is_main_frame, 2278 validated_url, 2279 params.error_code, 2280 params.error_description, 2281 render_view_host)); 2282} 2283 2284void WebContentsImpl::OnDidLoadResourceFromMemoryCache( 2285 const GURL& url, 2286 const std::string& security_info, 2287 const std::string& http_method, 2288 const std::string& mime_type, 2289 ResourceType::Type resource_type) { 2290 base::StatsCounter cache("WebKit.CacheHit"); 2291 cache.Increment(); 2292 2293 // Send out a notification that we loaded a resource from our memory cache. 2294 int cert_id = 0; 2295 net::CertStatus cert_status = 0; 2296 int security_bits = -1; 2297 int connection_status = 0; 2298 DeserializeSecurityInfo(security_info, &cert_id, &cert_status, 2299 &security_bits, &connection_status); 2300 LoadFromMemoryCacheDetails details( 2301 url, GetRenderProcessHost()->GetID(), cert_id, cert_status, http_method, 2302 mime_type, resource_type); 2303 2304 controller_.ssl_manager()->DidLoadFromMemoryCache(details); 2305 2306 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2307 DidLoadResourceFromMemoryCache(details)); 2308 2309 // TODO(avi): Remove. http://crbug.com/170921 2310 NotificationService::current()->Notify( 2311 NOTIFICATION_LOAD_FROM_MEMORY_CACHE, 2312 Source<NavigationController>(&controller_), 2313 Details<LoadFromMemoryCacheDetails>(&details)); 2314 2315 if (url.is_valid() && url.SchemeIsHTTPOrHTTPS()) { 2316 scoped_refptr<net::URLRequestContextGetter> request_context( 2317 resource_type == ResourceType::MEDIA ? 2318 GetBrowserContext()->GetMediaRequestContextForRenderProcess( 2319 GetRenderProcessHost()->GetID()) : 2320 GetBrowserContext()->GetRequestContextForRenderProcess( 2321 GetRenderProcessHost()->GetID())); 2322 BrowserThread::PostTask( 2323 BrowserThread::IO, 2324 FROM_HERE, 2325 base::Bind(&NotifyCacheOnIO, request_context, url, http_method)); 2326 } 2327} 2328 2329void WebContentsImpl::OnDidDisplayInsecureContent() { 2330 RecordAction(UserMetricsAction("SSL.DisplayedInsecureContent")); 2331 displayed_insecure_content_ = true; 2332 SSLManager::NotifySSLInternalStateChanged( 2333 GetController().GetBrowserContext()); 2334} 2335 2336void WebContentsImpl::OnDidRunInsecureContent( 2337 const std::string& security_origin, const GURL& target_url) { 2338 LOG(INFO) << security_origin << " ran insecure content from " 2339 << target_url.possibly_invalid_spec(); 2340 RecordAction(UserMetricsAction("SSL.RanInsecureContent")); 2341 if (EndsWith(security_origin, kDotGoogleDotCom, false)) 2342 RecordAction(UserMetricsAction("SSL.RanInsecureContentGoogle")); 2343 controller_.ssl_manager()->DidRunInsecureContent(security_origin); 2344 displayed_insecure_content_ = true; 2345 SSLManager::NotifySSLInternalStateChanged( 2346 GetController().GetBrowserContext()); 2347} 2348 2349void WebContentsImpl::OnDocumentLoadedInFrame(int64 frame_id) { 2350 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2351 DocumentLoadedInFrame(frame_id, message_source_)); 2352} 2353 2354void WebContentsImpl::OnDidFinishLoad( 2355 int64 frame_id, 2356 const GURL& url, 2357 bool is_main_frame) { 2358 GURL validated_url(url); 2359 RenderProcessHost* render_process_host = message_source_->GetProcess(); 2360 RenderViewHost::FilterURL(render_process_host, false, &validated_url); 2361 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2362 DidFinishLoad(frame_id, validated_url, is_main_frame, 2363 message_source_)); 2364} 2365 2366void WebContentsImpl::OnDidFailLoadWithError( 2367 int64 frame_id, 2368 const GURL& url, 2369 bool is_main_frame, 2370 int error_code, 2371 const string16& error_description) { 2372 GURL validated_url(url); 2373 RenderProcessHost* render_process_host = message_source_->GetProcess(); 2374 RenderViewHost::FilterURL(render_process_host, false, &validated_url); 2375 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2376 DidFailLoad(frame_id, validated_url, is_main_frame, 2377 error_code, error_description, 2378 message_source_)); 2379} 2380 2381void WebContentsImpl::OnGoToEntryAtOffset(int offset) { 2382 if (!delegate_ || delegate_->OnGoToEntryOffset(offset)) { 2383 NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( 2384 controller_.GetEntryAtOffset(offset)); 2385 if (!entry) 2386 return; 2387 // Note that we don't call NavigationController::GotToOffset() as we don't 2388 // want to create a pending navigation entry (it might end up lingering 2389 // http://crbug.com/51680). 2390 entry->SetTransitionType( 2391 PageTransitionFromInt( 2392 entry->GetTransitionType() | 2393 PAGE_TRANSITION_FORWARD_BACK)); 2394 NavigateToEntry(*entry, NavigationControllerImpl::NO_RELOAD); 2395 2396 // If the entry is being restored and doesn't have a SiteInstance yet, fill 2397 // it in now that we know. This allows us to find the entry when it commits. 2398 if (!entry->site_instance() && 2399 entry->restore_type() != NavigationEntryImpl::RESTORE_NONE) { 2400 entry->set_site_instance( 2401 static_cast<SiteInstanceImpl*>(GetPendingSiteInstance())); 2402 } 2403 } 2404} 2405 2406void WebContentsImpl::OnUpdateZoomLimits(int minimum_percent, 2407 int maximum_percent, 2408 bool remember) { 2409 minimum_zoom_percent_ = minimum_percent; 2410 maximum_zoom_percent_ = maximum_percent; 2411 temporary_zoom_settings_ = !remember; 2412} 2413 2414void WebContentsImpl::OnEnumerateDirectory(int request_id, 2415 const base::FilePath& path) { 2416 if (!delegate_) 2417 return; 2418 2419 ChildProcessSecurityPolicyImpl* policy = 2420 ChildProcessSecurityPolicyImpl::GetInstance(); 2421 if (policy->CanReadDirectory(GetRenderProcessHost()->GetID(), path)) 2422 delegate_->EnumerateDirectory(this, request_id, path); 2423} 2424 2425void WebContentsImpl::OnJSOutOfMemory() { 2426 if (delegate_) 2427 delegate_->JSOutOfMemory(this); 2428} 2429 2430void WebContentsImpl::OnRegisterProtocolHandler(const std::string& protocol, 2431 const GURL& url, 2432 const string16& title, 2433 bool user_gesture) { 2434 if (!delegate_) 2435 return; 2436 2437 ChildProcessSecurityPolicyImpl* policy = 2438 ChildProcessSecurityPolicyImpl::GetInstance(); 2439 if (policy->IsPseudoScheme(protocol)) 2440 return; 2441 2442 delegate_->RegisterProtocolHandler(this, protocol, url, title, user_gesture); 2443} 2444 2445void WebContentsImpl::OnFindReply(int request_id, 2446 int number_of_matches, 2447 const gfx::Rect& selection_rect, 2448 int active_match_ordinal, 2449 bool final_update) { 2450 if (delegate_) { 2451 delegate_->FindReply(this, request_id, number_of_matches, selection_rect, 2452 active_match_ordinal, final_update); 2453 } 2454} 2455 2456void WebContentsImpl::OnDidProgrammaticallyScroll( 2457 const gfx::Vector2d& scroll_point) { 2458 if (delegate_) 2459 delegate_->DidProgrammaticallyScroll(this, scroll_point); 2460} 2461 2462#if defined(OS_ANDROID) 2463void WebContentsImpl::OnFindMatchRectsReply( 2464 int version, 2465 const std::vector<gfx::RectF>& rects, 2466 const gfx::RectF& active_rect) { 2467 if (delegate_) 2468 delegate_->FindMatchRectsReply(this, version, rects, active_rect); 2469} 2470 2471void WebContentsImpl::OnOpenDateTimeDialog( 2472 const ViewHostMsg_DateTimeDialogValue_Params& value) { 2473 date_time_chooser_->ShowDialog(ContentViewCore::FromWebContents(this), 2474 GetRenderViewHost(), 2475 value.dialog_type, 2476 value.year, 2477 value.month, 2478 value.day, 2479 value.hour, 2480 value.minute, 2481 value.second, 2482 value.milli, 2483 value.week, 2484 value.minimum, 2485 value.maximum, 2486 value.step); 2487} 2488 2489#endif 2490 2491void WebContentsImpl::OnCrashedPlugin(const base::FilePath& plugin_path, 2492 base::ProcessId plugin_pid) { 2493 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2494 PluginCrashed(plugin_path, plugin_pid)); 2495} 2496 2497void WebContentsImpl::OnAppCacheAccessed(const GURL& manifest_url, 2498 bool blocked_by_policy) { 2499 // Notify observers about navigation. 2500 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2501 AppCacheAccessed(manifest_url, blocked_by_policy)); 2502} 2503 2504void WebContentsImpl::OnOpenColorChooser(int color_chooser_id, 2505 SkColor color) { 2506 ColorChooser* new_color_chooser = delegate_->OpenColorChooser(this, color); 2507 if (color_chooser_ == new_color_chooser) 2508 return; 2509 color_chooser_.reset(new_color_chooser); 2510 color_chooser_identifier_ = color_chooser_id; 2511} 2512 2513void WebContentsImpl::OnEndColorChooser(int color_chooser_id) { 2514 if (color_chooser_ && 2515 color_chooser_id == color_chooser_identifier_) 2516 color_chooser_->End(); 2517} 2518 2519void WebContentsImpl::OnSetSelectedColorInColorChooser(int color_chooser_id, 2520 SkColor color) { 2521 if (color_chooser_ && 2522 color_chooser_id == color_chooser_identifier_) 2523 color_chooser_->SetSelectedColor(color); 2524} 2525 2526void WebContentsImpl::OnPepperPluginHung(int plugin_child_id, 2527 const base::FilePath& path, 2528 bool is_hung) { 2529 UMA_HISTOGRAM_COUNTS("Pepper.PluginHung", 1); 2530 2531 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2532 PluginHungStatusChanged(plugin_child_id, path, is_hung)); 2533} 2534 2535// This exists for render views that don't have a WebUI, but do have WebUI 2536// bindings enabled. 2537void WebContentsImpl::OnWebUISend(const GURL& source_url, 2538 const std::string& name, 2539 const base::ListValue& args) { 2540 if (delegate_) 2541 delegate_->WebUISend(this, source_url, name, args); 2542} 2543 2544void WebContentsImpl::OnRequestPpapiBrokerPermission( 2545 int routing_id, 2546 const GURL& url, 2547 const base::FilePath& plugin_path) { 2548 if (!delegate_) { 2549 OnPpapiBrokerPermissionResult(routing_id, false); 2550 return; 2551 } 2552 2553 if (!delegate_->RequestPpapiBrokerPermission( 2554 this, url, plugin_path, 2555 base::Bind(&WebContentsImpl::OnPpapiBrokerPermissionResult, 2556 base::Unretained(this), routing_id))) { 2557 NOTIMPLEMENTED(); 2558 OnPpapiBrokerPermissionResult(routing_id, false); 2559 } 2560} 2561 2562void WebContentsImpl::OnPpapiBrokerPermissionResult(int routing_id, 2563 bool result) { 2564 Send(new ViewMsg_PpapiBrokerPermissionResult(routing_id, result)); 2565} 2566 2567void WebContentsImpl::OnBrowserPluginMessage(const IPC::Message& message) { 2568 // This creates a BrowserPluginEmbedder, which handles all the BrowserPlugin 2569 // specific messages for this WebContents. This means that any message from 2570 // a BrowserPlugin prior to this will be ignored. 2571 // For more info, see comment above classes BrowserPluginEmbedder and 2572 // BrowserPluginGuest. 2573 CHECK(!browser_plugin_embedder_.get()); 2574 browser_plugin_embedder_.reset(BrowserPluginEmbedder::Create(this)); 2575 browser_plugin_embedder_->OnMessageReceived(message); 2576} 2577 2578void WebContentsImpl::OnDidDownloadImage( 2579 int id, 2580 int http_status_code, 2581 const GURL& image_url, 2582 int requested_size, 2583 const std::vector<SkBitmap>& bitmaps) { 2584 ImageDownloadMap::iterator iter = image_download_map_.find(id); 2585 if (iter == image_download_map_.end()) { 2586 // Currently WebContents notifies us of ANY downloads so that it is 2587 // possible to get here. 2588 return; 2589 } 2590 if (!iter->second.is_null()) { 2591 iter->second.Run(id, http_status_code, image_url, requested_size, bitmaps); 2592 } 2593 image_download_map_.erase(id); 2594} 2595 2596void WebContentsImpl::OnUpdateFaviconURL( 2597 int32 page_id, 2598 const std::vector<FaviconURL>& candidates) { 2599 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2600 DidUpdateFaviconURL(page_id, candidates)); 2601} 2602 2603FrameTreeNode* WebContentsImpl::FindFrameTreeNodeByID(int64 frame_id) { 2604 // TODO(nasko): Remove this check once we move to creating the root node 2605 // through RenderFrameHost creation. 2606 if (!frame_tree_root_.get()) 2607 return NULL; 2608 2609 FrameTreeNode* node = NULL; 2610 std::queue<FrameTreeNode*> queue; 2611 queue.push(frame_tree_root_.get()); 2612 2613 while (!queue.empty()) { 2614 node = queue.front(); 2615 queue.pop(); 2616 if (node->frame_id() == frame_id) 2617 return node; 2618 2619 for (size_t i = 0; i < node->child_count(); ++i) 2620 queue.push(node->child_at(i)); 2621 } 2622 2623 return NULL; 2624} 2625 2626void WebContentsImpl::OnFrameAttached( 2627 int64 parent_frame_id, 2628 int64 frame_id, 2629 const std::string& frame_name) { 2630 FrameTreeNode* parent = FindFrameTreeNodeByID(parent_frame_id); 2631 if (!parent) 2632 return; 2633 2634 FrameTreeNode* node = new FrameTreeNode(frame_id, frame_name); 2635 parent->AddChild(node); 2636} 2637 2638void WebContentsImpl::OnFrameDetached(int64 parent_frame_id, int64 frame_id) { 2639 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2640 FrameDetached(message_source_, frame_id)); 2641 2642 FrameTreeNode* parent = FindFrameTreeNodeByID(parent_frame_id); 2643 if (!parent) 2644 return; 2645 2646 parent->RemoveChild(frame_id); 2647} 2648 2649void WebContentsImpl::OnMediaNotification(int64 player_cookie, 2650 bool has_video, 2651 bool has_audio, 2652 bool is_playing) { 2653 // Chrome OS does its own detection of audio and video. 2654#if !defined(OS_CHROMEOS) 2655 if (is_playing) { 2656 scoped_ptr<PowerSaveBlocker> blocker; 2657 if (has_video) { 2658 blocker = PowerSaveBlocker::Create( 2659 PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, 2660 "Playing video"); 2661#if defined(OS_ANDROID) 2662 static_cast<PowerSaveBlockerImpl*>(blocker.get())-> 2663 InitDisplaySleepBlocker(GetView()->GetNativeView()); 2664#endif 2665 } else if (has_audio) { 2666 blocker = PowerSaveBlocker::Create( 2667 PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, 2668 "Playing audio"); 2669 } 2670 2671 if (blocker) 2672 power_save_blockers_[message_source_][player_cookie] = blocker.release(); 2673 } else { 2674 delete power_save_blockers_[message_source_][player_cookie]; 2675 power_save_blockers_[message_source_].erase(player_cookie); 2676 } 2677#endif // !defined(OS_CHROMEOS) 2678} 2679 2680 2681void WebContentsImpl::DidChangeVisibleSSLState() { 2682 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2683 DidChangeVisibleSSLState()); 2684} 2685 2686void WebContentsImpl::NotifyBeforeFormRepostWarningShow() { 2687 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2688 BeforeFormRepostWarningShow()); 2689} 2690 2691// Notifies the RenderWidgetHost instance about the fact that the page is 2692// loading, or done loading and calls the base implementation. 2693void WebContentsImpl::SetIsLoading(bool is_loading, 2694 LoadNotificationDetails* details) { 2695 if (is_loading == is_loading_) 2696 return; 2697 2698 if (!is_loading) { 2699 load_state_ = net::LoadStateWithParam(net::LOAD_STATE_IDLE, string16()); 2700 load_state_host_.clear(); 2701 upload_size_ = 0; 2702 upload_position_ = 0; 2703 } 2704 2705 render_manager_.SetIsLoading(is_loading); 2706 2707 is_loading_ = is_loading; 2708 waiting_for_response_ = is_loading; 2709 2710 if (delegate_) 2711 delegate_->LoadingStateChanged(this); 2712 NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD); 2713 2714 if (is_loading) 2715 TRACE_EVENT_ASYNC_BEGIN0("browser", "WebContentsImpl Loading", this); 2716 else 2717 TRACE_EVENT_ASYNC_END0("browser", "WebContentsImpl Loading", this); 2718 int type = is_loading ? NOTIFICATION_LOAD_START : NOTIFICATION_LOAD_STOP; 2719 NotificationDetails det = NotificationService::NoDetails(); 2720 if (details) 2721 det = Details<LoadNotificationDetails>(details); 2722 NotificationService::current()->Notify( 2723 type, Source<NavigationController>(&controller_), det); 2724} 2725 2726void WebContentsImpl::DidNavigateMainFramePostCommit( 2727 const LoadCommittedDetails& details, 2728 const ViewHostMsg_FrameNavigate_Params& params) { 2729 if (details.is_navigation_to_different_page()) { 2730 // Clear the status bubble. This is a workaround for a bug where WebKit 2731 // doesn't let us know that the cursor left an element during a 2732 // transition (this is also why the mouse cursor remains as a hand after 2733 // clicking on a link); see bugs 1184641 and 980803. We don't want to 2734 // clear the bubble when a user navigates to a named anchor in the same 2735 // page. 2736 UpdateTargetURL(details.entry->GetPageID(), GURL()); 2737 } 2738 2739 if (!details.is_in_page) { 2740 // Once the main frame is navigated, we're no longer considered to have 2741 // displayed insecure content. 2742 displayed_insecure_content_ = false; 2743 SSLManager::NotifySSLInternalStateChanged( 2744 GetController().GetBrowserContext()); 2745 } 2746 2747 // Notify observers about navigation. 2748 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2749 DidNavigateMainFrame(details, params)); 2750} 2751 2752void WebContentsImpl::DidNavigateAnyFramePostCommit( 2753 RenderViewHost* render_view_host, 2754 const LoadCommittedDetails& details, 2755 const ViewHostMsg_FrameNavigate_Params& params) { 2756 // If we navigate off the page, close all JavaScript dialogs. 2757 if (dialog_manager_ && !details.is_in_page) 2758 dialog_manager_->CancelActiveAndPendingDialogs(this); 2759 2760 // Notify observers about navigation. 2761 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2762 DidNavigateAnyFrame(details, params)); 2763} 2764 2765bool WebContentsImpl::ShouldAssignSiteForURL(const GURL& url) { 2766 // about:blank should not "use up" a new SiteInstance. The SiteInstance can 2767 // still be used for a normal web site. 2768 if (url == GURL(kAboutBlankURL)) 2769 return false; 2770 2771 // The embedder will then have the opportunity to determine if the URL 2772 // should "use up" the SiteInstance. 2773 return GetContentClient()->browser()->ShouldAssignSiteForURL(url); 2774} 2775 2776void WebContentsImpl::UpdateMaxPageIDIfNecessary(RenderViewHost* rvh) { 2777 // If we are creating a RVH for a restored controller, then we need to make 2778 // sure the RenderView starts with a next_page_id_ larger than the number 2779 // of restored entries. This must be called before the RenderView starts 2780 // navigating (to avoid a race between the browser updating max_page_id and 2781 // the renderer updating next_page_id_). Because of this, we only call this 2782 // from CreateRenderView and allow that to notify the RenderView for us. 2783 int max_restored_page_id = controller_.GetMaxRestoredPageID(); 2784 if (max_restored_page_id > 2785 GetMaxPageIDForSiteInstance(rvh->GetSiteInstance())) 2786 UpdateMaxPageIDForSiteInstance(rvh->GetSiteInstance(), 2787 max_restored_page_id); 2788} 2789 2790bool WebContentsImpl::UpdateTitleForEntry(NavigationEntryImpl* entry, 2791 const string16& title) { 2792 // For file URLs without a title, use the pathname instead. In the case of a 2793 // synthesized title, we don't want the update to count toward the "one set 2794 // per page of the title to history." 2795 string16 final_title; 2796 bool explicit_set; 2797 if (entry && entry->GetURL().SchemeIsFile() && title.empty()) { 2798 final_title = UTF8ToUTF16(entry->GetURL().ExtractFileName()); 2799 explicit_set = false; // Don't count synthetic titles toward the set limit. 2800 } else { 2801 TrimWhitespace(title, TRIM_ALL, &final_title); 2802 explicit_set = true; 2803 } 2804 2805 // If a page is created via window.open and never navigated, 2806 // there will be no navigation entry. In this situation, 2807 // |page_title_when_no_navigation_entry_| will be used for page title. 2808 if (entry) { 2809 if (final_title == entry->GetTitle()) 2810 return false; // Nothing changed, don't bother. 2811 2812 entry->SetTitle(final_title); 2813 } else { 2814 if (page_title_when_no_navigation_entry_ == final_title) 2815 return false; // Nothing changed, don't bother. 2816 2817 page_title_when_no_navigation_entry_ = final_title; 2818 } 2819 2820 // Lastly, set the title for the view. 2821 view_->SetPageTitle(final_title); 2822 2823 std::pair<NavigationEntry*, bool> details = 2824 std::make_pair(entry, explicit_set); 2825 2826 NotificationService::current()->Notify( 2827 NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED, 2828 Source<WebContents>(this), 2829 Details<std::pair<NavigationEntry*, bool> >(&details)); 2830 2831 return true; 2832} 2833 2834void WebContentsImpl::NotifySwapped(RenderViewHost* old_render_view_host) { 2835 // After sending out a swap notification, we need to send a disconnect 2836 // notification so that clients that pick up a pointer to |this| can NULL the 2837 // pointer. See Bug 1230284. 2838 notify_disconnection_ = true; 2839 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2840 RenderViewHostSwapped(old_render_view_host)); 2841 2842 // TODO(avi): Remove. http://crbug.com/170921 2843 NotificationService::current()->Notify( 2844 NOTIFICATION_WEB_CONTENTS_SWAPPED, 2845 Source<WebContents>(this), 2846 Details<RenderViewHost>(old_render_view_host)); 2847 2848 // Ensure that the associated embedder gets cleared after a RenderViewHost 2849 // gets swapped, so we don't reuse the same embedder next time a 2850 // RenderViewHost is attached to this WebContents. 2851 RemoveBrowserPluginEmbedder(); 2852} 2853 2854// TODO(avi): Remove this entire function because this notification is already 2855// covered by two observer functions. http://crbug.com/170921 2856void WebContentsImpl::NotifyDisconnected() { 2857 if (!notify_disconnection_) 2858 return; 2859 2860 notify_disconnection_ = false; 2861 NotificationService::current()->Notify( 2862 NOTIFICATION_WEB_CONTENTS_DISCONNECTED, 2863 Source<WebContents>(this), 2864 NotificationService::NoDetails()); 2865} 2866 2867void WebContentsImpl::NotifyNavigationEntryCommitted( 2868 const LoadCommittedDetails& load_details) { 2869 FOR_EACH_OBSERVER( 2870 WebContentsObserver, observers_, NavigationEntryCommitted(load_details)); 2871} 2872 2873RenderViewHostDelegateView* WebContentsImpl::GetDelegateView() { 2874 return render_view_host_delegate_view_; 2875} 2876 2877RenderViewHostDelegate::RendererManagement* 2878WebContentsImpl::GetRendererManagementDelegate() { 2879 return &render_manager_; 2880} 2881 2882RendererPreferences WebContentsImpl::GetRendererPrefs( 2883 BrowserContext* browser_context) const { 2884 return renderer_preferences_; 2885} 2886 2887WebContents* WebContentsImpl::GetAsWebContents() { 2888 return this; 2889} 2890 2891gfx::Rect WebContentsImpl::GetRootWindowResizerRect() const { 2892 if (delegate_) 2893 return delegate_->GetRootWindowResizerRect(); 2894 return gfx::Rect(); 2895} 2896 2897void WebContentsImpl::RemoveBrowserPluginEmbedder() { 2898 if (browser_plugin_embedder_) 2899 browser_plugin_embedder_.reset(); 2900} 2901 2902void WebContentsImpl::RenderViewCreated(RenderViewHost* render_view_host) { 2903 // Don't send notifications if we are just creating a swapped-out RVH for 2904 // the opener chain. These won't be used for view-source or WebUI, so it's 2905 // ok to return early. 2906 if (static_cast<RenderViewHostImpl*>(render_view_host)->is_swapped_out()) 2907 return; 2908 2909 if (delegate_) 2910 view_->SetOverscrollControllerEnabled(delegate_->CanOverscrollContent()); 2911 2912 NotificationService::current()->Notify( 2913 NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED, 2914 Source<WebContents>(this), 2915 Details<RenderViewHost>(render_view_host)); 2916 2917 // When we're creating views, we're still doing initial setup, so we always 2918 // use the pending Web UI rather than any possibly existing committed one. 2919 if (render_manager_.pending_web_ui()) 2920 render_manager_.pending_web_ui()->RenderViewCreated(render_view_host); 2921 2922 NavigationEntry* entry = controller_.GetActiveEntry(); 2923 if (entry && entry->IsViewSourceMode()) { 2924 // Put the renderer in view source mode. 2925 render_view_host->Send( 2926 new ViewMsg_EnableViewSourceMode(render_view_host->GetRoutingID())); 2927 } 2928 2929 view_->RenderViewCreated(render_view_host); 2930 2931 FOR_EACH_OBSERVER( 2932 WebContentsObserver, observers_, RenderViewCreated(render_view_host)); 2933} 2934 2935void WebContentsImpl::RenderViewReady(RenderViewHost* rvh) { 2936 if (rvh != GetRenderViewHost()) { 2937 // Don't notify the world, since this came from a renderer in the 2938 // background. 2939 return; 2940 } 2941 2942 notify_disconnection_ = true; 2943 // TODO(avi): Remove. http://crbug.com/170921 2944 NotificationService::current()->Notify( 2945 NOTIFICATION_WEB_CONTENTS_CONNECTED, 2946 Source<WebContents>(this), 2947 NotificationService::NoDetails()); 2948 2949 bool was_crashed = IsCrashed(); 2950 SetIsCrashed(base::TERMINATION_STATUS_STILL_RUNNING, 0); 2951 2952 // Restore the focus to the tab (otherwise the focus will be on the top 2953 // window). 2954 if (was_crashed && !FocusLocationBarByDefault() && 2955 (!delegate_ || delegate_->ShouldFocusPageAfterCrash())) { 2956 view_->Focus(); 2957 } 2958 2959 FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewReady()); 2960} 2961 2962void WebContentsImpl::RenderViewTerminated(RenderViewHost* rvh, 2963 base::TerminationStatus status, 2964 int error_code) { 2965 if (rvh != GetRenderViewHost()) { 2966 // The pending page's RenderViewHost is gone. 2967 return; 2968 } 2969 2970 ClearPowerSaveBlockers(rvh); 2971 SetIsLoading(false, NULL); 2972 NotifyDisconnected(); 2973 SetIsCrashed(status, error_code); 2974 GetView()->OnTabCrashed(GetCrashedStatus(), crashed_error_code_); 2975 2976 FOR_EACH_OBSERVER(WebContentsObserver, 2977 observers_, 2978 RenderProcessGone(GetCrashedStatus())); 2979} 2980 2981void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) { 2982 ClearPowerSaveBlockers(rvh); 2983 render_manager_.RenderViewDeleted(rvh); 2984 FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewDeleted(rvh)); 2985} 2986 2987void WebContentsImpl::DidGetResourceResponseStart( 2988 const ResourceRequestDetails& details) { 2989 controller_.ssl_manager()->DidStartResourceResponse(details); 2990 2991 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 2992 DidGetResourceResponseStart(details)); 2993 2994 // TODO(avi): Remove. http://crbug.com/170921 2995 NotificationService::current()->Notify( 2996 NOTIFICATION_RESOURCE_RESPONSE_STARTED, 2997 Source<WebContents>(this), 2998 Details<const ResourceRequestDetails>(&details)); 2999} 3000 3001void WebContentsImpl::DidGetRedirectForResourceRequest( 3002 const ResourceRedirectDetails& details) { 3003 controller_.ssl_manager()->DidReceiveResourceRedirect(details); 3004 3005 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3006 DidGetRedirectForResourceRequest(details)); 3007 3008 // TODO(avi): Remove. http://crbug.com/170921 3009 NotificationService::current()->Notify( 3010 NOTIFICATION_RESOURCE_RECEIVED_REDIRECT, 3011 Source<WebContents>(this), 3012 Details<const ResourceRedirectDetails>(&details)); 3013} 3014 3015void WebContentsImpl::DidNavigate( 3016 RenderViewHost* rvh, 3017 const ViewHostMsg_FrameNavigate_Params& params) { 3018 // If we don't have a frame tree root yet, this is the first navigation in 3019 // using the current RenderViewHost, so we need to create it with the proper 3020 // frame id. 3021 if (!frame_tree_root_.get()) { 3022 DCHECK(PageTransitionIsMainFrame(params.transition)); 3023 frame_tree_root_.reset(new FrameTreeNode(params.frame_id, std::string())); 3024 } 3025 3026 if (PageTransitionIsMainFrame(params.transition)) { 3027 // When overscroll navigation gesture is enabled, a screenshot of the page 3028 // in its current state is taken so that it can be used during the 3029 // nav-gesture. It is necessary to take the screenshot here, before calling 3030 // RenderViewHostManager::DidNavigateMainFrame, because that can change 3031 // WebContents::GetRenderViewHost to return the new host, instead of the one 3032 // that may have just been swapped out. 3033 if (delegate_ && delegate_->CanOverscrollContent()) 3034 controller_.TakeScreenshot(); 3035 3036 render_manager_.DidNavigateMainFrame(rvh); 3037 } 3038 3039 // We expect to have a valid frame tree root node at all times when 3040 // navigating. 3041 DCHECK(frame_tree_root_.get()); 3042 3043 // Update the site of the SiteInstance if it doesn't have one yet, unless 3044 // assigning a site is not necessary for this URL. In that case, the 3045 // SiteInstance can still be considered unused until a navigation to a real 3046 // page. 3047 if (!static_cast<SiteInstanceImpl*>(GetSiteInstance())->HasSite() && 3048 ShouldAssignSiteForURL(params.url)) { 3049 static_cast<SiteInstanceImpl*>(GetSiteInstance())->SetSite(params.url); 3050 } 3051 3052 // Need to update MIME type here because it's referred to in 3053 // UpdateNavigationCommands() called by RendererDidNavigate() to 3054 // determine whether or not to enable the encoding menu. 3055 // It's updated only for the main frame. For a subframe, 3056 // RenderView::UpdateURL does not set params.contents_mime_type. 3057 // (see http://code.google.com/p/chromium/issues/detail?id=2929 ) 3058 // TODO(jungshik): Add a test for the encoding menu to avoid 3059 // regressing it again. 3060 if (PageTransitionIsMainFrame(params.transition)) 3061 contents_mime_type_ = params.contents_mime_type; 3062 3063 LoadCommittedDetails details; 3064 bool did_navigate = controller_.RendererDidNavigate(params, &details); 3065 3066 // For now, keep track of each frame's URL in its FrameTreeNode. This lets 3067 // us estimate our process count for implementing OOP iframes. 3068 // TODO(creis): Remove this when we track which pages commit in each frame. 3069 FrameTreeNode* node = FindFrameTreeNodeByID(params.frame_id); 3070 if (node) 3071 node->set_current_url(params.url); 3072 3073 // Send notification about committed provisional loads. This notification is 3074 // different from the NAV_ENTRY_COMMITTED notification which doesn't include 3075 // the actual URL navigated to and isn't sent for AUTO_SUBFRAME navigations. 3076 if (details.type != NAVIGATION_TYPE_NAV_IGNORE) { 3077 // For AUTO_SUBFRAME navigations, an event for the main frame is generated 3078 // that is not recorded in the navigation history. For the purpose of 3079 // tracking navigation events, we treat this event as a sub frame navigation 3080 // event. 3081 bool is_main_frame = did_navigate ? details.is_main_frame : false; 3082 PageTransition transition_type = params.transition; 3083 // Whether or not a page transition was triggered by going backward or 3084 // forward in the history is only stored in the navigation controller's 3085 // entry list. 3086 if (did_navigate && 3087 (controller_.GetActiveEntry()->GetTransitionType() & 3088 PAGE_TRANSITION_FORWARD_BACK)) { 3089 transition_type = PageTransitionFromInt( 3090 params.transition | PAGE_TRANSITION_FORWARD_BACK); 3091 } 3092 // Notify observers about the commit of the provisional load. 3093 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3094 DidCommitProvisionalLoadForFrame(params.frame_id, 3095 is_main_frame, params.url, transition_type, rvh)); 3096 } 3097 3098 if (!did_navigate) 3099 return; // No navigation happened. 3100 3101 // DO NOT ADD MORE STUFF TO THIS FUNCTION! Your component should either listen 3102 // for the appropriate notification (best) or you can add it to 3103 // DidNavigateMainFramePostCommit / DidNavigateAnyFramePostCommit (only if 3104 // necessary, please). 3105 3106 // Run post-commit tasks. 3107 if (details.is_main_frame) { 3108 DidNavigateMainFramePostCommit(details, params); 3109 if (delegate_) { 3110 delegate_->DidNavigateMainFramePostCommit(this); 3111 view_->SetOverscrollControllerEnabled(delegate_->CanOverscrollContent()); 3112 } 3113 } 3114 DidNavigateAnyFramePostCommit(rvh, details, params); 3115} 3116 3117void WebContentsImpl::UpdateState(RenderViewHost* rvh, 3118 int32 page_id, 3119 const PageState& page_state) { 3120 // Ensure that this state update comes from either the active RVH or one of 3121 // the swapped out RVHs. We don't expect to hear from any other RVHs. 3122 DCHECK(rvh == GetRenderViewHost() || render_manager_.IsOnSwappedOutList(rvh)); 3123 3124 // We must be prepared to handle state updates for any page, these occur 3125 // when the user is scrolling and entering form data, as well as when we're 3126 // leaving a page, in which case our state may have already been moved to 3127 // the next page. The navigation controller will look up the appropriate 3128 // NavigationEntry and update it when it is notified via the delegate. 3129 3130 int entry_index = controller_.GetEntryIndexWithPageID( 3131 rvh->GetSiteInstance(), page_id); 3132 if (entry_index < 0) 3133 return; 3134 NavigationEntry* entry = controller_.GetEntryAtIndex(entry_index); 3135 3136 if (page_state == entry->GetPageState()) 3137 return; // Nothing to update. 3138 entry->SetPageState(page_state); 3139 controller_.NotifyEntryChanged(entry, entry_index); 3140} 3141 3142void WebContentsImpl::UpdateTitle(RenderViewHost* rvh, 3143 int32 page_id, 3144 const string16& title, 3145 base::i18n::TextDirection title_direction) { 3146 // If we have a title, that's a pretty good indication that we've started 3147 // getting useful data. 3148 SetNotWaitingForResponse(); 3149 3150 // Try to find the navigation entry, which might not be the current one. 3151 // For example, it might be from a pending RVH for the pending entry. 3152 NavigationEntryImpl* entry = controller_.GetEntryWithPageID( 3153 rvh->GetSiteInstance(), page_id); 3154 3155 // We can handle title updates when we don't have an entry in 3156 // UpdateTitleForEntry, but only if the update is from the current RVH. 3157 if (!entry && rvh != GetRenderViewHost()) 3158 return; 3159 3160 // TODO(evan): make use of title_direction. 3161 // http://code.google.com/p/chromium/issues/detail?id=27094 3162 if (!UpdateTitleForEntry(entry, title)) 3163 return; 3164 3165 // Broadcast notifications when the UI should be updated. 3166 if (entry == controller_.GetEntryAtOffset(0)) 3167 NotifyNavigationStateChanged(INVALIDATE_TYPE_TITLE); 3168} 3169 3170void WebContentsImpl::UpdateEncoding(RenderViewHost* render_view_host, 3171 const std::string& encoding) { 3172 SetEncoding(encoding); 3173} 3174 3175void WebContentsImpl::UpdateTargetURL(int32 page_id, const GURL& url) { 3176 if (delegate_) 3177 delegate_->UpdateTargetURL(this, page_id, url); 3178} 3179 3180void WebContentsImpl::Close(RenderViewHost* rvh) { 3181#if defined(OS_MACOSX) 3182 // The UI may be in an event-tracking loop, such as between the 3183 // mouse-down and mouse-up in text selection or a button click. 3184 // Defer the close until after tracking is complete, so that we 3185 // don't free objects out from under the UI. 3186 // TODO(shess): This could get more fine-grained. For instance, 3187 // closing a tab in another window while selecting text in the 3188 // current window's Omnibox should be just fine. 3189 if (view_->IsEventTracking()) { 3190 view_->CloseTabAfterEventTracking(); 3191 return; 3192 } 3193#endif 3194 3195 // Ignore this if it comes from a RenderViewHost that we aren't showing. 3196 if (delegate_ && rvh == GetRenderViewHost()) 3197 delegate_->CloseContents(this); 3198} 3199 3200void WebContentsImpl::SwappedOut(RenderViewHost* rvh) { 3201 if (delegate_ && rvh == GetRenderViewHost()) 3202 delegate_->SwappedOut(this); 3203 3204 // Allow the navigation to proceed. 3205 render_manager_.SwappedOut(rvh); 3206} 3207 3208void WebContentsImpl::RequestMove(const gfx::Rect& new_bounds) { 3209 if (delegate_ && delegate_->IsPopupOrPanel(this)) 3210 delegate_->MoveContents(this, new_bounds); 3211} 3212 3213void WebContentsImpl::DidStartLoading(RenderViewHost* render_view_host) { 3214 SetIsLoading(true, NULL); 3215 3216 // Notify observers about navigation. 3217 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3218 DidStartLoading(render_view_host)); 3219} 3220 3221void WebContentsImpl::DidStopLoading(RenderViewHost* render_view_host) { 3222 scoped_ptr<LoadNotificationDetails> details; 3223 3224 // Use the last committed entry rather than the active one, in case a 3225 // pending entry has been created. 3226 NavigationEntry* entry = controller_.GetLastCommittedEntry(); 3227 3228 // An entry may not exist for a stop when loading an initial blank page or 3229 // if an iframe injected by script into a blank page finishes loading. 3230 if (entry) { 3231 base::TimeDelta elapsed = base::TimeTicks::Now() - current_load_start_; 3232 3233 details.reset(new LoadNotificationDetails( 3234 entry->GetVirtualURL(), 3235 entry->GetTransitionType(), 3236 elapsed, 3237 &controller_, 3238 controller_.GetCurrentEntryIndex())); 3239 } 3240 3241 SetIsLoading(false, details.get()); 3242 3243 // Notify observers about navigation. 3244 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3245 DidStopLoading(render_view_host)); 3246} 3247 3248void WebContentsImpl::DidCancelLoading() { 3249 controller_.DiscardNonCommittedEntries(); 3250 3251 // Update the URL display. 3252 NotifyNavigationStateChanged(INVALIDATE_TYPE_URL); 3253} 3254 3255void WebContentsImpl::DidChangeLoadProgress(double progress) { 3256 if (delegate_) 3257 delegate_->LoadProgressChanged(this, progress); 3258} 3259 3260void WebContentsImpl::DidDisownOpener(RenderViewHost* rvh) { 3261 if (opener_) { 3262 // Clear our opener so that future cross-process navigations don't have an 3263 // opener assigned. 3264 RemoveDestructionObserver(opener_); 3265 opener_ = NULL; 3266 } 3267 3268 // Notify all swapped out RenderViewHosts for this tab. This is important 3269 // in case we go back to them, or if another window in those processes tries 3270 // to access window.opener. 3271 render_manager_.DidDisownOpener(rvh); 3272} 3273 3274void WebContentsImpl::DidAccessInitialDocument() { 3275 // Update the URL display. 3276 NotifyNavigationStateChanged(content::INVALIDATE_TYPE_URL); 3277} 3278 3279void WebContentsImpl::DocumentAvailableInMainFrame( 3280 RenderViewHost* render_view_host) { 3281 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3282 DocumentAvailableInMainFrame()); 3283} 3284 3285void WebContentsImpl::DocumentOnLoadCompletedInMainFrame( 3286 RenderViewHost* render_view_host, 3287 int32 page_id) { 3288 NotificationService::current()->Notify( 3289 NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, 3290 Source<WebContents>(this), 3291 Details<int>(&page_id)); 3292} 3293 3294void WebContentsImpl::RequestOpenURL(RenderViewHost* rvh, 3295 const GURL& url, 3296 const Referrer& referrer, 3297 WindowOpenDisposition disposition, 3298 int64 source_frame_id, 3299 bool should_replace_current_entry, 3300 bool user_gesture) { 3301 // If this came from a swapped out RenderViewHost, we only allow the request 3302 // if we are still in the same BrowsingInstance. 3303 if (static_cast<RenderViewHostImpl*>(rvh)->is_swapped_out() && 3304 !rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance())) { 3305 return; 3306 } 3307 3308 // Delegate to RequestTransferURL because this is just the generic 3309 // case where |old_request_id| is empty. 3310 RequestTransferURL(url, referrer, disposition, source_frame_id, 3311 GlobalRequestID(), 3312 should_replace_current_entry, user_gesture); 3313} 3314 3315void WebContentsImpl::RequestTransferURL( 3316 const GURL& url, 3317 const Referrer& referrer, 3318 WindowOpenDisposition disposition, 3319 int64 source_frame_id, 3320 const GlobalRequestID& old_request_id, 3321 bool should_replace_current_entry, 3322 bool user_gesture) { 3323 WebContents* new_contents = NULL; 3324 PageTransition transition_type = PAGE_TRANSITION_LINK; 3325 GURL dest_url(url); 3326 if (!GetContentClient()->browser()->ShouldAllowOpenURL( 3327 GetSiteInstance(), url)) 3328 dest_url = GURL(kAboutBlankURL); 3329 3330 if (render_manager_.web_ui()) { 3331 // When we're a Web UI, it will provide a page transition type for us (this 3332 // is so the new tab page can specify AUTO_BOOKMARK for automatically 3333 // generated suggestions). 3334 // 3335 // Note also that we hide the referrer for Web UI pages. We don't really 3336 // want web sites to see a referrer of "chrome://blah" (and some 3337 // chrome: URLs might have search terms or other stuff we don't want to 3338 // send to the site), so we send no referrer. 3339 OpenURLParams params(dest_url, Referrer(), source_frame_id, disposition, 3340 render_manager_.web_ui()->GetLinkTransitionType(), 3341 false /* is_renderer_initiated */); 3342 params.transferred_global_request_id = old_request_id; 3343 new_contents = OpenURL(params); 3344 transition_type = render_manager_.web_ui()->GetLinkTransitionType(); 3345 } else { 3346 OpenURLParams params(dest_url, referrer, source_frame_id, disposition, 3347 PAGE_TRANSITION_LINK, true /* is_renderer_initiated */); 3348 params.transferred_global_request_id = old_request_id; 3349 params.should_replace_current_entry = should_replace_current_entry; 3350 params.user_gesture = user_gesture; 3351 new_contents = OpenURL(params); 3352 } 3353 if (new_contents) { 3354 // Notify observers. 3355 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3356 DidOpenRequestedURL(new_contents, 3357 dest_url, 3358 referrer, 3359 disposition, 3360 transition_type, 3361 source_frame_id)); 3362 } 3363} 3364 3365void WebContentsImpl::RouteCloseEvent(RenderViewHost* rvh) { 3366 // Tell the active RenderViewHost to run unload handlers and close, as long 3367 // as the request came from a RenderViewHost in the same BrowsingInstance. 3368 // In most cases, we receive this from a swapped out RenderViewHost. 3369 // It is possible to receive it from one that has just been swapped in, 3370 // in which case we might as well deliver the message anyway. 3371 if (rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance())) 3372 GetRenderViewHost()->ClosePage(); 3373} 3374 3375void WebContentsImpl::RouteMessageEvent( 3376 RenderViewHost* rvh, 3377 const ViewMsg_PostMessage_Params& params) { 3378 // Only deliver the message to the active RenderViewHost if the request 3379 // came from a RenderViewHost in the same BrowsingInstance or if this 3380 // WebContents is dedicated to a browser plugin guest. 3381 // Note: This check means that an embedder could theoretically receive a 3382 // postMessage from anyone (not just its own guests). However, this is 3383 // probably not a risk for apps since other pages won't have references 3384 // to App windows. 3385 if (!rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance()) && 3386 !GetBrowserPluginGuest() && !GetBrowserPluginEmbedder()) 3387 return; 3388 3389 ViewMsg_PostMessage_Params new_params(params); 3390 3391 // If there is a source_routing_id, translate it to the routing ID for 3392 // the equivalent swapped out RVH in the target process. If we need 3393 // to create a swapped out RVH for the source tab, we create its opener 3394 // chain as well, since those will also be accessible to the target page. 3395 if (new_params.source_routing_id != MSG_ROUTING_NONE) { 3396 // Try to look up the WebContents for the source page. 3397 WebContentsImpl* source_contents = NULL; 3398 RenderViewHostImpl* source_rvh = RenderViewHostImpl::FromID( 3399 rvh->GetProcess()->GetID(), params.source_routing_id); 3400 if (source_rvh) { 3401 source_contents = static_cast<WebContentsImpl*>( 3402 source_rvh->GetDelegate()->GetAsWebContents()); 3403 } 3404 3405 if (source_contents) { 3406 if (GetBrowserPluginGuest()) { 3407 // We create a swapped out RenderView for the embedder in the guest's 3408 // render process but we intentionally do not expose the embedder's 3409 // opener chain to it. 3410 new_params.source_routing_id = 3411 source_contents->CreateSwappedOutRenderView(GetSiteInstance()); 3412 } else { 3413 new_params.source_routing_id = 3414 source_contents->CreateOpenerRenderViews(GetSiteInstance()); 3415 } 3416 } else { 3417 // We couldn't find it, so don't pass a source frame. 3418 new_params.source_routing_id = MSG_ROUTING_NONE; 3419 } 3420 } 3421 3422 // In most cases, we receive this from a swapped out RenderViewHost. 3423 // It is possible to receive it from one that has just been swapped in, 3424 // in which case we might as well deliver the message anyway. 3425 Send(new ViewMsg_PostMessageEvent(GetRoutingID(), new_params)); 3426} 3427 3428void WebContentsImpl::RunJavaScriptMessage( 3429 RenderViewHost* rvh, 3430 const string16& message, 3431 const string16& default_prompt, 3432 const GURL& frame_url, 3433 JavaScriptMessageType javascript_message_type, 3434 bool user_gesture, 3435 IPC::Message* reply_msg, 3436 bool* did_suppress_message) { 3437 // Suppress JavaScript dialogs when requested. Also suppress messages when 3438 // showing an interstitial as it's shown over the previous page and we don't 3439 // want the hidden page's dialogs to interfere with the interstitial. 3440 bool suppress_this_message = 3441 static_cast<RenderViewHostImpl*>(rvh)->is_swapped_out() || 3442 ShowingInterstitialPage() || 3443 !delegate_ || 3444 delegate_->ShouldSuppressDialogs() || 3445 !delegate_->GetJavaScriptDialogManager(); 3446 3447 if (!suppress_this_message) { 3448 std::string accept_lang = GetContentClient()->browser()-> 3449 GetAcceptLangs(GetBrowserContext()); 3450 dialog_manager_ = delegate_->GetJavaScriptDialogManager(); 3451 dialog_manager_->RunJavaScriptDialog( 3452 this, 3453 frame_url.GetOrigin(), 3454 accept_lang, 3455 javascript_message_type, 3456 message, 3457 default_prompt, 3458 user_gesture, 3459 base::Bind(&WebContentsImpl::OnDialogClosed, 3460 base::Unretained(this), 3461 rvh, 3462 reply_msg), 3463 &suppress_this_message); 3464 } 3465 3466 *did_suppress_message = suppress_this_message; 3467 3468 if (suppress_this_message) { 3469 // If we are suppressing messages, just reply as if the user immediately 3470 // pressed "Cancel". 3471 OnDialogClosed(rvh, reply_msg, false, string16()); 3472 } 3473 3474 // OnDialogClosed (two lines up) may have caused deletion of this object (see 3475 // http://crbug.com/288961 ). The only safe thing to do here is return. 3476} 3477 3478void WebContentsImpl::RunBeforeUnloadConfirm(RenderViewHost* rvh, 3479 const string16& message, 3480 bool is_reload, 3481 IPC::Message* reply_msg) { 3482 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(rvh); 3483 if (delegate_) 3484 delegate_->WillRunBeforeUnloadConfirm(); 3485 3486 bool suppress_this_message = 3487 rvhi->is_swapped_out() || 3488 !delegate_ || 3489 delegate_->ShouldSuppressDialogs() || 3490 !delegate_->GetJavaScriptDialogManager(); 3491 if (suppress_this_message) { 3492 // The reply must be sent to the RVH that sent the request. 3493 rvhi->JavaScriptDialogClosed(reply_msg, true, string16()); 3494 return; 3495 } 3496 3497 is_showing_before_unload_dialog_ = true; 3498 dialog_manager_ = delegate_->GetJavaScriptDialogManager(); 3499 dialog_manager_->RunBeforeUnloadDialog( 3500 this, message, is_reload, 3501 base::Bind(&WebContentsImpl::OnDialogClosed, base::Unretained(this), rvh, 3502 reply_msg)); 3503} 3504 3505bool WebContentsImpl::AddMessageToConsole(int32 level, 3506 const string16& message, 3507 int32 line_no, 3508 const string16& source_id) { 3509 if (!delegate_) 3510 return false; 3511 return delegate_->AddMessageToConsole(this, level, message, line_no, 3512 source_id); 3513} 3514 3515WebPreferences WebContentsImpl::GetWebkitPrefs() { 3516 // We want to base the page config off of the real URL, rather than the 3517 // display URL. 3518 GURL url = controller_.GetActiveEntry() 3519 ? controller_.GetActiveEntry()->GetURL() : GURL::EmptyGURL(); 3520 return GetWebkitPrefs(GetRenderViewHost(), url); 3521} 3522 3523int WebContentsImpl::CreateSwappedOutRenderView( 3524 SiteInstance* instance) { 3525 return render_manager_.CreateRenderView(instance, MSG_ROUTING_NONE, 3526 true, true); 3527} 3528 3529void WebContentsImpl::OnUserGesture() { 3530 // Notify observers. 3531 FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetUserGesture()); 3532 3533 ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get(); 3534 if (rdh) // NULL in unittests. 3535 rdh->OnUserGesture(this); 3536} 3537 3538void WebContentsImpl::OnIgnoredUIEvent() { 3539 // Notify observers. 3540 FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetIgnoredUIEvent()); 3541} 3542 3543void WebContentsImpl::RendererUnresponsive(RenderViewHost* rvh, 3544 bool is_during_beforeunload, 3545 bool is_during_unload) { 3546 // Don't show hung renderer dialog for a swapped out RVH. 3547 if (rvh != GetRenderViewHost()) 3548 return; 3549 3550 RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(rvh); 3551 3552 // Ignore renderer unresponsive event if debugger is attached to the tab 3553 // since the event may be a result of the renderer sitting on a breakpoint. 3554 // See http://crbug.com/65458 3555 if (DevToolsAgentHost::IsDebuggerAttached(this)) 3556 return; 3557 3558 if (is_during_beforeunload || is_during_unload) { 3559 // Hang occurred while firing the beforeunload/unload handler. 3560 // Pretend the handler fired so tab closing continues as if it had. 3561 rvhi->set_sudden_termination_allowed(true); 3562 3563 if (!render_manager_.ShouldCloseTabOnUnresponsiveRenderer()) 3564 return; 3565 3566 // If the tab hangs in the beforeunload/unload handler there's really 3567 // nothing we can do to recover. If the hang is in the beforeunload handler, 3568 // pretend the beforeunload listeners have all fired and allow the delegate 3569 // to continue closing; the user will not have the option of cancelling the 3570 // close. Otherwise, pretend the unload listeners have all fired and close 3571 // the tab. 3572 bool close = true; 3573 if (is_during_beforeunload) { 3574 delegate_->BeforeUnloadFired(this, true, &close); 3575 } 3576 if (close) 3577 Close(rvh); 3578 return; 3579 } 3580 3581 if (!GetRenderViewHostImpl() || !GetRenderViewHostImpl()->IsRenderViewLive()) 3582 return; 3583 3584 if (delegate_) 3585 delegate_->RendererUnresponsive(this); 3586} 3587 3588void WebContentsImpl::RendererResponsive(RenderViewHost* render_view_host) { 3589 if (delegate_) 3590 delegate_->RendererResponsive(this); 3591} 3592 3593void WebContentsImpl::LoadStateChanged( 3594 const GURL& url, 3595 const net::LoadStateWithParam& load_state, 3596 uint64 upload_position, 3597 uint64 upload_size) { 3598 load_state_ = load_state; 3599 upload_position_ = upload_position; 3600 upload_size_ = upload_size; 3601 load_state_host_ = net::IDNToUnicode(url.host(), 3602 GetContentClient()->browser()->GetAcceptLangs( 3603 GetBrowserContext())); 3604 if (load_state_.state == net::LOAD_STATE_READING_RESPONSE) 3605 SetNotWaitingForResponse(); 3606 if (IsLoading()) { 3607 NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD | INVALIDATE_TYPE_TAB); 3608 } 3609} 3610 3611void WebContentsImpl::WorkerCrashed() { 3612 if (delegate_) 3613 delegate_->WorkerCrashed(this); 3614} 3615 3616void WebContentsImpl::BeforeUnloadFiredFromRenderManager( 3617 bool proceed, const base::TimeTicks& proceed_time, 3618 bool* proceed_to_fire_unload) { 3619 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3620 BeforeUnloadFired(proceed_time)); 3621 if (delegate_) 3622 delegate_->BeforeUnloadFired(this, proceed, proceed_to_fire_unload); 3623 // Note: |this| might be deleted at this point. 3624} 3625 3626void WebContentsImpl::RenderProcessGoneFromRenderManager( 3627 RenderViewHost* render_view_host) { 3628 DCHECK(crashed_status_ != base::TERMINATION_STATUS_STILL_RUNNING); 3629 RenderViewTerminated(render_view_host, crashed_status_, crashed_error_code_); 3630} 3631 3632void WebContentsImpl::UpdateRenderViewSizeForRenderManager() { 3633 // TODO(brettw) this is a hack. See WebContentsView::SizeContents. 3634 gfx::Size size = GetSizeForNewRenderView(); 3635 // 0x0 isn't a valid window size (minimal window size is 1x1) but it may be 3636 // here during container initialization and normal window size will be set 3637 // later. In case of tab duplication this resizing to 0x0 prevents setting 3638 // normal size later so just ignore it. 3639 if (!size.IsEmpty()) 3640 view_->SizeContents(size); 3641} 3642 3643void WebContentsImpl::NotifySwappedFromRenderManager(RenderViewHost* rvh) { 3644 NotifySwapped(rvh); 3645 3646 // Make sure the visible RVH reflects the new delegate's preferences. 3647 if (delegate_) 3648 view_->SetOverscrollControllerEnabled(delegate_->CanOverscrollContent()); 3649 3650 view_->RenderViewSwappedIn(render_manager_.current_host()); 3651 3652 FrameTreeNode* root = NULL; 3653 RenderViewHostImpl* new_rvh = static_cast<RenderViewHostImpl*>( 3654 render_manager_.current_host()); 3655 3656 // We are doing a cross-site navigation and swapping processes. Since frame 3657 // ids are unique to a process, we need to recreate the frame tree with the 3658 // proper main frame id. 3659 // Note that it is possible for this method to be called before the new RVH 3660 // has committed a navigation (if RenderViewHostManager short-circuits the 3661 // CommitPending call because the current RVH is dead). In that case, we 3662 // haven't heard a valid frame id to use to initialize the root node, so clear 3663 // out the root node and the first subsequent navigation message will set it 3664 // correctly. 3665 if (new_rvh->main_frame_id() != -1) 3666 root = new FrameTreeNode(new_rvh->main_frame_id(), std::string()); 3667 3668 frame_tree_root_.reset(root); 3669} 3670 3671int WebContentsImpl::CreateOpenerRenderViewsForRenderManager( 3672 SiteInstance* instance) { 3673 if (!opener_) 3674 return MSG_ROUTING_NONE; 3675 3676 // Recursively create RenderViews for anything else in the opener chain. 3677 return opener_->CreateOpenerRenderViews(instance); 3678} 3679 3680int WebContentsImpl::CreateOpenerRenderViews(SiteInstance* instance) { 3681 int opener_route_id = MSG_ROUTING_NONE; 3682 3683 // If this tab has an opener, ensure it has a RenderView in the given 3684 // SiteInstance as well. 3685 if (opener_) 3686 opener_route_id = opener_->CreateOpenerRenderViews(instance); 3687 3688 // If any of the renderers (current, pending, or swapped out) for this 3689 // WebContents has the same SiteInstance, use it. 3690 if (render_manager_.current_host()->GetSiteInstance() == instance) 3691 return render_manager_.current_host()->GetRoutingID(); 3692 3693 if (render_manager_.pending_render_view_host() && 3694 render_manager_.pending_render_view_host()->GetSiteInstance() == instance) 3695 return render_manager_.pending_render_view_host()->GetRoutingID(); 3696 3697 RenderViewHostImpl* rvh = render_manager_.GetSwappedOutRenderViewHost( 3698 instance); 3699 if (rvh) 3700 return rvh->GetRoutingID(); 3701 3702 // Create a swapped out RenderView in the given SiteInstance if none exists, 3703 // setting its opener to the given route_id. Return the new view's route_id. 3704 return render_manager_.CreateRenderView(instance, opener_route_id, 3705 true, true); 3706} 3707 3708NavigationControllerImpl& WebContentsImpl::GetControllerForRenderManager() { 3709 return GetController(); 3710} 3711 3712WebUIImpl* WebContentsImpl::CreateWebUIForRenderManager(const GURL& url) { 3713 return static_cast<WebUIImpl*>(CreateWebUI(url)); 3714} 3715 3716NavigationEntry* 3717 WebContentsImpl::GetLastCommittedNavigationEntryForRenderManager() { 3718 return controller_.GetLastCommittedEntry(); 3719} 3720 3721bool WebContentsImpl::CreateRenderViewForRenderManager( 3722 RenderViewHost* render_view_host, int opener_route_id) { 3723 TRACE_EVENT0("browser", "WebContentsImpl::CreateRenderViewForRenderManager"); 3724 // Can be NULL during tests. 3725 RenderWidgetHostView* rwh_view = view_->CreateViewForWidget(render_view_host); 3726 3727 // Now that the RenderView has been created, we need to tell it its size. 3728 if (rwh_view) 3729 rwh_view->SetSize(GetSizeForNewRenderView()); 3730 3731 // Make sure we use the correct starting page_id in the new RenderView. 3732 UpdateMaxPageIDIfNecessary(render_view_host); 3733 int32 max_page_id = 3734 GetMaxPageIDForSiteInstance(render_view_host->GetSiteInstance()); 3735 3736 if (!static_cast<RenderViewHostImpl*>( 3737 render_view_host)->CreateRenderView(string16(), 3738 opener_route_id, 3739 max_page_id)) { 3740 return false; 3741 } 3742 3743#if defined(OS_LINUX) || defined(OS_OPENBSD) 3744 // Force a ViewMsg_Resize to be sent, needed to make plugins show up on 3745 // linux. See crbug.com/83941. 3746 if (rwh_view) { 3747 if (RenderWidgetHost* render_widget_host = rwh_view->GetRenderWidgetHost()) 3748 render_widget_host->WasResized(); 3749 } 3750#endif 3751 3752 return true; 3753} 3754 3755#if defined(OS_ANDROID) 3756bool WebContentsImpl::CreateRenderViewForInitialEmptyDocument() { 3757 return CreateRenderViewForRenderManager(GetRenderViewHost(), 3758 MSG_ROUTING_NONE); 3759} 3760#endif 3761 3762void WebContentsImpl::OnDialogClosed(RenderViewHost* rvh, 3763 IPC::Message* reply_msg, 3764 bool success, 3765 const string16& user_input) { 3766 if (is_showing_before_unload_dialog_ && !success) { 3767 // If a beforeunload dialog is canceled, we need to stop the throbber from 3768 // spinning, since we forced it to start spinning in Navigate. 3769 DidStopLoading(rvh); 3770 controller_.DiscardNonCommittedEntries(); 3771 3772 FOR_EACH_OBSERVER(WebContentsObserver, observers_, 3773 BeforeUnloadDialogCancelled()); 3774 } 3775 is_showing_before_unload_dialog_ = false; 3776 static_cast<RenderViewHostImpl*>( 3777 rvh)->JavaScriptDialogClosed(reply_msg, success, user_input); 3778} 3779 3780void WebContentsImpl::SetEncoding(const std::string& encoding) { 3781 encoding_ = GetContentClient()->browser()-> 3782 GetCanonicalEncodingNameByAliasName(encoding); 3783} 3784 3785void WebContentsImpl::CreateViewAndSetSizeForRVH(RenderViewHost* rvh) { 3786 RenderWidgetHostView* rwh_view = view_->CreateViewForWidget(rvh); 3787 // Can be NULL during tests. 3788 if (rwh_view) 3789 rwh_view->SetSize(GetView()->GetContainerSize()); 3790} 3791 3792bool WebContentsImpl::IsHidden() { 3793 return capturer_count_ == 0 && !should_normally_be_visible_; 3794} 3795 3796RenderViewHostImpl* WebContentsImpl::GetRenderViewHostImpl() { 3797 return static_cast<RenderViewHostImpl*>(GetRenderViewHost()); 3798} 3799 3800BrowserPluginGuest* WebContentsImpl::GetBrowserPluginGuest() const { 3801 return browser_plugin_guest_.get(); 3802} 3803 3804void WebContentsImpl::SetBrowserPluginGuest(BrowserPluginGuest* guest) { 3805 CHECK(!browser_plugin_guest_); 3806 browser_plugin_guest_.reset(guest); 3807} 3808 3809BrowserPluginEmbedder* WebContentsImpl::GetBrowserPluginEmbedder() const { 3810 return browser_plugin_embedder_.get(); 3811} 3812 3813BrowserPluginGuestManager* 3814 WebContentsImpl::GetBrowserPluginGuestManager() const { 3815 return static_cast<BrowserPluginGuestManager*>( 3816 GetBrowserContext()->GetUserData( 3817 browser_plugin::kBrowserPluginGuestManagerKeyName)); 3818} 3819 3820void WebContentsImpl::ClearPowerSaveBlockers( 3821 RenderViewHost* render_view_host) { 3822 STLDeleteValues(&power_save_blockers_[render_view_host]); 3823 power_save_blockers_.erase(render_view_host); 3824} 3825 3826void WebContentsImpl::ClearAllPowerSaveBlockers() { 3827 for (PowerSaveBlockerMap::iterator i(power_save_blockers_.begin()); 3828 i != power_save_blockers_.end(); ++i) 3829 STLDeleteValues(&power_save_blockers_[i->first]); 3830 power_save_blockers_.clear(); 3831} 3832 3833gfx::Size WebContentsImpl::GetSizeForNewRenderView() const { 3834 gfx::Size size; 3835 if (delegate_) 3836 size = delegate_->GetSizeForNewRenderView(this); 3837 if (size.IsEmpty()) 3838 size = view_->GetContainerSize(); 3839 return size; 3840} 3841 3842} // namespace content 3843