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