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