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