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