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