web_contents_impl.cc revision 34680572440d7894ef8dafce81d8039ed80726a2
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/browser/web_contents/web_contents_impl.h"
6
7#include <utility>
8
9#include "base/command_line.h"
10#include "base/debug/trace_event.h"
11#include "base/lazy_instance.h"
12#include "base/logging.h"
13#include "base/metrics/histogram.h"
14#include "base/metrics/stats_counters.h"
15#include "base/process/process.h"
16#include "base/strings/string16.h"
17#include "base/strings/string_number_conversions.h"
18#include "base/strings/string_util.h"
19#include "base/strings/utf_string_conversions.h"
20#include "base/time/time.h"
21#include "content/browser/accessibility/accessibility_mode_helper.h"
22#include "content/browser/accessibility/browser_accessibility_state_impl.h"
23#include "content/browser/browser_plugin/browser_plugin_embedder.h"
24#include "content/browser/browser_plugin/browser_plugin_guest.h"
25#include "content/browser/child_process_security_policy_impl.h"
26#include "content/browser/devtools/render_view_devtools_agent_host.h"
27#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
28#include "content/browser/dom_storage/session_storage_namespace_impl.h"
29#include "content/browser/download/download_stats.h"
30#include "content/browser/download/mhtml_generation_manager.h"
31#include "content/browser/download/save_package.h"
32#include "content/browser/frame_host/cross_process_frame_connector.h"
33#include "content/browser/frame_host/interstitial_page_impl.h"
34#include "content/browser/frame_host/navigation_entry_impl.h"
35#include "content/browser/frame_host/navigator_impl.h"
36#include "content/browser/frame_host/render_frame_host_impl.h"
37#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
38#include "content/browser/geolocation/geolocation_dispatcher_host.h"
39#include "content/browser/host_zoom_map_impl.h"
40#include "content/browser/loader/resource_dispatcher_host_impl.h"
41#include "content/browser/manifest/manifest_manager_host.h"
42#include "content/browser/media/audio_stream_monitor.h"
43#include "content/browser/media/capture/web_contents_audio_muter.h"
44#include "content/browser/media/midi_dispatcher_host.h"
45#include "content/browser/message_port_message_filter.h"
46#include "content/browser/message_port_service.h"
47#include "content/browser/power_save_blocker_impl.h"
48#include "content/browser/renderer_host/render_process_host_impl.h"
49#include "content/browser/renderer_host/render_view_host_delegate_view.h"
50#include "content/browser/renderer_host/render_view_host_impl.h"
51#include "content/browser/renderer_host/render_widget_host_impl.h"
52#include "content/browser/renderer_host/render_widget_host_view_base.h"
53#include "content/browser/screen_orientation/screen_orientation_dispatcher_host_impl.h"
54#include "content/browser/site_instance_impl.h"
55#include "content/browser/web_contents/web_contents_view_guest.h"
56#include "content/browser/webui/generic_handler.h"
57#include "content/browser/webui/web_ui_controller_factory_registry.h"
58#include "content/browser/webui/web_ui_impl.h"
59#include "content/common/browser_plugin/browser_plugin_constants.h"
60#include "content/common/browser_plugin/browser_plugin_messages.h"
61#include "content/common/frame_messages.h"
62#include "content/common/image_messages.h"
63#include "content/common/input_messages.h"
64#include "content/common/ssl_status_serialization.h"
65#include "content/common/view_messages.h"
66#include "content/public/browser/ax_event_notification_details.h"
67#include "content/public/browser/browser_context.h"
68#include "content/public/browser/browser_plugin_guest_manager.h"
69#include "content/public/browser/content_browser_client.h"
70#include "content/public/browser/devtools_agent_host.h"
71#include "content/public/browser/download_manager.h"
72#include "content/public/browser/download_url_parameters.h"
73#include "content/public/browser/invalidate_type.h"
74#include "content/public/browser/javascript_dialog_manager.h"
75#include "content/public/browser/load_from_memory_cache_details.h"
76#include "content/public/browser/load_notification_details.h"
77#include "content/public/browser/navigation_details.h"
78#include "content/public/browser/notification_details.h"
79#include "content/public/browser/notification_service.h"
80#include "content/public/browser/render_widget_host_iterator.h"
81#include "content/public/browser/resource_request_details.h"
82#include "content/public/browser/screen_orientation_dispatcher_host.h"
83#include "content/public/browser/storage_partition.h"
84#include "content/public/browser/user_metrics.h"
85#include "content/public/browser/web_contents_delegate.h"
86#include "content/public/browser/web_contents_observer.h"
87#include "content/public/common/bindings_policy.h"
88#include "content/public/common/content_constants.h"
89#include "content/public/common/content_switches.h"
90#include "content/public/common/page_zoom.h"
91#include "content/public/common/result_codes.h"
92#include "content/public/common/url_constants.h"
93#include "content/public/common/url_utils.h"
94#include "content/public/common/web_preferences.h"
95#include "net/base/mime_util.h"
96#include "net/base/net_util.h"
97#include "net/http/http_cache.h"
98#include "net/http/http_transaction_factory.h"
99#include "net/url_request/url_request_context.h"
100#include "net/url_request/url_request_context_getter.h"
101#include "ui/base/layout.h"
102#include "ui/gfx/display.h"
103#include "ui/gfx/screen.h"
104#include "ui/gl/gl_switches.h"
105
106#if defined(OS_ANDROID)
107#include "content/browser/android/content_view_core_impl.h"
108#include "content/browser/android/date_time_chooser_android.h"
109#include "content/browser/media/android/browser_media_player_manager.h"
110#include "content/browser/web_contents/web_contents_android.h"
111#include "content/public/browser/android/content_view_core.h"
112#endif
113
114#if defined(OS_MACOSX)
115#include "base/mac/foundation_util.h"
116#endif
117
118// Cross-Site Navigations
119//
120// If a WebContentsImpl is told to navigate to a different web site (as
121// determined by SiteInstance), it will replace its current RenderViewHost with
122// a new RenderViewHost dedicated to the new SiteInstance.  This works as
123// follows:
124//
125// - RVHM::Navigate determines whether the destination is cross-site, and if so,
126//   it creates a pending_render_view_host_.
127// - The pending RVH is "suspended," so that no navigation messages are sent to
128//   its renderer until the beforeunload JavaScript handler has a chance to
129//   run in the current RVH.
130// - The pending RVH tells CrossSiteRequestManager (a thread-safe singleton)
131//   that it has a pending cross-site request.  We will check this on the IO
132//   thread when deciding how to handle the response.
133// - The current RVH runs its beforeunload handler.  If it returns false, we
134//   cancel all the pending logic.  Otherwise we allow the pending RVH to send
135//   the navigation request to its renderer.
136// - ResourceDispatcherHost receives a ResourceRequest on the IO thread for the
137//   main resource load on the pending RVH.  It creates a
138//   CrossSiteResourceHandler to check whether a process swap is needed when
139//   the request is ready to commit.
140// - When RDH receives a response, the BufferedResourceHandler determines
141//   whether it is a download.  If so, it sends a message to the new renderer
142//   causing it to cancel the request, and the download proceeds. For now, the
143//   pending RVH remains until the next DidNavigate event for this
144//   WebContentsImpl. This isn't ideal, but it doesn't affect any functionality.
145// - After RDH receives a response and determines that it is safe and not a
146//   download, the CrossSiteResourceHandler checks whether a process swap is
147//   needed (either because CrossSiteRequestManager has state for it or because
148//   a transfer was needed for a redirect).
149// - If so, CrossSiteResourceHandler pauses the response to first run the old
150//   page's unload handler.  It does this by asynchronously calling the
151//   OnCrossSiteResponse method of RenderFrameHostManager on the UI thread,
152//   which sends a SwapOut message to the current RVH.
153// - Once the unload handler is finished, RVHM::SwappedOut checks if a transfer
154//   to a new process is needed, based on the stored pending_nav_params_.  (This
155//   is independent of whether we started out with a cross-process navigation.)
156//   - If not, it just tells the ResourceDispatcherHost to resume the response
157//     to its current RenderViewHost.
158//   - If so, it cancels the current pending RenderViewHost and sets up a new
159//     navigation using RequestTransferURL.  When the transferred request
160//     arrives in the ResourceDispatcherHost, we transfer the response and
161//     resume it.
162// - The pending renderer sends a FrameNavigate message that invokes the
163//   DidNavigate method.  This replaces the current RVH with the
164//   pending RVH.
165// - The previous renderer is kept swapped out in RenderFrameHostManager in case
166//   the user goes back.  The process only stays live if another tab is using
167//   it, but if so, the existing frame relationships will be maintained.
168
169namespace content {
170namespace {
171
172const int kMinimumDelayBetweenLoadingUpdatesMS = 100;
173
174// This matches what Blink's ProgressTracker has traditionally used for a
175// minimum progress value.
176const double kMinimumLoadingProgress = 0.1;
177
178const char kDotGoogleDotCom[] = ".google.com";
179
180#if defined(OS_ANDROID)
181const char kWebContentsAndroidKey[] = "web_contents_android";
182#endif  // OS_ANDROID
183
184base::LazyInstance<std::vector<WebContentsImpl::CreatedCallback> >
185g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
186
187static int StartDownload(RenderFrameHost* rfh,
188                         const GURL& url,
189                         bool is_favicon,
190                         uint32_t max_bitmap_size) {
191  static int g_next_image_download_id = 0;
192  rfh->Send(new ImageMsg_DownloadImage(rfh->GetRoutingID(),
193                                       ++g_next_image_download_id,
194                                       url,
195                                       is_favicon,
196                                       max_bitmap_size));
197  return g_next_image_download_id;
198}
199
200void NotifyCacheOnIO(
201    scoped_refptr<net::URLRequestContextGetter> request_context,
202    const GURL& url,
203    const std::string& http_method) {
204  request_context->GetURLRequestContext()->http_transaction_factory()->
205      GetCache()->OnExternalCacheHit(url, http_method);
206}
207
208// Helper function for retrieving all the sites in a frame tree.
209bool CollectSites(BrowserContext* context,
210                  std::set<GURL>* sites,
211                  FrameTreeNode* node) {
212  sites->insert(SiteInstance::GetSiteForURL(context, node->current_url()));
213  return true;
214}
215
216bool ForEachFrameInternal(
217    const base::Callback<void(RenderFrameHost*)>& on_frame,
218    FrameTreeNode* node) {
219  on_frame.Run(node->current_frame_host());
220  return true;
221}
222
223bool ForEachPendingFrameInternal(
224    const base::Callback<void(RenderFrameHost*)>& on_frame,
225    FrameTreeNode* node) {
226  RenderFrameHost* pending_frame_host =
227      node->render_manager()->pending_frame_host();
228  if (pending_frame_host)
229    on_frame.Run(pending_frame_host);
230  return true;
231}
232
233void SendToAllFramesInternal(IPC::Message* message, RenderFrameHost* rfh) {
234  IPC::Message* message_copy = new IPC::Message(*message);
235  message_copy->set_routing_id(rfh->GetRoutingID());
236  rfh->Send(message_copy);
237}
238
239void AddRenderWidgetHostViewToSet(std::set<RenderWidgetHostView*>* set,
240                                  RenderFrameHost* rfh) {
241  RenderWidgetHostView* rwhv = static_cast<RenderFrameHostImpl*>(rfh)
242                                   ->frame_tree_node()
243                                   ->render_manager()
244                                   ->GetRenderWidgetHostView();
245  set->insert(rwhv);
246}
247
248void SetAccessibilityModeOnFrame(AccessibilityMode mode,
249                                 RenderFrameHost* frame_host) {
250  static_cast<RenderFrameHostImpl*>(frame_host)->SetAccessibilityMode(mode);
251}
252
253}  // namespace
254
255WebContents* WebContents::Create(const WebContents::CreateParams& params) {
256  return WebContentsImpl::CreateWithOpener(
257      params, static_cast<WebContentsImpl*>(params.opener));
258}
259
260WebContents* WebContents::CreateWithSessionStorage(
261    const WebContents::CreateParams& params,
262    const SessionStorageNamespaceMap& session_storage_namespace_map) {
263  WebContentsImpl* new_contents = new WebContentsImpl(
264      params.browser_context, NULL);
265
266  for (SessionStorageNamespaceMap::const_iterator it =
267           session_storage_namespace_map.begin();
268       it != session_storage_namespace_map.end();
269       ++it) {
270    new_contents->GetController()
271        .SetSessionStorageNamespace(it->first, it->second.get());
272  }
273
274  new_contents->Init(params);
275  return new_contents;
276}
277
278void WebContentsImpl::AddCreatedCallback(const CreatedCallback& callback) {
279  g_created_callbacks.Get().push_back(callback);
280}
281
282void WebContentsImpl::RemoveCreatedCallback(const CreatedCallback& callback) {
283  for (size_t i = 0; i < g_created_callbacks.Get().size(); ++i) {
284    if (g_created_callbacks.Get().at(i).Equals(callback)) {
285      g_created_callbacks.Get().erase(g_created_callbacks.Get().begin() + i);
286      return;
287    }
288  }
289}
290
291WebContents* WebContents::FromRenderViewHost(const RenderViewHost* rvh) {
292  return rvh->GetDelegate()->GetAsWebContents();
293}
294
295WebContents* WebContents::FromRenderFrameHost(RenderFrameHost* rfh) {
296  RenderFrameHostImpl* rfh_impl = static_cast<RenderFrameHostImpl*>(rfh);
297  if (!rfh_impl)
298    return NULL;
299  return rfh_impl->delegate()->GetAsWebContents();
300}
301
302// WebContentsImpl::DestructionObserver ----------------------------------------
303
304class WebContentsImpl::DestructionObserver : public WebContentsObserver {
305 public:
306  DestructionObserver(WebContentsImpl* owner, WebContents* watched_contents)
307      : WebContentsObserver(watched_contents),
308        owner_(owner) {
309  }
310
311  // WebContentsObserver:
312  virtual void WebContentsDestroyed() OVERRIDE {
313    owner_->OnWebContentsDestroyed(
314        static_cast<WebContentsImpl*>(web_contents()));
315  }
316
317 private:
318  WebContentsImpl* owner_;
319
320  DISALLOW_COPY_AND_ASSIGN(DestructionObserver);
321};
322
323WebContentsImpl::ColorChooserInfo::ColorChooserInfo(int render_process_id,
324                                                    int render_frame_id,
325                                                    ColorChooser* chooser,
326                                                    int identifier)
327    : render_process_id(render_process_id),
328      render_frame_id(render_frame_id),
329      chooser(chooser),
330      identifier(identifier) {
331}
332
333WebContentsImpl::ColorChooserInfo::~ColorChooserInfo() {
334}
335
336// WebContentsImpl -------------------------------------------------------------
337
338WebContentsImpl::WebContentsImpl(
339    BrowserContext* browser_context,
340    WebContentsImpl* opener)
341    : delegate_(NULL),
342      controller_(this, browser_context),
343      render_view_host_delegate_view_(NULL),
344      opener_(opener),
345      created_with_opener_(!!opener),
346#if defined(OS_WIN)
347      accessible_parent_(NULL),
348#endif
349      frame_tree_(new NavigatorImpl(&controller_, this),
350                  this, this, this, this),
351      is_loading_(false),
352      is_load_to_different_document_(false),
353      crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING),
354      crashed_error_code_(0),
355      waiting_for_response_(false),
356      load_state_(net::LOAD_STATE_IDLE, base::string16()),
357      loading_total_progress_(0.0),
358      loading_frames_in_progress_(0),
359      upload_size_(0),
360      upload_position_(0),
361      displayed_insecure_content_(false),
362      has_accessed_initial_document_(false),
363      capturer_count_(0),
364      should_normally_be_visible_(true),
365      is_being_destroyed_(false),
366      notify_disconnection_(false),
367      dialog_manager_(NULL),
368      is_showing_before_unload_dialog_(false),
369      last_active_time_(base::TimeTicks::Now()),
370      closed_by_user_gesture_(false),
371      minimum_zoom_percent_(static_cast<int>(kMinimumZoomFactor * 100)),
372      maximum_zoom_percent_(static_cast<int>(kMaximumZoomFactor * 100)),
373      totalPinchGestureAmount_(0),
374      currentPinchZoomStepDelta_(0),
375      render_view_message_source_(NULL),
376      fullscreen_widget_routing_id_(MSG_ROUTING_NONE),
377      fullscreen_widget_had_focus_at_shutdown_(false),
378      is_subframe_(false),
379      force_disable_overscroll_content_(false),
380      last_dialog_suppressed_(false),
381      accessibility_mode_(
382          BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode()),
383      audio_stream_monitor_(this),
384      loading_weak_factory_(this) {
385  for (size_t i = 0; i < g_created_callbacks.Get().size(); i++)
386    g_created_callbacks.Get().at(i).Run(this);
387  frame_tree_.SetFrameRemoveListener(
388      base::Bind(&WebContentsImpl::OnFrameRemoved,
389                 base::Unretained(this)));
390}
391
392WebContentsImpl::~WebContentsImpl() {
393  is_being_destroyed_ = true;
394
395  // Delete all RFH pending shutdown, which will lead the corresponding RVH to
396  // shutdown and be deleted as well.
397  frame_tree_.ForEach(
398      base::Bind(&RenderFrameHostManager::ClearRFHsPendingShutdown));
399
400  ClearAllPowerSaveBlockers();
401
402  for (std::set<RenderWidgetHostImpl*>::iterator iter =
403           created_widgets_.begin(); iter != created_widgets_.end(); ++iter) {
404    (*iter)->DetachDelegate();
405  }
406  created_widgets_.clear();
407
408  // Clear out any JavaScript state.
409  if (dialog_manager_)
410    dialog_manager_->WebContentsDestroyed(this);
411
412  if (color_chooser_info_.get())
413    color_chooser_info_->chooser->End();
414
415  NotifyDisconnected();
416
417  // Notify any observer that have a reference on this WebContents.
418  NotificationService::current()->Notify(
419      NOTIFICATION_WEB_CONTENTS_DESTROYED,
420      Source<WebContents>(this),
421      NotificationService::NoDetails());
422
423  // Destroy all frame tree nodes except for the root; this notifies observers.
424  frame_tree_.ResetForMainFrameSwap();
425  GetRenderManager()->ResetProxyHosts();
426
427  // Manually call the observer methods for the root frame tree node.
428  RenderFrameHostManager* root = GetRenderManager();
429  if (root->pending_frame_host()) {
430    FOR_EACH_OBSERVER(WebContentsObserver,
431                      observers_,
432                      RenderFrameDeleted(root->pending_frame_host()));
433  }
434  FOR_EACH_OBSERVER(WebContentsObserver,
435                    observers_,
436                    RenderFrameDeleted(root->current_frame_host()));
437
438  if (root->pending_render_view_host()) {
439    FOR_EACH_OBSERVER(WebContentsObserver,
440                      observers_,
441                      RenderViewDeleted(root->pending_render_view_host()));
442  }
443
444  FOR_EACH_OBSERVER(WebContentsObserver,
445                    observers_,
446                    RenderViewDeleted(root->current_host()));
447
448  FOR_EACH_OBSERVER(WebContentsObserver,
449                    observers_,
450                    WebContentsDestroyed());
451
452  FOR_EACH_OBSERVER(WebContentsObserver,
453                    observers_,
454                    ResetWebContents());
455
456  SetDelegate(NULL);
457
458  STLDeleteContainerPairSecondPointers(destruction_observers_.begin(),
459                                       destruction_observers_.end());
460}
461
462WebContentsImpl* WebContentsImpl::CreateWithOpener(
463    const WebContents::CreateParams& params,
464    WebContentsImpl* opener) {
465  TRACE_EVENT0("browser", "WebContentsImpl::CreateWithOpener");
466  WebContentsImpl* new_contents = new WebContentsImpl(
467      params.browser_context, params.opener_suppressed ? NULL : opener);
468
469  if (params.guest_delegate) {
470    // This makes |new_contents| act as a guest.
471    // For more info, see comment above class BrowserPluginGuest.
472    BrowserPluginGuest::Create(new_contents, params.guest_delegate);
473    // We are instantiating a WebContents for browser plugin. Set its subframe
474    // bit to true.
475    new_contents->is_subframe_ = true;
476  }
477  new_contents->Init(params);
478  return new_contents;
479}
480
481// static
482std::vector<WebContentsImpl*> WebContentsImpl::GetAllWebContents() {
483  std::vector<WebContentsImpl*> result;
484  scoped_ptr<RenderWidgetHostIterator> widgets(
485      RenderWidgetHostImpl::GetRenderWidgetHosts());
486  std::set<WebContentsImpl*> web_contents_set;
487  while (RenderWidgetHost* rwh = widgets->GetNextHost()) {
488    if (!rwh->IsRenderView())
489      continue;
490    RenderViewHost* rvh = RenderViewHost::From(rwh);
491    if (!rvh)
492      continue;
493    WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
494    if (!web_contents)
495      continue;
496    WebContentsImpl* wci = static_cast<WebContentsImpl*>(web_contents);
497    if (web_contents_set.find(wci) == web_contents_set.end()) {
498      web_contents_set.insert(wci);
499      result.push_back(wci);
500    }
501  }
502  return result;
503}
504
505RenderFrameHostManager* WebContentsImpl::GetRenderManagerForTesting() {
506  return GetRenderManager();
507}
508
509bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host,
510                                        const IPC::Message& message) {
511  return OnMessageReceived(render_view_host, NULL, message);
512}
513
514bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host,
515                                        RenderFrameHost* render_frame_host,
516                                        const IPC::Message& message) {
517  DCHECK(render_view_host || render_frame_host);
518  if (GetWebUI() &&
519      static_cast<WebUIImpl*>(GetWebUI())->OnMessageReceived(message)) {
520    return true;
521  }
522
523  ObserverListBase<WebContentsObserver>::Iterator it(observers_);
524  WebContentsObserver* observer;
525  if (render_frame_host) {
526    while ((observer = it.GetNext()) != NULL)
527      if (observer->OnMessageReceived(message, render_frame_host))
528        return true;
529  } else {
530    while ((observer = it.GetNext()) != NULL)
531      if (observer->OnMessageReceived(message))
532        return true;
533  }
534
535  // Message handlers should be aware of which
536  // RenderViewHost/RenderFrameHost sent the message, which is temporarily
537  // stored in render_(view|frame)_message_source_.
538  if (render_frame_host)
539    render_frame_message_source_ = render_frame_host;
540  else
541    render_view_message_source_ = render_view_host;
542
543  bool handled = true;
544  IPC_BEGIN_MESSAGE_MAP(WebContentsImpl, message)
545    IPC_MESSAGE_HANDLER(FrameHostMsg_PepperPluginHung, OnPepperPluginHung)
546    IPC_MESSAGE_HANDLER(FrameHostMsg_PluginCrashed, OnPluginCrashed)
547    IPC_MESSAGE_HANDLER(FrameHostMsg_DomOperationResponse,
548                        OnDomOperationResponse)
549    IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeThemeColor,
550                        OnThemeColorChanged)
551    IPC_MESSAGE_HANDLER(FrameHostMsg_DidFinishDocumentLoad,
552                        OnDocumentLoadedInFrame)
553    IPC_MESSAGE_HANDLER(FrameHostMsg_DidFinishLoad, OnDidFinishLoad)
554    IPC_MESSAGE_HANDLER(FrameHostMsg_DidStartLoading, OnDidStartLoading)
555    IPC_MESSAGE_HANDLER(FrameHostMsg_DidStopLoading, OnDidStopLoading)
556    IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeLoadProgress,
557                        OnDidChangeLoadProgress)
558    IPC_MESSAGE_HANDLER(FrameHostMsg_OpenColorChooser, OnOpenColorChooser)
559    IPC_MESSAGE_HANDLER(FrameHostMsg_EndColorChooser, OnEndColorChooser)
560    IPC_MESSAGE_HANDLER(FrameHostMsg_SetSelectedColorInColorChooser,
561                        OnSetSelectedColorInColorChooser)
562    IPC_MESSAGE_HANDLER(FrameHostMsg_MediaPlayingNotification,
563                        OnMediaPlayingNotification)
564    IPC_MESSAGE_HANDLER(FrameHostMsg_MediaPausedNotification,
565                        OnMediaPausedNotification)
566    IPC_MESSAGE_HANDLER(FrameHostMsg_DidFirstVisuallyNonEmptyPaint,
567                        OnFirstVisuallyNonEmptyPaint)
568    IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache,
569                        OnDidLoadResourceFromMemoryCache)
570    IPC_MESSAGE_HANDLER(ViewHostMsg_DidDisplayInsecureContent,
571                        OnDidDisplayInsecureContent)
572    IPC_MESSAGE_HANDLER(ViewHostMsg_DidRunInsecureContent,
573                        OnDidRunInsecureContent)
574    IPC_MESSAGE_HANDLER(ViewHostMsg_GoToEntryAtOffset, OnGoToEntryAtOffset)
575    IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateZoomLimits, OnUpdateZoomLimits)
576    IPC_MESSAGE_HANDLER(ViewHostMsg_EnumerateDirectory, OnEnumerateDirectory)
577    IPC_MESSAGE_HANDLER(ViewHostMsg_RegisterProtocolHandler,
578                        OnRegisterProtocolHandler)
579    IPC_MESSAGE_HANDLER(ViewHostMsg_UnregisterProtocolHandler,
580                        OnUnregisterProtocolHandler)
581    IPC_MESSAGE_HANDLER(ViewHostMsg_Find_Reply, OnFindReply)
582    IPC_MESSAGE_HANDLER(ViewHostMsg_AppCacheAccessed, OnAppCacheAccessed)
583    IPC_MESSAGE_HANDLER(ViewHostMsg_WebUISend, OnWebUISend)
584#if defined(ENABLE_PLUGINS)
585    IPC_MESSAGE_HANDLER(ViewHostMsg_RequestPpapiBrokerPermission,
586                        OnRequestPpapiBrokerPermission)
587    IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginHostMsg_Attach,
588                                OnBrowserPluginMessage(message))
589#endif
590    IPC_MESSAGE_HANDLER(ImageHostMsg_DidDownloadImage, OnDidDownloadImage)
591    IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFaviconURL, OnUpdateFaviconURL)
592    IPC_MESSAGE_HANDLER(ViewHostMsg_ShowValidationMessage,
593                        OnShowValidationMessage)
594    IPC_MESSAGE_HANDLER(ViewHostMsg_HideValidationMessage,
595                        OnHideValidationMessage)
596    IPC_MESSAGE_HANDLER(ViewHostMsg_MoveValidationMessage,
597                        OnMoveValidationMessage)
598#if defined(OS_ANDROID)
599    IPC_MESSAGE_HANDLER(ViewHostMsg_FindMatchRects_Reply,
600                        OnFindMatchRectsReply)
601    IPC_MESSAGE_HANDLER(ViewHostMsg_OpenDateTimeDialog,
602                        OnOpenDateTimeDialog)
603#endif
604    IPC_MESSAGE_UNHANDLED(handled = false)
605  IPC_END_MESSAGE_MAP()
606  render_view_message_source_ = NULL;
607  render_frame_message_source_ = NULL;
608
609  return handled;
610}
611
612void WebContentsImpl::RunFileChooser(
613    RenderViewHost* render_view_host,
614    const FileChooserParams& params) {
615  if (delegate_)
616    delegate_->RunFileChooser(this, params);
617}
618
619NavigationControllerImpl& WebContentsImpl::GetController() {
620  return controller_;
621}
622
623const NavigationControllerImpl& WebContentsImpl::GetController() const {
624  return controller_;
625}
626
627BrowserContext* WebContentsImpl::GetBrowserContext() const {
628  return controller_.GetBrowserContext();
629}
630
631const GURL& WebContentsImpl::GetURL() const {
632  // We may not have a navigation entry yet.
633  NavigationEntry* entry = controller_.GetVisibleEntry();
634  return entry ? entry->GetVirtualURL() : GURL::EmptyGURL();
635}
636
637const GURL& WebContentsImpl::GetVisibleURL() const {
638  // We may not have a navigation entry yet.
639  NavigationEntry* entry = controller_.GetVisibleEntry();
640  return entry ? entry->GetVirtualURL() : GURL::EmptyGURL();
641}
642
643const GURL& WebContentsImpl::GetLastCommittedURL() const {
644  // We may not have a navigation entry yet.
645  NavigationEntry* entry = controller_.GetLastCommittedEntry();
646  return entry ? entry->GetVirtualURL() : GURL::EmptyGURL();
647}
648
649WebContentsDelegate* WebContentsImpl::GetDelegate() {
650  return delegate_;
651}
652
653void WebContentsImpl::SetDelegate(WebContentsDelegate* delegate) {
654  // TODO(cbentzel): remove this debugging code?
655  if (delegate == delegate_)
656    return;
657  if (delegate_)
658    delegate_->Detach(this);
659  delegate_ = delegate;
660  if (delegate_) {
661    delegate_->Attach(this);
662    // Ensure the visible RVH reflects the new delegate's preferences.
663    if (view_)
664      view_->SetOverscrollControllerEnabled(CanOverscrollContent());
665  }
666}
667
668RenderProcessHost* WebContentsImpl::GetRenderProcessHost() const {
669  RenderViewHostImpl* host = GetRenderManager()->current_host();
670  return host ? host->GetProcess() : NULL;
671}
672
673RenderFrameHost* WebContentsImpl::GetMainFrame() {
674  return frame_tree_.root()->current_frame_host();
675}
676
677RenderFrameHost* WebContentsImpl::GetFocusedFrame() {
678  if (!frame_tree_.GetFocusedFrame())
679    return NULL;
680  return frame_tree_.GetFocusedFrame()->current_frame_host();
681}
682
683void WebContentsImpl::ForEachFrame(
684    const base::Callback<void(RenderFrameHost*)>& on_frame) {
685  frame_tree_.ForEach(base::Bind(&ForEachFrameInternal, on_frame));
686}
687
688void WebContentsImpl::SendToAllFrames(IPC::Message* message) {
689  ForEachFrame(base::Bind(&SendToAllFramesInternal, message));
690  delete message;
691}
692
693RenderViewHost* WebContentsImpl::GetRenderViewHost() const {
694  return GetRenderManager()->current_host();
695}
696
697int WebContentsImpl::GetRoutingID() const {
698  if (!GetRenderViewHost())
699    return MSG_ROUTING_NONE;
700
701  return GetRenderViewHost()->GetRoutingID();
702}
703
704int WebContentsImpl::GetFullscreenWidgetRoutingID() const {
705  return fullscreen_widget_routing_id_;
706}
707
708RenderWidgetHostView* WebContentsImpl::GetRenderWidgetHostView() const {
709  return GetRenderManager()->GetRenderWidgetHostView();
710}
711
712RenderWidgetHostView* WebContentsImpl::GetFullscreenRenderWidgetHostView()
713    const {
714  RenderWidgetHost* const widget_host =
715      RenderWidgetHostImpl::FromID(GetRenderProcessHost()->GetID(),
716                                   GetFullscreenWidgetRoutingID());
717  return widget_host ? widget_host->GetView() : NULL;
718}
719
720WebContentsView* WebContentsImpl::GetView() const {
721  return view_.get();
722}
723
724void WebContentsImpl::SetAccessibilityMode(AccessibilityMode mode) {
725  if (mode == accessibility_mode_)
726    return;
727
728  accessibility_mode_ = mode;
729  frame_tree_.ForEach(
730      base::Bind(&ForEachFrameInternal,
731                 base::Bind(&SetAccessibilityModeOnFrame, mode)));
732  frame_tree_.ForEach(
733      base::Bind(&ForEachPendingFrameInternal,
734                 base::Bind(&SetAccessibilityModeOnFrame, mode)));
735}
736
737void WebContentsImpl::AddAccessibilityMode(AccessibilityMode mode) {
738  SetAccessibilityMode(AddAccessibilityModeTo(accessibility_mode_, mode));
739}
740
741void WebContentsImpl::RemoveAccessibilityMode(AccessibilityMode mode) {
742  SetAccessibilityMode(RemoveAccessibilityModeFrom(accessibility_mode_, mode));
743}
744
745WebUI* WebContentsImpl::CreateWebUI(const GURL& url) {
746  WebUIImpl* web_ui = new WebUIImpl(this);
747  WebUIController* controller = WebUIControllerFactoryRegistry::GetInstance()->
748      CreateWebUIControllerForURL(web_ui, url);
749  if (controller) {
750    web_ui->AddMessageHandler(new GenericHandler());
751    web_ui->SetController(controller);
752    return web_ui;
753  }
754
755  delete web_ui;
756  return NULL;
757}
758
759WebUI* WebContentsImpl::GetWebUI() const {
760  return GetRenderManager()->web_ui() ? GetRenderManager()->web_ui()
761      : GetRenderManager()->pending_web_ui();
762}
763
764WebUI* WebContentsImpl::GetCommittedWebUI() const {
765  return GetRenderManager()->web_ui();
766}
767
768void WebContentsImpl::SetUserAgentOverride(const std::string& override) {
769  if (GetUserAgentOverride() == override)
770    return;
771
772  renderer_preferences_.user_agent_override = override;
773
774  // Send the new override string to the renderer.
775  RenderViewHost* host = GetRenderViewHost();
776  if (host)
777    host->SyncRendererPrefs();
778
779  // Reload the page if a load is currently in progress to avoid having
780  // different parts of the page loaded using different user agents.
781  NavigationEntry* entry = controller_.GetVisibleEntry();
782  if (is_loading_ && entry != NULL && entry->GetIsOverridingUserAgent())
783    controller_.ReloadIgnoringCache(true);
784
785  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
786                    UserAgentOverrideSet(override));
787}
788
789const std::string& WebContentsImpl::GetUserAgentOverride() const {
790  return renderer_preferences_.user_agent_override;
791}
792
793void WebContentsImpl::EnableTreeOnlyAccessibilityMode() {
794  AddAccessibilityMode(AccessibilityModeTreeOnly);
795}
796
797bool WebContentsImpl::IsTreeOnlyAccessibilityModeForTesting() const {
798  return accessibility_mode_ == AccessibilityModeTreeOnly;
799}
800
801bool WebContentsImpl::IsFullAccessibilityModeForTesting() const {
802  return accessibility_mode_ == AccessibilityModeComplete;
803}
804
805#if defined(OS_WIN)
806void WebContentsImpl::SetParentNativeViewAccessible(
807gfx::NativeViewAccessible accessible_parent) {
808  accessible_parent_ = accessible_parent;
809  RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(GetMainFrame());
810  if (rfh)
811    rfh->SetParentNativeViewAccessible(accessible_parent);
812}
813#endif
814
815const base::string16& WebContentsImpl::GetTitle() const {
816  // Transient entries take precedence. They are used for interstitial pages
817  // that are shown on top of existing pages.
818  NavigationEntry* entry = controller_.GetTransientEntry();
819  std::string accept_languages =
820      GetContentClient()->browser()->GetAcceptLangs(
821          GetBrowserContext());
822  if (entry) {
823    return entry->GetTitleForDisplay(accept_languages);
824  }
825  WebUI* our_web_ui = GetRenderManager()->pending_web_ui() ?
826      GetRenderManager()->pending_web_ui() : GetRenderManager()->web_ui();
827  if (our_web_ui) {
828    // Don't override the title in view source mode.
829    entry = controller_.GetVisibleEntry();
830    if (!(entry && entry->IsViewSourceMode())) {
831      // Give the Web UI the chance to override our title.
832      const base::string16& title = our_web_ui->GetOverriddenTitle();
833      if (!title.empty())
834        return title;
835    }
836  }
837
838  // We use the title for the last committed entry rather than a pending
839  // navigation entry. For example, when the user types in a URL, we want to
840  // keep the old page's title until the new load has committed and we get a new
841  // title.
842  entry = controller_.GetLastCommittedEntry();
843
844  // We make an exception for initial navigations.
845  if (controller_.IsInitialNavigation()) {
846    // We only want to use the title from the visible entry in one of two cases:
847    // 1. There's already a committed entry for an initial navigation, in which
848    //    case we are doing a history navigation in a new tab (e.g., Ctrl+Back).
849    // 2. The pending entry has been explicitly assigned a title to display.
850    //
851    // If there's no last committed entry and no assigned title, we should fall
852    // back to |page_title_when_no_navigation_entry_| rather than showing the
853    // URL.
854    if (entry ||
855        (controller_.GetVisibleEntry() &&
856         !controller_.GetVisibleEntry()->GetTitle().empty())) {
857      entry = controller_.GetVisibleEntry();
858    }
859  }
860
861  if (entry) {
862    return entry->GetTitleForDisplay(accept_languages);
863  }
864
865  // |page_title_when_no_navigation_entry_| is finally used
866  // if no title cannot be retrieved.
867  return page_title_when_no_navigation_entry_;
868}
869
870int32 WebContentsImpl::GetMaxPageID() {
871  return GetMaxPageIDForSiteInstance(GetSiteInstance());
872}
873
874int32 WebContentsImpl::GetMaxPageIDForSiteInstance(
875    SiteInstance* site_instance) {
876  if (max_page_ids_.find(site_instance->GetId()) == max_page_ids_.end())
877    max_page_ids_[site_instance->GetId()] = -1;
878
879  return max_page_ids_[site_instance->GetId()];
880}
881
882void WebContentsImpl::UpdateMaxPageID(int32 page_id) {
883  UpdateMaxPageIDForSiteInstance(GetSiteInstance(), page_id);
884}
885
886void WebContentsImpl::UpdateMaxPageIDForSiteInstance(
887    SiteInstance* site_instance, int32 page_id) {
888  if (GetMaxPageIDForSiteInstance(site_instance) < page_id)
889    max_page_ids_[site_instance->GetId()] = page_id;
890}
891
892void WebContentsImpl::CopyMaxPageIDsFrom(WebContents* web_contents) {
893  WebContentsImpl* contents = static_cast<WebContentsImpl*>(web_contents);
894  max_page_ids_ = contents->max_page_ids_;
895}
896
897SiteInstance* WebContentsImpl::GetSiteInstance() const {
898  return GetRenderManager()->current_host()->GetSiteInstance();
899}
900
901SiteInstance* WebContentsImpl::GetPendingSiteInstance() const {
902  RenderViewHost* dest_rvh = GetRenderManager()->pending_render_view_host() ?
903      GetRenderManager()->pending_render_view_host() :
904      GetRenderManager()->current_host();
905  return dest_rvh->GetSiteInstance();
906}
907
908bool WebContentsImpl::IsLoading() const {
909  return is_loading_;
910}
911
912bool WebContentsImpl::IsLoadingToDifferentDocument() const {
913  return is_loading_ && is_load_to_different_document_;
914}
915
916bool WebContentsImpl::IsWaitingForResponse() const {
917  return waiting_for_response_ && is_load_to_different_document_;
918}
919
920const net::LoadStateWithParam& WebContentsImpl::GetLoadState() const {
921  return load_state_;
922}
923
924const base::string16& WebContentsImpl::GetLoadStateHost() const {
925  return load_state_host_;
926}
927
928uint64 WebContentsImpl::GetUploadSize() const {
929  return upload_size_;
930}
931
932uint64 WebContentsImpl::GetUploadPosition() const {
933  return upload_position_;
934}
935
936std::set<GURL> WebContentsImpl::GetSitesInTab() const {
937  std::set<GURL> sites;
938  frame_tree_.ForEach(base::Bind(&CollectSites,
939                                 base::Unretained(GetBrowserContext()),
940                                 base::Unretained(&sites)));
941  return sites;
942}
943
944const std::string& WebContentsImpl::GetEncoding() const {
945  return canonical_encoding_;
946}
947
948bool WebContentsImpl::DisplayedInsecureContent() const {
949  return displayed_insecure_content_;
950}
951
952void WebContentsImpl::IncrementCapturerCount(const gfx::Size& capture_size) {
953  DCHECK(!is_being_destroyed_);
954  ++capturer_count_;
955  DVLOG(1) << "There are now " << capturer_count_
956           << " capturing(s) of WebContentsImpl@" << this;
957
958  // Note: This provides a hint to upstream code to size the views optimally
959  // for quality (e.g., to avoid scaling).
960  if (!capture_size.IsEmpty() && preferred_size_for_capture_.IsEmpty()) {
961    preferred_size_for_capture_ = capture_size;
962    OnPreferredSizeChanged(preferred_size_);
963  }
964}
965
966void WebContentsImpl::DecrementCapturerCount() {
967  --capturer_count_;
968  DVLOG(1) << "There are now " << capturer_count_
969           << " capturing(s) of WebContentsImpl@" << this;
970  DCHECK_LE(0, capturer_count_);
971
972  if (is_being_destroyed_)
973    return;
974
975  if (capturer_count_ == 0) {
976    const gfx::Size old_size = preferred_size_for_capture_;
977    preferred_size_for_capture_ = gfx::Size();
978    OnPreferredSizeChanged(old_size);
979  }
980
981  if (IsHidden()) {
982    DVLOG(1) << "Executing delayed WasHidden().";
983    WasHidden();
984  }
985}
986
987int WebContentsImpl::GetCapturerCount() const {
988  return capturer_count_;
989}
990
991bool WebContentsImpl::IsAudioMuted() const {
992  return audio_muter_.get() && audio_muter_->is_muting();
993}
994
995void WebContentsImpl::SetAudioMuted(bool mute) {
996  DVLOG(1) << "SetAudioMuted(mute=" << mute << "), was " << IsAudioMuted()
997           << " for WebContentsImpl@" << this;
998
999  if (mute == IsAudioMuted())
1000    return;
1001
1002  if (mute) {
1003    if (!audio_muter_)
1004      audio_muter_.reset(new WebContentsAudioMuter(this));
1005    audio_muter_->StartMuting();
1006  } else {
1007    DCHECK(audio_muter_);
1008    audio_muter_->StopMuting();
1009  }
1010
1011  // Notification for UI updates in response to the changed muting state.
1012  NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
1013}
1014
1015bool WebContentsImpl::IsCrashed() const {
1016  return (crashed_status_ == base::TERMINATION_STATUS_PROCESS_CRASHED ||
1017          crashed_status_ == base::TERMINATION_STATUS_ABNORMAL_TERMINATION ||
1018          crashed_status_ == base::TERMINATION_STATUS_PROCESS_WAS_KILLED);
1019}
1020
1021void WebContentsImpl::SetIsCrashed(base::TerminationStatus status,
1022                                   int error_code) {
1023  if (status == crashed_status_)
1024    return;
1025
1026  crashed_status_ = status;
1027  crashed_error_code_ = error_code;
1028  NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
1029}
1030
1031base::TerminationStatus WebContentsImpl::GetCrashedStatus() const {
1032  return crashed_status_;
1033}
1034
1035bool WebContentsImpl::IsBeingDestroyed() const {
1036  return is_being_destroyed_;
1037}
1038
1039void WebContentsImpl::NotifyNavigationStateChanged(
1040    InvalidateTypes changed_flags) {
1041  // Create and release the audio power save blocker depending on whether the
1042  // tab is actively producing audio or not.
1043  if (changed_flags == INVALIDATE_TYPE_TAB &&
1044      AudioStreamMonitor::monitoring_available()) {
1045    if (WasRecentlyAudible()) {
1046      if (!audio_power_save_blocker_)
1047        CreateAudioPowerSaveBlocker();
1048    } else {
1049      audio_power_save_blocker_.reset();
1050    }
1051  }
1052
1053  if (delegate_)
1054    delegate_->NavigationStateChanged(this, changed_flags);
1055}
1056
1057base::TimeTicks WebContentsImpl::GetLastActiveTime() const {
1058  return last_active_time_;
1059}
1060
1061void WebContentsImpl::WasShown() {
1062  controller_.SetActive(true);
1063
1064  std::set<RenderWidgetHostView*> widgets = GetRenderWidgetHostViewsInTree();
1065  for (std::set<RenderWidgetHostView*>::iterator iter = widgets.begin();
1066       iter != widgets.end();
1067       iter++) {
1068    if (*iter) {
1069      (*iter)->Show();
1070#if defined(OS_MACOSX)
1071      (*iter)->SetActive(true);
1072#endif
1073    }
1074  }
1075
1076  last_active_time_ = base::TimeTicks::Now();
1077
1078  // The resize rect might have changed while this was inactive -- send the new
1079  // one to make sure it's up to date.
1080  RenderViewHostImpl* rvh =
1081      static_cast<RenderViewHostImpl*>(GetRenderViewHost());
1082  if (rvh) {
1083    rvh->ResizeRectChanged(GetRootWindowResizerRect());
1084  }
1085
1086  // Restore power save blocker if there are active video players running.
1087  if (!active_video_players_.empty() && !video_power_save_blocker_)
1088    CreateVideoPowerSaveBlocker();
1089
1090  FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasShown());
1091
1092  should_normally_be_visible_ = true;
1093}
1094
1095void WebContentsImpl::WasHidden() {
1096  // If there are entities capturing screenshots or video (e.g., mirroring),
1097  // don't activate the "disable rendering" optimization.
1098  if (capturer_count_ == 0) {
1099    // |GetRenderViewHost()| can be NULL if the user middle clicks a link to
1100    // open a tab in the background, then closes the tab before selecting it.
1101    // This is because closing the tab calls WebContentsImpl::Destroy(), which
1102    // removes the |GetRenderViewHost()|; then when we actually destroy the
1103    // window, OnWindowPosChanged() notices and calls WasHidden() (which
1104    // calls us).
1105    std::set<RenderWidgetHostView*> widgets = GetRenderWidgetHostViewsInTree();
1106    for (std::set<RenderWidgetHostView*>::iterator iter = widgets.begin();
1107         iter != widgets.end();
1108         iter++) {
1109      if (*iter)
1110        (*iter)->Hide();
1111    }
1112
1113    // Release any video power save blockers held as video is not visible.
1114    video_power_save_blocker_.reset();
1115  }
1116
1117  FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasHidden());
1118
1119  should_normally_be_visible_ = false;
1120}
1121
1122bool WebContentsImpl::NeedToFireBeforeUnload() {
1123  // TODO(creis): Should we fire even for interstitial pages?
1124  return WillNotifyDisconnection() &&
1125      !ShowingInterstitialPage() &&
1126      !static_cast<RenderViewHostImpl*>(
1127          GetRenderViewHost())->SuddenTerminationAllowed();
1128}
1129
1130void WebContentsImpl::DispatchBeforeUnload(bool for_cross_site_transition) {
1131  static_cast<RenderFrameHostImpl*>(GetMainFrame())->DispatchBeforeUnload(
1132      for_cross_site_transition);
1133}
1134
1135void WebContentsImpl::Stop() {
1136  GetRenderManager()->Stop();
1137  FOR_EACH_OBSERVER(WebContentsObserver, observers_, NavigationStopped());
1138}
1139
1140WebContents* WebContentsImpl::Clone() {
1141  // We use our current SiteInstance since the cloned entry will use it anyway.
1142  // We pass our own opener so that the cloned page can access it if it was
1143  // before.
1144  CreateParams create_params(GetBrowserContext(), GetSiteInstance());
1145  create_params.initial_size = GetContainerBounds().size();
1146  WebContentsImpl* tc = CreateWithOpener(create_params, opener_);
1147  tc->GetController().CopyStateFrom(controller_);
1148  FOR_EACH_OBSERVER(WebContentsObserver,
1149                    observers_,
1150                    DidCloneToNewWebContents(this, tc));
1151  return tc;
1152}
1153
1154void WebContentsImpl::Observe(int type,
1155                              const NotificationSource& source,
1156                              const NotificationDetails& details) {
1157  switch (type) {
1158    case NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED: {
1159      RenderWidgetHost* host = Source<RenderWidgetHost>(source).ptr();
1160      RenderWidgetHostView* view = host->GetView();
1161      if (view == GetFullscreenRenderWidgetHostView()) {
1162        // We cannot just call view_->RestoreFocus() here.  On some platforms,
1163        // attempting to focus the currently-invisible WebContentsView will be
1164        // flat-out ignored.  Therefore, this boolean is used to track whether
1165        // we will request focus after the fullscreen widget has been
1166        // destroyed.
1167        fullscreen_widget_had_focus_at_shutdown_ = (view && view->HasFocus());
1168      } else {
1169        for (PendingWidgetViews::iterator i = pending_widget_views_.begin();
1170             i != pending_widget_views_.end(); ++i) {
1171          if (host->GetView() == i->second) {
1172            pending_widget_views_.erase(i);
1173            break;
1174          }
1175        }
1176      }
1177      break;
1178    }
1179    default:
1180      NOTREACHED();
1181  }
1182}
1183
1184WebContents* WebContentsImpl::GetWebContents() {
1185  return this;
1186}
1187
1188void WebContentsImpl::Init(const WebContents::CreateParams& params) {
1189  // This is set before initializing the render manager since
1190  // RenderFrameHostManager::Init calls back into us via its delegate to ask if
1191  // it should be hidden.
1192  should_normally_be_visible_ = !params.initially_hidden;
1193
1194  GetRenderManager()->Init(
1195      params.browser_context, params.site_instance, params.routing_id,
1196      params.main_frame_routing_id);
1197
1198  WebContentsViewDelegate* delegate =
1199      GetContentClient()->browser()->GetWebContentsViewDelegate(this);
1200
1201  if (browser_plugin_guest_) {
1202    scoped_ptr<WebContentsView> platform_view(CreateWebContentsView(
1203        this, delegate, &render_view_host_delegate_view_));
1204
1205    WebContentsViewGuest* rv = new WebContentsViewGuest(
1206        this, browser_plugin_guest_.get(), platform_view.Pass(),
1207        render_view_host_delegate_view_);
1208    render_view_host_delegate_view_ = rv;
1209    view_.reset(rv);
1210  } else {
1211    // Regular WebContentsView.
1212    view_.reset(CreateWebContentsView(
1213        this, delegate, &render_view_host_delegate_view_));
1214  }
1215  CHECK(render_view_host_delegate_view_);
1216  CHECK(view_.get());
1217
1218  gfx::Size initial_size = params.initial_size;
1219  view_->CreateView(initial_size, params.context);
1220
1221  // Listen for whether our opener gets destroyed.
1222  if (opener_)
1223    AddDestructionObserver(opener_);
1224
1225  registrar_.Add(this,
1226                 NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
1227                 NotificationService::AllBrowserContextsAndSources());
1228
1229  geolocation_dispatcher_host_.reset(new GeolocationDispatcherHost(this));
1230  midi_dispatcher_host_.reset(new MidiDispatcherHost(this));
1231
1232  screen_orientation_dispatcher_host_.reset(
1233      new ScreenOrientationDispatcherHostImpl(this));
1234
1235  manifest_manager_host_.reset(new ManifestManagerHost(this));
1236
1237#if defined(OS_ANDROID)
1238  date_time_chooser_.reset(new DateTimeChooserAndroid());
1239#endif
1240}
1241
1242void WebContentsImpl::OnWebContentsDestroyed(WebContentsImpl* web_contents) {
1243  RemoveDestructionObserver(web_contents);
1244
1245  // Clear the opener if it has been closed.
1246  if (web_contents == opener_) {
1247    opener_ = NULL;
1248    return;
1249  }
1250  // Clear a pending contents that has been closed before being shown.
1251  for (PendingContents::iterator iter = pending_contents_.begin();
1252       iter != pending_contents_.end();
1253       ++iter) {
1254    if (iter->second != web_contents)
1255      continue;
1256    pending_contents_.erase(iter);
1257    return;
1258  }
1259  NOTREACHED();
1260}
1261
1262void WebContentsImpl::AddDestructionObserver(WebContentsImpl* web_contents) {
1263  if (!ContainsKey(destruction_observers_, web_contents)) {
1264    destruction_observers_[web_contents] =
1265        new DestructionObserver(this, web_contents);
1266  }
1267}
1268
1269void WebContentsImpl::RemoveDestructionObserver(WebContentsImpl* web_contents) {
1270  DestructionObservers::iterator iter =
1271      destruction_observers_.find(web_contents);
1272  if (iter != destruction_observers_.end()) {
1273    delete destruction_observers_[web_contents];
1274    destruction_observers_.erase(iter);
1275  }
1276}
1277
1278void WebContentsImpl::AddObserver(WebContentsObserver* observer) {
1279  observers_.AddObserver(observer);
1280}
1281
1282void WebContentsImpl::RemoveObserver(WebContentsObserver* observer) {
1283  observers_.RemoveObserver(observer);
1284}
1285
1286std::set<RenderWidgetHostView*>
1287WebContentsImpl::GetRenderWidgetHostViewsInTree() {
1288  std::set<RenderWidgetHostView*> set;
1289  if (ShowingInterstitialPage()) {
1290    set.insert(GetRenderWidgetHostView());
1291  } else {
1292    ForEachFrame(
1293        base::Bind(&AddRenderWidgetHostViewToSet, base::Unretained(&set)));
1294  }
1295  return set;
1296}
1297
1298void WebContentsImpl::Activate() {
1299  if (delegate_)
1300    delegate_->ActivateContents(this);
1301}
1302
1303void WebContentsImpl::Deactivate() {
1304  if (delegate_)
1305    delegate_->DeactivateContents(this);
1306}
1307
1308void WebContentsImpl::LostCapture() {
1309  if (delegate_)
1310    delegate_->LostCapture();
1311}
1312
1313void WebContentsImpl::RenderWidgetDeleted(
1314    RenderWidgetHostImpl* render_widget_host) {
1315  if (is_being_destroyed_) {
1316    // |created_widgets_| might have been destroyed.
1317    return;
1318  }
1319
1320  std::set<RenderWidgetHostImpl*>::iterator iter =
1321      created_widgets_.find(render_widget_host);
1322  if (iter != created_widgets_.end())
1323    created_widgets_.erase(iter);
1324
1325  if (render_widget_host &&
1326      render_widget_host->GetRoutingID() == fullscreen_widget_routing_id_) {
1327    if (delegate_ && delegate_->EmbedsFullscreenWidget())
1328      delegate_->ToggleFullscreenModeForTab(this, false);
1329    FOR_EACH_OBSERVER(WebContentsObserver,
1330                      observers_,
1331                      DidDestroyFullscreenWidget(
1332                          fullscreen_widget_routing_id_));
1333    fullscreen_widget_routing_id_ = MSG_ROUTING_NONE;
1334    if (fullscreen_widget_had_focus_at_shutdown_)
1335      view_->RestoreFocus();
1336  }
1337}
1338
1339bool WebContentsImpl::PreHandleKeyboardEvent(
1340    const NativeWebKeyboardEvent& event,
1341    bool* is_keyboard_shortcut) {
1342  return delegate_ &&
1343      delegate_->PreHandleKeyboardEvent(this, event, is_keyboard_shortcut);
1344}
1345
1346void WebContentsImpl::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
1347  if (browser_plugin_embedder_ &&
1348      browser_plugin_embedder_->HandleKeyboardEvent(event)) {
1349    return;
1350  }
1351  if (delegate_)
1352    delegate_->HandleKeyboardEvent(this, event);
1353}
1354
1355bool WebContentsImpl::HandleWheelEvent(
1356    const blink::WebMouseWheelEvent& event) {
1357#if !defined(OS_MACOSX)
1358  // On platforms other than Mac, control+mousewheel changes zoom. On Mac, this
1359  // isn't done for two reasons:
1360  //   -the OS already has a gesture to do this through pinch-zoom
1361  //   -if a user starts an inertial scroll, let's go, and presses control
1362  //      (i.e. control+tab) then the OS's buffered scroll events will come in
1363  //      with control key set which isn't what the user wants
1364  if (delegate_ &&
1365      event.wheelTicksY &&
1366      (event.modifiers & blink::WebInputEvent::ControlKey) &&
1367      // Avoid adjusting the zoom in response to two-finger-scrolling touchpad
1368      // gestures, which are regrettably easy to trigger accidentally.
1369      !event.hasPreciseScrollingDeltas) {
1370    delegate_->ContentsZoomChange(event.wheelTicksY > 0);
1371    return true;
1372  }
1373#endif
1374  return false;
1375}
1376
1377bool WebContentsImpl::PreHandleGestureEvent(
1378    const blink::WebGestureEvent& event) {
1379  return delegate_ && delegate_->PreHandleGestureEvent(this, event);
1380}
1381
1382bool WebContentsImpl::HandleGestureEvent(
1383    const blink::WebGestureEvent& event) {
1384  // Some platforms (eg. Mac) send GesturePinch events for trackpad pinch-zoom.
1385  // Use them to implement browser zoom, as for HandleWheelEvent above.
1386  if (event.type == blink::WebInputEvent::GesturePinchUpdate &&
1387      event.sourceDevice == blink::WebGestureDeviceTouchpad) {
1388    // The scale difference necessary to trigger a zoom action. Derived from
1389    // experimentation to find a value that feels reasonable.
1390    const float kZoomStepValue = 0.6f;
1391
1392    // Find the (absolute) thresholds on either side of the current zoom factor,
1393    // then convert those to actual numbers to trigger a zoom in or out.
1394    // This logic deliberately makes the range around the starting zoom value
1395    // for the gesture twice as large as the other ranges (i.e., the notches are
1396    // at ..., -3*step, -2*step, -step, step, 2*step, 3*step, ... but not at 0)
1397    // so that it's easier to get back to your starting point than it is to
1398    // overshoot.
1399    float nextStep = (abs(currentPinchZoomStepDelta_) + 1) * kZoomStepValue;
1400    float backStep = abs(currentPinchZoomStepDelta_) * kZoomStepValue;
1401    float zoomInThreshold = (currentPinchZoomStepDelta_ >= 0) ? nextStep
1402        : -backStep;
1403    float zoomOutThreshold = (currentPinchZoomStepDelta_ <= 0) ? -nextStep
1404        : backStep;
1405
1406    totalPinchGestureAmount_ += (event.data.pinchUpdate.scale - 1.0);
1407    if (totalPinchGestureAmount_ > zoomInThreshold) {
1408      currentPinchZoomStepDelta_++;
1409      if (delegate_)
1410        delegate_->ContentsZoomChange(true);
1411    } else if (totalPinchGestureAmount_ < zoomOutThreshold) {
1412      currentPinchZoomStepDelta_--;
1413      if (delegate_)
1414        delegate_->ContentsZoomChange(false);
1415    }
1416    return true;
1417  }
1418
1419  return false;
1420}
1421
1422void WebContentsImpl::HandleMouseDown() {
1423  if (delegate_)
1424    delegate_->HandleMouseDown();
1425}
1426
1427void WebContentsImpl::HandleMouseUp() {
1428  if (delegate_)
1429    delegate_->HandleMouseUp();
1430}
1431
1432void WebContentsImpl::HandlePointerActivate() {
1433  if (delegate_)
1434    delegate_->HandlePointerActivate();
1435}
1436
1437void WebContentsImpl::HandleGestureBegin() {
1438  if (delegate_)
1439    delegate_->HandleGestureBegin();
1440}
1441
1442void WebContentsImpl::HandleGestureEnd() {
1443  if (delegate_)
1444    delegate_->HandleGestureEnd();
1445}
1446
1447void WebContentsImpl::ToggleFullscreenMode(bool enter_fullscreen) {
1448  // This method is being called to enter or leave renderer-initiated fullscreen
1449  // mode.  Either way, make sure any existing fullscreen widget is shut down
1450  // first.
1451  RenderWidgetHostView* const widget_view = GetFullscreenRenderWidgetHostView();
1452  if (widget_view)
1453    RenderWidgetHostImpl::From(widget_view->GetRenderWidgetHost())->Shutdown();
1454
1455  if (delegate_)
1456    delegate_->ToggleFullscreenModeForTab(this, enter_fullscreen);
1457
1458  FOR_EACH_OBSERVER(WebContentsObserver,
1459                    observers_,
1460                    DidToggleFullscreenModeForTab(IsFullscreenForCurrentTab()));
1461}
1462
1463bool WebContentsImpl::IsFullscreenForCurrentTab() const {
1464  return delegate_ ? delegate_->IsFullscreenForTabOrPending(this) : false;
1465}
1466
1467void WebContentsImpl::RequestToLockMouse(bool user_gesture,
1468                                         bool last_unlocked_by_target) {
1469  if (delegate_) {
1470    delegate_->RequestToLockMouse(this, user_gesture, last_unlocked_by_target);
1471  } else {
1472    GotResponseToLockMouseRequest(false);
1473  }
1474}
1475
1476void WebContentsImpl::LostMouseLock() {
1477  if (delegate_)
1478    delegate_->LostMouseLock();
1479}
1480
1481void WebContentsImpl::CreateNewWindow(
1482    int render_process_id,
1483    int route_id,
1484    int main_frame_route_id,
1485    const ViewHostMsg_CreateWindow_Params& params,
1486    SessionStorageNamespace* session_storage_namespace) {
1487  // We usually create the new window in the same BrowsingInstance (group of
1488  // script-related windows), by passing in the current SiteInstance.  However,
1489  // if the opener is being suppressed (in a non-guest), we create a new
1490  // SiteInstance in its own BrowsingInstance.
1491  bool is_guest = BrowserPluginGuest::IsGuest(this);
1492
1493  // If the opener is to be suppressed, the new window can be in any process.
1494  // Since routing ids are process specific, we must not have one passed in
1495  // as argument here.
1496  DCHECK(!params.opener_suppressed || route_id == MSG_ROUTING_NONE);
1497
1498  scoped_refptr<SiteInstance> site_instance =
1499      params.opener_suppressed && !is_guest ?
1500      SiteInstance::CreateForURL(GetBrowserContext(), params.target_url) :
1501      GetSiteInstance();
1502
1503  // A message to create a new window can only come from the active process for
1504  // this WebContentsImpl instance. If any other process sends the request,
1505  // it is invalid and the process must be terminated.
1506  if (GetRenderProcessHost()->GetID() != render_process_id) {
1507    base::ProcessHandle process_handle =
1508        RenderProcessHost::FromID(render_process_id)->GetHandle();
1509    if (process_handle != base::kNullProcessHandle) {
1510      RecordAction(
1511          base::UserMetricsAction("Terminate_ProcessMismatch_CreateNewWindow"));
1512      base::KillProcess(process_handle, RESULT_CODE_KILLED, false);
1513    }
1514    return;
1515  }
1516
1517  // We must assign the SessionStorageNamespace before calling Init().
1518  //
1519  // http://crbug.com/142685
1520  const std::string& partition_id =
1521      GetContentClient()->browser()->
1522          GetStoragePartitionIdForSite(GetBrowserContext(),
1523                                       site_instance->GetSiteURL());
1524  StoragePartition* partition = BrowserContext::GetStoragePartition(
1525      GetBrowserContext(), site_instance.get());
1526  DOMStorageContextWrapper* dom_storage_context =
1527      static_cast<DOMStorageContextWrapper*>(partition->GetDOMStorageContext());
1528  SessionStorageNamespaceImpl* session_storage_namespace_impl =
1529      static_cast<SessionStorageNamespaceImpl*>(session_storage_namespace);
1530  CHECK(session_storage_namespace_impl->IsFromContext(dom_storage_context));
1531
1532  if (delegate_ &&
1533      !delegate_->ShouldCreateWebContents(this,
1534                                          route_id,
1535                                          params.window_container_type,
1536                                          params.frame_name,
1537                                          params.target_url,
1538                                          partition_id,
1539                                          session_storage_namespace)) {
1540    if (route_id != MSG_ROUTING_NONE &&
1541        !RenderViewHost::FromID(render_process_id, route_id)) {
1542      // If the embedder didn't create a WebContents for this route, we need to
1543      // delete the RenderView that had already been created.
1544      Send(new ViewMsg_Close(route_id));
1545    }
1546    GetRenderViewHost()->GetProcess()->ResumeRequestsForView(route_id);
1547    GetRenderViewHost()->GetProcess()->ResumeRequestsForView(
1548        main_frame_route_id);
1549    return;
1550  }
1551
1552  // Create the new web contents. This will automatically create the new
1553  // WebContentsView. In the future, we may want to create the view separately.
1554  CreateParams create_params(GetBrowserContext(), site_instance.get());
1555  create_params.routing_id = route_id;
1556  create_params.main_frame_routing_id = main_frame_route_id;
1557  create_params.opener = this;
1558  create_params.opener_suppressed = params.opener_suppressed;
1559  if (params.disposition == NEW_BACKGROUND_TAB)
1560    create_params.initially_hidden = true;
1561
1562  WebContentsImpl* new_contents = NULL;
1563  if (!is_guest) {
1564    create_params.context = view_->GetNativeView();
1565    create_params.initial_size = GetContainerBounds().size();
1566    new_contents = static_cast<WebContentsImpl*>(
1567        WebContents::Create(create_params));
1568  }  else {
1569    new_contents = GetBrowserPluginGuest()->CreateNewGuestWindow(create_params);
1570  }
1571  new_contents->GetController().SetSessionStorageNamespace(
1572      partition_id,
1573      session_storage_namespace);
1574  new_contents->RenderViewCreated(new_contents->GetRenderViewHost());
1575
1576  // Save the window for later if we're not suppressing the opener (since it
1577  // will be shown immediately).
1578  if (!params.opener_suppressed) {
1579    if (!is_guest) {
1580      WebContentsView* new_view = new_contents->view_.get();
1581
1582      // TODO(brettw): It seems bogus that we have to call this function on the
1583      // newly created object and give it one of its own member variables.
1584      new_view->CreateViewForWidget(new_contents->GetRenderViewHost());
1585    }
1586    // Save the created window associated with the route so we can show it
1587    // later.
1588    DCHECK_NE(MSG_ROUTING_NONE, route_id);
1589    pending_contents_[route_id] = new_contents;
1590    AddDestructionObserver(new_contents);
1591  }
1592
1593  if (delegate_) {
1594    delegate_->WebContentsCreated(
1595        this, params.opener_render_frame_id, params.frame_name,
1596        params.target_url, new_contents);
1597  }
1598
1599  if (params.opener_suppressed) {
1600    // When the opener is suppressed, the original renderer cannot access the
1601    // new window.  As a result, we need to show and navigate the window here.
1602    bool was_blocked = false;
1603    if (delegate_) {
1604      gfx::Rect initial_pos;
1605      delegate_->AddNewContents(
1606          this, new_contents, params.disposition, initial_pos,
1607          params.user_gesture, &was_blocked);
1608    }
1609    if (!was_blocked) {
1610      OpenURLParams open_params(params.target_url,
1611                                Referrer(),
1612                                CURRENT_TAB,
1613                                ui::PAGE_TRANSITION_LINK,
1614                                true /* is_renderer_initiated */);
1615      open_params.user_gesture = params.user_gesture;
1616      new_contents->OpenURL(open_params);
1617    }
1618  }
1619}
1620
1621void WebContentsImpl::CreateNewWidget(int render_process_id,
1622                                      int route_id,
1623                                      blink::WebPopupType popup_type) {
1624  CreateNewWidget(render_process_id, route_id, false, popup_type);
1625}
1626
1627void WebContentsImpl::CreateNewFullscreenWidget(int render_process_id,
1628                                                int route_id) {
1629  CreateNewWidget(render_process_id, route_id, true, blink::WebPopupTypeNone);
1630}
1631
1632void WebContentsImpl::CreateNewWidget(int render_process_id,
1633                                      int route_id,
1634                                      bool is_fullscreen,
1635                                      blink::WebPopupType popup_type) {
1636  RenderProcessHost* process = GetRenderProcessHost();
1637  // A message to create a new widget can only come from the active process for
1638  // this WebContentsImpl instance. If any other process sends the request,
1639  // it is invalid and the process must be terminated.
1640  if (process->GetID() != render_process_id) {
1641    base::ProcessHandle process_handle =
1642        RenderProcessHost::FromID(render_process_id)->GetHandle();
1643    if (process_handle != base::kNullProcessHandle) {
1644      RecordAction(
1645          base::UserMetricsAction("Terminate_ProcessMismatch_CreateNewWidget"));
1646      base::KillProcess(process_handle, RESULT_CODE_KILLED, false);
1647    }
1648    return;
1649  }
1650
1651  RenderWidgetHostImpl* widget_host =
1652      new RenderWidgetHostImpl(this, process, route_id, IsHidden());
1653  created_widgets_.insert(widget_host);
1654
1655  RenderWidgetHostViewBase* widget_view =
1656      static_cast<RenderWidgetHostViewBase*>(
1657          view_->CreateViewForPopupWidget(widget_host));
1658  if (!widget_view)
1659    return;
1660  if (!is_fullscreen) {
1661    // Popups should not get activated.
1662    widget_view->SetPopupType(popup_type);
1663  }
1664  // Save the created widget associated with the route so we can show it later.
1665  pending_widget_views_[route_id] = widget_view;
1666
1667#if defined(OS_MACOSX)
1668  // A RenderWidgetHostViewMac has lifetime scoped to the view. We'll retain it
1669  // to allow it to survive the trip without being hosted.
1670  base::mac::NSObjectRetain(widget_view->GetNativeView());
1671#endif
1672}
1673
1674void WebContentsImpl::ShowCreatedWindow(int route_id,
1675                                        WindowOpenDisposition disposition,
1676                                        const gfx::Rect& initial_pos,
1677                                        bool user_gesture) {
1678  WebContentsImpl* contents = GetCreatedWindow(route_id);
1679  if (contents) {
1680    WebContentsDelegate* delegate = GetDelegate();
1681    if (delegate) {
1682      delegate->AddNewContents(
1683          this, contents, disposition, initial_pos, user_gesture, NULL);
1684    }
1685  }
1686}
1687
1688void WebContentsImpl::ShowCreatedWidget(int route_id,
1689                                        const gfx::Rect& initial_pos) {
1690  ShowCreatedWidget(route_id, false, initial_pos);
1691}
1692
1693void WebContentsImpl::ShowCreatedFullscreenWidget(int route_id) {
1694  ShowCreatedWidget(route_id, true, gfx::Rect());
1695}
1696
1697void WebContentsImpl::ShowCreatedWidget(int route_id,
1698                                        bool is_fullscreen,
1699                                        const gfx::Rect& initial_pos) {
1700  RenderWidgetHostViewBase* widget_host_view =
1701      static_cast<RenderWidgetHostViewBase*>(GetCreatedWidget(route_id));
1702  if (!widget_host_view)
1703    return;
1704
1705  RenderWidgetHostView* view = NULL;
1706  BrowserPluginGuest* guest = GetBrowserPluginGuest();
1707  if (guest && guest->embedder_web_contents()) {
1708    view = guest->embedder_web_contents()->GetRenderWidgetHostView();
1709  } else {
1710    view = GetRenderWidgetHostView();
1711  }
1712
1713  if (is_fullscreen) {
1714    DCHECK_EQ(MSG_ROUTING_NONE, fullscreen_widget_routing_id_);
1715    view_->StoreFocus();
1716    fullscreen_widget_routing_id_ = route_id;
1717    if (delegate_ && delegate_->EmbedsFullscreenWidget()) {
1718      widget_host_view->InitAsChild(GetRenderWidgetHostView()->GetNativeView());
1719      delegate_->ToggleFullscreenModeForTab(this, true);
1720    } else {
1721      widget_host_view->InitAsFullscreen(view);
1722    }
1723    FOR_EACH_OBSERVER(WebContentsObserver,
1724                      observers_,
1725                      DidShowFullscreenWidget(route_id));
1726    if (!widget_host_view->HasFocus())
1727      widget_host_view->Focus();
1728  } else {
1729    widget_host_view->InitAsPopup(view, initial_pos);
1730  }
1731
1732  RenderWidgetHostImpl* render_widget_host_impl =
1733      RenderWidgetHostImpl::From(widget_host_view->GetRenderWidgetHost());
1734  render_widget_host_impl->Init();
1735  // Only allow privileged mouse lock for fullscreen render widget, which is
1736  // used to implement Pepper Flash fullscreen.
1737  render_widget_host_impl->set_allow_privileged_mouse_lock(is_fullscreen);
1738
1739#if defined(OS_MACOSX)
1740  // A RenderWidgetHostViewMac has lifetime scoped to the view. Now that it's
1741  // properly embedded (or purposefully ignored) we can release the retain we
1742  // took in CreateNewWidget().
1743  base::mac::NSObjectRelease(widget_host_view->GetNativeView());
1744#endif
1745}
1746
1747WebContentsImpl* WebContentsImpl::GetCreatedWindow(int route_id) {
1748  PendingContents::iterator iter = pending_contents_.find(route_id);
1749
1750  // Certain systems can block the creation of new windows. If we didn't succeed
1751  // in creating one, just return NULL.
1752  if (iter == pending_contents_.end()) {
1753    return NULL;
1754  }
1755
1756  WebContentsImpl* new_contents = iter->second;
1757  pending_contents_.erase(route_id);
1758  RemoveDestructionObserver(new_contents);
1759
1760  // Don't initialize the guest WebContents immediately.
1761  if (BrowserPluginGuest::IsGuest(new_contents))
1762    return new_contents;
1763
1764  if (!new_contents->GetRenderProcessHost()->HasConnection() ||
1765      !new_contents->GetRenderViewHost()->GetView())
1766    return NULL;
1767
1768  // Resume blocked requests for both the RenderViewHost and RenderFrameHost.
1769  // TODO(brettw): It seems bogus to reach into here and initialize the host.
1770  static_cast<RenderViewHostImpl*>(new_contents->GetRenderViewHost())->Init();
1771  static_cast<RenderFrameHostImpl*>(new_contents->GetMainFrame())->Init();
1772
1773  return new_contents;
1774}
1775
1776RenderWidgetHostView* WebContentsImpl::GetCreatedWidget(int route_id) {
1777  PendingWidgetViews::iterator iter = pending_widget_views_.find(route_id);
1778  if (iter == pending_widget_views_.end()) {
1779    DCHECK(false);
1780    return NULL;
1781  }
1782
1783  RenderWidgetHostView* widget_host_view = iter->second;
1784  pending_widget_views_.erase(route_id);
1785
1786  RenderWidgetHost* widget_host = widget_host_view->GetRenderWidgetHost();
1787  if (!widget_host->GetProcess()->HasConnection()) {
1788    // The view has gone away or the renderer crashed. Nothing to do.
1789    return NULL;
1790  }
1791
1792  return widget_host_view;
1793}
1794
1795void WebContentsImpl::RequestMediaAccessPermission(
1796    const MediaStreamRequest& request,
1797    const MediaResponseCallback& callback) {
1798  if (delegate_) {
1799    delegate_->RequestMediaAccessPermission(this, request, callback);
1800  } else {
1801    callback.Run(MediaStreamDevices(),
1802                 MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN,
1803                 scoped_ptr<MediaStreamUI>());
1804  }
1805}
1806
1807bool WebContentsImpl::CheckMediaAccessPermission(const GURL& security_origin,
1808                                                 MediaStreamType type) {
1809  DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
1810         type == MEDIA_DEVICE_VIDEO_CAPTURE);
1811  return delegate_ &&
1812         delegate_->CheckMediaAccessPermission(this, security_origin, type);
1813}
1814
1815SessionStorageNamespace* WebContentsImpl::GetSessionStorageNamespace(
1816    SiteInstance* instance) {
1817  return controller_.GetSessionStorageNamespace(instance);
1818}
1819
1820SessionStorageNamespaceMap WebContentsImpl::GetSessionStorageNamespaceMap() {
1821  return controller_.GetSessionStorageNamespaceMap();
1822}
1823
1824FrameTree* WebContentsImpl::GetFrameTree() {
1825  return &frame_tree_;
1826}
1827
1828AccessibilityMode WebContentsImpl::GetAccessibilityMode() const {
1829  return accessibility_mode_;
1830}
1831
1832void WebContentsImpl::AccessibilityEventReceived(
1833    const std::vector<AXEventNotificationDetails>& details) {
1834  FOR_EACH_OBSERVER(
1835      WebContentsObserver, observers_, AccessibilityEventReceived(details));
1836}
1837
1838RenderFrameHost* WebContentsImpl::GetGuestByInstanceID(
1839    int browser_plugin_instance_id) {
1840  BrowserPluginGuestManager* guest_manager =
1841      GetBrowserContext()->GetGuestManager();
1842  WebContents* guest = guest_manager->GetGuestByInstanceID(
1843      this, browser_plugin_instance_id);
1844  if (!guest)
1845    return NULL;
1846  return guest->GetMainFrame();
1847}
1848
1849void WebContentsImpl::OnShowValidationMessage(
1850    const gfx::Rect& anchor_in_root_view,
1851    const base::string16& main_text,
1852    const base::string16& sub_text) {
1853  if (delegate_)
1854    delegate_->ShowValidationMessage(
1855        this, anchor_in_root_view, main_text, sub_text);
1856}
1857
1858void WebContentsImpl::OnHideValidationMessage() {
1859  if (delegate_)
1860    delegate_->HideValidationMessage(this);
1861}
1862
1863void WebContentsImpl::OnMoveValidationMessage(
1864    const gfx::Rect& anchor_in_root_view) {
1865  if (delegate_)
1866    delegate_->MoveValidationMessage(this, anchor_in_root_view);
1867}
1868
1869void WebContentsImpl::DidSendScreenRects(RenderWidgetHostImpl* rwh) {
1870  if (browser_plugin_embedder_)
1871    browser_plugin_embedder_->DidSendScreenRects();
1872}
1873
1874BrowserAccessibilityManager*
1875    WebContentsImpl::GetRootBrowserAccessibilityManager() {
1876  RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(GetMainFrame());
1877  return rfh ? rfh->browser_accessibility_manager() : NULL;
1878}
1879
1880BrowserAccessibilityManager*
1881    WebContentsImpl::GetOrCreateRootBrowserAccessibilityManager() {
1882  RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(GetMainFrame());
1883  return rfh ? rfh->GetOrCreateBrowserAccessibilityManager() : NULL;
1884}
1885
1886void WebContentsImpl::UpdatePreferredSize(const gfx::Size& pref_size) {
1887  const gfx::Size old_size = GetPreferredSize();
1888  preferred_size_ = pref_size;
1889  OnPreferredSizeChanged(old_size);
1890}
1891
1892void WebContentsImpl::ResizeDueToAutoResize(const gfx::Size& new_size) {
1893  if (delegate_)
1894    delegate_->ResizeDueToAutoResize(this, new_size);
1895}
1896
1897WebContents* WebContentsImpl::OpenURL(const OpenURLParams& params) {
1898  if (!delegate_)
1899    return NULL;
1900
1901  WebContents* new_contents = delegate_->OpenURLFromTab(this, params);
1902  return new_contents;
1903}
1904
1905bool WebContentsImpl::Send(IPC::Message* message) {
1906  if (!GetRenderViewHost()) {
1907    delete message;
1908    return false;
1909  }
1910
1911  return GetRenderViewHost()->Send(message);
1912}
1913
1914bool WebContentsImpl::NavigateToPendingEntry(
1915    NavigationController::ReloadType reload_type) {
1916  FrameTreeNode* node = frame_tree_.root();
1917
1918  // Navigate in the FrameTreeNode specified in the pending entry, if any.  This
1919  // is currently only used in --site-per-process and tests.
1920  NavigationEntryImpl* pending_entry =
1921      NavigationEntryImpl::FromNavigationEntry(controller_.GetPendingEntry());
1922  if (pending_entry->frame_tree_node_id() != -1) {
1923    FrameTreeNode* subframe =
1924        frame_tree_.FindByID(pending_entry->frame_tree_node_id());
1925    DCHECK(subframe);
1926    if (subframe)
1927      node = subframe;
1928  }
1929
1930  return node->navigator()->NavigateToPendingEntry(
1931      node->current_frame_host(), reload_type);
1932}
1933
1934void WebContentsImpl::RenderFrameForInterstitialPageCreated(
1935    RenderFrameHost* render_frame_host) {
1936  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
1937                    RenderFrameForInterstitialPageCreated(render_frame_host));
1938}
1939
1940void WebContentsImpl::AttachInterstitialPage(
1941    InterstitialPageImpl* interstitial_page) {
1942  DCHECK(interstitial_page);
1943  GetRenderManager()->set_interstitial_page(interstitial_page);
1944
1945  // Cancel any visible dialogs so that they don't interfere with the
1946  // interstitial.
1947  if (dialog_manager_)
1948    dialog_manager_->CancelActiveAndPendingDialogs(this);
1949
1950  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
1951                    DidAttachInterstitialPage());
1952}
1953
1954void WebContentsImpl::DetachInterstitialPage() {
1955  if (ShowingInterstitialPage())
1956    GetRenderManager()->remove_interstitial_page();
1957  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
1958                    DidDetachInterstitialPage());
1959}
1960
1961void WebContentsImpl::SetHistoryLengthAndPrune(
1962    const SiteInstance* site_instance,
1963    int history_length,
1964    int32 minimum_page_id) {
1965  // SetHistoryLengthAndPrune doesn't work when there are pending cross-site
1966  // navigations. Callers should ensure that this is the case.
1967  if (GetRenderManager()->pending_render_view_host()) {
1968    NOTREACHED();
1969    return;
1970  }
1971  RenderViewHostImpl* rvh = GetRenderViewHostImpl();
1972  if (!rvh) {
1973    NOTREACHED();
1974    return;
1975  }
1976  if (site_instance && rvh->GetSiteInstance() != site_instance) {
1977    NOTREACHED();
1978    return;
1979  }
1980  Send(new ViewMsg_SetHistoryLengthAndPrune(GetRoutingID(),
1981                                            history_length,
1982                                            minimum_page_id));
1983}
1984
1985void WebContentsImpl::ReloadFocusedFrame(bool ignore_cache) {
1986  RenderFrameHost* focused_frame = GetFocusedFrame();
1987  if (!focused_frame)
1988    return;
1989
1990  focused_frame->Send(new FrameMsg_Reload(
1991      focused_frame->GetRoutingID(), ignore_cache));
1992}
1993
1994void WebContentsImpl::Undo() {
1995  RenderFrameHost* focused_frame = GetFocusedFrame();
1996  if (!focused_frame)
1997    return;
1998
1999  focused_frame->Send(new InputMsg_Undo(focused_frame->GetRoutingID()));
2000  RecordAction(base::UserMetricsAction("Undo"));
2001}
2002
2003void WebContentsImpl::Redo() {
2004  RenderFrameHost* focused_frame = GetFocusedFrame();
2005  if (!focused_frame)
2006    return;
2007  focused_frame->Send(new InputMsg_Redo(focused_frame->GetRoutingID()));
2008  RecordAction(base::UserMetricsAction("Redo"));
2009}
2010
2011void WebContentsImpl::Cut() {
2012  RenderFrameHost* focused_frame = GetFocusedFrame();
2013  if (!focused_frame)
2014    return;
2015
2016  focused_frame->Send(new InputMsg_Cut(focused_frame->GetRoutingID()));
2017  RecordAction(base::UserMetricsAction("Cut"));
2018}
2019
2020void WebContentsImpl::Copy() {
2021  RenderFrameHost* focused_frame = GetFocusedFrame();
2022  if (!focused_frame)
2023    return;
2024
2025  focused_frame->Send(new InputMsg_Copy(focused_frame->GetRoutingID()));
2026  RecordAction(base::UserMetricsAction("Copy"));
2027}
2028
2029void WebContentsImpl::CopyToFindPboard() {
2030#if defined(OS_MACOSX)
2031  RenderFrameHost* focused_frame = GetFocusedFrame();
2032  if (!focused_frame)
2033    return;
2034
2035  // Windows/Linux don't have the concept of a find pasteboard.
2036  focused_frame->Send(
2037      new InputMsg_CopyToFindPboard(focused_frame->GetRoutingID()));
2038  RecordAction(base::UserMetricsAction("CopyToFindPboard"));
2039#endif
2040}
2041
2042void WebContentsImpl::Paste() {
2043  RenderFrameHost* focused_frame = GetFocusedFrame();
2044  if (!focused_frame)
2045    return;
2046
2047  focused_frame->Send(new InputMsg_Paste(focused_frame->GetRoutingID()));
2048  RecordAction(base::UserMetricsAction("Paste"));
2049}
2050
2051void WebContentsImpl::PasteAndMatchStyle() {
2052  RenderFrameHost* focused_frame = GetFocusedFrame();
2053  if (!focused_frame)
2054    return;
2055
2056  focused_frame->Send(new InputMsg_PasteAndMatchStyle(
2057      focused_frame->GetRoutingID()));
2058  RecordAction(base::UserMetricsAction("PasteAndMatchStyle"));
2059}
2060
2061void WebContentsImpl::Delete() {
2062  RenderFrameHost* focused_frame = GetFocusedFrame();
2063  if (!focused_frame)
2064    return;
2065
2066  focused_frame->Send(new InputMsg_Delete(focused_frame->GetRoutingID()));
2067  RecordAction(base::UserMetricsAction("DeleteSelection"));
2068}
2069
2070void WebContentsImpl::SelectAll() {
2071  RenderFrameHost* focused_frame = GetFocusedFrame();
2072  if (!focused_frame)
2073    return;
2074
2075  focused_frame->Send(new InputMsg_SelectAll(focused_frame->GetRoutingID()));
2076  RecordAction(base::UserMetricsAction("SelectAll"));
2077}
2078
2079void WebContentsImpl::Unselect() {
2080  RenderFrameHost* focused_frame = GetFocusedFrame();
2081  if (!focused_frame)
2082    return;
2083
2084  focused_frame->Send(new InputMsg_Unselect(focused_frame->GetRoutingID()));
2085  RecordAction(base::UserMetricsAction("Unselect"));
2086}
2087
2088void WebContentsImpl::Replace(const base::string16& word) {
2089  RenderFrameHost* focused_frame = GetFocusedFrame();
2090  if (!focused_frame)
2091    return;
2092
2093  focused_frame->Send(new InputMsg_Replace(
2094      focused_frame->GetRoutingID(), word));
2095}
2096
2097void WebContentsImpl::ReplaceMisspelling(const base::string16& word) {
2098  RenderFrameHost* focused_frame = GetFocusedFrame();
2099  if (!focused_frame)
2100    return;
2101
2102  focused_frame->Send(new InputMsg_ReplaceMisspelling(
2103      focused_frame->GetRoutingID(), word));
2104}
2105
2106void WebContentsImpl::NotifyContextMenuClosed(
2107    const CustomContextMenuContext& context) {
2108  RenderFrameHost* focused_frame = GetFocusedFrame();
2109  if (!focused_frame)
2110    return;
2111
2112  focused_frame->Send(new FrameMsg_ContextMenuClosed(
2113      focused_frame->GetRoutingID(), context));
2114}
2115
2116void WebContentsImpl::ExecuteCustomContextMenuCommand(
2117    int action, const CustomContextMenuContext& context) {
2118  RenderFrameHost* focused_frame = GetFocusedFrame();
2119  if (!focused_frame)
2120    return;
2121
2122  focused_frame->Send(new FrameMsg_CustomContextMenuAction(
2123      focused_frame->GetRoutingID(), context, action));
2124}
2125
2126gfx::NativeView WebContentsImpl::GetNativeView() {
2127  return view_->GetNativeView();
2128}
2129
2130gfx::NativeView WebContentsImpl::GetContentNativeView() {
2131  return view_->GetContentNativeView();
2132}
2133
2134gfx::NativeWindow WebContentsImpl::GetTopLevelNativeWindow() {
2135  return view_->GetTopLevelNativeWindow();
2136}
2137
2138gfx::Rect WebContentsImpl::GetViewBounds() {
2139  return view_->GetViewBounds();
2140}
2141
2142gfx::Rect WebContentsImpl::GetContainerBounds() {
2143  gfx::Rect rv;
2144  view_->GetContainerBounds(&rv);
2145  return rv;
2146}
2147
2148DropData* WebContentsImpl::GetDropData() {
2149  return view_->GetDropData();
2150}
2151
2152void WebContentsImpl::Focus() {
2153  RenderWidgetHostView* const fullscreen_view =
2154      GetFullscreenRenderWidgetHostView();
2155  if (fullscreen_view)
2156    fullscreen_view->Focus();
2157  else
2158    view_->Focus();
2159}
2160
2161void WebContentsImpl::SetInitialFocus() {
2162  RenderWidgetHostView* const fullscreen_view =
2163      GetFullscreenRenderWidgetHostView();
2164  if (fullscreen_view)
2165    fullscreen_view->Focus();
2166  else
2167    view_->SetInitialFocus();
2168}
2169
2170void WebContentsImpl::StoreFocus() {
2171  if (!GetFullscreenRenderWidgetHostView())
2172    view_->StoreFocus();
2173}
2174
2175void WebContentsImpl::RestoreFocus() {
2176  RenderWidgetHostView* const fullscreen_view =
2177      GetFullscreenRenderWidgetHostView();
2178  if (fullscreen_view)
2179    fullscreen_view->Focus();
2180  else
2181    view_->RestoreFocus();
2182}
2183
2184void WebContentsImpl::FocusThroughTabTraversal(bool reverse) {
2185  if (ShowingInterstitialPage()) {
2186    GetRenderManager()->interstitial_page()->FocusThroughTabTraversal(reverse);
2187    return;
2188  }
2189  RenderWidgetHostView* const fullscreen_view =
2190      GetFullscreenRenderWidgetHostView();
2191  if (fullscreen_view) {
2192    fullscreen_view->Focus();
2193    return;
2194  }
2195  GetRenderViewHostImpl()->SetInitialFocus(reverse);
2196}
2197
2198bool WebContentsImpl::ShowingInterstitialPage() const {
2199  return GetRenderManager()->interstitial_page() != NULL;
2200}
2201
2202InterstitialPage* WebContentsImpl::GetInterstitialPage() const {
2203  return GetRenderManager()->interstitial_page();
2204}
2205
2206bool WebContentsImpl::IsSavable() {
2207  // WebKit creates Document object when MIME type is application/xhtml+xml,
2208  // so we also support this MIME type.
2209  return contents_mime_type_ == "text/html" ||
2210         contents_mime_type_ == "text/xml" ||
2211         contents_mime_type_ == "application/xhtml+xml" ||
2212         contents_mime_type_ == "text/plain" ||
2213         contents_mime_type_ == "text/css" ||
2214         net::IsSupportedJavascriptMimeType(contents_mime_type_.c_str());
2215}
2216
2217void WebContentsImpl::OnSavePage() {
2218  // If we can not save the page, try to download it.
2219  if (!IsSavable()) {
2220    RecordDownloadSource(INITIATED_BY_SAVE_PACKAGE_ON_NON_HTML);
2221    SaveFrame(GetURL(), Referrer());
2222    return;
2223  }
2224
2225  Stop();
2226
2227  // Create the save package and possibly prompt the user for the name to save
2228  // the page as. The user prompt is an asynchronous operation that runs on
2229  // another thread.
2230  save_package_ = new SavePackage(this);
2231  save_package_->GetSaveInfo();
2232}
2233
2234// Used in automated testing to bypass prompting the user for file names.
2235// Instead, the names and paths are hard coded rather than running them through
2236// file name sanitation and extension / mime checking.
2237bool WebContentsImpl::SavePage(const base::FilePath& main_file,
2238                               const base::FilePath& dir_path,
2239                               SavePageType save_type) {
2240  // Stop the page from navigating.
2241  Stop();
2242
2243  save_package_ = new SavePackage(this, save_type, main_file, dir_path);
2244  return save_package_->Init(SavePackageDownloadCreatedCallback());
2245}
2246
2247void WebContentsImpl::SaveFrame(const GURL& url,
2248                                const Referrer& referrer) {
2249  if (!GetURL().is_valid())
2250    return;
2251  bool is_main_frame = (url == GetURL());
2252
2253  DownloadManager* dlm =
2254      BrowserContext::GetDownloadManager(GetBrowserContext());
2255  if (!dlm)
2256    return;
2257  int64 post_id = -1;
2258  if (is_main_frame) {
2259    const NavigationEntry* entry = controller_.GetLastCommittedEntry();
2260    if (entry)
2261      post_id = entry->GetPostID();
2262  }
2263  scoped_ptr<DownloadUrlParameters> params(
2264      DownloadUrlParameters::FromWebContents(this, url));
2265  params->set_referrer(referrer);
2266  params->set_post_id(post_id);
2267  params->set_prefer_cache(true);
2268  if (post_id >= 0)
2269    params->set_method("POST");
2270  params->set_prompt(true);
2271  dlm->DownloadUrl(params.Pass());
2272}
2273
2274void WebContentsImpl::GenerateMHTML(
2275    const base::FilePath& file,
2276    const base::Callback<void(int64)>& callback) {
2277  MHTMLGenerationManager::GetInstance()->SaveMHTML(this, file, callback);
2278}
2279
2280const std::string& WebContentsImpl::GetContentsMimeType() const {
2281  return contents_mime_type_;
2282}
2283
2284bool WebContentsImpl::WillNotifyDisconnection() const {
2285  return notify_disconnection_;
2286}
2287
2288void WebContentsImpl::SetOverrideEncoding(const std::string& encoding) {
2289  SetEncoding(encoding);
2290  Send(new ViewMsg_SetPageEncoding(GetRoutingID(), encoding));
2291}
2292
2293void WebContentsImpl::ResetOverrideEncoding() {
2294  canonical_encoding_.clear();
2295  Send(new ViewMsg_ResetPageEncodingToDefault(GetRoutingID()));
2296}
2297
2298RendererPreferences* WebContentsImpl::GetMutableRendererPrefs() {
2299  return &renderer_preferences_;
2300}
2301
2302void WebContentsImpl::Close() {
2303  Close(GetRenderViewHost());
2304}
2305
2306void WebContentsImpl::DragSourceEndedAt(int client_x, int client_y,
2307    int screen_x, int screen_y, blink::WebDragOperation operation) {
2308  if (browser_plugin_embedder_.get())
2309    browser_plugin_embedder_->DragSourceEndedAt(client_x, client_y,
2310        screen_x, screen_y, operation);
2311  if (GetRenderViewHost())
2312    GetRenderViewHostImpl()->DragSourceEndedAt(client_x, client_y,
2313        screen_x, screen_y, operation);
2314}
2315
2316void WebContentsImpl::DidGetResourceResponseStart(
2317  const ResourceRequestDetails& details) {
2318  controller_.ssl_manager()->DidStartResourceResponse(details);
2319
2320  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2321                    DidGetResourceResponseStart(details));
2322
2323  // TODO(avi): Remove. http://crbug.com/170921
2324  NotificationService::current()->Notify(
2325      NOTIFICATION_RESOURCE_RESPONSE_STARTED,
2326      Source<WebContents>(this),
2327      Details<const ResourceRequestDetails>(&details));
2328}
2329
2330void WebContentsImpl::DidGetRedirectForResourceRequest(
2331  RenderViewHost* render_view_host,
2332  const ResourceRedirectDetails& details) {
2333  controller_.ssl_manager()->DidReceiveResourceRedirect(details);
2334
2335  FOR_EACH_OBSERVER(
2336      WebContentsObserver,
2337      observers_,
2338      DidGetRedirectForResourceRequest(render_view_host, details));
2339
2340  // TODO(avi): Remove. http://crbug.com/170921
2341  NotificationService::current()->Notify(
2342      NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
2343      Source<WebContents>(this),
2344      Details<const ResourceRedirectDetails>(&details));
2345}
2346
2347void WebContentsImpl::SystemDragEnded() {
2348  if (GetRenderViewHost())
2349    GetRenderViewHostImpl()->DragSourceSystemDragEnded();
2350  if (delegate_)
2351    delegate_->DragEnded();
2352  if (browser_plugin_embedder_.get())
2353    browser_plugin_embedder_->SystemDragEnded();
2354}
2355
2356void WebContentsImpl::UserGestureDone() {
2357  OnUserGesture();
2358}
2359
2360void WebContentsImpl::SetClosedByUserGesture(bool value) {
2361  closed_by_user_gesture_ = value;
2362}
2363
2364bool WebContentsImpl::GetClosedByUserGesture() const {
2365  return closed_by_user_gesture_;
2366}
2367
2368void WebContentsImpl::ViewSource() {
2369  if (!delegate_)
2370    return;
2371
2372  NavigationEntry* entry = GetController().GetLastCommittedEntry();
2373  if (!entry)
2374    return;
2375
2376  delegate_->ViewSourceForTab(this, entry->GetURL());
2377}
2378
2379void WebContentsImpl::ViewFrameSource(const GURL& url,
2380                                      const PageState& page_state) {
2381  if (!delegate_)
2382    return;
2383
2384  delegate_->ViewSourceForFrame(this, url, page_state);
2385}
2386
2387int WebContentsImpl::GetMinimumZoomPercent() const {
2388  return minimum_zoom_percent_;
2389}
2390
2391int WebContentsImpl::GetMaximumZoomPercent() const {
2392  return maximum_zoom_percent_;
2393}
2394
2395gfx::Size WebContentsImpl::GetPreferredSize() const {
2396  return capturer_count_ == 0 ? preferred_size_ : preferred_size_for_capture_;
2397}
2398
2399bool WebContentsImpl::GotResponseToLockMouseRequest(bool allowed) {
2400  if (GetBrowserPluginGuest())
2401    return GetBrowserPluginGuest()->LockMouse(allowed);
2402
2403  return GetRenderViewHost() ?
2404      GetRenderViewHostImpl()->GotResponseToLockMouseRequest(allowed) : false;
2405}
2406
2407bool WebContentsImpl::HasOpener() const {
2408  return opener_ != NULL;
2409}
2410
2411void WebContentsImpl::DidChooseColorInColorChooser(SkColor color) {
2412  if (!color_chooser_info_.get())
2413    return;
2414  RenderFrameHost* rfh = RenderFrameHost::FromID(
2415      color_chooser_info_->render_process_id,
2416      color_chooser_info_->render_frame_id);
2417  if (!rfh)
2418    return;
2419
2420  rfh->Send(new FrameMsg_DidChooseColorResponse(
2421      rfh->GetRoutingID(), color_chooser_info_->identifier, color));
2422}
2423
2424void WebContentsImpl::DidEndColorChooser() {
2425  if (!color_chooser_info_.get())
2426    return;
2427  RenderFrameHost* rfh = RenderFrameHost::FromID(
2428      color_chooser_info_->render_process_id,
2429      color_chooser_info_->render_frame_id);
2430  if (!rfh)
2431    return;
2432
2433  rfh->Send(new FrameMsg_DidEndColorChooser(
2434      rfh->GetRoutingID(), color_chooser_info_->identifier));
2435  color_chooser_info_.reset();
2436}
2437
2438int WebContentsImpl::DownloadImage(const GURL& url,
2439                                   bool is_favicon,
2440                                   uint32_t max_bitmap_size,
2441                                   const ImageDownloadCallback& callback) {
2442  int id = StartDownload(GetMainFrame(), url, is_favicon, max_bitmap_size);
2443  image_download_map_[id] = callback;
2444  return id;
2445}
2446
2447bool WebContentsImpl::IsSubframe() const {
2448  return is_subframe_;
2449}
2450
2451void WebContentsImpl::Find(int request_id,
2452                           const base::string16& search_text,
2453                           const blink::WebFindOptions& options) {
2454  Send(new ViewMsg_Find(GetRoutingID(), request_id, search_text, options));
2455}
2456
2457void WebContentsImpl::StopFinding(StopFindAction action) {
2458  Send(new ViewMsg_StopFinding(GetRoutingID(), action));
2459}
2460
2461void WebContentsImpl::InsertCSS(const std::string& css) {
2462  GetMainFrame()->Send(new FrameMsg_CSSInsertRequest(
2463      GetMainFrame()->GetRoutingID(), css));
2464}
2465
2466bool WebContentsImpl::WasRecentlyAudible() {
2467  return audio_stream_monitor_.WasRecentlyAudible();
2468}
2469
2470void WebContentsImpl::GetManifest(const GetManifestCallback& callback) {
2471  manifest_manager_host_->GetManifest(GetMainFrame(), callback);
2472}
2473
2474bool WebContentsImpl::FocusLocationBarByDefault() {
2475  NavigationEntry* entry = controller_.GetVisibleEntry();
2476  if (entry && entry->GetURL() == GURL(url::kAboutBlankURL))
2477    return true;
2478  return delegate_ && delegate_->ShouldFocusLocationBarByDefault(this);
2479}
2480
2481void WebContentsImpl::SetFocusToLocationBar(bool select_all) {
2482  if (delegate_)
2483    delegate_->SetFocusToLocationBar(select_all);
2484}
2485
2486void WebContentsImpl::DidStartProvisionalLoad(
2487    RenderFrameHostImpl* render_frame_host,
2488    const GURL& validated_url,
2489    bool is_error_page,
2490    bool is_iframe_srcdoc) {
2491  // Notify observers about the start of the provisional load.
2492  FOR_EACH_OBSERVER(
2493      WebContentsObserver,
2494      observers_,
2495      DidStartProvisionalLoadForFrame(
2496          render_frame_host, validated_url, is_error_page, is_iframe_srcdoc));
2497}
2498
2499void WebContentsImpl::DidStartNavigationTransition(
2500    RenderFrameHostImpl* render_frame_host) {
2501#if defined(OS_ANDROID)
2502  int render_frame_id = render_frame_host->GetRoutingID();
2503  GetWebContentsAndroid()->DidStartNavigationTransitionForFrame(
2504      render_frame_id);
2505#endif
2506}
2507
2508void WebContentsImpl::DidFailProvisionalLoadWithError(
2509    RenderFrameHostImpl* render_frame_host,
2510    const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params) {
2511  GURL validated_url(params.url);
2512  FOR_EACH_OBSERVER(WebContentsObserver,
2513                    observers_,
2514                    DidFailProvisionalLoad(render_frame_host,
2515                                           validated_url,
2516                                           params.error_code,
2517                                           params.error_description));
2518}
2519
2520void WebContentsImpl::DidFailLoadWithError(
2521    RenderFrameHostImpl* render_frame_host,
2522    const GURL& url,
2523    int error_code,
2524    const base::string16& error_description) {
2525  FOR_EACH_OBSERVER(
2526      WebContentsObserver,
2527      observers_,
2528      DidFailLoad(render_frame_host, url, error_code, error_description));
2529}
2530
2531void WebContentsImpl::NotifyChangedNavigationState(
2532    InvalidateTypes changed_flags) {
2533  NotifyNavigationStateChanged(changed_flags);
2534}
2535
2536void WebContentsImpl::AboutToNavigateRenderFrame(
2537      RenderFrameHostImpl* render_frame_host) {
2538  // Notify observers that we will navigate in this RenderView.
2539  RenderViewHost* render_view_host = render_frame_host->render_view_host();
2540  FOR_EACH_OBSERVER(
2541      WebContentsObserver,
2542      observers_,
2543      AboutToNavigateRenderView(render_view_host));
2544}
2545
2546void WebContentsImpl::DidStartNavigationToPendingEntry(
2547      RenderFrameHostImpl* render_frame_host,
2548      const GURL& url,
2549      NavigationController::ReloadType reload_type) {
2550  // Notify observers about navigation.
2551  FOR_EACH_OBSERVER(
2552      WebContentsObserver,
2553      observers_,
2554      DidStartNavigationToPendingEntry(url, reload_type));
2555}
2556
2557void WebContentsImpl::RequestOpenURL(RenderFrameHostImpl* render_frame_host,
2558                                     const OpenURLParams& params) {
2559  int source_render_frame_id = render_frame_host->GetRoutingID();
2560  WebContents* new_contents = OpenURL(params);
2561
2562  if (new_contents) {
2563    // Notify observers.
2564    FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2565                      DidOpenRequestedURL(new_contents,
2566                                          params.url,
2567                                          params.referrer,
2568                                          params.disposition,
2569                                          params.transition,
2570                                          source_render_frame_id));
2571  }
2572}
2573
2574bool WebContentsImpl::ShouldPreserveAbortedURLs() {
2575  if (!delegate_)
2576    return false;
2577  return delegate_->ShouldPreserveAbortedURLs(this);
2578}
2579
2580void WebContentsImpl::DidCommitProvisionalLoad(
2581    RenderFrameHostImpl* render_frame_host,
2582    const GURL& url,
2583    ui::PageTransition transition_type) {
2584  // Notify observers about the commit of the provisional load.
2585  FOR_EACH_OBSERVER(WebContentsObserver,
2586                    observers_,
2587                    DidCommitProvisionalLoadForFrame(
2588                        render_frame_host, url, transition_type));
2589}
2590
2591void WebContentsImpl::DidNavigateMainFramePreCommit(
2592    bool navigation_is_within_page) {
2593  // Ensure fullscreen mode is exited before committing the navigation to a
2594  // different page.  The next page will not start out assuming it is in
2595  // fullscreen mode.
2596  if (navigation_is_within_page) {
2597    // No page change?  Then, the renderer and browser can remain in fullscreen.
2598    return;
2599  }
2600  if (IsFullscreenForCurrentTab())
2601    GetRenderViewHost()->ExitFullscreen();
2602  DCHECK(!IsFullscreenForCurrentTab());
2603}
2604
2605void WebContentsImpl::DidNavigateMainFramePostCommit(
2606    const LoadCommittedDetails& details,
2607    const FrameHostMsg_DidCommitProvisionalLoad_Params& params) {
2608  if (details.is_navigation_to_different_page()) {
2609    // Clear the status bubble. This is a workaround for a bug where WebKit
2610    // doesn't let us know that the cursor left an element during a
2611    // transition (this is also why the mouse cursor remains as a hand after
2612    // clicking on a link); see bugs 1184641 and 980803. We don't want to
2613    // clear the bubble when a user navigates to a named anchor in the same
2614    // page.
2615    UpdateTargetURL(GURL());
2616  }
2617
2618  if (!details.is_in_page) {
2619    // Once the main frame is navigated, we're no longer considered to have
2620    // displayed insecure content.
2621    displayed_insecure_content_ = false;
2622    SSLManager::NotifySSLInternalStateChanged(
2623        GetController().GetBrowserContext());
2624  }
2625
2626  // Notify observers about navigation.
2627  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2628                    DidNavigateMainFrame(details, params));
2629
2630  if (delegate_)
2631    delegate_->DidNavigateMainFramePostCommit(this);
2632  view_->SetOverscrollControllerEnabled(CanOverscrollContent());
2633}
2634
2635void WebContentsImpl::DidNavigateAnyFramePostCommit(
2636    RenderFrameHostImpl* render_frame_host,
2637    const LoadCommittedDetails& details,
2638    const FrameHostMsg_DidCommitProvisionalLoad_Params& params) {
2639  // Now that something has committed, we don't need to track whether the
2640  // initial page has been accessed.
2641  has_accessed_initial_document_ = false;
2642
2643  // If we navigate off the page, close all JavaScript dialogs.
2644  if (dialog_manager_ && !details.is_in_page)
2645    dialog_manager_->CancelActiveAndPendingDialogs(this);
2646
2647  // Notify observers about navigation.
2648  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2649                    DidNavigateAnyFrame(details, params));
2650}
2651
2652void WebContentsImpl::SetMainFrameMimeType(const std::string& mime_type) {
2653  contents_mime_type_ = mime_type;
2654}
2655
2656bool WebContentsImpl::CanOverscrollContent() const {
2657  // Disable overscroll when touch emulation is on. See crbug.com/369938.
2658  if (force_disable_overscroll_content_)
2659    return false;
2660
2661  if (delegate_)
2662    return delegate_->CanOverscrollContent();
2663
2664  return false;
2665}
2666
2667void WebContentsImpl::OnThemeColorChanged(SkColor theme_color) {
2668  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2669                    DidChangeThemeColor(theme_color));
2670}
2671
2672void WebContentsImpl::OnDidLoadResourceFromMemoryCache(
2673    const GURL& url,
2674    const std::string& security_info,
2675    const std::string& http_method,
2676    const std::string& mime_type,
2677    ResourceType resource_type) {
2678  base::StatsCounter cache("WebKit.CacheHit");
2679  cache.Increment();
2680
2681  // Send out a notification that we loaded a resource from our memory cache.
2682  int cert_id = 0;
2683  net::CertStatus cert_status = 0;
2684  int security_bits = -1;
2685  int connection_status = 0;
2686  SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids;
2687  DeserializeSecurityInfo(security_info, &cert_id, &cert_status,
2688                          &security_bits, &connection_status,
2689                          &signed_certificate_timestamp_ids);
2690  // TODO(alcutter,eranm): Pass signed_certificate_timestamp_ids into details
2691  LoadFromMemoryCacheDetails details(
2692      url, GetRenderProcessHost()->GetID(), cert_id, cert_status, http_method,
2693      mime_type, resource_type);
2694
2695  controller_.ssl_manager()->DidLoadFromMemoryCache(details);
2696
2697  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2698                    DidLoadResourceFromMemoryCache(details));
2699
2700  if (url.is_valid() && url.SchemeIsHTTPOrHTTPS()) {
2701    scoped_refptr<net::URLRequestContextGetter> request_context(
2702        resource_type == RESOURCE_TYPE_MEDIA ?
2703            GetBrowserContext()->GetMediaRequestContextForRenderProcess(
2704                GetRenderProcessHost()->GetID()) :
2705            GetBrowserContext()->GetRequestContextForRenderProcess(
2706                GetRenderProcessHost()->GetID()));
2707    BrowserThread::PostTask(
2708        BrowserThread::IO,
2709        FROM_HERE,
2710        base::Bind(&NotifyCacheOnIO, request_context, url, http_method));
2711  }
2712}
2713
2714void WebContentsImpl::OnDidDisplayInsecureContent() {
2715  RecordAction(base::UserMetricsAction("SSL.DisplayedInsecureContent"));
2716  displayed_insecure_content_ = true;
2717  SSLManager::NotifySSLInternalStateChanged(
2718      GetController().GetBrowserContext());
2719}
2720
2721void WebContentsImpl::OnDidRunInsecureContent(
2722    const std::string& security_origin, const GURL& target_url) {
2723  LOG(WARNING) << security_origin << " ran insecure content from "
2724               << target_url.possibly_invalid_spec();
2725  RecordAction(base::UserMetricsAction("SSL.RanInsecureContent"));
2726  if (EndsWith(security_origin, kDotGoogleDotCom, false))
2727    RecordAction(base::UserMetricsAction("SSL.RanInsecureContentGoogle"));
2728  controller_.ssl_manager()->DidRunInsecureContent(security_origin);
2729  displayed_insecure_content_ = true;
2730  SSLManager::NotifySSLInternalStateChanged(
2731      GetController().GetBrowserContext());
2732}
2733
2734void WebContentsImpl::OnDocumentLoadedInFrame() {
2735  CHECK(render_frame_message_source_);
2736  CHECK(!render_view_message_source_);
2737  RenderFrameHostImpl* rfh =
2738      static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
2739  FOR_EACH_OBSERVER(
2740      WebContentsObserver, observers_, DocumentLoadedInFrame(rfh));
2741}
2742
2743void WebContentsImpl::OnDidFinishLoad(
2744    const GURL& url) {
2745  if (!render_frame_message_source_) {
2746    RecordAction(base::UserMetricsAction("BadMessageTerminate_RVD2"));
2747    GetRenderProcessHost()->ReceivedBadMessage();
2748    return;
2749  }
2750
2751  GURL validated_url(url);
2752  RenderProcessHost* render_process_host =
2753      render_frame_message_source_->GetProcess();
2754  render_process_host->FilterURL(false, &validated_url);
2755
2756  RenderFrameHostImpl* rfh =
2757      static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
2758  FOR_EACH_OBSERVER(
2759      WebContentsObserver, observers_, DidFinishLoad(rfh, validated_url));
2760}
2761
2762void WebContentsImpl::OnDidStartLoading(bool to_different_document) {
2763  RenderFrameHostImpl* rfh =
2764      static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
2765  int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id();
2766
2767  // It is possible to get multiple calls to OnDidStartLoading that don't have
2768  // corresponding calls to OnDidStopLoading:
2769  // - With "swappedout://" URLs, this happens when a RenderView gets swapped
2770  //   out for a cross-process navigation, and it turns into a placeholder for
2771  //   one being rendered in a different process.
2772  // - Also, there might be more than one RenderFrameHost sharing the same
2773  //   FrameTreeNode (and thus sharing its ID) each sending a start.
2774  // - But in the future, once clamy@ moves navigation network requests to the
2775  //   browser process, there's a good chance that callbacks about starting and
2776  //   stopping will all be handled by the browser. When that happens, there
2777  //   should no longer be a start/stop call imbalance. TODO(avi): When this
2778  //   future arrives, update this code to not allow this case.
2779  DCHECK_GE(loading_frames_in_progress_, 0);
2780  if (loading_progresses_.find(render_frame_id) == loading_progresses_.end()) {
2781    if (loading_frames_in_progress_ == 0)
2782      DidStartLoading(rfh, to_different_document);
2783    ++loading_frames_in_progress_;
2784  }
2785
2786  loading_progresses_[render_frame_id] = kMinimumLoadingProgress;
2787  SendLoadProgressChanged();
2788}
2789
2790void WebContentsImpl::OnDidStopLoading() {
2791  RenderFrameHostImpl* rfh =
2792      static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
2793  int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id();
2794
2795  if (loading_progresses_.find(render_frame_id) != loading_progresses_.end()) {
2796    // Load stopped while we were still tracking load.  Make sure we update
2797    // progress based on this frame's completion.
2798    loading_progresses_[render_frame_id] = 1.0;
2799    SendLoadProgressChanged();
2800    // Then we clean-up our states.
2801    if (loading_total_progress_ == 1.0)
2802      ResetLoadProgressState();
2803  }
2804
2805  // TODO(japhet): This should be a DCHECK, but the pdf plugin sometimes
2806  // calls DidStopLoading() without a matching DidStartLoading().
2807  if (loading_frames_in_progress_ == 0)
2808    return;
2809  --loading_frames_in_progress_;
2810  if (loading_frames_in_progress_ == 0)
2811    DidStopLoading(rfh);
2812}
2813
2814void WebContentsImpl::OnDidChangeLoadProgress(double load_progress) {
2815  RenderFrameHostImpl* rfh =
2816      static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
2817  int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id();
2818
2819  loading_progresses_[render_frame_id] = load_progress;
2820
2821  // We notify progress change immediately for the first and last updates.
2822  // Also, since the message loop may be pretty busy when a page is loaded, it
2823  // might not execute a posted task in a timely manner so we make sure to
2824  // immediately send progress report if enough time has passed.
2825  base::TimeDelta min_delay =
2826      base::TimeDelta::FromMilliseconds(kMinimumDelayBetweenLoadingUpdatesMS);
2827  if (load_progress == 1.0 || loading_last_progress_update_.is_null() ||
2828      base::TimeTicks::Now() - loading_last_progress_update_ > min_delay) {
2829    // If there is a pending task to send progress, it is now obsolete.
2830    loading_weak_factory_.InvalidateWeakPtrs();
2831    SendLoadProgressChanged();
2832    if (loading_total_progress_ == 1.0)
2833      ResetLoadProgressState();
2834    return;
2835  }
2836
2837  if (loading_weak_factory_.HasWeakPtrs())
2838    return;
2839
2840  base::MessageLoop::current()->PostDelayedTask(
2841      FROM_HERE,
2842      base::Bind(&WebContentsImpl::SendLoadProgressChanged,
2843                 loading_weak_factory_.GetWeakPtr()),
2844      min_delay);
2845}
2846
2847void WebContentsImpl::OnGoToEntryAtOffset(int offset) {
2848  if (!delegate_ || delegate_->OnGoToEntryOffset(offset))
2849    controller_.GoToOffset(offset);
2850}
2851
2852void WebContentsImpl::OnUpdateZoomLimits(int minimum_percent,
2853                                         int maximum_percent) {
2854  minimum_zoom_percent_ = minimum_percent;
2855  maximum_zoom_percent_ = maximum_percent;
2856}
2857
2858void WebContentsImpl::OnEnumerateDirectory(int request_id,
2859                                           const base::FilePath& path) {
2860  if (!delegate_)
2861    return;
2862
2863  ChildProcessSecurityPolicyImpl* policy =
2864      ChildProcessSecurityPolicyImpl::GetInstance();
2865  if (policy->CanReadFile(GetRenderProcessHost()->GetID(), path))
2866    delegate_->EnumerateDirectory(this, request_id, path);
2867}
2868
2869void WebContentsImpl::OnRegisterProtocolHandler(const std::string& protocol,
2870                                                const GURL& url,
2871                                                const base::string16& title,
2872                                                bool user_gesture) {
2873  if (!delegate_)
2874    return;
2875
2876  ChildProcessSecurityPolicyImpl* policy =
2877      ChildProcessSecurityPolicyImpl::GetInstance();
2878  if (policy->IsPseudoScheme(protocol))
2879    return;
2880
2881  delegate_->RegisterProtocolHandler(this, protocol, url, user_gesture);
2882}
2883
2884void WebContentsImpl::OnUnregisterProtocolHandler(const std::string& protocol,
2885                                                  const GURL& url,
2886                                                  bool user_gesture) {
2887  if (!delegate_)
2888    return;
2889
2890  ChildProcessSecurityPolicyImpl* policy =
2891      ChildProcessSecurityPolicyImpl::GetInstance();
2892  if (policy->IsPseudoScheme(protocol))
2893    return;
2894
2895  delegate_->UnregisterProtocolHandler(this, protocol, url, user_gesture);
2896}
2897
2898void WebContentsImpl::OnFindReply(int request_id,
2899                                  int number_of_matches,
2900                                  const gfx::Rect& selection_rect,
2901                                  int active_match_ordinal,
2902                                  bool final_update) {
2903  if (delegate_) {
2904    delegate_->FindReply(this, request_id, number_of_matches, selection_rect,
2905                         active_match_ordinal, final_update);
2906  }
2907}
2908
2909#if defined(OS_ANDROID)
2910void WebContentsImpl::OnFindMatchRectsReply(
2911    int version,
2912    const std::vector<gfx::RectF>& rects,
2913    const gfx::RectF& active_rect) {
2914  if (delegate_)
2915    delegate_->FindMatchRectsReply(this, version, rects, active_rect);
2916}
2917
2918void WebContentsImpl::OnOpenDateTimeDialog(
2919    const ViewHostMsg_DateTimeDialogValue_Params& value) {
2920  date_time_chooser_->ShowDialog(ContentViewCore::FromWebContents(this),
2921                                 GetRenderViewHost(),
2922                                 value.dialog_type,
2923                                 value.dialog_value,
2924                                 value.minimum,
2925                                 value.maximum,
2926                                 value.step,
2927                                 value.suggestions);
2928}
2929
2930#endif
2931
2932void WebContentsImpl::OnPepperPluginHung(int plugin_child_id,
2933                                         const base::FilePath& path,
2934                                         bool is_hung) {
2935  UMA_HISTOGRAM_COUNTS("Pepper.PluginHung", 1);
2936
2937  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2938                    PluginHungStatusChanged(plugin_child_id, path, is_hung));
2939}
2940
2941void WebContentsImpl::OnPluginCrashed(const base::FilePath& plugin_path,
2942                                      base::ProcessId plugin_pid) {
2943  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2944                    PluginCrashed(plugin_path, plugin_pid));
2945}
2946
2947void WebContentsImpl::OnDomOperationResponse(const std::string& json_string,
2948                                             int automation_id) {
2949  DomOperationNotificationDetails details(json_string, automation_id);
2950  NotificationService::current()->Notify(
2951      NOTIFICATION_DOM_OPERATION_RESPONSE,
2952      Source<WebContents>(this),
2953      Details<DomOperationNotificationDetails>(&details));
2954}
2955
2956void WebContentsImpl::OnAppCacheAccessed(const GURL& manifest_url,
2957                                         bool blocked_by_policy) {
2958  // Notify observers about navigation.
2959  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2960                    AppCacheAccessed(manifest_url, blocked_by_policy));
2961}
2962
2963void WebContentsImpl::OnOpenColorChooser(
2964    int color_chooser_id,
2965    SkColor color,
2966    const std::vector<ColorSuggestion>& suggestions) {
2967  ColorChooser* new_color_chooser = delegate_ ?
2968      delegate_->OpenColorChooser(this, color, suggestions) :
2969      NULL;
2970  if (!new_color_chooser)
2971    return;
2972  if (color_chooser_info_.get())
2973    color_chooser_info_->chooser->End();
2974
2975  color_chooser_info_.reset(new ColorChooserInfo(
2976      render_frame_message_source_->GetProcess()->GetID(),
2977      render_frame_message_source_->GetRoutingID(),
2978      new_color_chooser,
2979      color_chooser_id));
2980}
2981
2982void WebContentsImpl::OnEndColorChooser(int color_chooser_id) {
2983  if (color_chooser_info_ &&
2984      color_chooser_id == color_chooser_info_->identifier)
2985    color_chooser_info_->chooser->End();
2986}
2987
2988void WebContentsImpl::OnSetSelectedColorInColorChooser(int color_chooser_id,
2989                                                       SkColor color) {
2990  if (color_chooser_info_ &&
2991      color_chooser_id == color_chooser_info_->identifier)
2992    color_chooser_info_->chooser->SetSelectedColor(color);
2993}
2994
2995// This exists for render views that don't have a WebUI, but do have WebUI
2996// bindings enabled.
2997void WebContentsImpl::OnWebUISend(const GURL& source_url,
2998                                  const std::string& name,
2999                                  const base::ListValue& args) {
3000  if (delegate_)
3001    delegate_->WebUISend(this, source_url, name, args);
3002}
3003
3004#if defined(ENABLE_PLUGINS)
3005void WebContentsImpl::OnRequestPpapiBrokerPermission(
3006    int routing_id,
3007    const GURL& url,
3008    const base::FilePath& plugin_path) {
3009  if (!delegate_) {
3010    OnPpapiBrokerPermissionResult(routing_id, false);
3011    return;
3012  }
3013
3014  if (!delegate_->RequestPpapiBrokerPermission(
3015      this, url, plugin_path,
3016      base::Bind(&WebContentsImpl::OnPpapiBrokerPermissionResult,
3017                 base::Unretained(this), routing_id))) {
3018    NOTIMPLEMENTED();
3019    OnPpapiBrokerPermissionResult(routing_id, false);
3020  }
3021}
3022
3023void WebContentsImpl::OnPpapiBrokerPermissionResult(int routing_id,
3024                                                    bool result) {
3025  Send(new ViewMsg_PpapiBrokerPermissionResult(routing_id, result));
3026}
3027
3028void WebContentsImpl::OnBrowserPluginMessage(const IPC::Message& message) {
3029  // This creates a BrowserPluginEmbedder, which handles all the BrowserPlugin
3030  // specific messages for this WebContents. This means that any message from
3031  // a BrowserPlugin prior to this will be ignored.
3032  // For more info, see comment above classes BrowserPluginEmbedder and
3033  // BrowserPluginGuest.
3034  CHECK(!browser_plugin_embedder_.get());
3035  browser_plugin_embedder_.reset(BrowserPluginEmbedder::Create(this));
3036  browser_plugin_embedder_->OnMessageReceived(message);
3037}
3038#endif
3039
3040void WebContentsImpl::OnDidDownloadImage(
3041    int id,
3042    int http_status_code,
3043    const GURL& image_url,
3044    const std::vector<SkBitmap>& bitmaps,
3045    const std::vector<gfx::Size>& original_bitmap_sizes) {
3046  if (bitmaps.size() != original_bitmap_sizes.size())
3047    return;
3048
3049  ImageDownloadMap::iterator iter = image_download_map_.find(id);
3050  if (iter == image_download_map_.end()) {
3051    // Currently WebContents notifies us of ANY downloads so that it is
3052    // possible to get here.
3053    return;
3054  }
3055  if (!iter->second.is_null()) {
3056    iter->second.Run(
3057        id, http_status_code, image_url, bitmaps, original_bitmap_sizes);
3058  }
3059  image_download_map_.erase(id);
3060}
3061
3062void WebContentsImpl::OnUpdateFaviconURL(
3063    const std::vector<FaviconURL>& candidates) {
3064  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3065                    DidUpdateFaviconURL(candidates));
3066}
3067
3068void WebContentsImpl::CreateAudioPowerSaveBlocker() {
3069  // ChromeOS has its own way of handling power save blocks for media.
3070#if !defined(OS_CHROMEOS)
3071  DCHECK(!audio_power_save_blocker_);
3072  audio_power_save_blocker_ = PowerSaveBlocker::Create(
3073      PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, "Playing Audio");
3074#endif
3075}
3076
3077void WebContentsImpl::CreateVideoPowerSaveBlocker() {
3078  // ChromeOS has its own way of handling power save blocks for media.
3079#if !defined(OS_CHROMEOS)
3080  DCHECK(!video_power_save_blocker_);
3081  DCHECK(!active_video_players_.empty());
3082  video_power_save_blocker_ = PowerSaveBlocker::Create(
3083      PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, "Playing Video");
3084#if defined(OS_ANDROID)
3085  static_cast<PowerSaveBlockerImpl*>(video_power_save_blocker_.get())
3086      ->InitDisplaySleepBlocker(GetView()->GetNativeView());
3087#endif
3088#endif
3089}
3090
3091void WebContentsImpl::MaybeReleasePowerSaveBlockers() {
3092  // If there are no more audio players and we don't have audio stream
3093  // monitoring, release the audio power save blocker here instead of during
3094  // NotifyNavigationStateChanged().
3095  if (active_audio_players_.empty() &&
3096      !AudioStreamMonitor::monitoring_available()) {
3097    audio_power_save_blocker_.reset();
3098  }
3099
3100  // If there are no more video players, clear the video power save blocker.
3101  if (active_video_players_.empty())
3102    video_power_save_blocker_.reset();
3103}
3104
3105void WebContentsImpl::OnMediaPlayingNotification(int64 player_cookie,
3106                                                 bool has_video,
3107                                                 bool has_audio,
3108                                                 bool is_remote) {
3109  // Ignore the videos playing remotely and don't hold the wake lock for the
3110  // screen.
3111  if (is_remote) return;
3112
3113  if (has_audio) {
3114    AddMediaPlayerEntry(player_cookie, &active_audio_players_);
3115
3116    // If we don't have audio stream monitoring, allocate the audio power save
3117    // blocker here instead of during NotifyNavigationStateChanged().
3118    if (!audio_power_save_blocker_ &&
3119        !AudioStreamMonitor::monitoring_available()) {
3120      CreateAudioPowerSaveBlocker();
3121    }
3122  }
3123
3124  if (has_video) {
3125    AddMediaPlayerEntry(player_cookie, &active_video_players_);
3126
3127    // If we're not hidden and have just created a player, create a blocker.
3128    if (!video_power_save_blocker_ && !IsHidden())
3129      CreateVideoPowerSaveBlocker();
3130  }
3131}
3132
3133void WebContentsImpl::OnMediaPausedNotification(int64 player_cookie) {
3134  RemoveMediaPlayerEntry(player_cookie, &active_audio_players_);
3135  RemoveMediaPlayerEntry(player_cookie, &active_video_players_);
3136  MaybeReleasePowerSaveBlockers();
3137}
3138
3139void WebContentsImpl::OnFirstVisuallyNonEmptyPaint() {
3140  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3141                    DidFirstVisuallyNonEmptyPaint());
3142}
3143
3144void WebContentsImpl::DidChangeVisibleSSLState() {
3145  if (delegate_)
3146    delegate_->VisibleSSLStateChanged(this);
3147}
3148
3149void WebContentsImpl::NotifyBeforeFormRepostWarningShow() {
3150  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3151                    BeforeFormRepostWarningShow());
3152}
3153
3154void WebContentsImpl::ActivateAndShowRepostFormWarningDialog() {
3155  Activate();
3156  if (delegate_)
3157    delegate_->ShowRepostFormWarningDialog(this);
3158}
3159
3160bool WebContentsImpl::HasAccessedInitialDocument() {
3161  return has_accessed_initial_document_;
3162}
3163
3164// Notifies the RenderWidgetHost instance about the fact that the page is
3165// loading, or done loading.
3166void WebContentsImpl::SetIsLoading(RenderViewHost* render_view_host,
3167                                   bool is_loading,
3168                                   bool to_different_document,
3169                                   LoadNotificationDetails* details) {
3170  if (is_loading == is_loading_)
3171    return;
3172
3173  if (!is_loading) {
3174    load_state_ = net::LoadStateWithParam(net::LOAD_STATE_IDLE,
3175                                          base::string16());
3176    load_state_host_.clear();
3177    upload_size_ = 0;
3178    upload_position_ = 0;
3179  }
3180
3181  GetRenderManager()->SetIsLoading(is_loading);
3182
3183  is_loading_ = is_loading;
3184  waiting_for_response_ = is_loading;
3185  is_load_to_different_document_ = to_different_document;
3186
3187  if (delegate_)
3188    delegate_->LoadingStateChanged(this, to_different_document);
3189  NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD);
3190
3191  std::string url = (details ? details->url.possibly_invalid_spec() : "NULL");
3192  if (is_loading) {
3193    TRACE_EVENT_ASYNC_BEGIN1("browser,navigation", "WebContentsImpl Loading",
3194                             this, "URL", url);
3195    FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3196                      DidStartLoading(render_view_host));
3197  } else {
3198    TRACE_EVENT_ASYNC_END1("browser,navigation", "WebContentsImpl Loading",
3199                           this, "URL", url);
3200    FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3201                      DidStopLoading(render_view_host));
3202  }
3203
3204  // TODO(avi): Remove. http://crbug.com/170921
3205  int type = is_loading ? NOTIFICATION_LOAD_START : NOTIFICATION_LOAD_STOP;
3206  NotificationDetails det = NotificationService::NoDetails();
3207  if (details)
3208      det = Details<LoadNotificationDetails>(details);
3209  NotificationService::current()->Notify(
3210      type, Source<NavigationController>(&controller_), det);
3211}
3212
3213void WebContentsImpl::SelectRange(const gfx::Point& start,
3214                                  const gfx::Point& end) {
3215  RenderFrameHost* focused_frame = GetFocusedFrame();
3216  if (!focused_frame)
3217    return;
3218
3219  focused_frame->Send(
3220      new InputMsg_SelectRange(focused_frame->GetRoutingID(), start, end));
3221}
3222
3223void WebContentsImpl::UpdateMaxPageIDIfNecessary(RenderViewHost* rvh) {
3224  // If we are creating a RVH for a restored controller, then we need to make
3225  // sure the RenderView starts with a next_page_id_ larger than the number
3226  // of restored entries.  This must be called before the RenderView starts
3227  // navigating (to avoid a race between the browser updating max_page_id and
3228  // the renderer updating next_page_id_).  Because of this, we only call this
3229  // from CreateRenderView and allow that to notify the RenderView for us.
3230  int max_restored_page_id = controller_.GetMaxRestoredPageID();
3231  if (max_restored_page_id >
3232      GetMaxPageIDForSiteInstance(rvh->GetSiteInstance()))
3233    UpdateMaxPageIDForSiteInstance(rvh->GetSiteInstance(),
3234                                   max_restored_page_id);
3235}
3236
3237bool WebContentsImpl::UpdateTitleForEntry(NavigationEntryImpl* entry,
3238                                          const base::string16& title) {
3239  // For file URLs without a title, use the pathname instead. In the case of a
3240  // synthesized title, we don't want the update to count toward the "one set
3241  // per page of the title to history."
3242  base::string16 final_title;
3243  bool explicit_set;
3244  if (entry && entry->GetURL().SchemeIsFile() && title.empty()) {
3245    final_title = base::UTF8ToUTF16(entry->GetURL().ExtractFileName());
3246    explicit_set = false;  // Don't count synthetic titles toward the set limit.
3247  } else {
3248    base::TrimWhitespace(title, base::TRIM_ALL, &final_title);
3249    explicit_set = true;
3250  }
3251
3252  // If a page is created via window.open and never navigated,
3253  // there will be no navigation entry. In this situation,
3254  // |page_title_when_no_navigation_entry_| will be used for page title.
3255  if (entry) {
3256    if (final_title == entry->GetTitle())
3257      return false;  // Nothing changed, don't bother.
3258
3259    entry->SetTitle(final_title);
3260  } else {
3261    if (page_title_when_no_navigation_entry_ == final_title)
3262      return false;  // Nothing changed, don't bother.
3263
3264    page_title_when_no_navigation_entry_ = final_title;
3265  }
3266
3267  // Lastly, set the title for the view.
3268  view_->SetPageTitle(final_title);
3269
3270  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3271                    TitleWasSet(entry, explicit_set));
3272
3273  // TODO(avi): Remove. http://crbug.com/170921
3274  std::pair<NavigationEntry*, bool> details =
3275      std::make_pair(entry, explicit_set);
3276  NotificationService::current()->Notify(
3277      NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
3278      Source<WebContents>(this),
3279      Details<std::pair<NavigationEntry*, bool> >(&details));
3280
3281  return true;
3282}
3283
3284void WebContentsImpl::SendLoadProgressChanged() {
3285  loading_last_progress_update_ = base::TimeTicks::Now();
3286  double progress = 0.0;
3287  int frame_count = 0;
3288
3289  for (LoadingProgressMap::iterator it = loading_progresses_.begin();
3290       it != loading_progresses_.end();
3291       ++it) {
3292    progress += it->second;
3293    ++frame_count;
3294  }
3295  if (frame_count == 0)
3296    return;
3297  progress /= frame_count;
3298  DCHECK(progress <= 1.0);
3299
3300  if (progress <= loading_total_progress_)
3301    return;
3302  loading_total_progress_ = progress;
3303
3304  if (delegate_)
3305    delegate_->LoadProgressChanged(this, progress);
3306}
3307
3308void WebContentsImpl::ResetLoadProgressState() {
3309  loading_progresses_.clear();
3310  loading_total_progress_ = 0.0;
3311  loading_weak_factory_.InvalidateWeakPtrs();
3312  loading_last_progress_update_ = base::TimeTicks();
3313}
3314
3315void WebContentsImpl::NotifyViewSwapped(RenderViewHost* old_host,
3316                                        RenderViewHost* new_host) {
3317  // After sending out a swap notification, we need to send a disconnect
3318  // notification so that clients that pick up a pointer to |this| can NULL the
3319  // pointer.  See Bug 1230284.
3320  notify_disconnection_ = true;
3321  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3322                    RenderViewHostChanged(old_host, new_host));
3323
3324  // TODO(avi): Remove. http://crbug.com/170921
3325  std::pair<RenderViewHost*, RenderViewHost*> details =
3326      std::make_pair(old_host, new_host);
3327  NotificationService::current()->Notify(
3328      NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
3329      Source<WebContents>(this),
3330      Details<std::pair<RenderViewHost*, RenderViewHost*> >(&details));
3331
3332  // Ensure that the associated embedder gets cleared after a RenderViewHost
3333  // gets swapped, so we don't reuse the same embedder next time a
3334  // RenderViewHost is attached to this WebContents.
3335  RemoveBrowserPluginEmbedder();
3336}
3337
3338void WebContentsImpl::NotifyFrameSwapped(RenderFrameHost* old_host,
3339                                         RenderFrameHost* new_host) {
3340  FOR_EACH_OBSERVER(WebContentsObserver,
3341                    observers_,
3342                    RenderFrameHostChanged(old_host, new_host));
3343}
3344
3345// TODO(avi): Remove this entire function because this notification is already
3346// covered by two observer functions. http://crbug.com/170921
3347void WebContentsImpl::NotifyDisconnected() {
3348  if (!notify_disconnection_)
3349    return;
3350
3351  notify_disconnection_ = false;
3352  NotificationService::current()->Notify(
3353      NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
3354      Source<WebContents>(this),
3355      NotificationService::NoDetails());
3356}
3357
3358void WebContentsImpl::NotifyNavigationEntryCommitted(
3359    const LoadCommittedDetails& load_details) {
3360  FOR_EACH_OBSERVER(
3361      WebContentsObserver, observers_, NavigationEntryCommitted(load_details));
3362}
3363
3364bool WebContentsImpl::OnMessageReceived(RenderFrameHost* render_frame_host,
3365                                        const IPC::Message& message) {
3366  return OnMessageReceived(NULL, render_frame_host, message);
3367}
3368
3369const GURL& WebContentsImpl::GetMainFrameLastCommittedURL() const {
3370  return GetLastCommittedURL();
3371}
3372
3373void WebContentsImpl::RenderFrameCreated(RenderFrameHost* render_frame_host) {
3374  // Note this is only for subframes, the notification for the main frame
3375  // happens in RenderViewCreated.
3376  FOR_EACH_OBSERVER(WebContentsObserver,
3377                    observers_,
3378                    RenderFrameCreated(render_frame_host));
3379  SetAccessibilityModeOnFrame(accessibility_mode_, render_frame_host);
3380}
3381
3382void WebContentsImpl::RenderFrameDeleted(RenderFrameHost* render_frame_host) {
3383  ClearPowerSaveBlockers(render_frame_host);
3384  FOR_EACH_OBSERVER(WebContentsObserver,
3385                    observers_,
3386                    RenderFrameDeleted(render_frame_host));
3387}
3388
3389void WebContentsImpl::WorkerCrashed(RenderFrameHost* render_frame_host) {
3390  if (delegate_)
3391    delegate_->WorkerCrashed(this);
3392}
3393
3394void WebContentsImpl::ShowContextMenu(RenderFrameHost* render_frame_host,
3395                                      const ContextMenuParams& params) {
3396  ContextMenuParams context_menu_params(params);
3397  // Allow WebContentsDelegates to handle the context menu operation first.
3398  if (GetBrowserPluginGuest()) {
3399    WebContentsViewGuest* view_guest =
3400        static_cast<WebContentsViewGuest*>(GetView());
3401    context_menu_params = view_guest->ConvertContextMenuParams(params);
3402  }
3403  if (delegate_ && delegate_->HandleContextMenu(context_menu_params))
3404    return;
3405
3406  render_view_host_delegate_view_->ShowContextMenu(render_frame_host,
3407                                                   context_menu_params);
3408}
3409
3410void WebContentsImpl::RunJavaScriptMessage(
3411    RenderFrameHost* render_frame_host,
3412    const base::string16& message,
3413    const base::string16& default_prompt,
3414    const GURL& frame_url,
3415    JavaScriptMessageType javascript_message_type,
3416    IPC::Message* reply_msg) {
3417  // Suppress JavaScript dialogs when requested. Also suppress messages when
3418  // showing an interstitial as it's shown over the previous page and we don't
3419  // want the hidden page's dialogs to interfere with the interstitial.
3420  bool suppress_this_message =
3421      static_cast<RenderViewHostImpl*>(render_frame_host->GetRenderViewHost())->
3422          IsSwappedOut() ||
3423      ShowingInterstitialPage() ||
3424      !delegate_ ||
3425      delegate_->ShouldSuppressDialogs() ||
3426      !delegate_->GetJavaScriptDialogManager();
3427
3428  if (!suppress_this_message) {
3429    std::string accept_lang = GetContentClient()->browser()->
3430      GetAcceptLangs(GetBrowserContext());
3431    dialog_manager_ = delegate_->GetJavaScriptDialogManager();
3432    dialog_manager_->RunJavaScriptDialog(
3433        this,
3434        frame_url.GetOrigin(),
3435        accept_lang,
3436        javascript_message_type,
3437        message,
3438        default_prompt,
3439        base::Bind(&WebContentsImpl::OnDialogClosed,
3440                   base::Unretained(this),
3441                   render_frame_host->GetProcess()->GetID(),
3442                   render_frame_host->GetRoutingID(),
3443                   reply_msg,
3444                   false),
3445        &suppress_this_message);
3446  }
3447
3448  if (suppress_this_message) {
3449    // If we are suppressing messages, just reply as if the user immediately
3450    // pressed "Cancel", passing true to |dialog_was_suppressed|.
3451    OnDialogClosed(render_frame_host->GetProcess()->GetID(),
3452                   render_frame_host->GetRoutingID(), reply_msg,
3453                   true, false, base::string16());
3454  }
3455
3456  // OnDialogClosed (two lines up) may have caused deletion of this object (see
3457  // http://crbug.com/288961 ). The only safe thing to do here is return.
3458}
3459
3460void WebContentsImpl::RunBeforeUnloadConfirm(
3461    RenderFrameHost* render_frame_host,
3462    const base::string16& message,
3463    bool is_reload,
3464    IPC::Message* reply_msg) {
3465  RenderFrameHostImpl* rfhi =
3466      static_cast<RenderFrameHostImpl*>(render_frame_host);
3467  RenderViewHostImpl* rvhi =
3468      static_cast<RenderViewHostImpl*>(render_frame_host->GetRenderViewHost());
3469  if (delegate_)
3470    delegate_->WillRunBeforeUnloadConfirm();
3471
3472  bool suppress_this_message =
3473      rvhi->rvh_state() != RenderViewHostImpl::STATE_DEFAULT ||
3474      !delegate_ ||
3475      delegate_->ShouldSuppressDialogs() ||
3476      !delegate_->GetJavaScriptDialogManager();
3477  if (suppress_this_message) {
3478    rfhi->JavaScriptDialogClosed(reply_msg, true, base::string16(), true);
3479    return;
3480  }
3481
3482  is_showing_before_unload_dialog_ = true;
3483  dialog_manager_ = delegate_->GetJavaScriptDialogManager();
3484  dialog_manager_->RunBeforeUnloadDialog(
3485      this, message, is_reload,
3486      base::Bind(&WebContentsImpl::OnDialogClosed, base::Unretained(this),
3487                 render_frame_host->GetProcess()->GetID(),
3488                 render_frame_host->GetRoutingID(), reply_msg,
3489                 false));
3490}
3491
3492WebContents* WebContentsImpl::GetAsWebContents() {
3493  return this;
3494}
3495
3496bool WebContentsImpl::IsNeverVisible() {
3497  if (!delegate_)
3498    return false;
3499  return delegate_->IsNeverVisible(this);
3500}
3501
3502#if defined(OS_WIN)
3503gfx::NativeViewAccessible WebContentsImpl::GetParentNativeViewAccessible() {
3504  return accessible_parent_;
3505}
3506#endif
3507
3508RenderViewHostDelegateView* WebContentsImpl::GetDelegateView() {
3509  return render_view_host_delegate_view_;
3510}
3511
3512RendererPreferences WebContentsImpl::GetRendererPrefs(
3513    BrowserContext* browser_context) const {
3514  return renderer_preferences_;
3515}
3516
3517gfx::Rect WebContentsImpl::GetRootWindowResizerRect() const {
3518  if (delegate_)
3519    return delegate_->GetRootWindowResizerRect();
3520  return gfx::Rect();
3521}
3522
3523void WebContentsImpl::RemoveBrowserPluginEmbedder() {
3524  if (browser_plugin_embedder_)
3525    browser_plugin_embedder_.reset();
3526}
3527
3528void WebContentsImpl::RenderViewCreated(RenderViewHost* render_view_host) {
3529  // Don't send notifications if we are just creating a swapped-out RVH for
3530  // the opener chain.  These won't be used for view-source or WebUI, so it's
3531  // ok to return early.
3532  if (static_cast<RenderViewHostImpl*>(render_view_host)->IsSwappedOut())
3533    return;
3534
3535  if (delegate_)
3536    view_->SetOverscrollControllerEnabled(CanOverscrollContent());
3537
3538  NotificationService::current()->Notify(
3539      NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED,
3540      Source<WebContents>(this),
3541      Details<RenderViewHost>(render_view_host));
3542
3543  // When we're creating views, we're still doing initial setup, so we always
3544  // use the pending Web UI rather than any possibly existing committed one.
3545  if (GetRenderManager()->pending_web_ui())
3546    GetRenderManager()->pending_web_ui()->RenderViewCreated(render_view_host);
3547
3548  NavigationEntry* entry = controller_.GetPendingEntry();
3549  if (entry && entry->IsViewSourceMode()) {
3550    // Put the renderer in view source mode.
3551    render_view_host->Send(
3552        new ViewMsg_EnableViewSourceMode(render_view_host->GetRoutingID()));
3553  }
3554
3555  view_->RenderViewCreated(render_view_host);
3556
3557  FOR_EACH_OBSERVER(
3558      WebContentsObserver, observers_, RenderViewCreated(render_view_host));
3559
3560  // We tell the observers now instead of when the main RenderFrameHostImpl is
3561  // constructed because otherwise it would be too early (i.e. IPCs sent to the
3562  // frame would be dropped because it's not created yet).
3563  RenderFrameHost* main_frame = render_view_host->GetMainFrame();
3564  FOR_EACH_OBSERVER(
3565      WebContentsObserver, observers_, RenderFrameCreated(main_frame));
3566  SetAccessibilityModeOnFrame(accessibility_mode_, main_frame);
3567}
3568
3569void WebContentsImpl::RenderViewReady(RenderViewHost* rvh) {
3570  if (rvh != GetRenderViewHost()) {
3571    // Don't notify the world, since this came from a renderer in the
3572    // background.
3573    return;
3574  }
3575
3576  notify_disconnection_ = true;
3577  // TODO(avi): Remove. http://crbug.com/170921
3578  NotificationService::current()->Notify(
3579      NOTIFICATION_WEB_CONTENTS_CONNECTED,
3580      Source<WebContents>(this),
3581      NotificationService::NoDetails());
3582
3583  bool was_crashed = IsCrashed();
3584  SetIsCrashed(base::TERMINATION_STATUS_STILL_RUNNING, 0);
3585
3586  // Restore the focus to the tab (otherwise the focus will be on the top
3587  // window).
3588  if (was_crashed && !FocusLocationBarByDefault() &&
3589      (!delegate_ || delegate_->ShouldFocusPageAfterCrash())) {
3590    view_->Focus();
3591  }
3592
3593  FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewReady());
3594}
3595
3596void WebContentsImpl::RenderViewTerminated(RenderViewHost* rvh,
3597                                           base::TerminationStatus status,
3598                                           int error_code) {
3599  if (rvh != GetRenderViewHost()) {
3600    // The pending page's RenderViewHost is gone.
3601    return;
3602  }
3603
3604  // Ensure fullscreen mode is exited in the |delegate_| since a crashed
3605  // renderer may not have made a clean exit.
3606  if (IsFullscreenForCurrentTab())
3607    ToggleFullscreenMode(false);
3608
3609  // Cancel any visible dialogs so they are not left dangling over the sad tab.
3610  if (dialog_manager_)
3611    dialog_manager_->CancelActiveAndPendingDialogs(this);
3612
3613  if (delegate_)
3614    delegate_->HideValidationMessage(this);
3615
3616  SetIsLoading(rvh, false, true, NULL);
3617  NotifyDisconnected();
3618  SetIsCrashed(status, error_code);
3619
3620  // Reset the loading progress. TODO(avi): What does it mean to have a
3621  // "renderer crash" when there is more than one renderer process serving a
3622  // webpage? Once this function is called at a more granular frame level, we
3623  // probably will need to more granularly reset the state here.
3624  ResetLoadProgressState();
3625  loading_frames_in_progress_ = 0;
3626
3627  FOR_EACH_OBSERVER(WebContentsObserver,
3628                    observers_,
3629                    RenderProcessGone(GetCrashedStatus()));
3630}
3631
3632void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) {
3633  FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewDeleted(rvh));
3634}
3635
3636void WebContentsImpl::UpdateState(RenderViewHost* rvh,
3637                                  int32 page_id,
3638                                  const PageState& page_state) {
3639  // Ensure that this state update comes from either the active RVH or one of
3640  // the swapped out RVHs.  We don't expect to hear from any other RVHs.
3641  // TODO(nasko): This should go through RenderFrameHost.
3642  // TODO(creis): We can't update state for cross-process subframes until we
3643  // have FrameNavigationEntries.  Once we do, this should be a DCHECK.
3644  if (rvh != GetRenderViewHost() &&
3645      !GetRenderManager()->IsRVHOnSwappedOutList(
3646          static_cast<RenderViewHostImpl*>(rvh)))
3647    return;
3648
3649  // We must be prepared to handle state updates for any page, these occur
3650  // when the user is scrolling and entering form data, as well as when we're
3651  // leaving a page, in which case our state may have already been moved to
3652  // the next page. The navigation controller will look up the appropriate
3653  // NavigationEntry and update it when it is notified via the delegate.
3654
3655  int entry_index = controller_.GetEntryIndexWithPageID(
3656      rvh->GetSiteInstance(), page_id);
3657  if (entry_index < 0)
3658    return;
3659  NavigationEntry* entry = controller_.GetEntryAtIndex(entry_index);
3660
3661  if (page_state == entry->GetPageState())
3662    return;  // Nothing to update.
3663  entry->SetPageState(page_state);
3664  controller_.NotifyEntryChanged(entry, entry_index);
3665}
3666
3667void WebContentsImpl::UpdateTargetURL(const GURL& url) {
3668  if (delegate_)
3669    delegate_->UpdateTargetURL(this, url);
3670}
3671
3672void WebContentsImpl::Close(RenderViewHost* rvh) {
3673#if defined(OS_MACOSX)
3674  // The UI may be in an event-tracking loop, such as between the
3675  // mouse-down and mouse-up in text selection or a button click.
3676  // Defer the close until after tracking is complete, so that we
3677  // don't free objects out from under the UI.
3678  // TODO(shess): This could get more fine-grained.  For instance,
3679  // closing a tab in another window while selecting text in the
3680  // current window's Omnibox should be just fine.
3681  if (view_->IsEventTracking()) {
3682    view_->CloseTabAfterEventTracking();
3683    return;
3684  }
3685#endif
3686
3687  // Ignore this if it comes from a RenderViewHost that we aren't showing.
3688  if (delegate_ && rvh == GetRenderViewHost())
3689    delegate_->CloseContents(this);
3690}
3691
3692void WebContentsImpl::SwappedOut(RenderFrameHost* rfh) {
3693  if (delegate_ && rfh->GetRenderViewHost() == GetRenderViewHost())
3694    delegate_->SwappedOut(this);
3695}
3696
3697void WebContentsImpl::DidDeferAfterResponseStarted(
3698    const TransitionLayerData& transition_data) {
3699#if defined(OS_ANDROID)
3700  GetWebContentsAndroid()->DidDeferAfterResponseStarted(transition_data);
3701#endif
3702}
3703
3704bool WebContentsImpl::WillHandleDeferAfterResponseStarted() {
3705#if defined(OS_ANDROID)
3706  return GetWebContentsAndroid()->WillHandleDeferAfterResponseStarted();
3707#else
3708  return false;
3709#endif
3710}
3711
3712void WebContentsImpl::RequestMove(const gfx::Rect& new_bounds) {
3713  if (delegate_ && delegate_->IsPopupOrPanel(this))
3714    delegate_->MoveContents(this, new_bounds);
3715}
3716
3717void WebContentsImpl::DidStartLoading(RenderFrameHost* render_frame_host,
3718                                      bool to_different_document) {
3719  SetIsLoading(render_frame_host->GetRenderViewHost(), true,
3720               to_different_document, NULL);
3721}
3722
3723void WebContentsImpl::DidStopLoading(RenderFrameHost* render_frame_host) {
3724  scoped_ptr<LoadNotificationDetails> details;
3725
3726  // Use the last committed entry rather than the active one, in case a
3727  // pending entry has been created.
3728  NavigationEntry* entry = controller_.GetLastCommittedEntry();
3729  Navigator* navigator = frame_tree_.root()->navigator();
3730
3731  // An entry may not exist for a stop when loading an initial blank page or
3732  // if an iframe injected by script into a blank page finishes loading.
3733  if (entry) {
3734    base::TimeDelta elapsed =
3735        base::TimeTicks::Now() - navigator->GetCurrentLoadStart();
3736
3737    details.reset(new LoadNotificationDetails(
3738        entry->GetVirtualURL(),
3739        entry->GetTransitionType(),
3740        elapsed,
3741        &controller_,
3742        controller_.GetCurrentEntryIndex()));
3743  }
3744
3745  SetIsLoading(render_frame_host->GetRenderViewHost(), false, true,
3746               details.get());
3747}
3748
3749void WebContentsImpl::DidCancelLoading() {
3750  controller_.DiscardNonCommittedEntries();
3751
3752  // Update the URL display.
3753  NotifyNavigationStateChanged(INVALIDATE_TYPE_URL);
3754}
3755
3756void WebContentsImpl::DidAccessInitialDocument() {
3757  has_accessed_initial_document_ = true;
3758
3759  // We may have left a failed browser-initiated navigation in the address bar
3760  // to let the user edit it and try again.  Clear it now that content might
3761  // show up underneath it.
3762  if (!IsLoading() && controller_.GetPendingEntry())
3763    controller_.DiscardPendingEntry();
3764
3765  // Update the URL display.
3766  NotifyNavigationStateChanged(INVALIDATE_TYPE_URL);
3767}
3768
3769void WebContentsImpl::DidDisownOpener(RenderFrameHost* render_frame_host) {
3770  // No action is necessary if the opener has already been cleared.
3771  if (!opener_)
3772    return;
3773
3774  // Clear our opener so that future cross-process navigations don't have an
3775  // opener assigned.
3776  RemoveDestructionObserver(opener_);
3777  opener_ = NULL;
3778
3779  // Notify all swapped out RenderViewHosts for this tab.  This is important
3780  // in case we go back to them, or if another window in those processes tries
3781  // to access window.opener.
3782  GetRenderManager()->DidDisownOpener(render_frame_host);
3783}
3784
3785void WebContentsImpl::DocumentOnLoadCompleted(
3786    RenderFrameHost* render_frame_host) {
3787  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3788                    DocumentOnLoadCompletedInMainFrame());
3789
3790  // TODO(avi): Remove. http://crbug.com/170921
3791  NotificationService::current()->Notify(
3792      NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
3793      Source<WebContents>(this),
3794      NotificationService::NoDetails());
3795}
3796
3797void WebContentsImpl::UpdateTitle(RenderFrameHost* render_frame_host,
3798                                  int32 page_id,
3799                                  const base::string16& title,
3800                                  base::i18n::TextDirection title_direction) {
3801  RenderViewHost* rvh = render_frame_host->GetRenderViewHost();
3802
3803  // If we have a title, that's a pretty good indication that we've started
3804  // getting useful data.
3805  SetNotWaitingForResponse();
3806
3807  // Try to find the navigation entry, which might not be the current one.
3808  // For example, it might be from a pending RVH for the pending entry.
3809  NavigationEntryImpl* entry = controller_.GetEntryWithPageID(
3810      rvh->GetSiteInstance(), page_id);
3811
3812  // We can handle title updates when we don't have an entry in
3813  // UpdateTitleForEntry, but only if the update is from the current RVH.
3814  // TODO(avi): Change to make decisions based on the RenderFrameHost.
3815  if (!entry && rvh != GetRenderViewHost())
3816    return;
3817
3818  // TODO(evan): make use of title_direction.
3819  // http://code.google.com/p/chromium/issues/detail?id=27094
3820  if (!UpdateTitleForEntry(entry, title))
3821    return;
3822
3823  // Broadcast notifications when the UI should be updated.
3824  if (entry == controller_.GetEntryAtOffset(0))
3825    NotifyNavigationStateChanged(INVALIDATE_TYPE_TITLE);
3826}
3827
3828void WebContentsImpl::UpdateEncoding(RenderFrameHost* render_frame_host,
3829                                     const std::string& encoding) {
3830  SetEncoding(encoding);
3831}
3832
3833void WebContentsImpl::DocumentAvailableInMainFrame(
3834    RenderViewHost* render_view_host) {
3835  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3836                    DocumentAvailableInMainFrame());
3837}
3838void WebContentsImpl::RouteCloseEvent(RenderViewHost* rvh) {
3839  // Tell the active RenderViewHost to run unload handlers and close, as long
3840  // as the request came from a RenderViewHost in the same BrowsingInstance.
3841  // In most cases, we receive this from a swapped out RenderViewHost.
3842  // It is possible to receive it from one that has just been swapped in,
3843  // in which case we might as well deliver the message anyway.
3844  if (rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance()))
3845    GetRenderViewHost()->ClosePage();
3846}
3847
3848void WebContentsImpl::RouteMessageEvent(
3849    RenderViewHost* rvh,
3850    const ViewMsg_PostMessage_Params& params) {
3851  // Only deliver the message to the active RenderViewHost if the request
3852  // came from a RenderViewHost in the same BrowsingInstance or if this
3853  // WebContents is dedicated to a browser plugin guest.
3854  // Note: This check means that an embedder could theoretically receive a
3855  // postMessage from anyone (not just its own guests). However, this is
3856  // probably not a risk for apps since other pages won't have references
3857  // to App windows.
3858  if (!rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance()) &&
3859      !GetBrowserPluginGuest() && !GetBrowserPluginEmbedder())
3860    return;
3861
3862  ViewMsg_PostMessage_Params new_params(params);
3863
3864  if (!params.message_port_ids.empty()) {
3865    MessagePortMessageFilter* message_port_message_filter =
3866        static_cast<RenderProcessHostImpl*>(GetRenderProcessHost())
3867            ->message_port_message_filter();
3868    message_port_message_filter->UpdateMessagePortsWithNewRoutes(
3869        params.message_port_ids,
3870        &new_params.new_routing_ids);
3871  }
3872
3873  // If there is a source_routing_id, translate it to the routing ID for
3874  // the equivalent swapped out RVH in the target process.  If we need
3875  // to create a swapped out RVH for the source tab, we create its opener
3876  // chain as well, since those will also be accessible to the target page.
3877  if (new_params.source_routing_id != MSG_ROUTING_NONE) {
3878    // Try to look up the WebContents for the source page.
3879    WebContentsImpl* source_contents = NULL;
3880    RenderViewHostImpl* source_rvh = RenderViewHostImpl::FromID(
3881        rvh->GetProcess()->GetID(), params.source_routing_id);
3882    if (source_rvh) {
3883      source_contents = static_cast<WebContentsImpl*>(
3884          source_rvh->GetDelegate()->GetAsWebContents());
3885    }
3886
3887    if (source_contents) {
3888      if (GetBrowserPluginGuest()) {
3889        // We create a swapped out RenderView for the embedder in the guest's
3890        // render process but we intentionally do not expose the embedder's
3891        // opener chain to it.
3892        new_params.source_routing_id =
3893            source_contents->CreateSwappedOutRenderView(GetSiteInstance());
3894      } else {
3895        new_params.source_routing_id =
3896            source_contents->CreateOpenerRenderViews(GetSiteInstance());
3897      }
3898    } else {
3899      // We couldn't find it, so don't pass a source frame.
3900      new_params.source_routing_id = MSG_ROUTING_NONE;
3901    }
3902  }
3903
3904  // In most cases, we receive this from a swapped out RenderViewHost.
3905  // It is possible to receive it from one that has just been swapped in,
3906  // in which case we might as well deliver the message anyway.
3907  Send(new ViewMsg_PostMessageEvent(GetRoutingID(), new_params));
3908}
3909
3910bool WebContentsImpl::AddMessageToConsole(int32 level,
3911                                          const base::string16& message,
3912                                          int32 line_no,
3913                                          const base::string16& source_id) {
3914  if (!delegate_)
3915    return false;
3916  return delegate_->AddMessageToConsole(this, level, message, line_no,
3917                                        source_id);
3918}
3919
3920WebPreferences WebContentsImpl::ComputeWebkitPrefs() {
3921  // We want to base the page config off of the actual URL, rather than the
3922  // virtual URL.
3923  // TODO(nasko): Investigate how to remove the GetActiveEntry usage here,
3924  // as it is deprecated and can be out of sync with GetRenderViewHost().
3925  GURL url = controller_.GetActiveEntry()
3926      ? controller_.GetActiveEntry()->GetURL() : GURL::EmptyGURL();
3927
3928  return GetRenderManager()->current_host()->ComputeWebkitPrefs(url);
3929}
3930
3931int WebContentsImpl::CreateSwappedOutRenderView(
3932    SiteInstance* instance) {
3933  return GetRenderManager()->CreateRenderFrame(
3934      instance, MSG_ROUTING_NONE, true, true, true);
3935}
3936
3937void WebContentsImpl::OnUserGesture() {
3938  // Notify observers.
3939  FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetUserGesture());
3940
3941  ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
3942  if (rdh)  // NULL in unittests.
3943    rdh->OnUserGesture(this);
3944}
3945
3946void WebContentsImpl::OnIgnoredUIEvent() {
3947  // Notify observers.
3948  FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetIgnoredUIEvent());
3949}
3950
3951void WebContentsImpl::RendererUnresponsive(RenderViewHost* rvh,
3952                                           bool is_during_beforeunload,
3953                                           bool is_during_unload) {
3954  // Don't show hung renderer dialog for a swapped out RVH.
3955  if (rvh != GetRenderViewHost())
3956    return;
3957
3958  RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(rvh);
3959
3960  // Ignore renderer unresponsive event if debugger is attached to the tab
3961  // since the event may be a result of the renderer sitting on a breakpoint.
3962  // See http://crbug.com/65458
3963  if (DevToolsAgentHost::IsDebuggerAttached(this))
3964    return;
3965
3966  if (is_during_beforeunload || is_during_unload) {
3967    // Hang occurred while firing the beforeunload/unload handler.
3968    // Pretend the handler fired so tab closing continues as if it had.
3969    rvhi->set_sudden_termination_allowed(true);
3970
3971    if (!GetRenderManager()->ShouldCloseTabOnUnresponsiveRenderer())
3972      return;
3973
3974    // If the tab hangs in the beforeunload/unload handler there's really
3975    // nothing we can do to recover. If the hang is in the beforeunload handler,
3976    // pretend the beforeunload listeners have all fired and allow the delegate
3977    // to continue closing; the user will not have the option of cancelling the
3978    // close. Otherwise, pretend the unload listeners have all fired and close
3979    // the tab.
3980    bool close = true;
3981    if (is_during_beforeunload && delegate_) {
3982      delegate_->BeforeUnloadFired(this, true, &close);
3983    }
3984    if (close)
3985      Close(rvh);
3986    return;
3987  }
3988
3989  if (!GetRenderViewHostImpl() || !GetRenderViewHostImpl()->IsRenderViewLive())
3990    return;
3991
3992  if (delegate_)
3993    delegate_->RendererUnresponsive(this);
3994}
3995
3996void WebContentsImpl::RendererResponsive(RenderViewHost* render_view_host) {
3997  if (delegate_)
3998    delegate_->RendererResponsive(this);
3999}
4000
4001void WebContentsImpl::LoadStateChanged(
4002    const GURL& url,
4003    const net::LoadStateWithParam& load_state,
4004    uint64 upload_position,
4005    uint64 upload_size) {
4006  load_state_ = load_state;
4007  upload_position_ = upload_position;
4008  upload_size_ = upload_size;
4009  load_state_host_ = net::IDNToUnicode(url.host(),
4010      GetContentClient()->browser()->GetAcceptLangs(
4011          GetBrowserContext()));
4012  if (load_state_.state == net::LOAD_STATE_READING_RESPONSE)
4013    SetNotWaitingForResponse();
4014  if (IsLoading()) {
4015    NotifyNavigationStateChanged(static_cast<InvalidateTypes>(
4016        INVALIDATE_TYPE_LOAD | INVALIDATE_TYPE_TAB));
4017  }
4018}
4019
4020void WebContentsImpl::BeforeUnloadFiredFromRenderManager(
4021    bool proceed, const base::TimeTicks& proceed_time,
4022    bool* proceed_to_fire_unload) {
4023  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
4024                    BeforeUnloadFired(proceed_time));
4025  if (delegate_)
4026    delegate_->BeforeUnloadFired(this, proceed, proceed_to_fire_unload);
4027  // Note: |this| might be deleted at this point.
4028}
4029
4030void WebContentsImpl::RenderProcessGoneFromRenderManager(
4031    RenderViewHost* render_view_host) {
4032  DCHECK(crashed_status_ != base::TERMINATION_STATUS_STILL_RUNNING);
4033  RenderViewTerminated(render_view_host, crashed_status_, crashed_error_code_);
4034}
4035
4036void WebContentsImpl::UpdateRenderViewSizeForRenderManager() {
4037  // TODO(brettw) this is a hack. See WebContentsView::SizeContents.
4038  gfx::Size size = GetSizeForNewRenderView();
4039  // 0x0 isn't a valid window size (minimal window size is 1x1) but it may be
4040  // here during container initialization and normal window size will be set
4041  // later. In case of tab duplication this resizing to 0x0 prevents setting
4042  // normal size later so just ignore it.
4043  if (!size.IsEmpty())
4044    view_->SizeContents(size);
4045}
4046
4047void WebContentsImpl::CancelModalDialogsForRenderManager() {
4048  // We need to cancel modal dialogs when doing a process swap, since the load
4049  // deferrer would prevent us from swapping out.
4050  if (dialog_manager_)
4051    dialog_manager_->CancelActiveAndPendingDialogs(this);
4052}
4053
4054void WebContentsImpl::NotifySwappedFromRenderManager(RenderFrameHost* old_host,
4055                                                     RenderFrameHost* new_host,
4056                                                     bool is_main_frame) {
4057  if (is_main_frame) {
4058    NotifyViewSwapped(old_host ? old_host->GetRenderViewHost() : NULL,
4059                      new_host->GetRenderViewHost());
4060
4061    // Make sure the visible RVH reflects the new delegate's preferences.
4062    if (delegate_)
4063      view_->SetOverscrollControllerEnabled(CanOverscrollContent());
4064
4065    view_->RenderViewSwappedIn(new_host->GetRenderViewHost());
4066  }
4067
4068  NotifyFrameSwapped(old_host, new_host);
4069}
4070
4071int WebContentsImpl::CreateOpenerRenderViewsForRenderManager(
4072    SiteInstance* instance) {
4073  if (!opener_)
4074    return MSG_ROUTING_NONE;
4075
4076  // Recursively create RenderViews for anything else in the opener chain.
4077  return opener_->CreateOpenerRenderViews(instance);
4078}
4079
4080int WebContentsImpl::CreateOpenerRenderViews(SiteInstance* instance) {
4081  int opener_route_id = MSG_ROUTING_NONE;
4082
4083  // If this tab has an opener, ensure it has a RenderView in the given
4084  // SiteInstance as well.
4085  if (opener_)
4086    opener_route_id = opener_->CreateOpenerRenderViews(instance);
4087
4088  // If any of the renderers (current, pending, or swapped out) for this
4089  // WebContents has the same SiteInstance, use it.
4090  if (GetRenderManager()->current_host()->GetSiteInstance() == instance)
4091    return GetRenderManager()->current_host()->GetRoutingID();
4092
4093  if (GetRenderManager()->pending_render_view_host() &&
4094      GetRenderManager()->pending_render_view_host()->GetSiteInstance() ==
4095          instance)
4096    return GetRenderManager()->pending_render_view_host()->GetRoutingID();
4097
4098  RenderViewHostImpl* rvh = GetRenderManager()->GetSwappedOutRenderViewHost(
4099      instance);
4100  if (rvh)
4101    return rvh->GetRoutingID();
4102
4103  // Create a swapped out RenderView in the given SiteInstance if none exists,
4104  // setting its opener to the given route_id.  Return the new view's route_id.
4105  return GetRenderManager()->CreateRenderFrame(
4106      instance, opener_route_id, true, true, true);
4107}
4108
4109NavigationControllerImpl& WebContentsImpl::GetControllerForRenderManager() {
4110  return GetController();
4111}
4112
4113WebUIImpl* WebContentsImpl::CreateWebUIForRenderManager(const GURL& url) {
4114  return static_cast<WebUIImpl*>(CreateWebUI(url));
4115}
4116
4117NavigationEntry*
4118    WebContentsImpl::GetLastCommittedNavigationEntryForRenderManager() {
4119  return controller_.GetLastCommittedEntry();
4120}
4121
4122bool WebContentsImpl::CreateRenderViewForRenderManager(
4123    RenderViewHost* render_view_host,
4124    int opener_route_id,
4125    int proxy_routing_id,
4126    bool for_main_frame_navigation) {
4127  TRACE_EVENT0("browser,navigation",
4128               "WebContentsImpl::CreateRenderViewForRenderManager");
4129  // Can be NULL during tests.
4130  RenderWidgetHostViewBase* rwh_view;
4131  // TODO(kenrb): RenderWidgetHostViewChildFrame special casing is temporary
4132  // until RenderWidgetHost is attached to RenderFrameHost. We need to special
4133  // case this because RWH is still a base class of RenderViewHost, and child
4134  // frame RWHVs are unique in that they do not have their own WebContents.
4135  if (!for_main_frame_navigation) {
4136    RenderWidgetHostViewChildFrame* rwh_view_child =
4137        new RenderWidgetHostViewChildFrame(render_view_host);
4138    rwh_view = rwh_view_child;
4139  } else {
4140    rwh_view = view_->CreateViewForWidget(render_view_host);
4141  }
4142
4143  // Now that the RenderView has been created, we need to tell it its size.
4144  if (rwh_view)
4145    rwh_view->SetSize(GetSizeForNewRenderView());
4146
4147  // Make sure we use the correct starting page_id in the new RenderView.
4148  UpdateMaxPageIDIfNecessary(render_view_host);
4149  int32 max_page_id =
4150      GetMaxPageIDForSiteInstance(render_view_host->GetSiteInstance());
4151
4152  if (!static_cast<RenderViewHostImpl*>(
4153          render_view_host)->CreateRenderView(base::string16(),
4154                                              opener_route_id,
4155                                              proxy_routing_id,
4156                                              max_page_id,
4157                                              created_with_opener_)) {
4158    return false;
4159  }
4160
4161#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
4162  // Force a ViewMsg_Resize to be sent, needed to make plugins show up on
4163  // linux. See crbug.com/83941.
4164  if (rwh_view) {
4165    if (RenderWidgetHost* render_widget_host = rwh_view->GetRenderWidgetHost())
4166      render_widget_host->WasResized();
4167  }
4168#endif
4169
4170  return true;
4171}
4172
4173bool WebContentsImpl::CreateRenderFrameForRenderManager(
4174    RenderFrameHost* render_frame_host,
4175    int parent_routing_id) {
4176  TRACE_EVENT0("browser,navigation",
4177               "WebContentsImpl::CreateRenderFrameForRenderManager");
4178
4179  RenderFrameHostImpl* rfh =
4180      static_cast<RenderFrameHostImpl*>(render_frame_host);
4181  if (!rfh->CreateRenderFrame(parent_routing_id))
4182    return false;
4183
4184  // TODO(nasko): When RenderWidgetHost is owned by RenderFrameHost, the passed
4185  // RenderFrameHost will have to be associated with the appropriate
4186  // RenderWidgetHostView or a new one should be created here.
4187
4188  return true;
4189}
4190
4191#if defined(OS_ANDROID)
4192
4193base::android::ScopedJavaLocalRef<jobject>
4194WebContentsImpl::GetJavaWebContents() {
4195  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
4196  return GetWebContentsAndroid()->GetJavaObject();
4197}
4198
4199WebContentsAndroid* WebContentsImpl::GetWebContentsAndroid() {
4200  WebContentsAndroid* web_contents_android =
4201      static_cast<WebContentsAndroid*>(GetUserData(kWebContentsAndroidKey));
4202  if (!web_contents_android) {
4203    web_contents_android = new WebContentsAndroid(this);
4204    SetUserData(kWebContentsAndroidKey, web_contents_android);
4205  }
4206  return web_contents_android;
4207}
4208
4209bool WebContentsImpl::CreateRenderViewForInitialEmptyDocument() {
4210  return CreateRenderViewForRenderManager(GetRenderViewHost(),
4211                                          MSG_ROUTING_NONE,
4212                                          MSG_ROUTING_NONE,
4213                                          true);
4214}
4215
4216#elif defined(OS_MACOSX)
4217
4218void WebContentsImpl::SetAllowOtherViews(bool allow) {
4219  view_->SetAllowOtherViews(allow);
4220}
4221
4222bool WebContentsImpl::GetAllowOtherViews() {
4223  return view_->GetAllowOtherViews();
4224}
4225
4226#endif
4227
4228void WebContentsImpl::OnDialogClosed(int render_process_id,
4229                                     int render_frame_id,
4230                                     IPC::Message* reply_msg,
4231                                     bool dialog_was_suppressed,
4232                                     bool success,
4233                                     const base::string16& user_input) {
4234  RenderFrameHostImpl* rfh = RenderFrameHostImpl::FromID(render_process_id,
4235                                                         render_frame_id);
4236  last_dialog_suppressed_ = dialog_was_suppressed;
4237
4238  if (is_showing_before_unload_dialog_ && !success) {
4239    // If a beforeunload dialog is canceled, we need to stop the throbber from
4240    // spinning, since we forced it to start spinning in Navigate.
4241    if (rfh)
4242      DidStopLoading(rfh);
4243    controller_.DiscardNonCommittedEntries();
4244
4245    FOR_EACH_OBSERVER(WebContentsObserver, observers_,
4246                      BeforeUnloadDialogCancelled());
4247  }
4248
4249  is_showing_before_unload_dialog_ = false;
4250  if (rfh) {
4251    rfh->JavaScriptDialogClosed(reply_msg, success, user_input,
4252                                dialog_was_suppressed);
4253  } else {
4254    // Don't leak the sync IPC reply if the RFH or process is gone.
4255    delete reply_msg;
4256  }
4257}
4258
4259void WebContentsImpl::SetEncoding(const std::string& encoding) {
4260  if (encoding == last_reported_encoding_)
4261    return;
4262  last_reported_encoding_ = encoding;
4263
4264  canonical_encoding_ = GetContentClient()->browser()->
4265      GetCanonicalEncodingNameByAliasName(encoding);
4266}
4267
4268void WebContentsImpl::CreateViewAndSetSizeForRVH(RenderViewHost* rvh) {
4269  RenderWidgetHostViewBase* rwh_view = view_->CreateViewForWidget(rvh);
4270  // Can be NULL during tests.
4271  if (rwh_view)
4272    rwh_view->SetSize(GetContainerBounds().size());
4273}
4274
4275bool WebContentsImpl::IsHidden() {
4276  return capturer_count_ == 0 && !should_normally_be_visible_;
4277}
4278
4279RenderFrameHostManager* WebContentsImpl::GetRenderManager() const {
4280  return frame_tree_.root()->render_manager();
4281}
4282
4283RenderViewHostImpl* WebContentsImpl::GetRenderViewHostImpl() {
4284  return static_cast<RenderViewHostImpl*>(GetRenderViewHost());
4285}
4286
4287BrowserPluginGuest* WebContentsImpl::GetBrowserPluginGuest() const {
4288  return browser_plugin_guest_.get();
4289}
4290
4291void WebContentsImpl::SetBrowserPluginGuest(BrowserPluginGuest* guest) {
4292  CHECK(!browser_plugin_guest_);
4293  browser_plugin_guest_.reset(guest);
4294}
4295
4296BrowserPluginEmbedder* WebContentsImpl::GetBrowserPluginEmbedder() const {
4297  return browser_plugin_embedder_.get();
4298}
4299
4300void WebContentsImpl::ClearPowerSaveBlockers(
4301    RenderFrameHost* render_frame_host) {
4302  RemoveAllMediaPlayerEntries(render_frame_host, &active_audio_players_);
4303  RemoveAllMediaPlayerEntries(render_frame_host, &active_video_players_);
4304  MaybeReleasePowerSaveBlockers();
4305}
4306
4307void WebContentsImpl::ClearAllPowerSaveBlockers() {
4308  active_audio_players_.clear();
4309  active_video_players_.clear();
4310  audio_power_save_blocker_.reset();
4311  video_power_save_blocker_.reset();
4312}
4313
4314gfx::Size WebContentsImpl::GetSizeForNewRenderView() {
4315  gfx::Size size;
4316  if (delegate_)
4317    size = delegate_->GetSizeForNewRenderView(this);
4318  if (size.IsEmpty())
4319    size = GetContainerBounds().size();
4320  return size;
4321}
4322
4323void WebContentsImpl::OnFrameRemoved(RenderFrameHost* render_frame_host) {
4324  FOR_EACH_OBSERVER(
4325      WebContentsObserver, observers_, FrameDetached(render_frame_host));
4326}
4327
4328void WebContentsImpl::OnPreferredSizeChanged(const gfx::Size& old_size) {
4329  if (!delegate_)
4330    return;
4331  const gfx::Size new_size = GetPreferredSize();
4332  if (new_size != old_size)
4333    delegate_->UpdatePreferredSize(this, new_size);
4334}
4335
4336void WebContentsImpl::AddMediaPlayerEntry(int64 player_cookie,
4337                                          ActiveMediaPlayerMap* player_map) {
4338  const uintptr_t key =
4339      reinterpret_cast<uintptr_t>(render_frame_message_source_);
4340  DCHECK(std::find((*player_map)[key].begin(),
4341                   (*player_map)[key].end(),
4342                   player_cookie) == (*player_map)[key].end());
4343  (*player_map)[key].push_back(player_cookie);
4344}
4345
4346void WebContentsImpl::RemoveMediaPlayerEntry(int64 player_cookie,
4347                                             ActiveMediaPlayerMap* player_map) {
4348  const uintptr_t key =
4349      reinterpret_cast<uintptr_t>(render_frame_message_source_);
4350  ActiveMediaPlayerMap::iterator it = player_map->find(key);
4351  if (it == player_map->end())
4352    return;
4353
4354  // Remove the player.
4355  PlayerList::iterator player_it =
4356      std::find(it->second.begin(), it->second.end(), player_cookie);
4357  if (player_it != it->second.end())
4358    it->second.erase(player_it);
4359
4360  // If there are no players left, remove the map entry.
4361  if (it->second.empty())
4362    player_map->erase(it);
4363}
4364
4365void WebContentsImpl::RemoveAllMediaPlayerEntries(
4366    RenderFrameHost* render_frame_host,
4367    ActiveMediaPlayerMap* player_map) {
4368  ActiveMediaPlayerMap::iterator it =
4369      player_map->find(reinterpret_cast<uintptr_t>(render_frame_host));
4370  if (it == player_map->end())
4371    return;
4372  player_map->erase(it);
4373}
4374
4375void WebContentsImpl::ResumeResponseDeferredAtStart() {
4376  FrameTreeNode* node = frame_tree_.root();
4377  node->render_manager()->ResumeResponseDeferredAtStart();
4378}
4379
4380void WebContentsImpl::SetForceDisableOverscrollContent(bool force_disable) {
4381  force_disable_overscroll_content_ = force_disable;
4382  if (view_)
4383    view_->SetOverscrollControllerEnabled(CanOverscrollContent());
4384}
4385
4386}  // namespace content
4387