Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / content / browser / frame_host / render_frame_host_impl.cc
1 // Copyright 2013 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/frame_host/render_frame_host_impl.h"
6
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/containers/hash_tables.h"
10 #include "base/lazy_instance.h"
11 #include "base/metrics/histogram.h"
12 #include "base/metrics/user_metrics_action.h"
13 #include "base/time/time.h"
14 #include "content/browser/accessibility/accessibility_mode_helper.h"
15 #include "content/browser/accessibility/browser_accessibility_manager.h"
16 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
17 #include "content/browser/child_process_security_policy_impl.h"
18 #include "content/browser/frame_host/cross_process_frame_connector.h"
19 #include "content/browser/frame_host/cross_site_transferring_request.h"
20 #include "content/browser/frame_host/frame_accessibility.h"
21 #include "content/browser/frame_host/frame_tree.h"
22 #include "content/browser/frame_host/frame_tree_node.h"
23 #include "content/browser/frame_host/navigator.h"
24 #include "content/browser/frame_host/render_frame_host_delegate.h"
25 #include "content/browser/frame_host/render_frame_proxy_host.h"
26 #include "content/browser/frame_host/render_widget_host_view_child_frame.h"
27 #include "content/browser/renderer_host/input/input_router.h"
28 #include "content/browser/renderer_host/input/timeout_monitor.h"
29 #include "content/browser/renderer_host/render_process_host_impl.h"
30 #include "content/browser/renderer_host/render_view_host_delegate.h"
31 #include "content/browser/renderer_host/render_view_host_delegate_view.h"
32 #include "content/browser/renderer_host/render_view_host_impl.h"
33 #include "content/browser/renderer_host/render_widget_host_impl.h"
34 #include "content/browser/renderer_host/render_widget_host_view_base.h"
35 #include "content/browser/transition_request_manager.h"
36 #include "content/common/accessibility_messages.h"
37 #include "content/common/desktop_notification_messages.h"
38 #include "content/common/frame_messages.h"
39 #include "content/common/input_messages.h"
40 #include "content/common/inter_process_time_ticks_converter.h"
41 #include "content/common/platform_notification_messages.h"
42 #include "content/common/render_frame_setup.mojom.h"
43 #include "content/common/swapped_out_messages.h"
44 #include "content/public/browser/ax_event_notification_details.h"
45 #include "content/public/browser/browser_accessibility_state.h"
46 #include "content/public/browser/browser_context.h"
47 #include "content/public/browser/browser_plugin_guest_manager.h"
48 #include "content/public/browser/browser_thread.h"
49 #include "content/public/browser/content_browser_client.h"
50 #include "content/public/browser/desktop_notification_delegate.h"
51 #include "content/public/browser/render_process_host.h"
52 #include "content/public/browser/render_widget_host_view.h"
53 #include "content/public/browser/user_metrics.h"
54 #include "content/public/common/content_constants.h"
55 #include "content/public/common/content_switches.h"
56 #include "content/public/common/url_constants.h"
57 #include "content/public/common/url_utils.h"
58 #include "ui/accessibility/ax_tree.h"
59 #include "url/gurl.h"
60
61 #if defined(OS_MACOSX)
62 #include "content/browser/frame_host/popup_menu_helper_mac.h"
63 #endif
64
65 using base::TimeDelta;
66
67 namespace content {
68
69 namespace {
70
71 // The (process id, routing id) pair that identifies one RenderFrame.
72 typedef std::pair<int32, int32> RenderFrameHostID;
73 typedef base::hash_map<RenderFrameHostID, RenderFrameHostImpl*>
74     RoutingIDFrameMap;
75 base::LazyInstance<RoutingIDFrameMap> g_routing_id_frame_map =
76     LAZY_INSTANCE_INITIALIZER;
77
78 class DesktopNotificationDelegateImpl : public DesktopNotificationDelegate {
79  public:
80   DesktopNotificationDelegateImpl(RenderFrameHost* render_frame_host,
81                                   int notification_id)
82       : render_process_id_(render_frame_host->GetProcess()->GetID()),
83         render_frame_id_(render_frame_host->GetRoutingID()),
84         notification_id_(notification_id) {}
85
86   virtual ~DesktopNotificationDelegateImpl() {}
87
88   virtual void NotificationDisplayed() OVERRIDE {
89     RenderFrameHost* rfh =
90         RenderFrameHost::FromID(render_process_id_, render_frame_id_);
91     if (!rfh)
92       return;
93
94     rfh->Send(new DesktopNotificationMsg_PostDisplay(
95         rfh->GetRoutingID(), notification_id_));
96   }
97
98   virtual void NotificationError() OVERRIDE {
99     RenderFrameHost* rfh =
100         RenderFrameHost::FromID(render_process_id_, render_frame_id_);
101     if (!rfh)
102       return;
103
104     rfh->Send(new DesktopNotificationMsg_PostError(
105         rfh->GetRoutingID(), notification_id_));
106   }
107
108   virtual void NotificationClosed(bool by_user) OVERRIDE {
109     RenderFrameHost* rfh =
110         RenderFrameHost::FromID(render_process_id_, render_frame_id_);
111     if (!rfh)
112       return;
113
114     rfh->Send(new DesktopNotificationMsg_PostClose(
115         rfh->GetRoutingID(), notification_id_, by_user));
116     static_cast<RenderFrameHostImpl*>(rfh)->NotificationClosed(
117         notification_id_);
118   }
119
120   virtual void NotificationClick() OVERRIDE {
121     RenderFrameHost* rfh =
122         RenderFrameHost::FromID(render_process_id_, render_frame_id_);
123     if (!rfh)
124       return;
125
126     rfh->Send(new DesktopNotificationMsg_PostClick(
127         rfh->GetRoutingID(), notification_id_));
128   }
129
130  private:
131   int render_process_id_;
132   int render_frame_id_;
133   int notification_id_;
134 };
135
136 // Translate a WebKit text direction into a base::i18n one.
137 base::i18n::TextDirection WebTextDirectionToChromeTextDirection(
138     blink::WebTextDirection dir) {
139   switch (dir) {
140     case blink::WebTextDirectionLeftToRight:
141       return base::i18n::LEFT_TO_RIGHT;
142     case blink::WebTextDirectionRightToLeft:
143       return base::i18n::RIGHT_TO_LEFT;
144     default:
145       NOTREACHED();
146       return base::i18n::UNKNOWN_DIRECTION;
147   }
148 }
149
150 }  // namespace
151
152 RenderFrameHost* RenderFrameHost::FromID(int render_process_id,
153                                          int render_frame_id) {
154   return RenderFrameHostImpl::FromID(render_process_id, render_frame_id);
155 }
156
157 // static
158 RenderFrameHostImpl* RenderFrameHostImpl::FromID(int process_id,
159                                                  int routing_id) {
160   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
161   RoutingIDFrameMap* frames = g_routing_id_frame_map.Pointer();
162   RoutingIDFrameMap::iterator it = frames->find(
163       RenderFrameHostID(process_id, routing_id));
164   return it == frames->end() ? NULL : it->second;
165 }
166
167 RenderFrameHostImpl::RenderFrameHostImpl(RenderViewHostImpl* render_view_host,
168                                          RenderFrameHostDelegate* delegate,
169                                          FrameTree* frame_tree,
170                                          FrameTreeNode* frame_tree_node,
171                                          int routing_id,
172                                          bool is_swapped_out)
173     : render_view_host_(render_view_host),
174       delegate_(delegate),
175       cross_process_frame_connector_(NULL),
176       render_frame_proxy_host_(NULL),
177       frame_tree_(frame_tree),
178       frame_tree_node_(frame_tree_node),
179       routing_id_(routing_id),
180       is_swapped_out_(is_swapped_out),
181       render_frame_created_(false),
182       navigations_suspended_(false),
183       weak_ptr_factory_(this) {
184   frame_tree_->RegisterRenderFrameHost(this);
185   GetProcess()->AddRoute(routing_id_, this);
186   g_routing_id_frame_map.Get().insert(std::make_pair(
187       RenderFrameHostID(GetProcess()->GetID(), routing_id_),
188       this));
189
190   if (GetProcess()->GetServiceRegistry()) {
191     RenderFrameSetupPtr setup;
192     GetProcess()->GetServiceRegistry()->ConnectToRemoteService(&setup);
193     mojo::ServiceProviderPtr service_provider;
194     setup->GetServiceProviderForFrame(routing_id_,
195                                       mojo::Get(&service_provider));
196     service_registry_.BindRemoteServiceProvider(
197         service_provider.PassMessagePipe());
198   }
199 }
200
201 RenderFrameHostImpl::~RenderFrameHostImpl() {
202   GetProcess()->RemoveRoute(routing_id_);
203   g_routing_id_frame_map.Get().erase(
204       RenderFrameHostID(GetProcess()->GetID(), routing_id_));
205
206   if (delegate_)
207     delegate_->RenderFrameDeleted(this);
208
209   FrameAccessibility::GetInstance()->OnRenderFrameHostDestroyed(this);
210
211   // Notify the FrameTree that this RFH is going away, allowing it to shut down
212   // the corresponding RenderViewHost if it is no longer needed.
213   frame_tree_->UnregisterRenderFrameHost(this);
214 }
215
216 int RenderFrameHostImpl::GetRoutingID() {
217   return routing_id_;
218 }
219
220 SiteInstance* RenderFrameHostImpl::GetSiteInstance() {
221   return render_view_host_->GetSiteInstance();
222 }
223
224 RenderProcessHost* RenderFrameHostImpl::GetProcess() {
225   // TODO(nasko): This should return its own process, once we have working
226   // cross-process navigation for subframes.
227   return render_view_host_->GetProcess();
228 }
229
230 RenderFrameHost* RenderFrameHostImpl::GetParent() {
231   FrameTreeNode* parent_node = frame_tree_node_->parent();
232   if (!parent_node)
233     return NULL;
234   return parent_node->current_frame_host();
235 }
236
237 const std::string& RenderFrameHostImpl::GetFrameName() {
238   return frame_tree_node_->frame_name();
239 }
240
241 bool RenderFrameHostImpl::IsCrossProcessSubframe() {
242   FrameTreeNode* parent_node = frame_tree_node_->parent();
243   if (!parent_node)
244     return false;
245   return GetSiteInstance() !=
246       parent_node->current_frame_host()->GetSiteInstance();
247 }
248
249 GURL RenderFrameHostImpl::GetLastCommittedURL() {
250   return frame_tree_node_->current_url();
251 }
252
253 gfx::NativeView RenderFrameHostImpl::GetNativeView() {
254   RenderWidgetHostView* view = render_view_host_->GetView();
255   if (!view)
256     return NULL;
257   return view->GetNativeView();
258 }
259
260 void RenderFrameHostImpl::ExecuteJavaScript(
261     const base::string16& javascript) {
262   Send(new FrameMsg_JavaScriptExecuteRequest(routing_id_,
263                                              javascript,
264                                              0, false));
265 }
266
267 void RenderFrameHostImpl::ExecuteJavaScript(
268      const base::string16& javascript,
269      const JavaScriptResultCallback& callback) {
270   static int next_id = 1;
271   int key = next_id++;
272   Send(new FrameMsg_JavaScriptExecuteRequest(routing_id_,
273                                              javascript,
274                                              key, true));
275   javascript_callbacks_.insert(std::make_pair(key, callback));
276 }
277
278 void RenderFrameHostImpl::ExecuteJavaScriptForTests(
279     const base::string16& javascript) {
280   Send(new FrameMsg_JavaScriptExecuteRequestForTests(routing_id_,
281                                                      javascript,
282                                                      0, false));
283 }
284
285 RenderViewHost* RenderFrameHostImpl::GetRenderViewHost() {
286   return render_view_host_;
287 }
288
289 ServiceRegistry* RenderFrameHostImpl::GetServiceRegistry() {
290   static_cast<RenderProcessHostImpl*>(GetProcess())->EnsureMojoActivated();
291   return &service_registry_;
292 }
293
294 bool RenderFrameHostImpl::Send(IPC::Message* message) {
295   if (IPC_MESSAGE_ID_CLASS(message->type()) == InputMsgStart) {
296     return render_view_host_->input_router()->SendInput(
297         make_scoped_ptr(message));
298   }
299
300   // Route IPCs through the RenderFrameProxyHost when in swapped out state.
301   // Note: For subframes in --site-per-process mode, we don't use swapped out
302   // RenderFrameHosts.
303   if (frame_tree_node_->IsMainFrame() && render_view_host_->IsSwappedOut()) {
304     DCHECK(render_frame_proxy_host_);
305     return render_frame_proxy_host_->Send(message);
306   }
307
308   return GetProcess()->Send(message);
309 }
310
311 bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
312   // Filter out most IPC messages if this renderer is swapped out.
313   // We still want to handle certain ACKs to keep our state consistent.
314   // TODO(nasko): Only check RenderViewHost state, as this object's own state
315   // isn't yet properly updated. Transition this check once the swapped out
316   // state is correct in RenderFrameHost itself.
317   if (render_view_host_->IsSwappedOut()) {
318     if (!SwappedOutMessages::CanHandleWhileSwappedOut(msg)) {
319       // If this is a synchronous message and we decided not to handle it,
320       // we must send an error reply, or else the renderer will be stuck
321       // and won't respond to future requests.
322       if (msg.is_sync()) {
323         IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg);
324         reply->set_reply_error();
325         Send(reply);
326       }
327       // Don't continue looking for someone to handle it.
328       return true;
329     }
330   }
331
332   if (delegate_->OnMessageReceived(this, msg))
333     return true;
334
335   RenderFrameProxyHost* proxy =
336       frame_tree_node_->render_manager()->GetProxyToParent();
337   if (proxy && proxy->cross_process_frame_connector() &&
338       proxy->cross_process_frame_connector()->OnMessageReceived(msg))
339     return true;
340
341   bool handled = true;
342   IPC_BEGIN_MESSAGE_MAP(RenderFrameHostImpl, msg)
343     IPC_MESSAGE_HANDLER(FrameHostMsg_AddMessageToConsole, OnAddMessageToConsole)
344     IPC_MESSAGE_HANDLER(FrameHostMsg_Detach, OnDetach)
345     IPC_MESSAGE_HANDLER(FrameHostMsg_FrameFocused, OnFrameFocused)
346     IPC_MESSAGE_HANDLER(FrameHostMsg_DidStartProvisionalLoadForFrame,
347                         OnDidStartProvisionalLoadForFrame)
348     IPC_MESSAGE_HANDLER(FrameHostMsg_DidFailProvisionalLoadWithError,
349                         OnDidFailProvisionalLoadWithError)
350     IPC_MESSAGE_HANDLER(FrameHostMsg_DidFailLoadWithError,
351                         OnDidFailLoadWithError)
352     IPC_MESSAGE_HANDLER_GENERIC(FrameHostMsg_DidCommitProvisionalLoad,
353                                 OnDidCommitProvisionalLoad(msg))
354     IPC_MESSAGE_HANDLER(FrameHostMsg_OpenURL, OnOpenURL)
355     IPC_MESSAGE_HANDLER(FrameHostMsg_DocumentOnLoadCompleted,
356                         OnDocumentOnLoadCompleted)
357     IPC_MESSAGE_HANDLER(FrameHostMsg_BeforeUnload_ACK, OnBeforeUnloadACK)
358     IPC_MESSAGE_HANDLER(FrameHostMsg_SwapOut_ACK, OnSwapOutACK)
359     IPC_MESSAGE_HANDLER(FrameHostMsg_ContextMenu, OnContextMenu)
360     IPC_MESSAGE_HANDLER(FrameHostMsg_JavaScriptExecuteResponse,
361                         OnJavaScriptExecuteResponse)
362     IPC_MESSAGE_HANDLER_DELAY_REPLY(FrameHostMsg_RunJavaScriptMessage,
363                                     OnRunJavaScriptMessage)
364     IPC_MESSAGE_HANDLER_DELAY_REPLY(FrameHostMsg_RunBeforeUnloadConfirm,
365                                     OnRunBeforeUnloadConfirm)
366     IPC_MESSAGE_HANDLER(FrameHostMsg_DidAccessInitialDocument,
367                         OnDidAccessInitialDocument)
368     IPC_MESSAGE_HANDLER(FrameHostMsg_DidDisownOpener, OnDidDisownOpener)
369     IPC_MESSAGE_HANDLER(FrameHostMsg_DidAssignPageId, OnDidAssignPageId)
370     IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateTitle, OnUpdateTitle)
371     IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateEncoding, OnUpdateEncoding)
372     IPC_MESSAGE_HANDLER(FrameHostMsg_BeginNavigation,
373                         OnBeginNavigation)
374     IPC_MESSAGE_HANDLER(PlatformNotificationHostMsg_RequestPermission,
375                         OnRequestPlatformNotificationPermission)
376     IPC_MESSAGE_HANDLER(DesktopNotificationHostMsg_Show,
377                         OnShowDesktopNotification)
378     IPC_MESSAGE_HANDLER(DesktopNotificationHostMsg_Cancel,
379                         OnCancelDesktopNotification)
380     IPC_MESSAGE_HANDLER(FrameHostMsg_TextSurroundingSelectionResponse,
381                         OnTextSurroundingSelectionResponse)
382     IPC_MESSAGE_HANDLER(AccessibilityHostMsg_Events, OnAccessibilityEvents)
383     IPC_MESSAGE_HANDLER(AccessibilityHostMsg_LocationChanges,
384                         OnAccessibilityLocationChanges)
385 #if defined(OS_MACOSX) || defined(OS_ANDROID)
386     IPC_MESSAGE_HANDLER(FrameHostMsg_ShowPopup, OnShowPopup)
387     IPC_MESSAGE_HANDLER(FrameHostMsg_HidePopup, OnHidePopup)
388 #endif
389   IPC_END_MESSAGE_MAP()
390
391   return handled;
392 }
393
394 void RenderFrameHostImpl::AccessibilitySetFocus(int object_id) {
395   Send(new AccessibilityMsg_SetFocus(routing_id_, object_id));
396 }
397
398 void RenderFrameHostImpl::AccessibilityDoDefaultAction(int object_id) {
399   Send(new AccessibilityMsg_DoDefaultAction(routing_id_, object_id));
400 }
401
402 void RenderFrameHostImpl::AccessibilityShowMenu(
403     const gfx::Point& global_point) {
404   RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
405       render_view_host_->GetView());
406   if (view)
407     view->AccessibilityShowMenu(global_point);
408 }
409
410 void RenderFrameHostImpl::AccessibilityScrollToMakeVisible(
411     int acc_obj_id, const gfx::Rect& subfocus) {
412   Send(new AccessibilityMsg_ScrollToMakeVisible(
413       routing_id_, acc_obj_id, subfocus));
414 }
415
416 void RenderFrameHostImpl::AccessibilityScrollToPoint(
417     int acc_obj_id, const gfx::Point& point) {
418   Send(new AccessibilityMsg_ScrollToPoint(
419       routing_id_, acc_obj_id, point));
420 }
421
422 void RenderFrameHostImpl::AccessibilitySetTextSelection(
423     int object_id, int start_offset, int end_offset) {
424   Send(new AccessibilityMsg_SetTextSelection(
425       routing_id_, object_id, start_offset, end_offset));
426 }
427
428 bool RenderFrameHostImpl::AccessibilityViewHasFocus() const {
429   RenderWidgetHostView* view = render_view_host_->GetView();
430   if (view)
431     return view->HasFocus();
432   return false;
433 }
434
435 gfx::Rect RenderFrameHostImpl::AccessibilityGetViewBounds() const {
436   RenderWidgetHostView* view = render_view_host_->GetView();
437   if (view)
438     return view->GetViewBounds();
439   return gfx::Rect();
440 }
441
442 gfx::Point RenderFrameHostImpl::AccessibilityOriginInScreen(
443     const gfx::Rect& bounds) const {
444   RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
445       render_view_host_->GetView());
446   if (view)
447     return view->AccessibilityOriginInScreen(bounds);
448   return gfx::Point();
449 }
450
451 void RenderFrameHostImpl::AccessibilityHitTest(const gfx::Point& point) {
452   Send(new AccessibilityMsg_HitTest(routing_id_, point));
453 }
454
455 void RenderFrameHostImpl::AccessibilityFatalError() {
456   Send(new AccessibilityMsg_FatalError(routing_id_));
457   browser_accessibility_manager_.reset(NULL);
458 }
459
460 gfx::AcceleratedWidget
461     RenderFrameHostImpl::AccessibilityGetAcceleratedWidget() {
462   RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
463       render_view_host_->GetView());
464   if (view)
465     return view->AccessibilityGetAcceleratedWidget();
466   return gfx::kNullAcceleratedWidget;
467 }
468
469 gfx::NativeViewAccessible
470     RenderFrameHostImpl::AccessibilityGetNativeViewAccessible() {
471   RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
472       render_view_host_->GetView());
473   if (view)
474     return view->AccessibilityGetNativeViewAccessible();
475   return NULL;
476 }
477
478 BrowserAccessibilityManager* RenderFrameHostImpl::AccessibilityGetChildFrame(
479     int accessibility_node_id) {
480   RenderFrameHostImpl* child_frame =
481       FrameAccessibility::GetInstance()->GetChild(this, accessibility_node_id);
482   if (!child_frame)
483     return NULL;
484
485   // Return NULL if this isn't an out-of-process iframe. Same-process iframes
486   // are already part of the accessibility tree.
487   if (child_frame->GetProcess()->GetID() == GetProcess()->GetID())
488     return NULL;
489
490   // As a sanity check, make sure the frame we're going to return belongs
491   // to the same BrowserContext.
492   if (GetSiteInstance()->GetBrowserContext() !=
493       child_frame->GetSiteInstance()->GetBrowserContext()) {
494     NOTREACHED();
495     return NULL;
496   }
497
498   return child_frame->GetOrCreateBrowserAccessibilityManager();
499 }
500
501 BrowserAccessibility* RenderFrameHostImpl::AccessibilityGetParentFrame() {
502   RenderFrameHostImpl* parent_frame = NULL;
503   int parent_node_id = 0;
504   if (!FrameAccessibility::GetInstance()->GetParent(
505       this, &parent_frame, &parent_node_id)) {
506     return NULL;
507   }
508
509   // As a sanity check, make sure the frame we're going to return belongs
510   // to the same BrowserContext.
511   if (GetSiteInstance()->GetBrowserContext() !=
512       parent_frame->GetSiteInstance()->GetBrowserContext()) {
513     NOTREACHED();
514     return NULL;
515   }
516
517   BrowserAccessibilityManager* manager =
518       parent_frame->browser_accessibility_manager();
519   if (!manager)
520     return NULL;
521
522   return manager->GetFromID(parent_node_id);
523 }
524
525 bool RenderFrameHostImpl::CreateRenderFrame(int parent_routing_id) {
526   TRACE_EVENT0("navigation", "RenderFrameHostImpl::CreateRenderFrame");
527   DCHECK(!IsRenderFrameLive()) << "Creating frame twice";
528
529   // The process may (if we're sharing a process with another host that already
530   // initialized it) or may not (we have our own process or the old process
531   // crashed) have been initialized. Calling Init multiple times will be
532   // ignored, so this is safe.
533   if (!GetProcess()->Init())
534     return false;
535
536   DCHECK(GetProcess()->HasConnection());
537
538   Send(new FrameMsg_NewFrame(routing_id_, parent_routing_id));
539
540   // The renderer now has a RenderFrame for this RenderFrameHost.  Note that
541   // this path is only used for out-of-process iframes.  Main frame RenderFrames
542   // are created with their RenderView, and same-site iframes are created at the
543   // time of OnCreateChildFrame.
544   set_render_frame_created(true);
545
546   return true;
547 }
548
549 bool RenderFrameHostImpl::IsRenderFrameLive() {
550   // RenderFrames are created for main frames at the same time as RenderViews,
551   // so we rely on IsRenderViewLive.  For subframes, we keep track of each
552   // RenderFrame individually with render_frame_created_.
553   bool is_live = !GetParent() ?
554       render_view_host_->IsRenderViewLive() :
555       GetProcess()->HasConnection() && render_frame_created_;
556
557   // Sanity check: the RenderView should always be live if the RenderFrame is.
558   DCHECK(!is_live || render_view_host_->IsRenderViewLive());
559
560   return is_live;
561 }
562
563 void RenderFrameHostImpl::Init() {
564   GetProcess()->ResumeRequestsForView(routing_id_);
565 }
566
567 void RenderFrameHostImpl::OnAddMessageToConsole(
568     int32 level,
569     const base::string16& message,
570     int32 line_no,
571     const base::string16& source_id) {
572   if (delegate_->AddMessageToConsole(level, message, line_no, source_id))
573     return;
574
575   // Pass through log level only on WebUI pages to limit console spew.
576   int32 resolved_level =
577       HasWebUIScheme(delegate_->GetMainFrameLastCommittedURL()) ? level : 0;
578
579   if (resolved_level >= ::logging::GetMinLogLevel()) {
580     logging::LogMessage("CONSOLE", line_no, resolved_level).stream() << "\"" <<
581         message << "\", source: " << source_id << " (" << line_no << ")";
582   }
583 }
584
585 void RenderFrameHostImpl::OnCreateChildFrame(int new_routing_id,
586                                              const std::string& frame_name) {
587   RenderFrameHostImpl* new_frame = frame_tree_->AddFrame(
588       frame_tree_node_, new_routing_id, frame_name);
589
590   // We know that the RenderFrame has been created in this case, immediately
591   // after the CreateChildFrame IPC was sent.
592   new_frame->set_render_frame_created(true);
593
594   if (delegate_)
595     delegate_->RenderFrameCreated(new_frame);
596 }
597
598 void RenderFrameHostImpl::OnDetach() {
599   frame_tree_->RemoveFrame(frame_tree_node_);
600 }
601
602 void RenderFrameHostImpl::OnFrameFocused() {
603   frame_tree_->SetFocusedFrame(frame_tree_node_);
604 }
605
606 void RenderFrameHostImpl::OnOpenURL(
607     const FrameHostMsg_OpenURL_Params& params) {
608   GURL validated_url(params.url);
609   GetProcess()->FilterURL(false, &validated_url);
610
611   TRACE_EVENT1("navigation", "RenderFrameHostImpl::OnOpenURL",
612                "url", validated_url.possibly_invalid_spec());
613   frame_tree_node_->navigator()->RequestOpenURL(
614       this, validated_url, params.referrer, params.disposition,
615       params.should_replace_current_entry, params.user_gesture);
616 }
617
618 void RenderFrameHostImpl::OnDocumentOnLoadCompleted() {
619   // This message is only sent for top-level frames. TODO(avi): when frame tree
620   // mirroring works correctly, add a check here to enforce it.
621   delegate_->DocumentOnLoadCompleted(this);
622 }
623
624 void RenderFrameHostImpl::OnDidStartProvisionalLoadForFrame(
625     const GURL& url,
626     bool is_transition_navigation) {
627   frame_tree_node_->navigator()->DidStartProvisionalLoad(
628       this, url, is_transition_navigation);
629 }
630
631 void RenderFrameHostImpl::OnDidFailProvisionalLoadWithError(
632     const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params) {
633   frame_tree_node_->navigator()->DidFailProvisionalLoadWithError(this, params);
634 }
635
636 void RenderFrameHostImpl::OnDidFailLoadWithError(
637     const GURL& url,
638     int error_code,
639     const base::string16& error_description) {
640   GURL validated_url(url);
641   GetProcess()->FilterURL(false, &validated_url);
642
643   frame_tree_node_->navigator()->DidFailLoadWithError(
644       this, validated_url, error_code, error_description);
645 }
646
647 // Called when the renderer navigates.  For every frame loaded, we'll get this
648 // notification containing parameters identifying the navigation.
649 //
650 // Subframes are identified by the page transition type.  For subframes loaded
651 // as part of a wider page load, the page_id will be the same as for the top
652 // level frame.  If the user explicitly requests a subframe navigation, we will
653 // get a new page_id because we need to create a new navigation entry for that
654 // action.
655 void RenderFrameHostImpl::OnDidCommitProvisionalLoad(const IPC::Message& msg) {
656   // Read the parameters out of the IPC message directly to avoid making another
657   // copy when we filter the URLs.
658   PickleIterator iter(msg);
659   FrameHostMsg_DidCommitProvisionalLoad_Params validated_params;
660   if (!IPC::ParamTraits<FrameHostMsg_DidCommitProvisionalLoad_Params>::
661       Read(&msg, &iter, &validated_params))
662     return;
663   TRACE_EVENT1("navigation", "RenderFrameHostImpl::OnDidCommitProvisionalLoad",
664                "url", validated_params.url.possibly_invalid_spec());
665
666   // If we're waiting for a cross-site beforeunload ack from this renderer and
667   // we receive a Navigate message from the main frame, then the renderer was
668   // navigating already and sent it before hearing the FrameMsg_Stop message.
669   // We do not want to cancel the pending navigation in this case, since the
670   // old page will soon be stopped.  Instead, treat this as a beforeunload ack
671   // to allow the pending navigation to continue.
672   if (render_view_host_->is_waiting_for_beforeunload_ack_ &&
673       render_view_host_->unload_ack_is_for_cross_site_transition_ &&
674       ui::PageTransitionIsMainFrame(validated_params.transition)) {
675     OnBeforeUnloadACK(true, send_before_unload_start_time_,
676                       base::TimeTicks::Now());
677     return;
678   }
679
680   // If we're waiting for an unload ack from this renderer and we receive a
681   // Navigate message, then the renderer was navigating before it received the
682   // unload request.  It will either respond to the unload request soon or our
683   // timer will expire.  Either way, we should ignore this message, because we
684   // have already committed to closing this renderer.
685   if (render_view_host_->IsWaitingForUnloadACK())
686     return;
687
688   RenderProcessHost* process = GetProcess();
689
690   // Attempts to commit certain off-limits URL should be caught more strictly
691   // than our FilterURL checks below.  If a renderer violates this policy, it
692   // should be killed.
693   if (!CanCommitURL(validated_params.url)) {
694     VLOG(1) << "Blocked URL " << validated_params.url.spec();
695     validated_params.url = GURL(url::kAboutBlankURL);
696     RecordAction(base::UserMetricsAction("CanCommitURL_BlockedAndKilled"));
697     // Kills the process.
698     process->ReceivedBadMessage();
699   }
700
701   // Without this check, an evil renderer can trick the browser into creating
702   // a navigation entry for a banned URL.  If the user clicks the back button
703   // followed by the forward button (or clicks reload, or round-trips through
704   // session restore, etc), we'll think that the browser commanded the
705   // renderer to load the URL and grant the renderer the privileges to request
706   // the URL.  To prevent this attack, we block the renderer from inserting
707   // banned URLs into the navigation controller in the first place.
708   process->FilterURL(false, &validated_params.url);
709   process->FilterURL(true, &validated_params.referrer.url);
710   for (std::vector<GURL>::iterator it(validated_params.redirects.begin());
711       it != validated_params.redirects.end(); ++it) {
712     process->FilterURL(false, &(*it));
713   }
714   process->FilterURL(true, &validated_params.searchable_form_url);
715
716   // Without this check, the renderer can trick the browser into using
717   // filenames it can't access in a future session restore.
718   if (!render_view_host_->CanAccessFilesOfPageState(
719           validated_params.page_state)) {
720     GetProcess()->ReceivedBadMessage();
721     return;
722   }
723
724   frame_tree_node()->navigator()->DidNavigate(this, validated_params);
725 }
726
727 RenderWidgetHostImpl* RenderFrameHostImpl::GetRenderWidgetHost() {
728   return static_cast<RenderWidgetHostImpl*>(render_view_host_);
729 }
730
731 int RenderFrameHostImpl::GetEnabledBindings() {
732   return render_view_host_->GetEnabledBindings();
733 }
734
735 void RenderFrameHostImpl::OnCrossSiteResponse(
736     const GlobalRequestID& global_request_id,
737     scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request,
738     const std::vector<GURL>& transfer_url_chain,
739     const Referrer& referrer,
740     ui::PageTransition page_transition,
741     bool should_replace_current_entry) {
742   frame_tree_node_->render_manager()->OnCrossSiteResponse(
743       this, global_request_id, cross_site_transferring_request.Pass(),
744       transfer_url_chain, referrer, page_transition,
745       should_replace_current_entry);
746 }
747
748 void RenderFrameHostImpl::OnDeferredAfterResponseStarted(
749     const GlobalRequestID& global_request_id,
750     const TransitionLayerData& transition_data) {
751   frame_tree_node_->render_manager()->OnDeferredAfterResponseStarted(
752       global_request_id, this);
753
754   if (GetParent() || !delegate_->WillHandleDeferAfterResponseStarted())
755     frame_tree_node_->render_manager()->ResumeResponseDeferredAtStart();
756   else
757     delegate_->DidDeferAfterResponseStarted(transition_data);
758 }
759
760 void RenderFrameHostImpl::SwapOut(RenderFrameProxyHost* proxy) {
761   // The end of this event is in OnSwapOutACK when the RenderFrame has completed
762   // the operation and sends back an IPC message.
763   // The trace event may not end properly if the ACK times out.  We expect this
764   // to be fixed when RenderViewHostImpl::OnSwapOut moves to RenderFrameHost.
765   TRACE_EVENT_ASYNC_BEGIN0("navigation", "RenderFrameHostImpl::SwapOut", this);
766
767   // TODO(creis): Move swapped out state to RFH.  Until then, only update it
768   // when swapping out the main frame.
769   if (!GetParent()) {
770     // If this RenderViewHost is not in the default state, it must have already
771     // gone through this, therefore just return.
772     if (render_view_host_->rvh_state_ != RenderViewHostImpl::STATE_DEFAULT)
773       return;
774
775     render_view_host_->SetState(
776         RenderViewHostImpl::STATE_PENDING_SWAP_OUT);
777     render_view_host_->unload_event_monitor_timeout_->Start(
778         base::TimeDelta::FromMilliseconds(
779             RenderViewHostImpl::kUnloadTimeoutMS));
780   }
781
782   set_render_frame_proxy_host(proxy);
783
784   if (IsRenderFrameLive())
785     Send(new FrameMsg_SwapOut(routing_id_, proxy->GetRoutingID()));
786
787   if (!GetParent())
788     delegate_->SwappedOut(this);
789   else
790     set_swapped_out(true);
791 }
792
793 void RenderFrameHostImpl::OnBeforeUnloadACK(
794     bool proceed,
795     const base::TimeTicks& renderer_before_unload_start_time,
796     const base::TimeTicks& renderer_before_unload_end_time) {
797   TRACE_EVENT_ASYNC_END0(
798       "navigation", "RenderFrameHostImpl::BeforeUnload", this);
799   // TODO(creis): Support properly beforeunload on subframes. For now just
800   // pretend that the handler ran and allowed the navigation to proceed.
801   if (GetParent()) {
802     render_view_host_->is_waiting_for_beforeunload_ack_ = false;
803     frame_tree_node_->render_manager()->OnBeforeUnloadACK(
804         render_view_host_->unload_ack_is_for_cross_site_transition_, proceed,
805         renderer_before_unload_end_time);
806     return;
807   }
808
809   render_view_host_->decrement_in_flight_event_count();
810   render_view_host_->StopHangMonitorTimeout();
811   // If this renderer navigated while the beforeunload request was in flight, we
812   // may have cleared this state in OnDidCommitProvisionalLoad, in which case we
813   // can ignore this message.
814   // However renderer might also be swapped out but we still want to proceed
815   // with navigation, otherwise it would block future navigations. This can
816   // happen when pending cross-site navigation is canceled by a second one just
817   // before OnDidCommitProvisionalLoad while current RVH is waiting for commit
818   // but second navigation is started from the beginning.
819   if (!render_view_host_->is_waiting_for_beforeunload_ack_) {
820     return;
821   }
822
823   render_view_host_->is_waiting_for_beforeunload_ack_ = false;
824
825   base::TimeTicks before_unload_end_time;
826   if (!send_before_unload_start_time_.is_null() &&
827       !renderer_before_unload_start_time.is_null() &&
828       !renderer_before_unload_end_time.is_null()) {
829     // When passing TimeTicks across process boundaries, we need to compensate
830     // for any skew between the processes. Here we are converting the
831     // renderer's notion of before_unload_end_time to TimeTicks in the browser
832     // process. See comments in inter_process_time_ticks_converter.h for more.
833     InterProcessTimeTicksConverter converter(
834         LocalTimeTicks::FromTimeTicks(send_before_unload_start_time_),
835         LocalTimeTicks::FromTimeTicks(base::TimeTicks::Now()),
836         RemoteTimeTicks::FromTimeTicks(renderer_before_unload_start_time),
837         RemoteTimeTicks::FromTimeTicks(renderer_before_unload_end_time));
838     LocalTimeTicks browser_before_unload_end_time =
839         converter.ToLocalTimeTicks(
840             RemoteTimeTicks::FromTimeTicks(renderer_before_unload_end_time));
841     before_unload_end_time = browser_before_unload_end_time.ToTimeTicks();
842
843     // Collect UMA on the inter-process skew.
844     bool is_skew_additive = false;
845     if (converter.IsSkewAdditiveForMetrics()) {
846       is_skew_additive = true;
847       base::TimeDelta skew = converter.GetSkewForMetrics();
848       if (skew >= base::TimeDelta()) {
849         UMA_HISTOGRAM_TIMES(
850             "InterProcessTimeTicks.BrowserBehind_RendererToBrowser", skew);
851       } else {
852         UMA_HISTOGRAM_TIMES(
853             "InterProcessTimeTicks.BrowserAhead_RendererToBrowser", -skew);
854       }
855     }
856     UMA_HISTOGRAM_BOOLEAN(
857         "InterProcessTimeTicks.IsSkewAdditive_RendererToBrowser",
858         is_skew_additive);
859   }
860   frame_tree_node_->render_manager()->OnBeforeUnloadACK(
861       render_view_host_->unload_ack_is_for_cross_site_transition_, proceed,
862       before_unload_end_time);
863
864   // If canceled, notify the delegate to cancel its pending navigation entry.
865   if (!proceed)
866     render_view_host_->GetDelegate()->DidCancelLoading();
867 }
868
869 void RenderFrameHostImpl::OnSwapOutACK() {
870   OnSwappedOut(false);
871   TRACE_EVENT_ASYNC_END0("navigation", "RenderFrameHostImpl::SwapOut", this);
872 }
873
874 void RenderFrameHostImpl::OnSwappedOut(bool timed_out) {
875   // For now, we only need to update the RVH state machine for top-level swaps.
876   if (!GetParent())
877     render_view_host_->OnSwappedOut(timed_out);
878 }
879
880 void RenderFrameHostImpl::OnContextMenu(const ContextMenuParams& params) {
881   // Validate the URLs in |params|.  If the renderer can't request the URLs
882   // directly, don't show them in the context menu.
883   ContextMenuParams validated_params(params);
884   RenderProcessHost* process = GetProcess();
885
886   // We don't validate |unfiltered_link_url| so that this field can be used
887   // when users want to copy the original link URL.
888   process->FilterURL(true, &validated_params.link_url);
889   process->FilterURL(true, &validated_params.src_url);
890   process->FilterURL(false, &validated_params.page_url);
891   process->FilterURL(true, &validated_params.frame_url);
892
893   delegate_->ShowContextMenu(this, validated_params);
894 }
895
896 void RenderFrameHostImpl::OnJavaScriptExecuteResponse(
897     int id, const base::ListValue& result) {
898   const base::Value* result_value;
899   if (!result.Get(0, &result_value)) {
900     // Programming error or rogue renderer.
901     NOTREACHED() << "Got bad arguments for OnJavaScriptExecuteResponse";
902     return;
903   }
904
905   std::map<int, JavaScriptResultCallback>::iterator it =
906       javascript_callbacks_.find(id);
907   if (it != javascript_callbacks_.end()) {
908     it->second.Run(result_value);
909     javascript_callbacks_.erase(it);
910   } else {
911     NOTREACHED() << "Received script response for unknown request";
912   }
913 }
914
915 void RenderFrameHostImpl::OnRunJavaScriptMessage(
916     const base::string16& message,
917     const base::string16& default_prompt,
918     const GURL& frame_url,
919     JavaScriptMessageType type,
920     IPC::Message* reply_msg) {
921   // While a JS message dialog is showing, tabs in the same process shouldn't
922   // process input events.
923   GetProcess()->SetIgnoreInputEvents(true);
924   render_view_host_->StopHangMonitorTimeout();
925   delegate_->RunJavaScriptMessage(this, message, default_prompt,
926                                   frame_url, type, reply_msg);
927 }
928
929 void RenderFrameHostImpl::OnRunBeforeUnloadConfirm(
930     const GURL& frame_url,
931     const base::string16& message,
932     bool is_reload,
933     IPC::Message* reply_msg) {
934   // While a JS before unload dialog is showing, tabs in the same process
935   // shouldn't process input events.
936   GetProcess()->SetIgnoreInputEvents(true);
937   render_view_host_->StopHangMonitorTimeout();
938   delegate_->RunBeforeUnloadConfirm(this, message, is_reload, reply_msg);
939 }
940
941 void RenderFrameHostImpl::OnRequestPlatformNotificationPermission(
942     const GURL& origin, int request_id) {
943   base::Callback<void(blink::WebNotificationPermission)> done_callback =
944       base::Bind(
945           &RenderFrameHostImpl::PlatformNotificationPermissionRequestDone,
946           weak_ptr_factory_.GetWeakPtr(),
947           request_id);
948
949   GetContentClient()->browser()->RequestDesktopNotificationPermission(
950       origin, this, done_callback);
951 }
952
953 void RenderFrameHostImpl::OnShowDesktopNotification(
954     int notification_id,
955     const ShowDesktopNotificationHostMsgParams& params) {
956   scoped_ptr<DesktopNotificationDelegateImpl> delegate(
957       new DesktopNotificationDelegateImpl(this, notification_id));
958
959   base::Closure cancel_callback;
960   GetContentClient()->browser()->ShowDesktopNotification(
961       params,
962       this,
963       delegate.PassAs<DesktopNotificationDelegate>(),
964       &cancel_callback);
965   cancel_notification_callbacks_[notification_id] = cancel_callback;
966 }
967
968 void RenderFrameHostImpl::OnCancelDesktopNotification(int notification_id) {
969   if (!cancel_notification_callbacks_.count(notification_id)) {
970     NOTREACHED();
971     return;
972   }
973   cancel_notification_callbacks_[notification_id].Run();
974   cancel_notification_callbacks_.erase(notification_id);
975 }
976
977 void RenderFrameHostImpl::OnTextSurroundingSelectionResponse(
978     const base::string16& content,
979     size_t start_offset,
980     size_t end_offset) {
981   render_view_host_->OnTextSurroundingSelectionResponse(
982       content, start_offset, end_offset);
983 }
984
985 void RenderFrameHostImpl::OnDidAccessInitialDocument() {
986   delegate_->DidAccessInitialDocument();
987 }
988
989 void RenderFrameHostImpl::OnDidDisownOpener() {
990   // This message is only sent for top-level frames. TODO(avi): when frame tree
991   // mirroring works correctly, add a check here to enforce it.
992   delegate_->DidDisownOpener(this);
993 }
994
995 void RenderFrameHostImpl::OnDidAssignPageId(int32 page_id) {
996   // Update the RVH's current page ID so that future IPCs from the renderer
997   // correspond to the new page.
998   render_view_host_->page_id_ = page_id;
999 }
1000
1001 void RenderFrameHostImpl::OnUpdateTitle(
1002     int32 page_id,
1003     const base::string16& title,
1004     blink::WebTextDirection title_direction) {
1005   // This message is only sent for top-level frames. TODO(avi): when frame tree
1006   // mirroring works correctly, add a check here to enforce it.
1007   if (title.length() > kMaxTitleChars) {
1008     NOTREACHED() << "Renderer sent too many characters in title.";
1009     return;
1010   }
1011
1012   delegate_->UpdateTitle(this, page_id, title,
1013                          WebTextDirectionToChromeTextDirection(
1014                              title_direction));
1015 }
1016
1017 void RenderFrameHostImpl::OnUpdateEncoding(const std::string& encoding_name) {
1018   // This message is only sent for top-level frames. TODO(avi): when frame tree
1019   // mirroring works correctly, add a check here to enforce it.
1020   delegate_->UpdateEncoding(this, encoding_name);
1021 }
1022
1023 void RenderFrameHostImpl::OnBeginNavigation(
1024     const FrameHostMsg_BeginNavigation_Params& params) {
1025   CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
1026       switches::kEnableBrowserSideNavigation));
1027   frame_tree_node()->render_manager()->OnBeginNavigation(params);
1028 }
1029
1030 void RenderFrameHostImpl::OnAccessibilityEvents(
1031     const std::vector<AccessibilityHostMsg_EventParams>& params) {
1032   RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
1033       render_view_host_->GetView());
1034
1035   AccessibilityMode accessibility_mode = delegate_->GetAccessibilityMode();
1036   if ((accessibility_mode != AccessibilityModeOff) && view &&
1037       RenderViewHostImpl::IsRVHStateActive(render_view_host_->rvh_state())) {
1038     if (accessibility_mode & AccessibilityModeFlagPlatform) {
1039       GetOrCreateBrowserAccessibilityManager();
1040       if (browser_accessibility_manager_)
1041         browser_accessibility_manager_->OnAccessibilityEvents(params);
1042     }
1043
1044     if (browser_accessibility_manager_) {
1045       // Get the frame routing ids from out-of-process iframes and
1046       // browser plugin instance ids from guests and update the mappings in
1047       // FrameAccessibility.
1048       for (unsigned int i = 0; i < params.size(); ++i) {
1049         const AccessibilityHostMsg_EventParams& param = params[i];
1050         UpdateCrossProcessIframeAccessibility(
1051             param.node_to_frame_routing_id_map);
1052         UpdateGuestFrameAccessibility(
1053             param.node_to_browser_plugin_instance_id_map);
1054       }
1055     }
1056
1057     // Send the updates to the automation extension API.
1058     std::vector<AXEventNotificationDetails> details;
1059     details.reserve(params.size());
1060     for (size_t i = 0; i < params.size(); ++i) {
1061       const AccessibilityHostMsg_EventParams& param = params[i];
1062       AXEventNotificationDetails detail(param.update.node_id_to_clear,
1063                                         param.update.nodes,
1064                                         param.event_type,
1065                                         param.id,
1066                                         GetProcess()->GetID(),
1067                                         routing_id_);
1068       details.push_back(detail);
1069     }
1070
1071     delegate_->AccessibilityEventReceived(details);
1072   }
1073
1074   // Always send an ACK or the renderer can be in a bad state.
1075   Send(new AccessibilityMsg_Events_ACK(routing_id_));
1076
1077   // The rest of this code is just for testing; bail out if we're not
1078   // in that mode.
1079   if (accessibility_testing_callback_.is_null())
1080     return;
1081
1082   for (size_t i = 0; i < params.size(); i++) {
1083     const AccessibilityHostMsg_EventParams& param = params[i];
1084     if (static_cast<int>(param.event_type) < 0)
1085       continue;
1086
1087     if (!ax_tree_for_testing_) {
1088       if (browser_accessibility_manager_) {
1089         ax_tree_for_testing_.reset(new ui::AXTree(
1090             browser_accessibility_manager_->SnapshotAXTreeForTesting()));
1091       } else {
1092         ax_tree_for_testing_.reset(new ui::AXTree());
1093         CHECK(ax_tree_for_testing_->Unserialize(param.update))
1094             << ax_tree_for_testing_->error();
1095       }
1096     } else {
1097       CHECK(ax_tree_for_testing_->Unserialize(param.update))
1098           << ax_tree_for_testing_->error();
1099     }
1100     accessibility_testing_callback_.Run(param.event_type, param.id);
1101   }
1102 }
1103
1104 void RenderFrameHostImpl::OnAccessibilityLocationChanges(
1105     const std::vector<AccessibilityHostMsg_LocationChangeParams>& params) {
1106   RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
1107       render_view_host_->GetView());
1108   if (view &&
1109       RenderViewHostImpl::IsRVHStateActive(render_view_host_->rvh_state())) {
1110     AccessibilityMode accessibility_mode = delegate_->GetAccessibilityMode();
1111     if (accessibility_mode & AccessibilityModeFlagPlatform) {
1112       if (!browser_accessibility_manager_) {
1113         browser_accessibility_manager_.reset(
1114             view->CreateBrowserAccessibilityManager(this));
1115       }
1116       if (browser_accessibility_manager_)
1117         browser_accessibility_manager_->OnLocationChanges(params);
1118     }
1119     // TODO(aboxhall): send location change events to web contents observers too
1120   }
1121 }
1122
1123 #if defined(OS_MACOSX) || defined(OS_ANDROID)
1124 void RenderFrameHostImpl::OnShowPopup(
1125     const FrameHostMsg_ShowPopup_Params& params) {
1126   RenderViewHostDelegateView* view =
1127       render_view_host_->delegate_->GetDelegateView();
1128   if (view) {
1129     view->ShowPopupMenu(this,
1130                         params.bounds,
1131                         params.item_height,
1132                         params.item_font_size,
1133                         params.selected_item,
1134                         params.popup_items,
1135                         params.right_aligned,
1136                         params.allow_multiple_selection);
1137   }
1138 }
1139
1140 void RenderFrameHostImpl::OnHidePopup() {
1141   RenderViewHostDelegateView* view =
1142       render_view_host_->delegate_->GetDelegateView();
1143   if (view)
1144     view->HidePopupMenu();
1145 }
1146 #endif
1147
1148 void RenderFrameHostImpl::SetPendingShutdown(const base::Closure& on_swap_out) {
1149   render_view_host_->SetPendingShutdown(on_swap_out);
1150 }
1151
1152 bool RenderFrameHostImpl::CanCommitURL(const GURL& url) {
1153   // TODO(creis): We should also check for WebUI pages here.  Also, when the
1154   // out-of-process iframes implementation is ready, we should check for
1155   // cross-site URLs that are not allowed to commit in this process.
1156
1157   // Give the client a chance to disallow URLs from committing.
1158   return GetContentClient()->browser()->CanCommitURL(GetProcess(), url);
1159 }
1160
1161 void RenderFrameHostImpl::Navigate(const FrameMsg_Navigate_Params& params) {
1162   TRACE_EVENT0("navigation", "RenderFrameHostImpl::Navigate");
1163   // Browser plugin guests are not allowed to navigate outside web-safe schemes,
1164   // so do not grant them the ability to request additional URLs.
1165   if (!GetProcess()->IsIsolatedGuest()) {
1166     ChildProcessSecurityPolicyImpl::GetInstance()->GrantRequestURL(
1167         GetProcess()->GetID(), params.url);
1168     if (params.url.SchemeIs(url::kDataScheme) &&
1169         params.base_url_for_data_url.SchemeIs(url::kFileScheme)) {
1170       // If 'data:' is used, and we have a 'file:' base url, grant access to
1171       // local files.
1172       ChildProcessSecurityPolicyImpl::GetInstance()->GrantRequestURL(
1173           GetProcess()->GetID(), params.base_url_for_data_url);
1174     }
1175   }
1176
1177   // Only send the message if we aren't suspended at the start of a cross-site
1178   // request.
1179   if (navigations_suspended_) {
1180     // Shouldn't be possible to have a second navigation while suspended, since
1181     // navigations will only be suspended during a cross-site request.  If a
1182     // second navigation occurs, RenderFrameHostManager will cancel this pending
1183     // RFH and create a new pending RFH.
1184     DCHECK(!suspended_nav_params_.get());
1185     suspended_nav_params_.reset(new FrameMsg_Navigate_Params(params));
1186   } else {
1187     // Get back to a clean state, in case we start a new navigation without
1188     // completing a RVH swap or unload handler.
1189     render_view_host_->SetState(RenderViewHostImpl::STATE_DEFAULT);
1190
1191     Send(new FrameMsg_Navigate(routing_id_, params));
1192   }
1193
1194   // Force the throbber to start. We do this because Blink's "started
1195   // loading" message will be received asynchronously from the UI of the
1196   // browser. But we want to keep the throbber in sync with what's happening
1197   // in the UI. For example, we want to start throbbing immediately when the
1198   // user naivgates even if the renderer is delayed. There is also an issue
1199   // with the throbber starting because the WebUI (which controls whether the
1200   // favicon is displayed) happens synchronously. If the start loading
1201   // messages was asynchronous, then the default favicon would flash in.
1202   //
1203   // Blink doesn't send throb notifications for JavaScript URLs, so we
1204   // don't want to either.
1205   if (!params.url.SchemeIs(url::kJavaScriptScheme))
1206     delegate_->DidStartLoading(this, true);
1207 }
1208
1209 void RenderFrameHostImpl::NavigateToURL(const GURL& url) {
1210   FrameMsg_Navigate_Params params;
1211   params.page_id = -1;
1212   params.pending_history_list_offset = -1;
1213   params.current_history_list_offset = -1;
1214   params.current_history_list_length = 0;
1215   params.url = url;
1216   params.transition = ui::PAGE_TRANSITION_LINK;
1217   params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
1218   params.browser_navigation_start = base::TimeTicks::Now();
1219   Navigate(params);
1220 }
1221
1222 void RenderFrameHostImpl::Stop() {
1223   Send(new FrameMsg_Stop(routing_id_));
1224 }
1225
1226 void RenderFrameHostImpl::DispatchBeforeUnload(bool for_cross_site_transition) {
1227   TRACE_EVENT_ASYNC_BEGIN0(
1228       "navigation", "RenderFrameHostImpl::BeforeUnload", this);
1229   // TODO(creis): Support subframes.
1230   if (GetParent() || !IsRenderFrameLive()) {
1231     // We don't have a live renderer, so just skip running beforeunload.
1232     render_view_host_->is_waiting_for_beforeunload_ack_ = true;
1233     render_view_host_->unload_ack_is_for_cross_site_transition_ =
1234         for_cross_site_transition;
1235     base::TimeTicks now = base::TimeTicks::Now();
1236     OnBeforeUnloadACK(true, now, now);
1237     return;
1238   }
1239
1240   // This may be called more than once (if the user clicks the tab close button
1241   // several times, or if she clicks the tab close button then the browser close
1242   // button), and we only send the message once.
1243   if (render_view_host_->is_waiting_for_beforeunload_ack_) {
1244     // Some of our close messages could be for the tab, others for cross-site
1245     // transitions. We always want to think it's for closing the tab if any
1246     // of the messages were, since otherwise it might be impossible to close
1247     // (if there was a cross-site "close" request pending when the user clicked
1248     // the close button). We want to keep the "for cross site" flag only if
1249     // both the old and the new ones are also for cross site.
1250     render_view_host_->unload_ack_is_for_cross_site_transition_ =
1251         render_view_host_->unload_ack_is_for_cross_site_transition_ &&
1252         for_cross_site_transition;
1253   } else {
1254     // Start the hang monitor in case the renderer hangs in the beforeunload
1255     // handler.
1256     render_view_host_->is_waiting_for_beforeunload_ack_ = true;
1257     render_view_host_->unload_ack_is_for_cross_site_transition_ =
1258         for_cross_site_transition;
1259     // Increment the in-flight event count, to ensure that input events won't
1260     // cancel the timeout timer.
1261     render_view_host_->increment_in_flight_event_count();
1262     render_view_host_->StartHangMonitorTimeout(
1263         TimeDelta::FromMilliseconds(RenderViewHostImpl::kUnloadTimeoutMS));
1264     send_before_unload_start_time_ = base::TimeTicks::Now();
1265     Send(new FrameMsg_BeforeUnload(routing_id_));
1266   }
1267 }
1268
1269 void RenderFrameHostImpl::DisownOpener() {
1270   Send(new FrameMsg_DisownOpener(GetRoutingID()));
1271 }
1272
1273 void RenderFrameHostImpl::ExtendSelectionAndDelete(size_t before,
1274                                                    size_t after) {
1275   Send(new InputMsg_ExtendSelectionAndDelete(routing_id_, before, after));
1276 }
1277
1278 void RenderFrameHostImpl::JavaScriptDialogClosed(
1279     IPC::Message* reply_msg,
1280     bool success,
1281     const base::string16& user_input,
1282     bool dialog_was_suppressed) {
1283   GetProcess()->SetIgnoreInputEvents(false);
1284   bool is_waiting = render_view_host_->is_waiting_for_beforeunload_ack() ||
1285                     render_view_host_->IsWaitingForUnloadACK();
1286
1287   // If we are executing as part of (before)unload event handling, we don't
1288   // want to use the regular hung_renderer_delay_ms_ if the user has agreed to
1289   // leave the current page. In this case, use the regular timeout value used
1290   // during the (before)unload handling.
1291   if (is_waiting) {
1292     render_view_host_->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(
1293         success ? RenderViewHostImpl::kUnloadTimeoutMS
1294                 : render_view_host_->hung_renderer_delay_ms_));
1295   }
1296
1297   FrameHostMsg_RunJavaScriptMessage::WriteReplyParams(reply_msg,
1298                                                       success, user_input);
1299   Send(reply_msg);
1300
1301   // If we are waiting for an unload or beforeunload ack and the user has
1302   // suppressed messages, kill the tab immediately; a page that's spamming
1303   // alerts in onbeforeunload is presumably malicious, so there's no point in
1304   // continuing to run its script and dragging out the process.
1305   // This must be done after sending the reply since RenderView can't close
1306   // correctly while waiting for a response.
1307   if (is_waiting && dialog_was_suppressed)
1308     render_view_host_->delegate_->RendererUnresponsive(
1309         render_view_host_,
1310         render_view_host_->is_waiting_for_beforeunload_ack(),
1311         render_view_host_->IsWaitingForUnloadACK());
1312 }
1313
1314 void RenderFrameHostImpl::NotificationClosed(int notification_id) {
1315   cancel_notification_callbacks_.erase(notification_id);
1316 }
1317
1318 void RenderFrameHostImpl::PlatformNotificationPermissionRequestDone(
1319     int request_id, blink::WebNotificationPermission permission) {
1320   Send(new PlatformNotificationMsg_PermissionRequestComplete(
1321       routing_id_, request_id, permission));
1322 }
1323
1324 void RenderFrameHostImpl::UpdateCrossProcessIframeAccessibility(
1325     const std::map<int32, int> node_to_frame_routing_id_map) {
1326   std::map<int32, int>::const_iterator iter;
1327   for (iter = node_to_frame_routing_id_map.begin();
1328        iter != node_to_frame_routing_id_map.end();
1329        ++iter) {
1330     // This is the id of the accessibility node that has a child frame.
1331     int32 node_id = iter->first;
1332     // The routing id from either a RenderFrame or a RenderFrameProxy.
1333     int frame_routing_id = iter->second;
1334
1335     FrameTree* frame_tree = frame_tree_node()->frame_tree();
1336     FrameTreeNode* child_frame_tree_node = frame_tree->FindByRoutingID(
1337         GetProcess()->GetID(), frame_routing_id);
1338     if (child_frame_tree_node) {
1339       FrameAccessibility::GetInstance()->AddChildFrame(
1340           this, node_id, child_frame_tree_node->frame_tree_node_id());
1341     }
1342   }
1343 }
1344
1345 void RenderFrameHostImpl::UpdateGuestFrameAccessibility(
1346     const std::map<int32, int> node_to_browser_plugin_instance_id_map) {
1347   std::map<int32, int>::const_iterator iter;
1348   for (iter = node_to_browser_plugin_instance_id_map.begin();
1349        iter != node_to_browser_plugin_instance_id_map.end();
1350        ++iter) {
1351     // This is the id of the accessibility node that hosts a plugin.
1352     int32 node_id = iter->first;
1353     // The id of the browser plugin.
1354     int browser_plugin_instance_id = iter->second;
1355     FrameAccessibility::GetInstance()->AddGuestWebContents(
1356         this, node_id, browser_plugin_instance_id);
1357   }
1358 }
1359
1360 void RenderFrameHostImpl::SetAccessibilityMode(AccessibilityMode mode) {
1361   Send(new FrameMsg_SetAccessibilityMode(routing_id_, mode));
1362 }
1363
1364 void RenderFrameHostImpl::SetAccessibilityCallbackForTesting(
1365     const base::Callback<void(ui::AXEvent, int)>& callback) {
1366   accessibility_testing_callback_ = callback;
1367 }
1368
1369 const ui::AXTree* RenderFrameHostImpl::GetAXTreeForTesting() {
1370   return ax_tree_for_testing_.get();
1371 }
1372
1373 BrowserAccessibilityManager*
1374     RenderFrameHostImpl::GetOrCreateBrowserAccessibilityManager() {
1375   RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
1376       render_view_host_->GetView());
1377   if (view &&
1378       !browser_accessibility_manager_) {
1379     browser_accessibility_manager_.reset(
1380         view->CreateBrowserAccessibilityManager(this));
1381   }
1382   return browser_accessibility_manager_.get();
1383 }
1384
1385 #if defined(OS_WIN)
1386
1387 void RenderFrameHostImpl::SetParentNativeViewAccessible(
1388     gfx::NativeViewAccessible accessible_parent) {
1389   RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
1390       render_view_host_->GetView());
1391   if (view)
1392     view->SetParentNativeViewAccessible(accessible_parent);
1393 }
1394
1395 gfx::NativeViewAccessible
1396 RenderFrameHostImpl::GetParentNativeViewAccessible() const {
1397   return delegate_->GetParentNativeViewAccessible();
1398 }
1399
1400 #elif defined(OS_MACOSX)
1401
1402 void RenderFrameHostImpl::DidSelectPopupMenuItem(int selected_index) {
1403   Send(new FrameMsg_SelectPopupMenuItem(routing_id_, selected_index));
1404 }
1405
1406 void RenderFrameHostImpl::DidCancelPopupMenu() {
1407   Send(new FrameMsg_SelectPopupMenuItem(routing_id_, -1));
1408 }
1409
1410 #elif defined(OS_ANDROID)
1411
1412 void RenderFrameHostImpl::DidSelectPopupMenuItems(
1413     const std::vector<int>& selected_indices) {
1414   Send(new FrameMsg_SelectPopupMenuItems(routing_id_, false, selected_indices));
1415 }
1416
1417 void RenderFrameHostImpl::DidCancelPopupMenu() {
1418   Send(new FrameMsg_SelectPopupMenuItems(
1419       routing_id_, true, std::vector<int>()));
1420 }
1421
1422 #endif
1423
1424 void RenderFrameHostImpl::ClearPendingTransitionRequestData() {
1425   BrowserThread::PostTask(
1426       BrowserThread::IO,
1427       FROM_HERE,
1428       base::Bind(
1429           &TransitionRequestManager::ClearPendingTransitionRequestData,
1430           base::Unretained(TransitionRequestManager::GetInstance()),
1431           GetProcess()->GetID(),
1432           routing_id_));
1433 }
1434
1435 void RenderFrameHostImpl::SetNavigationsSuspended(
1436     bool suspend,
1437     const base::TimeTicks& proceed_time) {
1438   // This should only be called to toggle the state.
1439   DCHECK(navigations_suspended_ != suspend);
1440
1441   navigations_suspended_ = suspend;
1442   if (navigations_suspended_) {
1443     TRACE_EVENT_ASYNC_BEGIN0("navigation",
1444                              "RenderFrameHostImpl navigation suspended", this);
1445   } else {
1446     TRACE_EVENT_ASYNC_END0("navigation",
1447                            "RenderFrameHostImpl navigation suspended", this);
1448   }
1449
1450   if (!suspend && suspended_nav_params_) {
1451     // There's navigation message params waiting to be sent. Now that we're not
1452     // suspended anymore, resume navigation by sending them. If we were swapped
1453     // out, we should also stop filtering out the IPC messages now.
1454     render_view_host_->SetState(RenderViewHostImpl::STATE_DEFAULT);
1455
1456     DCHECK(!proceed_time.is_null());
1457     suspended_nav_params_->browser_navigation_start = proceed_time;
1458     Send(new FrameMsg_Navigate(routing_id_, *suspended_nav_params_));
1459     suspended_nav_params_.reset();
1460   }
1461 }
1462
1463 void RenderFrameHostImpl::CancelSuspendedNavigations() {
1464   // Clear any state if a pending navigation is canceled or preempted.
1465   if (suspended_nav_params_)
1466     suspended_nav_params_.reset();
1467
1468   TRACE_EVENT_ASYNC_END0("navigation",
1469                          "RenderFrameHostImpl navigation suspended", this);
1470   navigations_suspended_ = false;
1471 }
1472
1473 }  // namespace content