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