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