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
1828void WebContentsImpl::SetIsVirtualKeyboardRequested(bool requested) {
1829  virtual_keyboard_requested_ = requested;
1830}
1831
1832bool WebContentsImpl::IsVirtualKeyboardRequested() {
1833  return virtual_keyboard_requested_;
1834}
1835
1836AccessibilityMode WebContentsImpl::GetAccessibilityMode() const {
1837  return accessibility_mode_;
1838}
1839
1840void WebContentsImpl::AccessibilityEventReceived(
1841    const std::vector<AXEventNotificationDetails>& details) {
1842  FOR_EACH_OBSERVER(
1843      WebContentsObserver, observers_, AccessibilityEventReceived(details));
1844}
1845
1846RenderFrameHost* WebContentsImpl::GetGuestByInstanceID(
1847    int browser_plugin_instance_id) {
1848  BrowserPluginGuestManager* guest_manager =
1849      GetBrowserContext()->GetGuestManager();
1850  WebContents* guest = guest_manager->GetGuestByInstanceID(
1851      this, browser_plugin_instance_id);
1852  if (!guest)
1853    return NULL;
1854  return guest->GetMainFrame();
1855}
1856
1857void WebContentsImpl::OnShowValidationMessage(
1858    const gfx::Rect& anchor_in_root_view,
1859    const base::string16& main_text,
1860    const base::string16& sub_text) {
1861  if (delegate_)
1862    delegate_->ShowValidationMessage(
1863        this, anchor_in_root_view, main_text, sub_text);
1864}
1865
1866void WebContentsImpl::OnHideValidationMessage() {
1867  if (delegate_)
1868    delegate_->HideValidationMessage(this);
1869}
1870
1871void WebContentsImpl::OnMoveValidationMessage(
1872    const gfx::Rect& anchor_in_root_view) {
1873  if (delegate_)
1874    delegate_->MoveValidationMessage(this, anchor_in_root_view);
1875}
1876
1877void WebContentsImpl::DidSendScreenRects(RenderWidgetHostImpl* rwh) {
1878  if (browser_plugin_embedder_)
1879    browser_plugin_embedder_->DidSendScreenRects();
1880}
1881
1882BrowserAccessibilityManager*
1883    WebContentsImpl::GetRootBrowserAccessibilityManager() {
1884  RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(GetMainFrame());
1885  return rfh ? rfh->browser_accessibility_manager() : NULL;
1886}
1887
1888BrowserAccessibilityManager*
1889    WebContentsImpl::GetOrCreateRootBrowserAccessibilityManager() {
1890  RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(GetMainFrame());
1891  return rfh ? rfh->GetOrCreateBrowserAccessibilityManager() : NULL;
1892}
1893
1894void WebContentsImpl::UpdatePreferredSize(const gfx::Size& pref_size) {
1895  const gfx::Size old_size = GetPreferredSize();
1896  preferred_size_ = pref_size;
1897  OnPreferredSizeChanged(old_size);
1898}
1899
1900void WebContentsImpl::ResizeDueToAutoResize(const gfx::Size& new_size) {
1901  if (delegate_)
1902    delegate_->ResizeDueToAutoResize(this, new_size);
1903}
1904
1905WebContents* WebContentsImpl::OpenURL(const OpenURLParams& params) {
1906  if (!delegate_)
1907    return NULL;
1908
1909  WebContents* new_contents = delegate_->OpenURLFromTab(this, params);
1910  return new_contents;
1911}
1912
1913bool WebContentsImpl::Send(IPC::Message* message) {
1914  if (!GetRenderViewHost()) {
1915    delete message;
1916    return false;
1917  }
1918
1919  return GetRenderViewHost()->Send(message);
1920}
1921
1922bool WebContentsImpl::NavigateToPendingEntry(
1923    NavigationController::ReloadType reload_type) {
1924  FrameTreeNode* node = frame_tree_.root();
1925
1926  // Navigate in the FrameTreeNode specified in the pending entry, if any.  This
1927  // is currently only used in --site-per-process and tests.
1928  NavigationEntryImpl* pending_entry =
1929      NavigationEntryImpl::FromNavigationEntry(controller_.GetPendingEntry());
1930  if (pending_entry->frame_tree_node_id() != -1) {
1931    FrameTreeNode* subframe =
1932        frame_tree_.FindByID(pending_entry->frame_tree_node_id());
1933    DCHECK(subframe);
1934    if (subframe)
1935      node = subframe;
1936  }
1937
1938  return node->navigator()->NavigateToPendingEntry(
1939      node->current_frame_host(), reload_type);
1940}
1941
1942void WebContentsImpl::RenderFrameForInterstitialPageCreated(
1943    RenderFrameHost* render_frame_host) {
1944  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
1945                    RenderFrameForInterstitialPageCreated(render_frame_host));
1946}
1947
1948void WebContentsImpl::AttachInterstitialPage(
1949    InterstitialPageImpl* interstitial_page) {
1950  DCHECK(interstitial_page);
1951  GetRenderManager()->set_interstitial_page(interstitial_page);
1952
1953  // Cancel any visible dialogs so that they don't interfere with the
1954  // interstitial.
1955  if (dialog_manager_)
1956    dialog_manager_->CancelActiveAndPendingDialogs(this);
1957
1958  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
1959                    DidAttachInterstitialPage());
1960}
1961
1962void WebContentsImpl::DetachInterstitialPage() {
1963  if (ShowingInterstitialPage())
1964    GetRenderManager()->remove_interstitial_page();
1965  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
1966                    DidDetachInterstitialPage());
1967}
1968
1969void WebContentsImpl::SetHistoryLengthAndPrune(
1970    const SiteInstance* site_instance,
1971    int history_length,
1972    int32 minimum_page_id) {
1973  // SetHistoryLengthAndPrune doesn't work when there are pending cross-site
1974  // navigations. Callers should ensure that this is the case.
1975  if (GetRenderManager()->pending_render_view_host()) {
1976    NOTREACHED();
1977    return;
1978  }
1979  RenderViewHostImpl* rvh = GetRenderViewHostImpl();
1980  if (!rvh) {
1981    NOTREACHED();
1982    return;
1983  }
1984  if (site_instance && rvh->GetSiteInstance() != site_instance) {
1985    NOTREACHED();
1986    return;
1987  }
1988  Send(new ViewMsg_SetHistoryLengthAndPrune(GetRoutingID(),
1989                                            history_length,
1990                                            minimum_page_id));
1991}
1992
1993void WebContentsImpl::ReloadFocusedFrame(bool ignore_cache) {
1994  RenderFrameHost* focused_frame = GetFocusedFrame();
1995  if (!focused_frame)
1996    return;
1997
1998  focused_frame->Send(new FrameMsg_Reload(
1999      focused_frame->GetRoutingID(), ignore_cache));
2000}
2001
2002void WebContentsImpl::Undo() {
2003  RenderFrameHost* focused_frame = GetFocusedFrame();
2004  if (!focused_frame)
2005    return;
2006
2007  focused_frame->Send(new InputMsg_Undo(focused_frame->GetRoutingID()));
2008  RecordAction(base::UserMetricsAction("Undo"));
2009}
2010
2011void WebContentsImpl::Redo() {
2012  RenderFrameHost* focused_frame = GetFocusedFrame();
2013  if (!focused_frame)
2014    return;
2015  focused_frame->Send(new InputMsg_Redo(focused_frame->GetRoutingID()));
2016  RecordAction(base::UserMetricsAction("Redo"));
2017}
2018
2019void WebContentsImpl::Cut() {
2020  RenderFrameHost* focused_frame = GetFocusedFrame();
2021  if (!focused_frame)
2022    return;
2023
2024  focused_frame->Send(new InputMsg_Cut(focused_frame->GetRoutingID()));
2025  RecordAction(base::UserMetricsAction("Cut"));
2026}
2027
2028void WebContentsImpl::Copy() {
2029  RenderFrameHost* focused_frame = GetFocusedFrame();
2030  if (!focused_frame)
2031    return;
2032
2033  focused_frame->Send(new InputMsg_Copy(focused_frame->GetRoutingID()));
2034  RecordAction(base::UserMetricsAction("Copy"));
2035}
2036
2037void WebContentsImpl::CopyToFindPboard() {
2038#if defined(OS_MACOSX)
2039  RenderFrameHost* focused_frame = GetFocusedFrame();
2040  if (!focused_frame)
2041    return;
2042
2043  // Windows/Linux don't have the concept of a find pasteboard.
2044  focused_frame->Send(
2045      new InputMsg_CopyToFindPboard(focused_frame->GetRoutingID()));
2046  RecordAction(base::UserMetricsAction("CopyToFindPboard"));
2047#endif
2048}
2049
2050void WebContentsImpl::Paste() {
2051  RenderFrameHost* focused_frame = GetFocusedFrame();
2052  if (!focused_frame)
2053    return;
2054
2055  focused_frame->Send(new InputMsg_Paste(focused_frame->GetRoutingID()));
2056  RecordAction(base::UserMetricsAction("Paste"));
2057}
2058
2059void WebContentsImpl::PasteAndMatchStyle() {
2060  RenderFrameHost* focused_frame = GetFocusedFrame();
2061  if (!focused_frame)
2062    return;
2063
2064  focused_frame->Send(new InputMsg_PasteAndMatchStyle(
2065      focused_frame->GetRoutingID()));
2066  RecordAction(base::UserMetricsAction("PasteAndMatchStyle"));
2067}
2068
2069void WebContentsImpl::Delete() {
2070  RenderFrameHost* focused_frame = GetFocusedFrame();
2071  if (!focused_frame)
2072    return;
2073
2074  focused_frame->Send(new InputMsg_Delete(focused_frame->GetRoutingID()));
2075  RecordAction(base::UserMetricsAction("DeleteSelection"));
2076}
2077
2078void WebContentsImpl::SelectAll() {
2079  RenderFrameHost* focused_frame = GetFocusedFrame();
2080  if (!focused_frame)
2081    return;
2082
2083  focused_frame->Send(new InputMsg_SelectAll(focused_frame->GetRoutingID()));
2084  RecordAction(base::UserMetricsAction("SelectAll"));
2085}
2086
2087void WebContentsImpl::Unselect() {
2088  RenderFrameHost* focused_frame = GetFocusedFrame();
2089  if (!focused_frame)
2090    return;
2091
2092  focused_frame->Send(new InputMsg_Unselect(focused_frame->GetRoutingID()));
2093  RecordAction(base::UserMetricsAction("Unselect"));
2094}
2095
2096void WebContentsImpl::Replace(const base::string16& word) {
2097  RenderFrameHost* focused_frame = GetFocusedFrame();
2098  if (!focused_frame)
2099    return;
2100
2101  focused_frame->Send(new InputMsg_Replace(
2102      focused_frame->GetRoutingID(), word));
2103}
2104
2105void WebContentsImpl::ReplaceMisspelling(const base::string16& word) {
2106  RenderFrameHost* focused_frame = GetFocusedFrame();
2107  if (!focused_frame)
2108    return;
2109
2110  focused_frame->Send(new InputMsg_ReplaceMisspelling(
2111      focused_frame->GetRoutingID(), word));
2112}
2113
2114void WebContentsImpl::NotifyContextMenuClosed(
2115    const CustomContextMenuContext& context) {
2116  RenderFrameHost* focused_frame = GetFocusedFrame();
2117  if (!focused_frame)
2118    return;
2119
2120  focused_frame->Send(new FrameMsg_ContextMenuClosed(
2121      focused_frame->GetRoutingID(), context));
2122}
2123
2124void WebContentsImpl::ExecuteCustomContextMenuCommand(
2125    int action, const CustomContextMenuContext& context) {
2126  RenderFrameHost* focused_frame = GetFocusedFrame();
2127  if (!focused_frame)
2128    return;
2129
2130  focused_frame->Send(new FrameMsg_CustomContextMenuAction(
2131      focused_frame->GetRoutingID(), context, action));
2132}
2133
2134gfx::NativeView WebContentsImpl::GetNativeView() {
2135  return view_->GetNativeView();
2136}
2137
2138gfx::NativeView WebContentsImpl::GetContentNativeView() {
2139  return view_->GetContentNativeView();
2140}
2141
2142gfx::NativeWindow WebContentsImpl::GetTopLevelNativeWindow() {
2143  return view_->GetTopLevelNativeWindow();
2144}
2145
2146gfx::Rect WebContentsImpl::GetViewBounds() {
2147  return view_->GetViewBounds();
2148}
2149
2150gfx::Rect WebContentsImpl::GetContainerBounds() {
2151  gfx::Rect rv;
2152  view_->GetContainerBounds(&rv);
2153  return rv;
2154}
2155
2156DropData* WebContentsImpl::GetDropData() {
2157  return view_->GetDropData();
2158}
2159
2160void WebContentsImpl::Focus() {
2161  RenderWidgetHostView* const fullscreen_view =
2162      GetFullscreenRenderWidgetHostView();
2163  if (fullscreen_view)
2164    fullscreen_view->Focus();
2165  else
2166    view_->Focus();
2167}
2168
2169void WebContentsImpl::SetInitialFocus() {
2170  RenderWidgetHostView* const fullscreen_view =
2171      GetFullscreenRenderWidgetHostView();
2172  if (fullscreen_view)
2173    fullscreen_view->Focus();
2174  else
2175    view_->SetInitialFocus();
2176}
2177
2178void WebContentsImpl::StoreFocus() {
2179  if (!GetFullscreenRenderWidgetHostView())
2180    view_->StoreFocus();
2181}
2182
2183void WebContentsImpl::RestoreFocus() {
2184  RenderWidgetHostView* const fullscreen_view =
2185      GetFullscreenRenderWidgetHostView();
2186  if (fullscreen_view)
2187    fullscreen_view->Focus();
2188  else
2189    view_->RestoreFocus();
2190}
2191
2192void WebContentsImpl::FocusThroughTabTraversal(bool reverse) {
2193  if (ShowingInterstitialPage()) {
2194    GetRenderManager()->interstitial_page()->FocusThroughTabTraversal(reverse);
2195    return;
2196  }
2197  RenderWidgetHostView* const fullscreen_view =
2198      GetFullscreenRenderWidgetHostView();
2199  if (fullscreen_view) {
2200    fullscreen_view->Focus();
2201    return;
2202  }
2203  GetRenderViewHostImpl()->SetInitialFocus(reverse);
2204}
2205
2206bool WebContentsImpl::ShowingInterstitialPage() const {
2207  return GetRenderManager()->interstitial_page() != NULL;
2208}
2209
2210InterstitialPage* WebContentsImpl::GetInterstitialPage() const {
2211  return GetRenderManager()->interstitial_page();
2212}
2213
2214bool WebContentsImpl::IsSavable() {
2215  // WebKit creates Document object when MIME type is application/xhtml+xml,
2216  // so we also support this MIME type.
2217  return contents_mime_type_ == "text/html" ||
2218         contents_mime_type_ == "text/xml" ||
2219         contents_mime_type_ == "application/xhtml+xml" ||
2220         contents_mime_type_ == "text/plain" ||
2221         contents_mime_type_ == "text/css" ||
2222         net::IsSupportedJavascriptMimeType(contents_mime_type_.c_str());
2223}
2224
2225void WebContentsImpl::OnSavePage() {
2226  // If we can not save the page, try to download it.
2227  if (!IsSavable()) {
2228    RecordDownloadSource(INITIATED_BY_SAVE_PACKAGE_ON_NON_HTML);
2229    SaveFrame(GetURL(), Referrer());
2230    return;
2231  }
2232
2233  Stop();
2234
2235  // Create the save package and possibly prompt the user for the name to save
2236  // the page as. The user prompt is an asynchronous operation that runs on
2237  // another thread.
2238  save_package_ = new SavePackage(this);
2239  save_package_->GetSaveInfo();
2240}
2241
2242// Used in automated testing to bypass prompting the user for file names.
2243// Instead, the names and paths are hard coded rather than running them through
2244// file name sanitation and extension / mime checking.
2245bool WebContentsImpl::SavePage(const base::FilePath& main_file,
2246                               const base::FilePath& dir_path,
2247                               SavePageType save_type) {
2248  // Stop the page from navigating.
2249  Stop();
2250
2251  save_package_ = new SavePackage(this, save_type, main_file, dir_path);
2252  return save_package_->Init(SavePackageDownloadCreatedCallback());
2253}
2254
2255void WebContentsImpl::SaveFrame(const GURL& url,
2256                                const Referrer& referrer) {
2257  if (!GetURL().is_valid())
2258    return;
2259  bool is_main_frame = (url == GetURL());
2260
2261  DownloadManager* dlm =
2262      BrowserContext::GetDownloadManager(GetBrowserContext());
2263  if (!dlm)
2264    return;
2265  int64 post_id = -1;
2266  if (is_main_frame) {
2267    const NavigationEntry* entry = controller_.GetLastCommittedEntry();
2268    if (entry)
2269      post_id = entry->GetPostID();
2270  }
2271  scoped_ptr<DownloadUrlParameters> params(
2272      DownloadUrlParameters::FromWebContents(this, url));
2273  params->set_referrer(referrer);
2274  params->set_post_id(post_id);
2275  params->set_prefer_cache(true);
2276  if (post_id >= 0)
2277    params->set_method("POST");
2278  params->set_prompt(true);
2279  dlm->DownloadUrl(params.Pass());
2280}
2281
2282void WebContentsImpl::GenerateMHTML(
2283    const base::FilePath& file,
2284    const base::Callback<void(int64)>& callback) {
2285  MHTMLGenerationManager::GetInstance()->SaveMHTML(this, file, callback);
2286}
2287
2288const std::string& WebContentsImpl::GetContentsMimeType() const {
2289  return contents_mime_type_;
2290}
2291
2292bool WebContentsImpl::WillNotifyDisconnection() const {
2293  return notify_disconnection_;
2294}
2295
2296void WebContentsImpl::SetOverrideEncoding(const std::string& encoding) {
2297  SetEncoding(encoding);
2298  Send(new ViewMsg_SetPageEncoding(GetRoutingID(), encoding));
2299}
2300
2301void WebContentsImpl::ResetOverrideEncoding() {
2302  canonical_encoding_.clear();
2303  Send(new ViewMsg_ResetPageEncodingToDefault(GetRoutingID()));
2304}
2305
2306RendererPreferences* WebContentsImpl::GetMutableRendererPrefs() {
2307  return &renderer_preferences_;
2308}
2309
2310void WebContentsImpl::Close() {
2311  Close(GetRenderViewHost());
2312}
2313
2314void WebContentsImpl::DragSourceEndedAt(int client_x, int client_y,
2315    int screen_x, int screen_y, blink::WebDragOperation operation) {
2316  if (browser_plugin_embedder_.get())
2317    browser_plugin_embedder_->DragSourceEndedAt(client_x, client_y,
2318        screen_x, screen_y, operation);
2319  if (GetRenderViewHost())
2320    GetRenderViewHostImpl()->DragSourceEndedAt(client_x, client_y,
2321        screen_x, screen_y, operation);
2322}
2323
2324void WebContentsImpl::DidGetResourceResponseStart(
2325  const ResourceRequestDetails& details) {
2326  controller_.ssl_manager()->DidStartResourceResponse(details);
2327
2328  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2329                    DidGetResourceResponseStart(details));
2330
2331  // TODO(avi): Remove. http://crbug.com/170921
2332  NotificationService::current()->Notify(
2333      NOTIFICATION_RESOURCE_RESPONSE_STARTED,
2334      Source<WebContents>(this),
2335      Details<const ResourceRequestDetails>(&details));
2336}
2337
2338void WebContentsImpl::DidGetRedirectForResourceRequest(
2339  RenderViewHost* render_view_host,
2340  const ResourceRedirectDetails& details) {
2341  controller_.ssl_manager()->DidReceiveResourceRedirect(details);
2342
2343  FOR_EACH_OBSERVER(
2344      WebContentsObserver,
2345      observers_,
2346      DidGetRedirectForResourceRequest(render_view_host, details));
2347
2348  // TODO(avi): Remove. http://crbug.com/170921
2349  NotificationService::current()->Notify(
2350      NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
2351      Source<WebContents>(this),
2352      Details<const ResourceRedirectDetails>(&details));
2353}
2354
2355void WebContentsImpl::SystemDragEnded() {
2356  if (GetRenderViewHost())
2357    GetRenderViewHostImpl()->DragSourceSystemDragEnded();
2358  if (delegate_)
2359    delegate_->DragEnded();
2360  if (browser_plugin_embedder_.get())
2361    browser_plugin_embedder_->SystemDragEnded();
2362}
2363
2364void WebContentsImpl::UserGestureDone() {
2365  OnUserGesture();
2366}
2367
2368void WebContentsImpl::SetClosedByUserGesture(bool value) {
2369  closed_by_user_gesture_ = value;
2370}
2371
2372bool WebContentsImpl::GetClosedByUserGesture() const {
2373  return closed_by_user_gesture_;
2374}
2375
2376void WebContentsImpl::ViewSource() {
2377  if (!delegate_)
2378    return;
2379
2380  NavigationEntry* entry = GetController().GetLastCommittedEntry();
2381  if (!entry)
2382    return;
2383
2384  delegate_->ViewSourceForTab(this, entry->GetURL());
2385}
2386
2387void WebContentsImpl::ViewFrameSource(const GURL& url,
2388                                      const PageState& page_state) {
2389  if (!delegate_)
2390    return;
2391
2392  delegate_->ViewSourceForFrame(this, url, page_state);
2393}
2394
2395int WebContentsImpl::GetMinimumZoomPercent() const {
2396  return minimum_zoom_percent_;
2397}
2398
2399int WebContentsImpl::GetMaximumZoomPercent() const {
2400  return maximum_zoom_percent_;
2401}
2402
2403gfx::Size WebContentsImpl::GetPreferredSize() const {
2404  return capturer_count_ == 0 ? preferred_size_ : preferred_size_for_capture_;
2405}
2406
2407bool WebContentsImpl::GotResponseToLockMouseRequest(bool allowed) {
2408  if (GetBrowserPluginGuest())
2409    return GetBrowserPluginGuest()->LockMouse(allowed);
2410
2411  return GetRenderViewHost() ?
2412      GetRenderViewHostImpl()->GotResponseToLockMouseRequest(allowed) : false;
2413}
2414
2415bool WebContentsImpl::HasOpener() const {
2416  return opener_ != NULL;
2417}
2418
2419void WebContentsImpl::DidChooseColorInColorChooser(SkColor color) {
2420  if (!color_chooser_info_.get())
2421    return;
2422  RenderFrameHost* rfh = RenderFrameHost::FromID(
2423      color_chooser_info_->render_process_id,
2424      color_chooser_info_->render_frame_id);
2425  if (!rfh)
2426    return;
2427
2428  rfh->Send(new FrameMsg_DidChooseColorResponse(
2429      rfh->GetRoutingID(), color_chooser_info_->identifier, color));
2430}
2431
2432void WebContentsImpl::DidEndColorChooser() {
2433  if (!color_chooser_info_.get())
2434    return;
2435  RenderFrameHost* rfh = RenderFrameHost::FromID(
2436      color_chooser_info_->render_process_id,
2437      color_chooser_info_->render_frame_id);
2438  if (!rfh)
2439    return;
2440
2441  rfh->Send(new FrameMsg_DidEndColorChooser(
2442      rfh->GetRoutingID(), color_chooser_info_->identifier));
2443  color_chooser_info_.reset();
2444}
2445
2446int WebContentsImpl::DownloadImage(const GURL& url,
2447                                   bool is_favicon,
2448                                   uint32_t max_bitmap_size,
2449                                   const ImageDownloadCallback& callback) {
2450  int id = StartDownload(GetMainFrame(), url, is_favicon, max_bitmap_size);
2451  image_download_map_[id] = callback;
2452  return id;
2453}
2454
2455bool WebContentsImpl::IsSubframe() const {
2456  return is_subframe_;
2457}
2458
2459void WebContentsImpl::Find(int request_id,
2460                           const base::string16& search_text,
2461                           const blink::WebFindOptions& options) {
2462  Send(new ViewMsg_Find(GetRoutingID(), request_id, search_text, options));
2463}
2464
2465void WebContentsImpl::StopFinding(StopFindAction action) {
2466  Send(new ViewMsg_StopFinding(GetRoutingID(), action));
2467}
2468
2469void WebContentsImpl::InsertCSS(const std::string& css) {
2470  GetMainFrame()->Send(new FrameMsg_CSSInsertRequest(
2471      GetMainFrame()->GetRoutingID(), css));
2472}
2473
2474bool WebContentsImpl::WasRecentlyAudible() {
2475  return audio_stream_monitor_.WasRecentlyAudible();
2476}
2477
2478void WebContentsImpl::GetManifest(const GetManifestCallback& callback) {
2479  manifest_manager_host_->GetManifest(GetMainFrame(), callback);
2480}
2481
2482bool WebContentsImpl::FocusLocationBarByDefault() {
2483  NavigationEntry* entry = controller_.GetVisibleEntry();
2484  if (entry && entry->GetURL() == GURL(url::kAboutBlankURL))
2485    return true;
2486  return delegate_ && delegate_->ShouldFocusLocationBarByDefault(this);
2487}
2488
2489void WebContentsImpl::SetFocusToLocationBar(bool select_all) {
2490  if (delegate_)
2491    delegate_->SetFocusToLocationBar(select_all);
2492}
2493
2494void WebContentsImpl::DidStartProvisionalLoad(
2495    RenderFrameHostImpl* render_frame_host,
2496    const GURL& validated_url,
2497    bool is_error_page,
2498    bool is_iframe_srcdoc) {
2499  // Notify observers about the start of the provisional load.
2500  FOR_EACH_OBSERVER(
2501      WebContentsObserver,
2502      observers_,
2503      DidStartProvisionalLoadForFrame(
2504          render_frame_host, validated_url, is_error_page, is_iframe_srcdoc));
2505}
2506
2507void WebContentsImpl::DidStartNavigationTransition(
2508    RenderFrameHostImpl* render_frame_host) {
2509#if defined(OS_ANDROID)
2510  int render_frame_id = render_frame_host->GetRoutingID();
2511  GetWebContentsAndroid()->DidStartNavigationTransitionForFrame(
2512      render_frame_id);
2513#endif
2514}
2515
2516void WebContentsImpl::DidFailProvisionalLoadWithError(
2517    RenderFrameHostImpl* render_frame_host,
2518    const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params) {
2519  GURL validated_url(params.url);
2520  FOR_EACH_OBSERVER(WebContentsObserver,
2521                    observers_,
2522                    DidFailProvisionalLoad(render_frame_host,
2523                                           validated_url,
2524                                           params.error_code,
2525                                           params.error_description));
2526}
2527
2528void WebContentsImpl::DidFailLoadWithError(
2529    RenderFrameHostImpl* render_frame_host,
2530    const GURL& url,
2531    int error_code,
2532    const base::string16& error_description) {
2533  FOR_EACH_OBSERVER(
2534      WebContentsObserver,
2535      observers_,
2536      DidFailLoad(render_frame_host, url, error_code, error_description));
2537}
2538
2539void WebContentsImpl::NotifyChangedNavigationState(
2540    InvalidateTypes changed_flags) {
2541  NotifyNavigationStateChanged(changed_flags);
2542}
2543
2544void WebContentsImpl::AboutToNavigateRenderFrame(
2545      RenderFrameHostImpl* render_frame_host) {
2546  // Notify observers that we will navigate in this RenderView.
2547  RenderViewHost* render_view_host = render_frame_host->render_view_host();
2548  FOR_EACH_OBSERVER(
2549      WebContentsObserver,
2550      observers_,
2551      AboutToNavigateRenderView(render_view_host));
2552}
2553
2554void WebContentsImpl::DidStartNavigationToPendingEntry(
2555      RenderFrameHostImpl* render_frame_host,
2556      const GURL& url,
2557      NavigationController::ReloadType reload_type) {
2558  // Notify observers about navigation.
2559  FOR_EACH_OBSERVER(
2560      WebContentsObserver,
2561      observers_,
2562      DidStartNavigationToPendingEntry(url, reload_type));
2563}
2564
2565void WebContentsImpl::RequestOpenURL(RenderFrameHostImpl* render_frame_host,
2566                                     const OpenURLParams& params) {
2567  int source_render_frame_id = render_frame_host->GetRoutingID();
2568  WebContents* new_contents = OpenURL(params);
2569
2570  if (new_contents) {
2571    // Notify observers.
2572    FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2573                      DidOpenRequestedURL(new_contents,
2574                                          params.url,
2575                                          params.referrer,
2576                                          params.disposition,
2577                                          params.transition,
2578                                          source_render_frame_id));
2579  }
2580}
2581
2582bool WebContentsImpl::ShouldPreserveAbortedURLs() {
2583  if (!delegate_)
2584    return false;
2585  return delegate_->ShouldPreserveAbortedURLs(this);
2586}
2587
2588void WebContentsImpl::DidCommitProvisionalLoad(
2589    RenderFrameHostImpl* render_frame_host,
2590    const GURL& url,
2591    ui::PageTransition transition_type) {
2592  // Notify observers about the commit of the provisional load.
2593  FOR_EACH_OBSERVER(WebContentsObserver,
2594                    observers_,
2595                    DidCommitProvisionalLoadForFrame(
2596                        render_frame_host, url, transition_type));
2597}
2598
2599void WebContentsImpl::DidNavigateMainFramePreCommit(
2600    bool navigation_is_within_page) {
2601  // Ensure fullscreen mode is exited before committing the navigation to a
2602  // different page.  The next page will not start out assuming it is in
2603  // fullscreen mode.
2604  if (navigation_is_within_page) {
2605    // No page change?  Then, the renderer and browser can remain in fullscreen.
2606    return;
2607  }
2608  if (IsFullscreenForCurrentTab())
2609    GetRenderViewHost()->ExitFullscreen();
2610  DCHECK(!IsFullscreenForCurrentTab());
2611}
2612
2613void WebContentsImpl::DidNavigateMainFramePostCommit(
2614    const LoadCommittedDetails& details,
2615    const FrameHostMsg_DidCommitProvisionalLoad_Params& params) {
2616  if (details.is_navigation_to_different_page()) {
2617    // Clear the status bubble. This is a workaround for a bug where WebKit
2618    // doesn't let us know that the cursor left an element during a
2619    // transition (this is also why the mouse cursor remains as a hand after
2620    // clicking on a link); see bugs 1184641 and 980803. We don't want to
2621    // clear the bubble when a user navigates to a named anchor in the same
2622    // page.
2623    UpdateTargetURL(GURL());
2624  }
2625
2626  if (!details.is_in_page) {
2627    // Once the main frame is navigated, we're no longer considered to have
2628    // displayed insecure content.
2629    displayed_insecure_content_ = false;
2630    SSLManager::NotifySSLInternalStateChanged(
2631        GetController().GetBrowserContext());
2632  }
2633
2634  // Notify observers about navigation.
2635  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2636                    DidNavigateMainFrame(details, params));
2637
2638  if (delegate_)
2639    delegate_->DidNavigateMainFramePostCommit(this);
2640  view_->SetOverscrollControllerEnabled(CanOverscrollContent());
2641}
2642
2643void WebContentsImpl::DidNavigateAnyFramePostCommit(
2644    RenderFrameHostImpl* render_frame_host,
2645    const LoadCommittedDetails& details,
2646    const FrameHostMsg_DidCommitProvisionalLoad_Params& params) {
2647  // Now that something has committed, we don't need to track whether the
2648  // initial page has been accessed.
2649  has_accessed_initial_document_ = false;
2650
2651  // If we navigate off the page, close all JavaScript dialogs.
2652  if (dialog_manager_ && !details.is_in_page)
2653    dialog_manager_->CancelActiveAndPendingDialogs(this);
2654
2655  // Notify observers about navigation.
2656  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2657                    DidNavigateAnyFrame(details, params));
2658}
2659
2660void WebContentsImpl::SetMainFrameMimeType(const std::string& mime_type) {
2661  contents_mime_type_ = mime_type;
2662}
2663
2664bool WebContentsImpl::CanOverscrollContent() const {
2665  // Disable overscroll when touch emulation is on. See crbug.com/369938.
2666  if (force_disable_overscroll_content_)
2667    return false;
2668
2669  if (delegate_)
2670    return delegate_->CanOverscrollContent();
2671
2672  return false;
2673}
2674
2675void WebContentsImpl::OnThemeColorChanged(SkColor theme_color) {
2676  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2677                    DidChangeThemeColor(theme_color));
2678}
2679
2680void WebContentsImpl::OnDidLoadResourceFromMemoryCache(
2681    const GURL& url,
2682    const std::string& security_info,
2683    const std::string& http_method,
2684    const std::string& mime_type,
2685    ResourceType resource_type) {
2686  base::StatsCounter cache("WebKit.CacheHit");
2687  cache.Increment();
2688
2689  // Send out a notification that we loaded a resource from our memory cache.
2690  int cert_id = 0;
2691  net::CertStatus cert_status = 0;
2692  int security_bits = -1;
2693  int connection_status = 0;
2694  SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids;
2695  DeserializeSecurityInfo(security_info, &cert_id, &cert_status,
2696                          &security_bits, &connection_status,
2697                          &signed_certificate_timestamp_ids);
2698  // TODO(alcutter,eranm): Pass signed_certificate_timestamp_ids into details
2699  LoadFromMemoryCacheDetails details(
2700      url, GetRenderProcessHost()->GetID(), cert_id, cert_status, http_method,
2701      mime_type, resource_type);
2702
2703  controller_.ssl_manager()->DidLoadFromMemoryCache(details);
2704
2705  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2706                    DidLoadResourceFromMemoryCache(details));
2707
2708  if (url.is_valid() && url.SchemeIsHTTPOrHTTPS()) {
2709    scoped_refptr<net::URLRequestContextGetter> request_context(
2710        resource_type == RESOURCE_TYPE_MEDIA ?
2711            GetBrowserContext()->GetMediaRequestContextForRenderProcess(
2712                GetRenderProcessHost()->GetID()) :
2713            GetBrowserContext()->GetRequestContextForRenderProcess(
2714                GetRenderProcessHost()->GetID()));
2715    BrowserThread::PostTask(
2716        BrowserThread::IO,
2717        FROM_HERE,
2718        base::Bind(&NotifyCacheOnIO, request_context, url, http_method));
2719  }
2720}
2721
2722void WebContentsImpl::OnDidDisplayInsecureContent() {
2723  RecordAction(base::UserMetricsAction("SSL.DisplayedInsecureContent"));
2724  displayed_insecure_content_ = true;
2725  SSLManager::NotifySSLInternalStateChanged(
2726      GetController().GetBrowserContext());
2727}
2728
2729void WebContentsImpl::OnDidRunInsecureContent(
2730    const std::string& security_origin, const GURL& target_url) {
2731  LOG(WARNING) << security_origin << " ran insecure content from "
2732               << target_url.possibly_invalid_spec();
2733  RecordAction(base::UserMetricsAction("SSL.RanInsecureContent"));
2734  if (EndsWith(security_origin, kDotGoogleDotCom, false))
2735    RecordAction(base::UserMetricsAction("SSL.RanInsecureContentGoogle"));
2736  controller_.ssl_manager()->DidRunInsecureContent(security_origin);
2737  displayed_insecure_content_ = true;
2738  SSLManager::NotifySSLInternalStateChanged(
2739      GetController().GetBrowserContext());
2740}
2741
2742void WebContentsImpl::OnDocumentLoadedInFrame() {
2743  CHECK(render_frame_message_source_);
2744  CHECK(!render_view_message_source_);
2745  RenderFrameHostImpl* rfh =
2746      static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
2747  FOR_EACH_OBSERVER(
2748      WebContentsObserver, observers_, DocumentLoadedInFrame(rfh));
2749}
2750
2751void WebContentsImpl::OnDidFinishLoad(
2752    const GURL& url) {
2753  if (!render_frame_message_source_) {
2754    RecordAction(base::UserMetricsAction("BadMessageTerminate_RVD2"));
2755    GetRenderProcessHost()->ReceivedBadMessage();
2756    return;
2757  }
2758
2759  GURL validated_url(url);
2760  RenderProcessHost* render_process_host =
2761      render_frame_message_source_->GetProcess();
2762  render_process_host->FilterURL(false, &validated_url);
2763
2764  RenderFrameHostImpl* rfh =
2765      static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
2766  FOR_EACH_OBSERVER(
2767      WebContentsObserver, observers_, DidFinishLoad(rfh, validated_url));
2768}
2769
2770void WebContentsImpl::OnDidStartLoading(bool to_different_document) {
2771  RenderFrameHostImpl* rfh =
2772      static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
2773  int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id();
2774
2775  // It is possible to get multiple calls to OnDidStartLoading that don't have
2776  // corresponding calls to OnDidStopLoading:
2777  // - With "swappedout://" URLs, this happens when a RenderView gets swapped
2778  //   out for a cross-process navigation, and it turns into a placeholder for
2779  //   one being rendered in a different process.
2780  // - Also, there might be more than one RenderFrameHost sharing the same
2781  //   FrameTreeNode (and thus sharing its ID) each sending a start.
2782  // - But in the future, once clamy@ moves navigation network requests to the
2783  //   browser process, there's a good chance that callbacks about starting and
2784  //   stopping will all be handled by the browser. When that happens, there
2785  //   should no longer be a start/stop call imbalance. TODO(avi): When this
2786  //   future arrives, update this code to not allow this case.
2787  DCHECK_GE(loading_frames_in_progress_, 0);
2788  if (loading_progresses_.find(render_frame_id) == loading_progresses_.end()) {
2789    if (loading_frames_in_progress_ == 0)
2790      DidStartLoading(rfh, to_different_document);
2791    ++loading_frames_in_progress_;
2792  }
2793
2794  loading_progresses_[render_frame_id] = kMinimumLoadingProgress;
2795  SendLoadProgressChanged();
2796}
2797
2798void WebContentsImpl::OnDidStopLoading() {
2799  RenderFrameHostImpl* rfh =
2800      static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
2801  int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id();
2802
2803  if (loading_progresses_.find(render_frame_id) != loading_progresses_.end()) {
2804    // Load stopped while we were still tracking load.  Make sure we update
2805    // progress based on this frame's completion.
2806    loading_progresses_[render_frame_id] = 1.0;
2807    SendLoadProgressChanged();
2808    // Then we clean-up our states.
2809    if (loading_total_progress_ == 1.0)
2810      ResetLoadProgressState();
2811  }
2812
2813  // TODO(japhet): This should be a DCHECK, but the pdf plugin sometimes
2814  // calls DidStopLoading() without a matching DidStartLoading().
2815  if (loading_frames_in_progress_ == 0)
2816    return;
2817  --loading_frames_in_progress_;
2818  if (loading_frames_in_progress_ == 0)
2819    DidStopLoading(rfh);
2820}
2821
2822void WebContentsImpl::OnDidChangeLoadProgress(double load_progress) {
2823  RenderFrameHostImpl* rfh =
2824      static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
2825  int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id();
2826
2827  loading_progresses_[render_frame_id] = load_progress;
2828
2829  // We notify progress change immediately for the first and last updates.
2830  // Also, since the message loop may be pretty busy when a page is loaded, it
2831  // might not execute a posted task in a timely manner so we make sure to
2832  // immediately send progress report if enough time has passed.
2833  base::TimeDelta min_delay =
2834      base::TimeDelta::FromMilliseconds(kMinimumDelayBetweenLoadingUpdatesMS);
2835  if (load_progress == 1.0 || loading_last_progress_update_.is_null() ||
2836      base::TimeTicks::Now() - loading_last_progress_update_ > min_delay) {
2837    // If there is a pending task to send progress, it is now obsolete.
2838    loading_weak_factory_.InvalidateWeakPtrs();
2839    SendLoadProgressChanged();
2840    if (loading_total_progress_ == 1.0)
2841      ResetLoadProgressState();
2842    return;
2843  }
2844
2845  if (loading_weak_factory_.HasWeakPtrs())
2846    return;
2847
2848  base::MessageLoop::current()->PostDelayedTask(
2849      FROM_HERE,
2850      base::Bind(&WebContentsImpl::SendLoadProgressChanged,
2851                 loading_weak_factory_.GetWeakPtr()),
2852      min_delay);
2853}
2854
2855void WebContentsImpl::OnGoToEntryAtOffset(int offset) {
2856  if (!delegate_ || delegate_->OnGoToEntryOffset(offset))
2857    controller_.GoToOffset(offset);
2858}
2859
2860void WebContentsImpl::OnUpdateZoomLimits(int minimum_percent,
2861                                         int maximum_percent) {
2862  minimum_zoom_percent_ = minimum_percent;
2863  maximum_zoom_percent_ = maximum_percent;
2864}
2865
2866void WebContentsImpl::OnEnumerateDirectory(int request_id,
2867                                           const base::FilePath& path) {
2868  if (!delegate_)
2869    return;
2870
2871  ChildProcessSecurityPolicyImpl* policy =
2872      ChildProcessSecurityPolicyImpl::GetInstance();
2873  if (policy->CanReadFile(GetRenderProcessHost()->GetID(), path))
2874    delegate_->EnumerateDirectory(this, request_id, path);
2875}
2876
2877void WebContentsImpl::OnRegisterProtocolHandler(const std::string& protocol,
2878                                                const GURL& url,
2879                                                const base::string16& title,
2880                                                bool user_gesture) {
2881  if (!delegate_)
2882    return;
2883
2884  ChildProcessSecurityPolicyImpl* policy =
2885      ChildProcessSecurityPolicyImpl::GetInstance();
2886  if (policy->IsPseudoScheme(protocol))
2887    return;
2888
2889  delegate_->RegisterProtocolHandler(this, protocol, url, user_gesture);
2890}
2891
2892void WebContentsImpl::OnUnregisterProtocolHandler(const std::string& protocol,
2893                                                  const GURL& url,
2894                                                  bool user_gesture) {
2895  if (!delegate_)
2896    return;
2897
2898  ChildProcessSecurityPolicyImpl* policy =
2899      ChildProcessSecurityPolicyImpl::GetInstance();
2900  if (policy->IsPseudoScheme(protocol))
2901    return;
2902
2903  delegate_->UnregisterProtocolHandler(this, protocol, url, user_gesture);
2904}
2905
2906void WebContentsImpl::OnFindReply(int request_id,
2907                                  int number_of_matches,
2908                                  const gfx::Rect& selection_rect,
2909                                  int active_match_ordinal,
2910                                  bool final_update) {
2911  if (delegate_) {
2912    delegate_->FindReply(this, request_id, number_of_matches, selection_rect,
2913                         active_match_ordinal, final_update);
2914  }
2915}
2916
2917#if defined(OS_ANDROID)
2918void WebContentsImpl::OnFindMatchRectsReply(
2919    int version,
2920    const std::vector<gfx::RectF>& rects,
2921    const gfx::RectF& active_rect) {
2922  if (delegate_)
2923    delegate_->FindMatchRectsReply(this, version, rects, active_rect);
2924}
2925
2926void WebContentsImpl::OnOpenDateTimeDialog(
2927    const ViewHostMsg_DateTimeDialogValue_Params& value) {
2928  date_time_chooser_->ShowDialog(ContentViewCore::FromWebContents(this),
2929                                 GetRenderViewHost(),
2930                                 value.dialog_type,
2931                                 value.dialog_value,
2932                                 value.minimum,
2933                                 value.maximum,
2934                                 value.step,
2935                                 value.suggestions);
2936}
2937
2938#endif
2939
2940void WebContentsImpl::OnPepperPluginHung(int plugin_child_id,
2941                                         const base::FilePath& path,
2942                                         bool is_hung) {
2943  UMA_HISTOGRAM_COUNTS("Pepper.PluginHung", 1);
2944
2945  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2946                    PluginHungStatusChanged(plugin_child_id, path, is_hung));
2947}
2948
2949void WebContentsImpl::OnPluginCrashed(const base::FilePath& plugin_path,
2950                                      base::ProcessId plugin_pid) {
2951  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2952                    PluginCrashed(plugin_path, plugin_pid));
2953}
2954
2955void WebContentsImpl::OnDomOperationResponse(const std::string& json_string,
2956                                             int automation_id) {
2957  DomOperationNotificationDetails details(json_string, automation_id);
2958  NotificationService::current()->Notify(
2959      NOTIFICATION_DOM_OPERATION_RESPONSE,
2960      Source<WebContents>(this),
2961      Details<DomOperationNotificationDetails>(&details));
2962}
2963
2964void WebContentsImpl::OnAppCacheAccessed(const GURL& manifest_url,
2965                                         bool blocked_by_policy) {
2966  // Notify observers about navigation.
2967  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
2968                    AppCacheAccessed(manifest_url, blocked_by_policy));
2969}
2970
2971void WebContentsImpl::OnOpenColorChooser(
2972    int color_chooser_id,
2973    SkColor color,
2974    const std::vector<ColorSuggestion>& suggestions) {
2975  ColorChooser* new_color_chooser = delegate_ ?
2976      delegate_->OpenColorChooser(this, color, suggestions) :
2977      NULL;
2978  if (!new_color_chooser)
2979    return;
2980  if (color_chooser_info_.get())
2981    color_chooser_info_->chooser->End();
2982
2983  color_chooser_info_.reset(new ColorChooserInfo(
2984      render_frame_message_source_->GetProcess()->GetID(),
2985      render_frame_message_source_->GetRoutingID(),
2986      new_color_chooser,
2987      color_chooser_id));
2988}
2989
2990void WebContentsImpl::OnEndColorChooser(int color_chooser_id) {
2991  if (color_chooser_info_ &&
2992      color_chooser_id == color_chooser_info_->identifier)
2993    color_chooser_info_->chooser->End();
2994}
2995
2996void WebContentsImpl::OnSetSelectedColorInColorChooser(int color_chooser_id,
2997                                                       SkColor color) {
2998  if (color_chooser_info_ &&
2999      color_chooser_id == color_chooser_info_->identifier)
3000    color_chooser_info_->chooser->SetSelectedColor(color);
3001}
3002
3003// This exists for render views that don't have a WebUI, but do have WebUI
3004// bindings enabled.
3005void WebContentsImpl::OnWebUISend(const GURL& source_url,
3006                                  const std::string& name,
3007                                  const base::ListValue& args) {
3008  if (delegate_)
3009    delegate_->WebUISend(this, source_url, name, args);
3010}
3011
3012#if defined(ENABLE_PLUGINS)
3013void WebContentsImpl::OnRequestPpapiBrokerPermission(
3014    int routing_id,
3015    const GURL& url,
3016    const base::FilePath& plugin_path) {
3017  if (!delegate_) {
3018    OnPpapiBrokerPermissionResult(routing_id, false);
3019    return;
3020  }
3021
3022  if (!delegate_->RequestPpapiBrokerPermission(
3023      this, url, plugin_path,
3024      base::Bind(&WebContentsImpl::OnPpapiBrokerPermissionResult,
3025                 base::Unretained(this), routing_id))) {
3026    NOTIMPLEMENTED();
3027    OnPpapiBrokerPermissionResult(routing_id, false);
3028  }
3029}
3030
3031void WebContentsImpl::OnPpapiBrokerPermissionResult(int routing_id,
3032                                                    bool result) {
3033  Send(new ViewMsg_PpapiBrokerPermissionResult(routing_id, result));
3034}
3035
3036void WebContentsImpl::OnBrowserPluginMessage(const IPC::Message& message) {
3037  // This creates a BrowserPluginEmbedder, which handles all the BrowserPlugin
3038  // specific messages for this WebContents. This means that any message from
3039  // a BrowserPlugin prior to this will be ignored.
3040  // For more info, see comment above classes BrowserPluginEmbedder and
3041  // BrowserPluginGuest.
3042  CHECK(!browser_plugin_embedder_.get());
3043  browser_plugin_embedder_.reset(BrowserPluginEmbedder::Create(this));
3044  browser_plugin_embedder_->OnMessageReceived(message);
3045}
3046#endif
3047
3048void WebContentsImpl::OnDidDownloadImage(
3049    int id,
3050    int http_status_code,
3051    const GURL& image_url,
3052    const std::vector<SkBitmap>& bitmaps,
3053    const std::vector<gfx::Size>& original_bitmap_sizes) {
3054  if (bitmaps.size() != original_bitmap_sizes.size())
3055    return;
3056
3057  ImageDownloadMap::iterator iter = image_download_map_.find(id);
3058  if (iter == image_download_map_.end()) {
3059    // Currently WebContents notifies us of ANY downloads so that it is
3060    // possible to get here.
3061    return;
3062  }
3063  if (!iter->second.is_null()) {
3064    iter->second.Run(
3065        id, http_status_code, image_url, bitmaps, original_bitmap_sizes);
3066  }
3067  image_download_map_.erase(id);
3068}
3069
3070void WebContentsImpl::OnUpdateFaviconURL(
3071    const std::vector<FaviconURL>& candidates) {
3072  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3073                    DidUpdateFaviconURL(candidates));
3074}
3075
3076void WebContentsImpl::CreateAudioPowerSaveBlocker() {
3077  // ChromeOS has its own way of handling power save blocks for media.
3078#if !defined(OS_CHROMEOS)
3079  DCHECK(!audio_power_save_blocker_);
3080  audio_power_save_blocker_ = PowerSaveBlocker::Create(
3081      PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, "Playing Audio");
3082#endif
3083}
3084
3085void WebContentsImpl::CreateVideoPowerSaveBlocker() {
3086  // ChromeOS has its own way of handling power save blocks for media.
3087#if !defined(OS_CHROMEOS)
3088  DCHECK(!video_power_save_blocker_);
3089  DCHECK(!active_video_players_.empty());
3090  video_power_save_blocker_ = PowerSaveBlocker::Create(
3091      PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, "Playing Video");
3092#if defined(OS_ANDROID)
3093  static_cast<PowerSaveBlockerImpl*>(video_power_save_blocker_.get())
3094      ->InitDisplaySleepBlocker(GetView()->GetNativeView());
3095#endif
3096#endif
3097}
3098
3099void WebContentsImpl::MaybeReleasePowerSaveBlockers() {
3100  // If there are no more audio players and we don't have audio stream
3101  // monitoring, release the audio power save blocker here instead of during
3102  // NotifyNavigationStateChanged().
3103  if (active_audio_players_.empty() &&
3104      !AudioStreamMonitor::monitoring_available()) {
3105    audio_power_save_blocker_.reset();
3106  }
3107
3108  // If there are no more video players, clear the video power save blocker.
3109  if (active_video_players_.empty())
3110    video_power_save_blocker_.reset();
3111}
3112
3113void WebContentsImpl::OnMediaPlayingNotification(int64 player_cookie,
3114                                                 bool has_video,
3115                                                 bool has_audio,
3116                                                 bool is_remote) {
3117  // Ignore the videos playing remotely and don't hold the wake lock for the
3118  // screen.
3119  if (is_remote) return;
3120
3121  if (has_audio) {
3122    AddMediaPlayerEntry(player_cookie, &active_audio_players_);
3123
3124    // If we don't have audio stream monitoring, allocate the audio power save
3125    // blocker here instead of during NotifyNavigationStateChanged().
3126    if (!audio_power_save_blocker_ &&
3127        !AudioStreamMonitor::monitoring_available()) {
3128      CreateAudioPowerSaveBlocker();
3129    }
3130  }
3131
3132  if (has_video) {
3133    AddMediaPlayerEntry(player_cookie, &active_video_players_);
3134
3135    // If we're not hidden and have just created a player, create a blocker.
3136    if (!video_power_save_blocker_ && !IsHidden())
3137      CreateVideoPowerSaveBlocker();
3138  }
3139}
3140
3141void WebContentsImpl::OnMediaPausedNotification(int64 player_cookie) {
3142  RemoveMediaPlayerEntry(player_cookie, &active_audio_players_);
3143  RemoveMediaPlayerEntry(player_cookie, &active_video_players_);
3144  MaybeReleasePowerSaveBlockers();
3145}
3146
3147void WebContentsImpl::OnFirstVisuallyNonEmptyPaint() {
3148  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3149                    DidFirstVisuallyNonEmptyPaint());
3150}
3151
3152void WebContentsImpl::DidChangeVisibleSSLState() {
3153  if (delegate_)
3154    delegate_->VisibleSSLStateChanged(this);
3155}
3156
3157void WebContentsImpl::NotifyBeforeFormRepostWarningShow() {
3158  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3159                    BeforeFormRepostWarningShow());
3160}
3161
3162void WebContentsImpl::ActivateAndShowRepostFormWarningDialog() {
3163  Activate();
3164  if (delegate_)
3165    delegate_->ShowRepostFormWarningDialog(this);
3166}
3167
3168bool WebContentsImpl::HasAccessedInitialDocument() {
3169  return has_accessed_initial_document_;
3170}
3171
3172// Notifies the RenderWidgetHost instance about the fact that the page is
3173// loading, or done loading.
3174void WebContentsImpl::SetIsLoading(RenderViewHost* render_view_host,
3175                                   bool is_loading,
3176                                   bool to_different_document,
3177                                   LoadNotificationDetails* details) {
3178  if (is_loading == is_loading_)
3179    return;
3180
3181  if (!is_loading) {
3182    load_state_ = net::LoadStateWithParam(net::LOAD_STATE_IDLE,
3183                                          base::string16());
3184    load_state_host_.clear();
3185    upload_size_ = 0;
3186    upload_position_ = 0;
3187  }
3188
3189  GetRenderManager()->SetIsLoading(is_loading);
3190
3191  is_loading_ = is_loading;
3192  waiting_for_response_ = is_loading;
3193  is_load_to_different_document_ = to_different_document;
3194
3195  if (delegate_)
3196    delegate_->LoadingStateChanged(this, to_different_document);
3197  NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD);
3198
3199  std::string url = (details ? details->url.possibly_invalid_spec() : "NULL");
3200  if (is_loading) {
3201    TRACE_EVENT_ASYNC_BEGIN1("browser,navigation", "WebContentsImpl Loading",
3202                             this, "URL", url);
3203    FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3204                      DidStartLoading(render_view_host));
3205  } else {
3206    TRACE_EVENT_ASYNC_END1("browser,navigation", "WebContentsImpl Loading",
3207                           this, "URL", url);
3208    FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3209                      DidStopLoading(render_view_host));
3210  }
3211
3212  // TODO(avi): Remove. http://crbug.com/170921
3213  int type = is_loading ? NOTIFICATION_LOAD_START : NOTIFICATION_LOAD_STOP;
3214  NotificationDetails det = NotificationService::NoDetails();
3215  if (details)
3216      det = Details<LoadNotificationDetails>(details);
3217  NotificationService::current()->Notify(
3218      type, Source<NavigationController>(&controller_), det);
3219}
3220
3221void WebContentsImpl::SelectRange(const gfx::Point& start,
3222                                  const gfx::Point& end) {
3223  RenderFrameHost* focused_frame = GetFocusedFrame();
3224  if (!focused_frame)
3225    return;
3226
3227  focused_frame->Send(
3228      new InputMsg_SelectRange(focused_frame->GetRoutingID(), start, end));
3229}
3230
3231void WebContentsImpl::UpdateMaxPageIDIfNecessary(RenderViewHost* rvh) {
3232  // If we are creating a RVH for a restored controller, then we need to make
3233  // sure the RenderView starts with a next_page_id_ larger than the number
3234  // of restored entries.  This must be called before the RenderView starts
3235  // navigating (to avoid a race between the browser updating max_page_id and
3236  // the renderer updating next_page_id_).  Because of this, we only call this
3237  // from CreateRenderView and allow that to notify the RenderView for us.
3238  int max_restored_page_id = controller_.GetMaxRestoredPageID();
3239  if (max_restored_page_id >
3240      GetMaxPageIDForSiteInstance(rvh->GetSiteInstance()))
3241    UpdateMaxPageIDForSiteInstance(rvh->GetSiteInstance(),
3242                                   max_restored_page_id);
3243}
3244
3245bool WebContentsImpl::UpdateTitleForEntry(NavigationEntryImpl* entry,
3246                                          const base::string16& title) {
3247  // For file URLs without a title, use the pathname instead. In the case of a
3248  // synthesized title, we don't want the update to count toward the "one set
3249  // per page of the title to history."
3250  base::string16 final_title;
3251  bool explicit_set;
3252  if (entry && entry->GetURL().SchemeIsFile() && title.empty()) {
3253    final_title = base::UTF8ToUTF16(entry->GetURL().ExtractFileName());
3254    explicit_set = false;  // Don't count synthetic titles toward the set limit.
3255  } else {
3256    base::TrimWhitespace(title, base::TRIM_ALL, &final_title);
3257    explicit_set = true;
3258  }
3259
3260  // If a page is created via window.open and never navigated,
3261  // there will be no navigation entry. In this situation,
3262  // |page_title_when_no_navigation_entry_| will be used for page title.
3263  if (entry) {
3264    if (final_title == entry->GetTitle())
3265      return false;  // Nothing changed, don't bother.
3266
3267    entry->SetTitle(final_title);
3268  } else {
3269    if (page_title_when_no_navigation_entry_ == final_title)
3270      return false;  // Nothing changed, don't bother.
3271
3272    page_title_when_no_navigation_entry_ = final_title;
3273  }
3274
3275  // Lastly, set the title for the view.
3276  view_->SetPageTitle(final_title);
3277
3278  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3279                    TitleWasSet(entry, explicit_set));
3280
3281  // TODO(avi): Remove. http://crbug.com/170921
3282  std::pair<NavigationEntry*, bool> details =
3283      std::make_pair(entry, explicit_set);
3284  NotificationService::current()->Notify(
3285      NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
3286      Source<WebContents>(this),
3287      Details<std::pair<NavigationEntry*, bool> >(&details));
3288
3289  return true;
3290}
3291
3292void WebContentsImpl::SendLoadProgressChanged() {
3293  loading_last_progress_update_ = base::TimeTicks::Now();
3294  double progress = 0.0;
3295  int frame_count = 0;
3296
3297  for (LoadingProgressMap::iterator it = loading_progresses_.begin();
3298       it != loading_progresses_.end();
3299       ++it) {
3300    progress += it->second;
3301    ++frame_count;
3302  }
3303  if (frame_count == 0)
3304    return;
3305  progress /= frame_count;
3306  DCHECK(progress <= 1.0);
3307
3308  if (progress <= loading_total_progress_)
3309    return;
3310  loading_total_progress_ = progress;
3311
3312  if (delegate_)
3313    delegate_->LoadProgressChanged(this, progress);
3314}
3315
3316void WebContentsImpl::ResetLoadProgressState() {
3317  loading_progresses_.clear();
3318  loading_total_progress_ = 0.0;
3319  loading_weak_factory_.InvalidateWeakPtrs();
3320  loading_last_progress_update_ = base::TimeTicks();
3321}
3322
3323void WebContentsImpl::NotifyViewSwapped(RenderViewHost* old_host,
3324                                        RenderViewHost* new_host) {
3325  // After sending out a swap notification, we need to send a disconnect
3326  // notification so that clients that pick up a pointer to |this| can NULL the
3327  // pointer.  See Bug 1230284.
3328  notify_disconnection_ = true;
3329  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3330                    RenderViewHostChanged(old_host, new_host));
3331
3332  // TODO(avi): Remove. http://crbug.com/170921
3333  std::pair<RenderViewHost*, RenderViewHost*> details =
3334      std::make_pair(old_host, new_host);
3335  NotificationService::current()->Notify(
3336      NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
3337      Source<WebContents>(this),
3338      Details<std::pair<RenderViewHost*, RenderViewHost*> >(&details));
3339
3340  // Ensure that the associated embedder gets cleared after a RenderViewHost
3341  // gets swapped, so we don't reuse the same embedder next time a
3342  // RenderViewHost is attached to this WebContents.
3343  RemoveBrowserPluginEmbedder();
3344}
3345
3346void WebContentsImpl::NotifyFrameSwapped(RenderFrameHost* old_host,
3347                                         RenderFrameHost* new_host) {
3348  FOR_EACH_OBSERVER(WebContentsObserver,
3349                    observers_,
3350                    RenderFrameHostChanged(old_host, new_host));
3351}
3352
3353// TODO(avi): Remove this entire function because this notification is already
3354// covered by two observer functions. http://crbug.com/170921
3355void WebContentsImpl::NotifyDisconnected() {
3356  if (!notify_disconnection_)
3357    return;
3358
3359  notify_disconnection_ = false;
3360  NotificationService::current()->Notify(
3361      NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
3362      Source<WebContents>(this),
3363      NotificationService::NoDetails());
3364}
3365
3366void WebContentsImpl::NotifyNavigationEntryCommitted(
3367    const LoadCommittedDetails& load_details) {
3368  FOR_EACH_OBSERVER(
3369      WebContentsObserver, observers_, NavigationEntryCommitted(load_details));
3370}
3371
3372bool WebContentsImpl::OnMessageReceived(RenderFrameHost* render_frame_host,
3373                                        const IPC::Message& message) {
3374  return OnMessageReceived(NULL, render_frame_host, message);
3375}
3376
3377const GURL& WebContentsImpl::GetMainFrameLastCommittedURL() const {
3378  return GetLastCommittedURL();
3379}
3380
3381void WebContentsImpl::RenderFrameCreated(RenderFrameHost* render_frame_host) {
3382  // Note this is only for subframes, the notification for the main frame
3383  // happens in RenderViewCreated.
3384  FOR_EACH_OBSERVER(WebContentsObserver,
3385                    observers_,
3386                    RenderFrameCreated(render_frame_host));
3387  SetAccessibilityModeOnFrame(accessibility_mode_, render_frame_host);
3388}
3389
3390void WebContentsImpl::RenderFrameDeleted(RenderFrameHost* render_frame_host) {
3391  ClearPowerSaveBlockers(render_frame_host);
3392  FOR_EACH_OBSERVER(WebContentsObserver,
3393                    observers_,
3394                    RenderFrameDeleted(render_frame_host));
3395}
3396
3397void WebContentsImpl::WorkerCrashed(RenderFrameHost* render_frame_host) {
3398  if (delegate_)
3399    delegate_->WorkerCrashed(this);
3400}
3401
3402void WebContentsImpl::ShowContextMenu(RenderFrameHost* render_frame_host,
3403                                      const ContextMenuParams& params) {
3404  ContextMenuParams context_menu_params(params);
3405  // Allow WebContentsDelegates to handle the context menu operation first.
3406  if (GetBrowserPluginGuest()) {
3407    WebContentsViewGuest* view_guest =
3408        static_cast<WebContentsViewGuest*>(GetView());
3409    context_menu_params = view_guest->ConvertContextMenuParams(params);
3410  }
3411  if (delegate_ && delegate_->HandleContextMenu(context_menu_params))
3412    return;
3413
3414  render_view_host_delegate_view_->ShowContextMenu(render_frame_host,
3415                                                   context_menu_params);
3416}
3417
3418void WebContentsImpl::RunJavaScriptMessage(
3419    RenderFrameHost* render_frame_host,
3420    const base::string16& message,
3421    const base::string16& default_prompt,
3422    const GURL& frame_url,
3423    JavaScriptMessageType javascript_message_type,
3424    IPC::Message* reply_msg) {
3425  // Suppress JavaScript dialogs when requested. Also suppress messages when
3426  // showing an interstitial as it's shown over the previous page and we don't
3427  // want the hidden page's dialogs to interfere with the interstitial.
3428  bool suppress_this_message =
3429      static_cast<RenderViewHostImpl*>(render_frame_host->GetRenderViewHost())->
3430          IsSwappedOut() ||
3431      ShowingInterstitialPage() ||
3432      !delegate_ ||
3433      delegate_->ShouldSuppressDialogs() ||
3434      !delegate_->GetJavaScriptDialogManager();
3435
3436  if (!suppress_this_message) {
3437    std::string accept_lang = GetContentClient()->browser()->
3438      GetAcceptLangs(GetBrowserContext());
3439    dialog_manager_ = delegate_->GetJavaScriptDialogManager();
3440    dialog_manager_->RunJavaScriptDialog(
3441        this,
3442        frame_url.GetOrigin(),
3443        accept_lang,
3444        javascript_message_type,
3445        message,
3446        default_prompt,
3447        base::Bind(&WebContentsImpl::OnDialogClosed,
3448                   base::Unretained(this),
3449                   render_frame_host->GetProcess()->GetID(),
3450                   render_frame_host->GetRoutingID(),
3451                   reply_msg,
3452                   false),
3453        &suppress_this_message);
3454  }
3455
3456  if (suppress_this_message) {
3457    // If we are suppressing messages, just reply as if the user immediately
3458    // pressed "Cancel", passing true to |dialog_was_suppressed|.
3459    OnDialogClosed(render_frame_host->GetProcess()->GetID(),
3460                   render_frame_host->GetRoutingID(), reply_msg,
3461                   true, false, base::string16());
3462  }
3463
3464  // OnDialogClosed (two lines up) may have caused deletion of this object (see
3465  // http://crbug.com/288961 ). The only safe thing to do here is return.
3466}
3467
3468void WebContentsImpl::RunBeforeUnloadConfirm(
3469    RenderFrameHost* render_frame_host,
3470    const base::string16& message,
3471    bool is_reload,
3472    IPC::Message* reply_msg) {
3473  RenderFrameHostImpl* rfhi =
3474      static_cast<RenderFrameHostImpl*>(render_frame_host);
3475  RenderViewHostImpl* rvhi =
3476      static_cast<RenderViewHostImpl*>(render_frame_host->GetRenderViewHost());
3477  if (delegate_)
3478    delegate_->WillRunBeforeUnloadConfirm();
3479
3480  bool suppress_this_message =
3481      rvhi->rvh_state() != RenderViewHostImpl::STATE_DEFAULT ||
3482      !delegate_ ||
3483      delegate_->ShouldSuppressDialogs() ||
3484      !delegate_->GetJavaScriptDialogManager();
3485  if (suppress_this_message) {
3486    rfhi->JavaScriptDialogClosed(reply_msg, true, base::string16(), true);
3487    return;
3488  }
3489
3490  is_showing_before_unload_dialog_ = true;
3491  dialog_manager_ = delegate_->GetJavaScriptDialogManager();
3492  dialog_manager_->RunBeforeUnloadDialog(
3493      this, message, is_reload,
3494      base::Bind(&WebContentsImpl::OnDialogClosed, base::Unretained(this),
3495                 render_frame_host->GetProcess()->GetID(),
3496                 render_frame_host->GetRoutingID(), reply_msg,
3497                 false));
3498}
3499
3500WebContents* WebContentsImpl::GetAsWebContents() {
3501  return this;
3502}
3503
3504bool WebContentsImpl::IsNeverVisible() {
3505  if (!delegate_)
3506    return false;
3507  return delegate_->IsNeverVisible(this);
3508}
3509
3510#if defined(OS_WIN)
3511gfx::NativeViewAccessible WebContentsImpl::GetParentNativeViewAccessible() {
3512  return accessible_parent_;
3513}
3514#endif
3515
3516RenderViewHostDelegateView* WebContentsImpl::GetDelegateView() {
3517  return render_view_host_delegate_view_;
3518}
3519
3520RendererPreferences WebContentsImpl::GetRendererPrefs(
3521    BrowserContext* browser_context) const {
3522  return renderer_preferences_;
3523}
3524
3525gfx::Rect WebContentsImpl::GetRootWindowResizerRect() const {
3526  if (delegate_)
3527    return delegate_->GetRootWindowResizerRect();
3528  return gfx::Rect();
3529}
3530
3531void WebContentsImpl::RemoveBrowserPluginEmbedder() {
3532  if (browser_plugin_embedder_)
3533    browser_plugin_embedder_.reset();
3534}
3535
3536void WebContentsImpl::RenderViewCreated(RenderViewHost* render_view_host) {
3537  // Don't send notifications if we are just creating a swapped-out RVH for
3538  // the opener chain.  These won't be used for view-source or WebUI, so it's
3539  // ok to return early.
3540  if (static_cast<RenderViewHostImpl*>(render_view_host)->IsSwappedOut())
3541    return;
3542
3543  if (delegate_)
3544    view_->SetOverscrollControllerEnabled(CanOverscrollContent());
3545
3546  NotificationService::current()->Notify(
3547      NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED,
3548      Source<WebContents>(this),
3549      Details<RenderViewHost>(render_view_host));
3550
3551  // When we're creating views, we're still doing initial setup, so we always
3552  // use the pending Web UI rather than any possibly existing committed one.
3553  if (GetRenderManager()->pending_web_ui())
3554    GetRenderManager()->pending_web_ui()->RenderViewCreated(render_view_host);
3555
3556  NavigationEntry* entry = controller_.GetPendingEntry();
3557  if (entry && entry->IsViewSourceMode()) {
3558    // Put the renderer in view source mode.
3559    render_view_host->Send(
3560        new ViewMsg_EnableViewSourceMode(render_view_host->GetRoutingID()));
3561  }
3562
3563  view_->RenderViewCreated(render_view_host);
3564
3565  FOR_EACH_OBSERVER(
3566      WebContentsObserver, observers_, RenderViewCreated(render_view_host));
3567
3568  // We tell the observers now instead of when the main RenderFrameHostImpl is
3569  // constructed because otherwise it would be too early (i.e. IPCs sent to the
3570  // frame would be dropped because it's not created yet).
3571  RenderFrameHost* main_frame = render_view_host->GetMainFrame();
3572  FOR_EACH_OBSERVER(
3573      WebContentsObserver, observers_, RenderFrameCreated(main_frame));
3574  SetAccessibilityModeOnFrame(accessibility_mode_, main_frame);
3575}
3576
3577void WebContentsImpl::RenderViewReady(RenderViewHost* rvh) {
3578  if (rvh != GetRenderViewHost()) {
3579    // Don't notify the world, since this came from a renderer in the
3580    // background.
3581    return;
3582  }
3583
3584  notify_disconnection_ = true;
3585  // TODO(avi): Remove. http://crbug.com/170921
3586  NotificationService::current()->Notify(
3587      NOTIFICATION_WEB_CONTENTS_CONNECTED,
3588      Source<WebContents>(this),
3589      NotificationService::NoDetails());
3590
3591  bool was_crashed = IsCrashed();
3592  SetIsCrashed(base::TERMINATION_STATUS_STILL_RUNNING, 0);
3593
3594  // Restore the focus to the tab (otherwise the focus will be on the top
3595  // window).
3596  if (was_crashed && !FocusLocationBarByDefault() &&
3597      (!delegate_ || delegate_->ShouldFocusPageAfterCrash())) {
3598    view_->Focus();
3599  }
3600
3601  FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewReady());
3602}
3603
3604void WebContentsImpl::RenderViewTerminated(RenderViewHost* rvh,
3605                                           base::TerminationStatus status,
3606                                           int error_code) {
3607  if (rvh != GetRenderViewHost()) {
3608    // The pending page's RenderViewHost is gone.
3609    return;
3610  }
3611
3612  // Ensure fullscreen mode is exited in the |delegate_| since a crashed
3613  // renderer may not have made a clean exit.
3614  if (IsFullscreenForCurrentTab())
3615    ToggleFullscreenMode(false);
3616
3617  // Cancel any visible dialogs so they are not left dangling over the sad tab.
3618  if (dialog_manager_)
3619    dialog_manager_->CancelActiveAndPendingDialogs(this);
3620
3621  if (delegate_)
3622    delegate_->HideValidationMessage(this);
3623
3624  SetIsLoading(rvh, false, true, NULL);
3625  NotifyDisconnected();
3626  SetIsCrashed(status, error_code);
3627
3628  // Reset the loading progress. TODO(avi): What does it mean to have a
3629  // "renderer crash" when there is more than one renderer process serving a
3630  // webpage? Once this function is called at a more granular frame level, we
3631  // probably will need to more granularly reset the state here.
3632  ResetLoadProgressState();
3633  loading_frames_in_progress_ = 0;
3634
3635  FOR_EACH_OBSERVER(WebContentsObserver,
3636                    observers_,
3637                    RenderProcessGone(GetCrashedStatus()));
3638}
3639
3640void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) {
3641  FOR_EACH_OBSERVER(WebContentsObserver, observers_, RenderViewDeleted(rvh));
3642}
3643
3644void WebContentsImpl::UpdateState(RenderViewHost* rvh,
3645                                  int32 page_id,
3646                                  const PageState& page_state) {
3647  // Ensure that this state update comes from either the active RVH or one of
3648  // the swapped out RVHs.  We don't expect to hear from any other RVHs.
3649  // TODO(nasko): This should go through RenderFrameHost.
3650  // TODO(creis): We can't update state for cross-process subframes until we
3651  // have FrameNavigationEntries.  Once we do, this should be a DCHECK.
3652  if (rvh != GetRenderViewHost() &&
3653      !GetRenderManager()->IsRVHOnSwappedOutList(
3654          static_cast<RenderViewHostImpl*>(rvh)))
3655    return;
3656
3657  // We must be prepared to handle state updates for any page, these occur
3658  // when the user is scrolling and entering form data, as well as when we're
3659  // leaving a page, in which case our state may have already been moved to
3660  // the next page. The navigation controller will look up the appropriate
3661  // NavigationEntry and update it when it is notified via the delegate.
3662
3663  int entry_index = controller_.GetEntryIndexWithPageID(
3664      rvh->GetSiteInstance(), page_id);
3665  if (entry_index < 0)
3666    return;
3667  NavigationEntry* entry = controller_.GetEntryAtIndex(entry_index);
3668
3669  if (page_state == entry->GetPageState())
3670    return;  // Nothing to update.
3671  entry->SetPageState(page_state);
3672  controller_.NotifyEntryChanged(entry, entry_index);
3673}
3674
3675void WebContentsImpl::UpdateTargetURL(const GURL& url) {
3676  if (delegate_)
3677    delegate_->UpdateTargetURL(this, url);
3678}
3679
3680void WebContentsImpl::Close(RenderViewHost* rvh) {
3681#if defined(OS_MACOSX)
3682  // The UI may be in an event-tracking loop, such as between the
3683  // mouse-down and mouse-up in text selection or a button click.
3684  // Defer the close until after tracking is complete, so that we
3685  // don't free objects out from under the UI.
3686  // TODO(shess): This could get more fine-grained.  For instance,
3687  // closing a tab in another window while selecting text in the
3688  // current window's Omnibox should be just fine.
3689  if (view_->IsEventTracking()) {
3690    view_->CloseTabAfterEventTracking();
3691    return;
3692  }
3693#endif
3694
3695  // Ignore this if it comes from a RenderViewHost that we aren't showing.
3696  if (delegate_ && rvh == GetRenderViewHost())
3697    delegate_->CloseContents(this);
3698}
3699
3700void WebContentsImpl::SwappedOut(RenderFrameHost* rfh) {
3701  if (delegate_ && rfh->GetRenderViewHost() == GetRenderViewHost())
3702    delegate_->SwappedOut(this);
3703}
3704
3705void WebContentsImpl::DidDeferAfterResponseStarted(
3706    const TransitionLayerData& transition_data) {
3707#if defined(OS_ANDROID)
3708  GetWebContentsAndroid()->DidDeferAfterResponseStarted(transition_data);
3709#endif
3710}
3711
3712bool WebContentsImpl::WillHandleDeferAfterResponseStarted() {
3713#if defined(OS_ANDROID)
3714  return GetWebContentsAndroid()->WillHandleDeferAfterResponseStarted();
3715#else
3716  return false;
3717#endif
3718}
3719
3720void WebContentsImpl::RequestMove(const gfx::Rect& new_bounds) {
3721  if (delegate_ && delegate_->IsPopupOrPanel(this))
3722    delegate_->MoveContents(this, new_bounds);
3723}
3724
3725void WebContentsImpl::DidStartLoading(RenderFrameHost* render_frame_host,
3726                                      bool to_different_document) {
3727  SetIsLoading(render_frame_host->GetRenderViewHost(), true,
3728               to_different_document, NULL);
3729}
3730
3731void WebContentsImpl::DidStopLoading(RenderFrameHost* render_frame_host) {
3732  scoped_ptr<LoadNotificationDetails> details;
3733
3734  // Use the last committed entry rather than the active one, in case a
3735  // pending entry has been created.
3736  NavigationEntry* entry = controller_.GetLastCommittedEntry();
3737  Navigator* navigator = frame_tree_.root()->navigator();
3738
3739  // An entry may not exist for a stop when loading an initial blank page or
3740  // if an iframe injected by script into a blank page finishes loading.
3741  if (entry) {
3742    base::TimeDelta elapsed =
3743        base::TimeTicks::Now() - navigator->GetCurrentLoadStart();
3744
3745    details.reset(new LoadNotificationDetails(
3746        entry->GetVirtualURL(),
3747        entry->GetTransitionType(),
3748        elapsed,
3749        &controller_,
3750        controller_.GetCurrentEntryIndex()));
3751  }
3752
3753  SetIsLoading(render_frame_host->GetRenderViewHost(), false, true,
3754               details.get());
3755}
3756
3757void WebContentsImpl::DidCancelLoading() {
3758  controller_.DiscardNonCommittedEntries();
3759
3760  // Update the URL display.
3761  NotifyNavigationStateChanged(INVALIDATE_TYPE_URL);
3762}
3763
3764void WebContentsImpl::DidAccessInitialDocument() {
3765  has_accessed_initial_document_ = true;
3766
3767  // We may have left a failed browser-initiated navigation in the address bar
3768  // to let the user edit it and try again.  Clear it now that content might
3769  // show up underneath it.
3770  if (!IsLoading() && controller_.GetPendingEntry())
3771    controller_.DiscardPendingEntry();
3772
3773  // Update the URL display.
3774  NotifyNavigationStateChanged(INVALIDATE_TYPE_URL);
3775}
3776
3777void WebContentsImpl::DidDisownOpener(RenderFrameHost* render_frame_host) {
3778  // No action is necessary if the opener has already been cleared.
3779  if (!opener_)
3780    return;
3781
3782  // Clear our opener so that future cross-process navigations don't have an
3783  // opener assigned.
3784  RemoveDestructionObserver(opener_);
3785  opener_ = NULL;
3786
3787  // Notify all swapped out RenderViewHosts for this tab.  This is important
3788  // in case we go back to them, or if another window in those processes tries
3789  // to access window.opener.
3790  GetRenderManager()->DidDisownOpener(render_frame_host);
3791}
3792
3793void WebContentsImpl::DocumentOnLoadCompleted(
3794    RenderFrameHost* render_frame_host) {
3795  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3796                    DocumentOnLoadCompletedInMainFrame());
3797
3798  // TODO(avi): Remove. http://crbug.com/170921
3799  NotificationService::current()->Notify(
3800      NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
3801      Source<WebContents>(this),
3802      NotificationService::NoDetails());
3803}
3804
3805void WebContentsImpl::UpdateTitle(RenderFrameHost* render_frame_host,
3806                                  int32 page_id,
3807                                  const base::string16& title,
3808                                  base::i18n::TextDirection title_direction) {
3809  RenderViewHost* rvh = render_frame_host->GetRenderViewHost();
3810
3811  // If we have a title, that's a pretty good indication that we've started
3812  // getting useful data.
3813  SetNotWaitingForResponse();
3814
3815  // Try to find the navigation entry, which might not be the current one.
3816  // For example, it might be from a pending RVH for the pending entry.
3817  NavigationEntryImpl* entry = controller_.GetEntryWithPageID(
3818      rvh->GetSiteInstance(), page_id);
3819
3820  // We can handle title updates when we don't have an entry in
3821  // UpdateTitleForEntry, but only if the update is from the current RVH.
3822  // TODO(avi): Change to make decisions based on the RenderFrameHost.
3823  if (!entry && rvh != GetRenderViewHost())
3824    return;
3825
3826  // TODO(evan): make use of title_direction.
3827  // http://code.google.com/p/chromium/issues/detail?id=27094
3828  if (!UpdateTitleForEntry(entry, title))
3829    return;
3830
3831  // Broadcast notifications when the UI should be updated.
3832  if (entry == controller_.GetEntryAtOffset(0))
3833    NotifyNavigationStateChanged(INVALIDATE_TYPE_TITLE);
3834}
3835
3836void WebContentsImpl::UpdateEncoding(RenderFrameHost* render_frame_host,
3837                                     const std::string& encoding) {
3838  SetEncoding(encoding);
3839}
3840
3841void WebContentsImpl::DocumentAvailableInMainFrame(
3842    RenderViewHost* render_view_host) {
3843  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
3844                    DocumentAvailableInMainFrame());
3845}
3846void WebContentsImpl::RouteCloseEvent(RenderViewHost* rvh) {
3847  // Tell the active RenderViewHost to run unload handlers and close, as long
3848  // as the request came from a RenderViewHost in the same BrowsingInstance.
3849  // In most cases, we receive this from a swapped out RenderViewHost.
3850  // It is possible to receive it from one that has just been swapped in,
3851  // in which case we might as well deliver the message anyway.
3852  if (rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance()))
3853    GetRenderViewHost()->ClosePage();
3854}
3855
3856void WebContentsImpl::RouteMessageEvent(
3857    RenderViewHost* rvh,
3858    const ViewMsg_PostMessage_Params& params) {
3859  // Only deliver the message to the active RenderViewHost if the request
3860  // came from a RenderViewHost in the same BrowsingInstance or if this
3861  // WebContents is dedicated to a browser plugin guest.
3862  // Note: This check means that an embedder could theoretically receive a
3863  // postMessage from anyone (not just its own guests). However, this is
3864  // probably not a risk for apps since other pages won't have references
3865  // to App windows.
3866  if (!rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance()) &&
3867      !GetBrowserPluginGuest() && !GetBrowserPluginEmbedder())
3868    return;
3869
3870  ViewMsg_PostMessage_Params new_params(params);
3871
3872  if (!params.message_port_ids.empty()) {
3873    MessagePortMessageFilter* message_port_message_filter =
3874        static_cast<RenderProcessHostImpl*>(GetRenderProcessHost())
3875            ->message_port_message_filter();
3876    message_port_message_filter->UpdateMessagePortsWithNewRoutes(
3877        params.message_port_ids,
3878        &new_params.new_routing_ids);
3879  }
3880
3881  // If there is a source_routing_id, translate it to the routing ID for
3882  // the equivalent swapped out RVH in the target process.  If we need
3883  // to create a swapped out RVH for the source tab, we create its opener
3884  // chain as well, since those will also be accessible to the target page.
3885  if (new_params.source_routing_id != MSG_ROUTING_NONE) {
3886    // Try to look up the WebContents for the source page.
3887    WebContentsImpl* source_contents = NULL;
3888    RenderViewHostImpl* source_rvh = RenderViewHostImpl::FromID(
3889        rvh->GetProcess()->GetID(), params.source_routing_id);
3890    if (source_rvh) {
3891      source_contents = static_cast<WebContentsImpl*>(
3892          source_rvh->GetDelegate()->GetAsWebContents());
3893    }
3894
3895    if (source_contents) {
3896      if (GetBrowserPluginGuest()) {
3897        // We create a swapped out RenderView for the embedder in the guest's
3898        // render process but we intentionally do not expose the embedder's
3899        // opener chain to it.
3900        new_params.source_routing_id =
3901            source_contents->CreateSwappedOutRenderView(GetSiteInstance());
3902      } else {
3903        new_params.source_routing_id =
3904            source_contents->CreateOpenerRenderViews(GetSiteInstance());
3905      }
3906    } else {
3907      // We couldn't find it, so don't pass a source frame.
3908      new_params.source_routing_id = MSG_ROUTING_NONE;
3909    }
3910  }
3911
3912  // In most cases, we receive this from a swapped out RenderViewHost.
3913  // It is possible to receive it from one that has just been swapped in,
3914  // in which case we might as well deliver the message anyway.
3915  Send(new ViewMsg_PostMessageEvent(GetRoutingID(), new_params));
3916}
3917
3918bool WebContentsImpl::AddMessageToConsole(int32 level,
3919                                          const base::string16& message,
3920                                          int32 line_no,
3921                                          const base::string16& source_id) {
3922  if (!delegate_)
3923    return false;
3924  return delegate_->AddMessageToConsole(this, level, message, line_no,
3925                                        source_id);
3926}
3927
3928WebPreferences WebContentsImpl::ComputeWebkitPrefs() {
3929  // We want to base the page config off of the actual URL, rather than the
3930  // virtual URL.
3931  // TODO(nasko): Investigate how to remove the GetActiveEntry usage here,
3932  // as it is deprecated and can be out of sync with GetRenderViewHost().
3933  GURL url = controller_.GetActiveEntry()
3934      ? controller_.GetActiveEntry()->GetURL() : GURL::EmptyGURL();
3935
3936  return GetRenderManager()->current_host()->ComputeWebkitPrefs(url);
3937}
3938
3939int WebContentsImpl::CreateSwappedOutRenderView(
3940    SiteInstance* instance) {
3941  return GetRenderManager()->CreateRenderFrame(
3942      instance, MSG_ROUTING_NONE, true, true, true);
3943}
3944
3945void WebContentsImpl::OnUserGesture() {
3946  // Notify observers.
3947  FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetUserGesture());
3948
3949  ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
3950  if (rdh)  // NULL in unittests.
3951    rdh->OnUserGesture(this);
3952}
3953
3954void WebContentsImpl::OnIgnoredUIEvent() {
3955  // Notify observers.
3956  FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetIgnoredUIEvent());
3957}
3958
3959void WebContentsImpl::RendererUnresponsive(RenderViewHost* rvh,
3960                                           bool is_during_beforeunload,
3961                                           bool is_during_unload) {
3962  // Don't show hung renderer dialog for a swapped out RVH.
3963  if (rvh != GetRenderViewHost())
3964    return;
3965
3966  RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(rvh);
3967
3968  // Ignore renderer unresponsive event if debugger is attached to the tab
3969  // since the event may be a result of the renderer sitting on a breakpoint.
3970  // See http://crbug.com/65458
3971  if (DevToolsAgentHost::IsDebuggerAttached(this))
3972    return;
3973
3974  if (is_during_beforeunload || is_during_unload) {
3975    // Hang occurred while firing the beforeunload/unload handler.
3976    // Pretend the handler fired so tab closing continues as if it had.
3977    rvhi->set_sudden_termination_allowed(true);
3978
3979    if (!GetRenderManager()->ShouldCloseTabOnUnresponsiveRenderer())
3980      return;
3981
3982    // If the tab hangs in the beforeunload/unload handler there's really
3983    // nothing we can do to recover. If the hang is in the beforeunload handler,
3984    // pretend the beforeunload listeners have all fired and allow the delegate
3985    // to continue closing; the user will not have the option of cancelling the
3986    // close. Otherwise, pretend the unload listeners have all fired and close
3987    // the tab.
3988    bool close = true;
3989    if (is_during_beforeunload && delegate_) {
3990      delegate_->BeforeUnloadFired(this, true, &close);
3991    }
3992    if (close)
3993      Close(rvh);
3994    return;
3995  }
3996
3997  if (!GetRenderViewHostImpl() || !GetRenderViewHostImpl()->IsRenderViewLive())
3998    return;
3999
4000  if (delegate_)
4001    delegate_->RendererUnresponsive(this);
4002}
4003
4004void WebContentsImpl::RendererResponsive(RenderViewHost* render_view_host) {
4005  if (delegate_)
4006    delegate_->RendererResponsive(this);
4007}
4008
4009void WebContentsImpl::LoadStateChanged(
4010    const GURL& url,
4011    const net::LoadStateWithParam& load_state,
4012    uint64 upload_position,
4013    uint64 upload_size) {
4014  load_state_ = load_state;
4015  upload_position_ = upload_position;
4016  upload_size_ = upload_size;
4017  load_state_host_ = net::IDNToUnicode(url.host(),
4018      GetContentClient()->browser()->GetAcceptLangs(
4019          GetBrowserContext()));
4020  if (load_state_.state == net::LOAD_STATE_READING_RESPONSE)
4021    SetNotWaitingForResponse();
4022  if (IsLoading()) {
4023    NotifyNavigationStateChanged(static_cast<InvalidateTypes>(
4024        INVALIDATE_TYPE_LOAD | INVALIDATE_TYPE_TAB));
4025  }
4026}
4027
4028void WebContentsImpl::BeforeUnloadFiredFromRenderManager(
4029    bool proceed, const base::TimeTicks& proceed_time,
4030    bool* proceed_to_fire_unload) {
4031  FOR_EACH_OBSERVER(WebContentsObserver, observers_,
4032                    BeforeUnloadFired(proceed_time));
4033  if (delegate_)
4034    delegate_->BeforeUnloadFired(this, proceed, proceed_to_fire_unload);
4035  // Note: |this| might be deleted at this point.
4036}
4037
4038void WebContentsImpl::RenderProcessGoneFromRenderManager(
4039    RenderViewHost* render_view_host) {
4040  DCHECK(crashed_status_ != base::TERMINATION_STATUS_STILL_RUNNING);
4041  RenderViewTerminated(render_view_host, crashed_status_, crashed_error_code_);
4042}
4043
4044void WebContentsImpl::UpdateRenderViewSizeForRenderManager() {
4045  // TODO(brettw) this is a hack. See WebContentsView::SizeContents.
4046  gfx::Size size = GetSizeForNewRenderView();
4047  // 0x0 isn't a valid window size (minimal window size is 1x1) but it may be
4048  // here during container initialization and normal window size will be set
4049  // later. In case of tab duplication this resizing to 0x0 prevents setting
4050  // normal size later so just ignore it.
4051  if (!size.IsEmpty())
4052    view_->SizeContents(size);
4053}
4054
4055void WebContentsImpl::CancelModalDialogsForRenderManager() {
4056  // We need to cancel modal dialogs when doing a process swap, since the load
4057  // deferrer would prevent us from swapping out.
4058  if (dialog_manager_)
4059    dialog_manager_->CancelActiveAndPendingDialogs(this);
4060}
4061
4062void WebContentsImpl::NotifySwappedFromRenderManager(RenderFrameHost* old_host,
4063                                                     RenderFrameHost* new_host,
4064                                                     bool is_main_frame) {
4065  if (is_main_frame) {
4066    NotifyViewSwapped(old_host ? old_host->GetRenderViewHost() : NULL,
4067                      new_host->GetRenderViewHost());
4068
4069    // Make sure the visible RVH reflects the new delegate's preferences.
4070    if (delegate_)
4071      view_->SetOverscrollControllerEnabled(CanOverscrollContent());
4072
4073    view_->RenderViewSwappedIn(new_host->GetRenderViewHost());
4074  }
4075
4076  NotifyFrameSwapped(old_host, new_host);
4077}
4078
4079int WebContentsImpl::CreateOpenerRenderViewsForRenderManager(
4080    SiteInstance* instance) {
4081  if (!opener_)
4082    return MSG_ROUTING_NONE;
4083
4084  // Recursively create RenderViews for anything else in the opener chain.
4085  return opener_->CreateOpenerRenderViews(instance);
4086}
4087
4088int WebContentsImpl::CreateOpenerRenderViews(SiteInstance* instance) {
4089  int opener_route_id = MSG_ROUTING_NONE;
4090
4091  // If this tab has an opener, ensure it has a RenderView in the given
4092  // SiteInstance as well.
4093  if (opener_)
4094    opener_route_id = opener_->CreateOpenerRenderViews(instance);
4095
4096  // If any of the renderers (current, pending, or swapped out) for this
4097  // WebContents has the same SiteInstance, use it.
4098  if (GetRenderManager()->current_host()->GetSiteInstance() == instance)
4099    return GetRenderManager()->current_host()->GetRoutingID();
4100
4101  if (GetRenderManager()->pending_render_view_host() &&
4102      GetRenderManager()->pending_render_view_host()->GetSiteInstance() ==
4103          instance)
4104    return GetRenderManager()->pending_render_view_host()->GetRoutingID();
4105
4106  RenderViewHostImpl* rvh = GetRenderManager()->GetSwappedOutRenderViewHost(
4107      instance);
4108  if (rvh)
4109    return rvh->GetRoutingID();
4110
4111  // Create a swapped out RenderView in the given SiteInstance if none exists,
4112  // setting its opener to the given route_id.  Return the new view's route_id.
4113  return GetRenderManager()->CreateRenderFrame(
4114      instance, opener_route_id, true, true, true);
4115}
4116
4117NavigationControllerImpl& WebContentsImpl::GetControllerForRenderManager() {
4118  return GetController();
4119}
4120
4121WebUIImpl* WebContentsImpl::CreateWebUIForRenderManager(const GURL& url) {
4122  return static_cast<WebUIImpl*>(CreateWebUI(url));
4123}
4124
4125NavigationEntry*
4126    WebContentsImpl::GetLastCommittedNavigationEntryForRenderManager() {
4127  return controller_.GetLastCommittedEntry();
4128}
4129
4130bool WebContentsImpl::CreateRenderViewForRenderManager(
4131    RenderViewHost* render_view_host,
4132    int opener_route_id,
4133    int proxy_routing_id,
4134    bool for_main_frame_navigation) {
4135  TRACE_EVENT0("browser,navigation",
4136               "WebContentsImpl::CreateRenderViewForRenderManager");
4137  // Can be NULL during tests.
4138  RenderWidgetHostViewBase* rwh_view;
4139  // TODO(kenrb): RenderWidgetHostViewChildFrame special casing is temporary
4140  // until RenderWidgetHost is attached to RenderFrameHost. We need to special
4141  // case this because RWH is still a base class of RenderViewHost, and child
4142  // frame RWHVs are unique in that they do not have their own WebContents.
4143  if (!for_main_frame_navigation) {
4144    RenderWidgetHostViewChildFrame* rwh_view_child =
4145        new RenderWidgetHostViewChildFrame(render_view_host);
4146    rwh_view = rwh_view_child;
4147  } else {
4148    rwh_view = view_->CreateViewForWidget(render_view_host);
4149  }
4150
4151  // Now that the RenderView has been created, we need to tell it its size.
4152  if (rwh_view)
4153    rwh_view->SetSize(GetSizeForNewRenderView());
4154
4155  // Make sure we use the correct starting page_id in the new RenderView.
4156  UpdateMaxPageIDIfNecessary(render_view_host);
4157  int32 max_page_id =
4158      GetMaxPageIDForSiteInstance(render_view_host->GetSiteInstance());
4159
4160  if (!static_cast<RenderViewHostImpl*>(
4161          render_view_host)->CreateRenderView(base::string16(),
4162                                              opener_route_id,
4163                                              proxy_routing_id,
4164                                              max_page_id,
4165                                              created_with_opener_)) {
4166    return false;
4167  }
4168
4169#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
4170  // Force a ViewMsg_Resize to be sent, needed to make plugins show up on
4171  // linux. See crbug.com/83941.
4172  if (rwh_view) {
4173    if (RenderWidgetHost* render_widget_host = rwh_view->GetRenderWidgetHost())
4174      render_widget_host->WasResized();
4175  }
4176#endif
4177
4178  return true;
4179}
4180
4181bool WebContentsImpl::CreateRenderFrameForRenderManager(
4182    RenderFrameHost* render_frame_host,
4183    int parent_routing_id) {
4184  TRACE_EVENT0("browser,navigation",
4185               "WebContentsImpl::CreateRenderFrameForRenderManager");
4186
4187  RenderFrameHostImpl* rfh =
4188      static_cast<RenderFrameHostImpl*>(render_frame_host);
4189  if (!rfh->CreateRenderFrame(parent_routing_id))
4190    return false;
4191
4192  // TODO(nasko): When RenderWidgetHost is owned by RenderFrameHost, the passed
4193  // RenderFrameHost will have to be associated with the appropriate
4194  // RenderWidgetHostView or a new one should be created here.
4195
4196  return true;
4197}
4198
4199#if defined(OS_ANDROID)
4200
4201base::android::ScopedJavaLocalRef<jobject>
4202WebContentsImpl::GetJavaWebContents() {
4203  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
4204  return GetWebContentsAndroid()->GetJavaObject();
4205}
4206
4207WebContentsAndroid* WebContentsImpl::GetWebContentsAndroid() {
4208  WebContentsAndroid* web_contents_android =
4209      static_cast<WebContentsAndroid*>(GetUserData(kWebContentsAndroidKey));
4210  if (!web_contents_android) {
4211    web_contents_android = new WebContentsAndroid(this);
4212    SetUserData(kWebContentsAndroidKey, web_contents_android);
4213  }
4214  return web_contents_android;
4215}
4216
4217bool WebContentsImpl::CreateRenderViewForInitialEmptyDocument() {
4218  return CreateRenderViewForRenderManager(GetRenderViewHost(),
4219                                          MSG_ROUTING_NONE,
4220                                          MSG_ROUTING_NONE,
4221                                          true);
4222}
4223
4224#elif defined(OS_MACOSX)
4225
4226void WebContentsImpl::SetAllowOtherViews(bool allow) {
4227  view_->SetAllowOtherViews(allow);
4228}
4229
4230bool WebContentsImpl::GetAllowOtherViews() {
4231  return view_->GetAllowOtherViews();
4232}
4233
4234#endif
4235
4236void WebContentsImpl::OnDialogClosed(int render_process_id,
4237                                     int render_frame_id,
4238                                     IPC::Message* reply_msg,
4239                                     bool dialog_was_suppressed,
4240                                     bool success,
4241                                     const base::string16& user_input) {
4242  RenderFrameHostImpl* rfh = RenderFrameHostImpl::FromID(render_process_id,
4243                                                         render_frame_id);
4244  last_dialog_suppressed_ = dialog_was_suppressed;
4245
4246  if (is_showing_before_unload_dialog_ && !success) {
4247    // If a beforeunload dialog is canceled, we need to stop the throbber from
4248    // spinning, since we forced it to start spinning in Navigate.
4249    if (rfh)
4250      DidStopLoading(rfh);
4251    controller_.DiscardNonCommittedEntries();
4252
4253    FOR_EACH_OBSERVER(WebContentsObserver, observers_,
4254                      BeforeUnloadDialogCancelled());
4255  }
4256
4257  is_showing_before_unload_dialog_ = false;
4258  if (rfh) {
4259    rfh->JavaScriptDialogClosed(reply_msg, success, user_input,
4260                                dialog_was_suppressed);
4261  } else {
4262    // Don't leak the sync IPC reply if the RFH or process is gone.
4263    delete reply_msg;
4264  }
4265}
4266
4267void WebContentsImpl::SetEncoding(const std::string& encoding) {
4268  if (encoding == last_reported_encoding_)
4269    return;
4270  last_reported_encoding_ = encoding;
4271
4272  canonical_encoding_ = GetContentClient()->browser()->
4273      GetCanonicalEncodingNameByAliasName(encoding);
4274}
4275
4276void WebContentsImpl::CreateViewAndSetSizeForRVH(RenderViewHost* rvh) {
4277  RenderWidgetHostViewBase* rwh_view = view_->CreateViewForWidget(rvh);
4278  // Can be NULL during tests.
4279  if (rwh_view)
4280    rwh_view->SetSize(GetContainerBounds().size());
4281}
4282
4283bool WebContentsImpl::IsHidden() {
4284  return capturer_count_ == 0 && !should_normally_be_visible_;
4285}
4286
4287RenderFrameHostManager* WebContentsImpl::GetRenderManager() const {
4288  return frame_tree_.root()->render_manager();
4289}
4290
4291RenderViewHostImpl* WebContentsImpl::GetRenderViewHostImpl() {
4292  return static_cast<RenderViewHostImpl*>(GetRenderViewHost());
4293}
4294
4295BrowserPluginGuest* WebContentsImpl::GetBrowserPluginGuest() const {
4296  return browser_plugin_guest_.get();
4297}
4298
4299void WebContentsImpl::SetBrowserPluginGuest(BrowserPluginGuest* guest) {
4300  CHECK(!browser_plugin_guest_);
4301  browser_plugin_guest_.reset(guest);
4302}
4303
4304BrowserPluginEmbedder* WebContentsImpl::GetBrowserPluginEmbedder() const {
4305  return browser_plugin_embedder_.get();
4306}
4307
4308void WebContentsImpl::ClearPowerSaveBlockers(
4309    RenderFrameHost* render_frame_host) {
4310  RemoveAllMediaPlayerEntries(render_frame_host, &active_audio_players_);
4311  RemoveAllMediaPlayerEntries(render_frame_host, &active_video_players_);
4312  MaybeReleasePowerSaveBlockers();
4313}
4314
4315void WebContentsImpl::ClearAllPowerSaveBlockers() {
4316  active_audio_players_.clear();
4317  active_video_players_.clear();
4318  audio_power_save_blocker_.reset();
4319  video_power_save_blocker_.reset();
4320}
4321
4322gfx::Size WebContentsImpl::GetSizeForNewRenderView() {
4323  gfx::Size size;
4324  if (delegate_)
4325    size = delegate_->GetSizeForNewRenderView(this);
4326  if (size.IsEmpty())
4327    size = GetContainerBounds().size();
4328  return size;
4329}
4330
4331void WebContentsImpl::OnFrameRemoved(RenderFrameHost* render_frame_host) {
4332  FOR_EACH_OBSERVER(
4333      WebContentsObserver, observers_, FrameDetached(render_frame_host));
4334}
4335
4336void WebContentsImpl::OnPreferredSizeChanged(const gfx::Size& old_size) {
4337  if (!delegate_)
4338    return;
4339  const gfx::Size new_size = GetPreferredSize();
4340  if (new_size != old_size)
4341    delegate_->UpdatePreferredSize(this, new_size);
4342}
4343
4344void WebContentsImpl::AddMediaPlayerEntry(int64 player_cookie,
4345                                          ActiveMediaPlayerMap* player_map) {
4346  const uintptr_t key =
4347      reinterpret_cast<uintptr_t>(render_frame_message_source_);
4348  DCHECK(std::find((*player_map)[key].begin(),
4349                   (*player_map)[key].end(),
4350                   player_cookie) == (*player_map)[key].end());
4351  (*player_map)[key].push_back(player_cookie);
4352}
4353
4354void WebContentsImpl::RemoveMediaPlayerEntry(int64 player_cookie,
4355                                             ActiveMediaPlayerMap* player_map) {
4356  const uintptr_t key =
4357      reinterpret_cast<uintptr_t>(render_frame_message_source_);
4358  ActiveMediaPlayerMap::iterator it = player_map->find(key);
4359  if (it == player_map->end())
4360    return;
4361
4362  // Remove the player.
4363  PlayerList::iterator player_it =
4364      std::find(it->second.begin(), it->second.end(), player_cookie);
4365  if (player_it != it->second.end())
4366    it->second.erase(player_it);
4367
4368  // If there are no players left, remove the map entry.
4369  if (it->second.empty())
4370    player_map->erase(it);
4371}
4372
4373void WebContentsImpl::RemoveAllMediaPlayerEntries(
4374    RenderFrameHost* render_frame_host,
4375    ActiveMediaPlayerMap* player_map) {
4376  ActiveMediaPlayerMap::iterator it =
4377      player_map->find(reinterpret_cast<uintptr_t>(render_frame_host));
4378  if (it == player_map->end())
4379    return;
4380  player_map->erase(it);
4381}
4382
4383void WebContentsImpl::ResumeResponseDeferredAtStart() {
4384  FrameTreeNode* node = frame_tree_.root();
4385  node->render_manager()->ResumeResponseDeferredAtStart();
4386}
4387
4388void WebContentsImpl::SetForceDisableOverscrollContent(bool force_disable) {
4389  force_disable_overscroll_content_ = force_disable;
4390  if (view_)
4391    view_->SetOverscrollControllerEnabled(CanOverscrollContent());
4392}
4393
4394}  // namespace content
4395