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