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