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