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/renderer/render_frame_impl.h" 6 7 #include <map> 8 #include <string> 9 10 #include "base/command_line.h" 11 #include "base/i18n/char_iterator.h" 12 #include "base/strings/utf_string_conversions.h" 13 #include "base/time/time.h" 14 #include "content/child/appcache/appcache_dispatcher.h" 15 #include "content/child/plugin_messages.h" 16 #include "content/child/quota_dispatcher.h" 17 #include "content/child/request_extra_data.h" 18 #include "content/child/service_worker/web_service_worker_provider_impl.h" 19 #include "content/common/frame_messages.h" 20 #include "content/common/socket_stream_handle_data.h" 21 #include "content/common/swapped_out_messages.h" 22 #include "content/common/view_messages.h" 23 #include "content/public/common/content_constants.h" 24 #include "content/public/common/content_switches.h" 25 #include "content/public/common/url_constants.h" 26 #include "content/public/renderer/content_renderer_client.h" 27 #include "content/public/renderer/document_state.h" 28 #include "content/public/renderer/navigation_state.h" 29 #include "content/public/renderer/render_frame_observer.h" 30 #include "content/renderer/accessibility/renderer_accessibility.h" 31 #include "content/renderer/browser_plugin/browser_plugin.h" 32 #include "content/renderer/browser_plugin/browser_plugin_manager.h" 33 #include "content/renderer/internal_document_state_data.h" 34 #include "content/renderer/npapi/plugin_channel_host.h" 35 #include "content/renderer/render_thread_impl.h" 36 #include "content/renderer/render_view_impl.h" 37 #include "content/renderer/render_widget_fullscreen_pepper.h" 38 #include "content/renderer/renderer_webapplicationcachehost_impl.h" 39 #include "content/renderer/websharedworker_proxy.h" 40 #include "net/base/net_errors.h" 41 #include "net/http/http_util.h" 42 #include "third_party/WebKit/public/platform/WebStorageQuotaCallbacks.h" 43 #include "third_party/WebKit/public/platform/WebString.h" 44 #include "third_party/WebKit/public/platform/WebURL.h" 45 #include "third_party/WebKit/public/platform/WebURLError.h" 46 #include "third_party/WebKit/public/platform/WebURLResponse.h" 47 #include "third_party/WebKit/public/platform/WebVector.h" 48 #include "third_party/WebKit/public/web/WebDocument.h" 49 #include "third_party/WebKit/public/web/WebFrame.h" 50 #include "third_party/WebKit/public/web/WebNavigationPolicy.h" 51 #include "third_party/WebKit/public/web/WebPlugin.h" 52 #include "third_party/WebKit/public/web/WebPluginParams.h" 53 #include "third_party/WebKit/public/web/WebSearchableFormData.h" 54 #include "third_party/WebKit/public/web/WebSecurityOrigin.h" 55 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" 56 #include "third_party/WebKit/public/web/WebView.h" 57 #include "webkit/child/weburlresponse_extradata_impl.h" 58 59 #if defined(ENABLE_PLUGINS) 60 #include "content/renderer/npapi/webplugin_impl.h" 61 #include "content/renderer/pepper/pepper_browser_connection.h" 62 #include "content/renderer/pepper/pepper_plugin_instance_impl.h" 63 #include "content/renderer/pepper/pepper_webplugin_impl.h" 64 #include "content/renderer/pepper/plugin_module.h" 65 #endif 66 67 #if defined(ENABLE_WEBRTC) 68 #include "content/renderer/media/rtc_peer_connection_handler.h" 69 #endif 70 71 using blink::WebDataSource; 72 using blink::WebDocument; 73 using blink::WebFrame; 74 using blink::WebNavigationPolicy; 75 using blink::WebPluginParams; 76 using blink::WebReferrerPolicy; 77 using blink::WebSearchableFormData; 78 using blink::WebSecurityOrigin; 79 using blink::WebServiceWorkerProvider; 80 using blink::WebStorageQuotaCallbacks; 81 using blink::WebString; 82 using blink::WebURL; 83 using blink::WebURLError; 84 using blink::WebURLRequest; 85 using blink::WebURLResponse; 86 using blink::WebUserGestureIndicator; 87 using blink::WebVector; 88 using blink::WebView; 89 using base::Time; 90 using base::TimeDelta; 91 using webkit_glue::WebURLResponseExtraDataImpl; 92 93 namespace content { 94 95 namespace { 96 97 typedef std::map<blink::WebFrame*, RenderFrameImpl*> FrameMap; 98 base::LazyInstance<FrameMap> g_child_frame_map = LAZY_INSTANCE_INITIALIZER; 99 100 } // namespace 101 102 static RenderFrameImpl* (*g_create_render_frame_impl)(RenderViewImpl*, int32) = 103 NULL; 104 105 // static 106 RenderFrameImpl* RenderFrameImpl::Create(RenderViewImpl* render_view, 107 int32 routing_id) { 108 DCHECK(routing_id != MSG_ROUTING_NONE); 109 110 if (g_create_render_frame_impl) 111 return g_create_render_frame_impl(render_view, routing_id); 112 else 113 return new RenderFrameImpl(render_view, routing_id); 114 } 115 116 // static 117 void RenderFrameImpl::InstallCreateHook( 118 RenderFrameImpl* (*create_render_frame_impl)(RenderViewImpl*, int32)) { 119 CHECK(!g_create_render_frame_impl); 120 g_create_render_frame_impl = create_render_frame_impl; 121 } 122 123 // RenderFrameImpl ---------------------------------------------------------- 124 RenderFrameImpl::RenderFrameImpl(RenderViewImpl* render_view, int routing_id) 125 : render_view_(render_view), 126 routing_id_(routing_id), 127 is_swapped_out_(false), 128 is_detaching_(false) { 129 RenderThread::Get()->AddRoute(routing_id_, this); 130 #if defined(ENABLE_PLUGINS) 131 new PepperBrowserConnection(this); 132 #endif 133 134 GetContentClient()->renderer()->RenderFrameCreated(this); 135 } 136 137 RenderFrameImpl::~RenderFrameImpl() { 138 FOR_EACH_OBSERVER(RenderFrameObserver, observers_, RenderFrameGone()); 139 FOR_EACH_OBSERVER(RenderFrameObserver, observers_, OnDestruct()); 140 RenderThread::Get()->RemoveRoute(routing_id_); 141 } 142 143 RenderWidget* RenderFrameImpl::GetRenderWidget() { 144 return render_view_; 145 } 146 147 #if defined(ENABLE_PLUGINS) 148 void RenderFrameImpl::PepperPluginCreated(RendererPpapiHost* host) { 149 FOR_EACH_OBSERVER(RenderFrameObserver, observers_, 150 DidCreatePepperPlugin(host)); 151 } 152 153 void RenderFrameImpl::PepperInstanceCreated( 154 PepperPluginInstanceImpl* instance) { 155 active_pepper_instances_.insert(instance); 156 } 157 158 void RenderFrameImpl::PepperInstanceDeleted( 159 PepperPluginInstanceImpl* instance) { 160 active_pepper_instances_.erase(instance); 161 162 if (render_view_->pepper_last_mouse_event_target() == instance) 163 render_view_->set_pepper_last_mouse_event_target(NULL); 164 if (render_view_->focused_pepper_plugin() == instance) 165 PepperFocusChanged(instance, false); 166 } 167 168 void RenderFrameImpl::PepperDidChangeCursor( 169 PepperPluginInstanceImpl* instance, 170 const blink::WebCursorInfo& cursor) { 171 // Update the cursor appearance immediately if the requesting plugin is the 172 // one which receives the last mouse event. Otherwise, the new cursor won't be 173 // picked up until the plugin gets the next input event. That is bad if, e.g., 174 // the plugin would like to set an invisible cursor when there isn't any user 175 // input for a while. 176 if (instance == render_view_->pepper_last_mouse_event_target()) 177 GetRenderWidget()->didChangeCursor(cursor); 178 } 179 180 void RenderFrameImpl::PepperDidReceiveMouseEvent( 181 PepperPluginInstanceImpl* instance) { 182 render_view_->set_pepper_last_mouse_event_target(instance); 183 } 184 185 void RenderFrameImpl::PepperFocusChanged(PepperPluginInstanceImpl* instance, 186 bool focused) { 187 if (focused) 188 render_view_->set_focused_pepper_plugin(instance); 189 else if (render_view_->focused_pepper_plugin() == instance) 190 render_view_->set_focused_pepper_plugin(NULL); 191 192 GetRenderWidget()->UpdateTextInputType(); 193 GetRenderWidget()->UpdateSelectionBounds(); 194 } 195 196 void RenderFrameImpl::PepperTextInputTypeChanged( 197 PepperPluginInstanceImpl* instance) { 198 if (instance != render_view_->focused_pepper_plugin()) 199 return; 200 201 GetRenderWidget()->UpdateTextInputType(); 202 if (render_view_->renderer_accessibility()) { 203 render_view_->renderer_accessibility()->FocusedNodeChanged( 204 blink::WebNode()); 205 } 206 } 207 208 void RenderFrameImpl::PepperCaretPositionChanged( 209 PepperPluginInstanceImpl* instance) { 210 if (instance != render_view_->focused_pepper_plugin()) 211 return; 212 GetRenderWidget()->UpdateSelectionBounds(); 213 } 214 215 void RenderFrameImpl::PepperCancelComposition( 216 PepperPluginInstanceImpl* instance) { 217 if (instance != render_view_->focused_pepper_plugin()) 218 return; 219 Send(new ViewHostMsg_ImeCancelComposition(render_view_->GetRoutingID()));; 220 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA) 221 GetRenderWidget()->UpdateCompositionInfo(true); 222 #endif 223 } 224 225 void RenderFrameImpl::PepperSelectionChanged( 226 PepperPluginInstanceImpl* instance) { 227 if (instance != render_view_->focused_pepper_plugin()) 228 return; 229 render_view_->SyncSelectionIfRequired(); 230 } 231 232 RenderWidgetFullscreenPepper* RenderFrameImpl::CreatePepperFullscreenContainer( 233 PepperPluginInstanceImpl* plugin) { 234 GURL active_url; 235 if (render_view_->webview() && render_view_->webview()->mainFrame()) 236 active_url = GURL(render_view_->webview()->mainFrame()->document().url()); 237 RenderWidgetFullscreenPepper* widget = RenderWidgetFullscreenPepper::Create( 238 GetRenderWidget()->routing_id(), plugin, active_url, 239 GetRenderWidget()->screenInfo()); 240 widget->show(blink::WebNavigationPolicyIgnore); 241 return widget; 242 } 243 244 bool RenderFrameImpl::IsPepperAcceptingCompositionEvents() const { 245 if (!render_view_->focused_pepper_plugin()) 246 return false; 247 return render_view_->focused_pepper_plugin()-> 248 IsPluginAcceptingCompositionEvents(); 249 } 250 251 void RenderFrameImpl::PluginCrashed(const base::FilePath& plugin_path, 252 base::ProcessId plugin_pid) { 253 // TODO(jam): dispatch this IPC in RenderFrameHost and switch to use 254 // routing_id_ as a result. 255 Send(new FrameHostMsg_PluginCrashed(routing_id_, plugin_path, plugin_pid)); 256 } 257 258 void RenderFrameImpl::DidInitiatePaint() { 259 // Notify all instances that we painted. The same caveats apply as for 260 // ViewFlushedPaint regarding instances closing themselves, so we take 261 // similar precautions. 262 PepperPluginSet plugins = active_pepper_instances_; 263 for (PepperPluginSet::iterator i = plugins.begin(); i != plugins.end(); ++i) { 264 if (active_pepper_instances_.find(*i) != active_pepper_instances_.end()) 265 (*i)->ViewInitiatedPaint(); 266 } 267 } 268 269 void RenderFrameImpl::DidFlushPaint() { 270 // Notify all instances that we flushed. This will call into the plugin, and 271 // we it may ask to close itself as a result. This will, in turn, modify our 272 // set, possibly invalidating the iterator. So we iterate on a copy that 273 // won't change out from under us. 274 PepperPluginSet plugins = active_pepper_instances_; 275 for (PepperPluginSet::iterator i = plugins.begin(); i != plugins.end(); ++i) { 276 // The copy above makes sure our iterator is never invalid if some plugins 277 // are destroyed. But some plugin may decide to close all of its views in 278 // response to a paint in one of them, so we need to make sure each one is 279 // still "current" before using it. 280 // 281 // It's possible that a plugin was destroyed, but another one was created 282 // with the same address. In this case, we'll call ViewFlushedPaint on that 283 // new plugin. But that's OK for this particular case since we're just 284 // notifying all of our instances that the view flushed, and the new one is 285 // one of our instances. 286 // 287 // What about the case where a new one is created in a callback at a new 288 // address and we don't issue the callback? We're still OK since this 289 // callback is used for flush callbacks and we could not have possibly 290 // started a new paint for the new plugin while processing a previous paint 291 // for an existing one. 292 if (active_pepper_instances_.find(*i) != active_pepper_instances_.end()) 293 (*i)->ViewFlushedPaint(); 294 } 295 } 296 297 PepperPluginInstanceImpl* RenderFrameImpl::GetBitmapForOptimizedPluginPaint( 298 const gfx::Rect& paint_bounds, 299 TransportDIB** dib, 300 gfx::Rect* location, 301 gfx::Rect* clip, 302 float* scale_factor) { 303 for (PepperPluginSet::iterator i = active_pepper_instances_.begin(); 304 i != active_pepper_instances_.end(); ++i) { 305 PepperPluginInstanceImpl* instance = *i; 306 // In Flash fullscreen , the plugin contents should be painted onto the 307 // fullscreen widget instead of the web page. 308 if (!instance->FlashIsFullscreenOrPending() && 309 instance->GetBitmapForOptimizedPluginPaint(paint_bounds, dib, location, 310 clip, scale_factor)) 311 return *i; 312 } 313 return NULL; 314 } 315 316 void RenderFrameImpl::PageVisibilityChanged(bool shown) { 317 // Inform PPAPI plugins that their page is no longer visible. 318 for (PepperPluginSet::iterator i = active_pepper_instances_.begin(); 319 i != active_pepper_instances_.end(); ++i) 320 (*i)->PageVisibilityChanged(shown); 321 } 322 323 void RenderFrameImpl::OnSetFocus(bool enable) { 324 // Notify all Pepper plugins. 325 for (PepperPluginSet::iterator i = active_pepper_instances_.begin(); 326 i != active_pepper_instances_.end(); ++i) 327 (*i)->SetContentAreaFocus(enable); 328 } 329 330 void RenderFrameImpl::WillHandleMouseEvent(const blink::WebMouseEvent& event) { 331 // This method is called for every mouse event that the render view receives. 332 // And then the mouse event is forwarded to WebKit, which dispatches it to the 333 // event target. Potentially a Pepper plugin will receive the event. 334 // In order to tell whether a plugin gets the last mouse event and which it 335 // is, we set |pepper_last_mouse_event_target_| to NULL here. If a plugin gets 336 // the event, it will notify us via DidReceiveMouseEvent() and set itself as 337 // |pepper_last_mouse_event_target_|. 338 render_view_->set_pepper_last_mouse_event_target(NULL); 339 } 340 341 void RenderFrameImpl::SimulateImeSetComposition( 342 const base::string16& text, 343 const std::vector<blink::WebCompositionUnderline>& underlines, 344 int selection_start, 345 int selection_end) { 346 render_view_->OnImeSetComposition( 347 text, underlines, selection_start, selection_end); 348 } 349 350 void RenderFrameImpl::SimulateImeConfirmComposition( 351 const base::string16& text, 352 const gfx::Range& replacement_range) { 353 render_view_->OnImeConfirmComposition(text, replacement_range, false); 354 } 355 356 357 void RenderFrameImpl::OnImeSetComposition( 358 const base::string16& text, 359 const std::vector<blink::WebCompositionUnderline>& underlines, 360 int selection_start, 361 int selection_end) { 362 // When a PPAPI plugin has focus, we bypass WebKit. 363 if (!IsPepperAcceptingCompositionEvents()) { 364 pepper_composition_text_ = text; 365 } else { 366 // TODO(kinaba) currently all composition events are sent directly to 367 // plugins. Use DOM event mechanism after WebKit is made aware about 368 // plugins that support composition. 369 // The code below mimics the behavior of WebCore::Editor::setComposition. 370 371 // Empty -> nonempty: composition started. 372 if (pepper_composition_text_.empty() && !text.empty()) { 373 render_view_->focused_pepper_plugin()->HandleCompositionStart( 374 base::string16()); 375 } 376 // Nonempty -> empty: composition canceled. 377 if (!pepper_composition_text_.empty() && text.empty()) { 378 render_view_->focused_pepper_plugin()->HandleCompositionEnd( 379 base::string16()); 380 } 381 pepper_composition_text_ = text; 382 // Nonempty: composition is ongoing. 383 if (!pepper_composition_text_.empty()) { 384 render_view_->focused_pepper_plugin()->HandleCompositionUpdate( 385 pepper_composition_text_, underlines, selection_start, 386 selection_end); 387 } 388 } 389 } 390 391 void RenderFrameImpl::OnImeConfirmComposition( 392 const base::string16& text, 393 const gfx::Range& replacement_range, 394 bool keep_selection) { 395 // When a PPAPI plugin has focus, we bypass WebKit. 396 // Here, text.empty() has a special meaning. It means to commit the last 397 // update of composition text (see 398 // RenderWidgetHost::ImeConfirmComposition()). 399 const base::string16& last_text = text.empty() ? pepper_composition_text_ 400 : text; 401 402 // last_text is empty only when both text and pepper_composition_text_ is. 403 // Ignore it. 404 if (last_text.empty()) 405 return; 406 407 if (!IsPepperAcceptingCompositionEvents()) { 408 base::i18n::UTF16CharIterator iterator(&last_text); 409 int32 i = 0; 410 while (iterator.Advance()) { 411 blink::WebKeyboardEvent char_event; 412 char_event.type = blink::WebInputEvent::Char; 413 char_event.timeStampSeconds = base::Time::Now().ToDoubleT(); 414 char_event.modifiers = 0; 415 char_event.windowsKeyCode = last_text[i]; 416 char_event.nativeKeyCode = last_text[i]; 417 418 const int32 char_start = i; 419 for (; i < iterator.array_pos(); ++i) { 420 char_event.text[i - char_start] = last_text[i]; 421 char_event.unmodifiedText[i - char_start] = last_text[i]; 422 } 423 424 if (GetRenderWidget()->webwidget()) 425 GetRenderWidget()->webwidget()->handleInputEvent(char_event); 426 } 427 } else { 428 // Mimics the order of events sent by WebKit. 429 // See WebCore::Editor::setComposition() for the corresponding code. 430 render_view_->focused_pepper_plugin()->HandleCompositionEnd(last_text); 431 render_view_->focused_pepper_plugin()->HandleTextInput(last_text); 432 } 433 pepper_composition_text_.clear(); 434 } 435 436 #endif // ENABLE_PLUGINS 437 438 bool RenderFrameImpl::Send(IPC::Message* message) { 439 if (is_detaching_ || 440 ((is_swapped_out_ || render_view_->is_swapped_out()) && 441 !SwappedOutMessages::CanSendWhileSwappedOut(message))) { 442 delete message; 443 return false; 444 } 445 446 return RenderThread::Get()->Send(message); 447 } 448 449 bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) { 450 ObserverListBase<RenderFrameObserver>::Iterator it(observers_); 451 RenderFrameObserver* observer; 452 while ((observer = it.GetNext()) != NULL) { 453 if (observer->OnMessageReceived(msg)) 454 return true; 455 } 456 457 // TODO(ajwong): Fill in with message handlers as various components 458 // are migrated over to understand frames. 459 return false; 460 } 461 462 RenderView* RenderFrameImpl::GetRenderView() { 463 return render_view_; 464 } 465 466 int RenderFrameImpl::GetRoutingID() { 467 return routing_id_; 468 } 469 470 WebPreferences& RenderFrameImpl::GetWebkitPreferences() { 471 return render_view_->GetWebkitPreferences(); 472 } 473 474 int RenderFrameImpl::ShowContextMenu(ContextMenuClient* client, 475 const ContextMenuParams& params) { 476 return render_view_->ShowContextMenu(client, params); 477 } 478 479 void RenderFrameImpl::CancelContextMenu(int request_id) { 480 return render_view_->CancelContextMenu(request_id); 481 } 482 483 blink::WebPlugin* RenderFrameImpl::CreatePlugin( 484 blink::WebFrame* frame, 485 const WebPluginInfo& info, 486 const blink::WebPluginParams& params) { 487 #if defined(ENABLE_PLUGINS) 488 bool pepper_plugin_was_registered = false; 489 scoped_refptr<PluginModule> pepper_module(PluginModule::Create( 490 this, info, &pepper_plugin_was_registered)); 491 if (pepper_plugin_was_registered) { 492 if (pepper_module.get()) { 493 // TODO(jam): change to take RenderFrame. 494 return new PepperWebPluginImpl( 495 pepper_module.get(), params, render_view_->AsWeakPtr(), this); 496 } 497 } 498 #if defined(OS_CHROMEOS) 499 LOG(WARNING) << "Pepper module/plugin creation failed."; 500 return NULL; 501 #else 502 // TODO(jam): change to take RenderFrame. 503 return new WebPluginImpl(frame, params, info.path, render_view_->AsWeakPtr(), 504 this); 505 #endif 506 #else 507 return NULL; 508 #endif 509 } 510 511 void RenderFrameImpl::LoadURLExternally( 512 blink::WebFrame* frame, 513 const blink::WebURLRequest& request, 514 blink::WebNavigationPolicy policy) { 515 loadURLExternally(frame, request, policy); 516 } 517 518 // blink::WebFrameClient implementation ---------------------------------------- 519 520 blink::WebPlugin* RenderFrameImpl::createPlugin( 521 blink::WebFrame* frame, 522 const blink::WebPluginParams& params) { 523 blink::WebPlugin* plugin = NULL; 524 if (GetContentClient()->renderer()->OverrideCreatePlugin( 525 this, frame, params, &plugin)) { 526 return plugin; 527 } 528 529 if (UTF16ToASCII(params.mimeType) == kBrowserPluginMimeType) { 530 return render_view_->GetBrowserPluginManager()->CreateBrowserPlugin( 531 render_view_, frame); 532 } 533 534 #if defined(ENABLE_PLUGINS) 535 WebPluginInfo info; 536 std::string mime_type; 537 bool found = false; 538 Send(new FrameHostMsg_GetPluginInfo( 539 routing_id_, params.url, frame->top()->document().url(), 540 params.mimeType.utf8(), &found, &info, &mime_type)); 541 if (!found) 542 return NULL; 543 544 WebPluginParams params_to_use = params; 545 params_to_use.mimeType = WebString::fromUTF8(mime_type); 546 return CreatePlugin(frame, info, params_to_use); 547 #else 548 return NULL; 549 #endif // defined(ENABLE_PLUGINS) 550 } 551 552 blink::WebMediaPlayer* RenderFrameImpl::createMediaPlayer( 553 blink::WebFrame* frame, 554 const blink::WebURL& url, 555 blink::WebMediaPlayerClient* client) { 556 // TODO(nasko): Moving the implementation here involves moving a few media 557 // related client objects here or referencing them in the RenderView. Needs 558 // more work to understand where the proper place for those objects is. 559 return render_view_->CreateMediaPlayer(this, frame, url, client); 560 } 561 562 blink::WebApplicationCacheHost* RenderFrameImpl::createApplicationCacheHost( 563 blink::WebFrame* frame, 564 blink::WebApplicationCacheHostClient* client) { 565 if (!frame || !frame->view()) 566 return NULL; 567 return new RendererWebApplicationCacheHostImpl( 568 RenderViewImpl::FromWebView(frame->view()), client, 569 RenderThreadImpl::current()->appcache_dispatcher()->backend_proxy()); 570 } 571 572 blink::WebWorkerPermissionClientProxy* 573 RenderFrameImpl::createWorkerPermissionClientProxy(WebFrame* frame) { 574 if (!frame || !frame->view()) 575 return NULL; 576 return GetContentClient()->renderer()->CreateWorkerPermissionClientProxy( 577 RenderViewImpl::FromWebView(frame->view()), frame); 578 } 579 580 blink::WebCookieJar* RenderFrameImpl::cookieJar(blink::WebFrame* frame) { 581 return render_view_->cookieJar(frame); 582 } 583 584 blink::WebServiceWorkerProvider* RenderFrameImpl::createServiceWorkerProvider( 585 blink::WebFrame* frame, 586 blink::WebServiceWorkerProviderClient* client) { 587 return new WebServiceWorkerProviderImpl( 588 ChildThread::current()->thread_safe_sender(), 589 make_scoped_ptr(client)); 590 } 591 592 void RenderFrameImpl::didAccessInitialDocument(blink::WebFrame* frame) { 593 render_view_->didAccessInitialDocument(frame); 594 } 595 596 blink::WebFrame* RenderFrameImpl::createChildFrame( 597 blink::WebFrame* parent, 598 const blink::WebString& name) { 599 RenderFrameImpl* child_render_frame = this; 600 long long child_frame_identifier = WebFrame::generateEmbedderIdentifier(); 601 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) { 602 // Synchronously notify the browser of a child frame creation to get the 603 // routing_id for the RenderFrame. 604 int routing_id; 605 Send(new FrameHostMsg_CreateChildFrame(routing_id_, 606 parent->identifier(), 607 child_frame_identifier, 608 UTF16ToUTF8(name), 609 &routing_id)); 610 child_render_frame = RenderFrameImpl::Create(render_view_, routing_id); 611 } 612 613 blink::WebFrame* web_frame = WebFrame::create(child_render_frame, 614 child_frame_identifier); 615 616 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) { 617 g_child_frame_map.Get().insert( 618 std::make_pair(web_frame, child_render_frame)); 619 } 620 621 return web_frame; 622 } 623 624 void RenderFrameImpl::didDisownOpener(blink::WebFrame* frame) { 625 render_view_->didDisownOpener(frame); 626 } 627 628 void RenderFrameImpl::frameDetached(blink::WebFrame* frame) { 629 // NOTE: This function is called on the frame that is being detached and not 630 // the parent frame. This is different from createChildFrame() which is 631 // called on the parent frame. 632 CHECK(!is_detaching_); 633 634 int64 parent_frame_id = -1; 635 if (frame->parent()) 636 parent_frame_id = frame->parent()->identifier(); 637 638 Send(new FrameHostMsg_Detach(routing_id_, parent_frame_id, 639 frame->identifier())); 640 641 // Currently multiple WebCore::Frames can send frameDetached to a single 642 // RenderFrameImpl. This is legacy behavior from when RenderViewImpl served 643 // as a shared WebFrameClient for multiple Webcore::Frame objects. It also 644 // prevents this class from entering the |is_detaching_| state because 645 // even though one WebCore::Frame may have detached itself, others will 646 // still need to use this object. 647 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) { 648 // The |is_detaching_| flag disables Send(). FrameHostMsg_Detach must be 649 // sent before setting |is_detaching_| to true. In contrast, Observers 650 // should only be notified afterwards so they cannot call back into and 651 // have IPCs fired off. 652 is_detaching_ = true; 653 } 654 655 // Call back to RenderViewImpl for observers to be notified. 656 // TODO(nasko): Remove once we have RenderFrameObserver. 657 render_view_->frameDetached(frame); 658 659 frame->close(); 660 661 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) { 662 // If the frame does not have a parent, it is the main frame. The main 663 // frame is owned by the containing RenderViewHost so it does not require 664 // any cleanup here. 665 if (frame->parent()) { 666 FrameMap::iterator it = g_child_frame_map.Get().find(frame); 667 DCHECK(it != g_child_frame_map.Get().end()); 668 DCHECK_EQ(it->second, this); 669 g_child_frame_map.Get().erase(it); 670 delete this; 671 // Object is invalid after this point. 672 } 673 } 674 } 675 676 void RenderFrameImpl::willClose(blink::WebFrame* frame) { 677 // Call back to RenderViewImpl for observers to be notified. 678 // TODO(nasko): Remove once we have RenderFrameObserver. 679 render_view_->willClose(frame); 680 } 681 682 void RenderFrameImpl::didChangeName(blink::WebFrame* frame, 683 const blink::WebString& name) { 684 if (!render_view_->renderer_preferences_.report_frame_name_changes) 685 return; 686 687 render_view_->Send( 688 new ViewHostMsg_UpdateFrameName(render_view_->GetRoutingID(), 689 frame->identifier(), 690 !frame->parent(), 691 UTF16ToUTF8(name))); 692 } 693 694 void RenderFrameImpl::didMatchCSS( 695 blink::WebFrame* frame, 696 const blink::WebVector<blink::WebString>& newly_matching_selectors, 697 const blink::WebVector<blink::WebString>& stopped_matching_selectors) { 698 render_view_->didMatchCSS( 699 frame, newly_matching_selectors, stopped_matching_selectors); 700 } 701 702 void RenderFrameImpl::loadURLExternally(blink::WebFrame* frame, 703 const blink::WebURLRequest& request, 704 blink::WebNavigationPolicy policy) { 705 loadURLExternally(frame, request, policy, WebString()); 706 } 707 708 void RenderFrameImpl::loadURLExternally( 709 blink::WebFrame* frame, 710 const blink::WebURLRequest& request, 711 blink::WebNavigationPolicy policy, 712 const blink::WebString& suggested_name) { 713 Referrer referrer(RenderViewImpl::GetReferrerFromRequest(frame, request)); 714 if (policy == blink::WebNavigationPolicyDownload) { 715 render_view_->Send(new ViewHostMsg_DownloadUrl(render_view_->GetRoutingID(), 716 request.url(), referrer, 717 suggested_name)); 718 } else { 719 render_view_->OpenURL(frame, request.url(), referrer, policy); 720 } 721 } 722 723 blink::WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation( 724 blink::WebFrame* frame, 725 blink::WebDataSource::ExtraData* extra_data, 726 const blink::WebURLRequest& request, 727 blink::WebNavigationType type, 728 blink::WebNavigationPolicy default_policy, 729 bool is_redirect) { 730 return render_view_->decidePolicyForNavigation( 731 frame, extra_data, request, type, default_policy, is_redirect); 732 } 733 734 blink::WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation( 735 blink::WebFrame* frame, 736 const blink::WebURLRequest& request, 737 blink::WebNavigationType type, 738 blink::WebNavigationPolicy default_policy, 739 bool is_redirect) { 740 return render_view_->decidePolicyForNavigation( 741 frame, request, type, default_policy, is_redirect); 742 } 743 744 void RenderFrameImpl::willSendSubmitEvent(blink::WebFrame* frame, 745 const blink::WebFormElement& form) { 746 // Call back to RenderViewImpl for observers to be notified. 747 // TODO(nasko): Remove once we have RenderFrameObserver. 748 render_view_->willSendSubmitEvent(frame, form); 749 } 750 751 void RenderFrameImpl::willSubmitForm(blink::WebFrame* frame, 752 const blink::WebFormElement& form) { 753 DocumentState* document_state = 754 DocumentState::FromDataSource(frame->provisionalDataSource()); 755 NavigationState* navigation_state = document_state->navigation_state(); 756 InternalDocumentStateData* internal_data = 757 InternalDocumentStateData::FromDocumentState(document_state); 758 759 if (PageTransitionCoreTypeIs(navigation_state->transition_type(), 760 PAGE_TRANSITION_LINK)) { 761 navigation_state->set_transition_type(PAGE_TRANSITION_FORM_SUBMIT); 762 } 763 764 // Save these to be processed when the ensuing navigation is committed. 765 WebSearchableFormData web_searchable_form_data(form); 766 internal_data->set_searchable_form_url(web_searchable_form_data.url()); 767 internal_data->set_searchable_form_encoding( 768 web_searchable_form_data.encoding().utf8()); 769 770 // Call back to RenderViewImpl for observers to be notified. 771 // TODO(nasko): Remove once we have RenderFrameObserver. 772 render_view_->willSubmitForm(frame, form); 773 } 774 775 void RenderFrameImpl::didCreateDataSource(blink::WebFrame* frame, 776 blink::WebDataSource* datasource) { 777 // TODO(nasko): Move implementation here. Needed state: 778 // * pending_navigation_params_ 779 // * webview 780 // Needed methods: 781 // * PopulateDocumentStateFromPending 782 // * CreateNavigationStateFromPending 783 render_view_->didCreateDataSource(frame, datasource); 784 } 785 786 void RenderFrameImpl::didStartProvisionalLoad(blink::WebFrame* frame) { 787 WebDataSource* ds = frame->provisionalDataSource(); 788 789 // In fast/loader/stop-provisional-loads.html, we abort the load before this 790 // callback is invoked. 791 if (!ds) 792 return; 793 794 DocumentState* document_state = DocumentState::FromDataSource(ds); 795 796 // We should only navigate to swappedout:// when is_swapped_out_ is true. 797 CHECK((ds->request().url() != GURL(kSwappedOutURL)) || 798 render_view_->is_swapped_out()) << 799 "Heard swappedout:// when not swapped out."; 800 801 // Update the request time if WebKit has better knowledge of it. 802 if (document_state->request_time().is_null()) { 803 double event_time = ds->triggeringEventTime(); 804 if (event_time != 0.0) 805 document_state->set_request_time(Time::FromDoubleT(event_time)); 806 } 807 808 // Start time is only set after request time. 809 document_state->set_start_load_time(Time::Now()); 810 811 bool is_top_most = !frame->parent(); 812 if (is_top_most) { 813 render_view_->set_navigation_gesture( 814 WebUserGestureIndicator::isProcessingUserGesture() ? 815 NavigationGestureUser : NavigationGestureAuto); 816 } else if (ds->replacesCurrentHistoryItem()) { 817 // Subframe navigations that don't add session history items must be 818 // marked with AUTO_SUBFRAME. See also didFailProvisionalLoad for how we 819 // handle loading of error pages. 820 document_state->navigation_state()->set_transition_type( 821 PAGE_TRANSITION_AUTO_SUBFRAME); 822 } 823 824 FOR_EACH_OBSERVER( 825 RenderViewObserver, render_view_->observers(), 826 DidStartProvisionalLoad(frame)); 827 828 Send(new FrameHostMsg_DidStartProvisionalLoadForFrame( 829 routing_id_, frame->identifier(), 830 frame->parent() ? frame->parent()->identifier() : -1, 831 is_top_most, ds->request().url())); 832 } 833 834 void RenderFrameImpl::didReceiveServerRedirectForProvisionalLoad( 835 blink::WebFrame* frame) { 836 // TODO(nasko): Move implementation here. Needed state: 837 // * page_id_ 838 render_view_->didReceiveServerRedirectForProvisionalLoad(frame); 839 } 840 841 void RenderFrameImpl::didFailProvisionalLoad( 842 blink::WebFrame* frame, 843 const blink::WebURLError& error) { 844 // TODO(nasko): Move implementation here. Needed state: 845 // * page_id_ 846 // * pending_navigation_params_ 847 // Needed methods 848 // * MaybeLoadAlternateErrorPage 849 // * LoadNavigationErrorPage 850 render_view_->didFailProvisionalLoad(frame, error); 851 } 852 853 void RenderFrameImpl::didCommitProvisionalLoad(blink::WebFrame* frame, 854 bool is_new_navigation) { 855 // TODO(nasko): Move implementation here. Needed state: 856 // * page_id_ 857 // * next_page_id_ 858 // * history_list_offset_ 859 // * history_list_length_ 860 // * history_page_ids_ 861 // Needed methods 862 // * webview 863 // * UpdateSessionHistory 864 // * GetLoadingUrl 865 render_view_->didCommitProvisionalLoad(frame, is_new_navigation); 866 } 867 868 void RenderFrameImpl::didClearWindowObject(blink::WebFrame* frame) { 869 // TODO(nasko): Move implementation here. Needed state: 870 // * enabled_bindings_ 871 // * dom_automation_controller_ 872 // * stats_collection_controller_ 873 render_view_->didClearWindowObject(frame); 874 } 875 876 void RenderFrameImpl::didCreateDocumentElement(blink::WebFrame* frame) { 877 // Notify the browser about non-blank documents loading in the top frame. 878 GURL url = frame->document().url(); 879 if (url.is_valid() && url.spec() != kAboutBlankURL) { 880 // TODO(nasko): Check if webview()->mainFrame() is the same as the 881 // frame->tree()->top(). 882 if (frame == render_view_->webview()->mainFrame()) { 883 render_view_->Send(new ViewHostMsg_DocumentAvailableInMainFrame( 884 render_view_->GetRoutingID())); 885 } 886 } 887 888 // Call back to RenderViewImpl for observers to be notified. 889 // TODO(nasko): Remove once we have RenderFrameObserver. 890 render_view_->didCreateDocumentElement(frame); 891 } 892 893 void RenderFrameImpl::didReceiveTitle(blink::WebFrame* frame, 894 const blink::WebString& title, 895 blink::WebTextDirection direction) { 896 // TODO(nasko): Investigate wheather implementation should move here. 897 render_view_->didReceiveTitle(frame, title, direction); 898 } 899 900 void RenderFrameImpl::didChangeIcon(blink::WebFrame* frame, 901 blink::WebIconURL::Type icon_type) { 902 // TODO(nasko): Investigate wheather implementation should move here. 903 render_view_->didChangeIcon(frame, icon_type); 904 } 905 906 void RenderFrameImpl::didFinishDocumentLoad(blink::WebFrame* frame) { 907 // TODO(nasko): Move implementation here. No state needed, just observers 908 // notification in before updating encoding. 909 render_view_->didFinishDocumentLoad(frame); 910 } 911 912 void RenderFrameImpl::didHandleOnloadEvents(blink::WebFrame* frame) { 913 // TODO(nasko): Move implementation here. Needed state: 914 // * page_id_ 915 render_view_->didHandleOnloadEvents(frame); 916 } 917 918 void RenderFrameImpl::didFailLoad(blink::WebFrame* frame, 919 const blink::WebURLError& error) { 920 // TODO(nasko): Move implementation here. No state needed. 921 render_view_->didFailLoad(frame, error); 922 } 923 924 void RenderFrameImpl::didFinishLoad(blink::WebFrame* frame) { 925 // TODO(nasko): Move implementation here. No state needed, just observers 926 // notification before sending message to the browser process. 927 render_view_->didFinishLoad(frame); 928 } 929 930 void RenderFrameImpl::didNavigateWithinPage(blink::WebFrame* frame, 931 bool is_new_navigation) { 932 // TODO(nasko): Move implementation here. No state needed, just observers 933 // notification before sending message to the browser process. 934 render_view_->didNavigateWithinPage(frame, is_new_navigation); 935 } 936 937 void RenderFrameImpl::didUpdateCurrentHistoryItem(blink::WebFrame* frame) { 938 // TODO(nasko): Move implementation here. Needed methods: 939 // * StartNavStateSyncTimerIfNecessary 940 render_view_->didUpdateCurrentHistoryItem(frame); 941 } 942 943 void RenderFrameImpl::willRequestAfterPreconnect( 944 blink::WebFrame* frame, 945 blink::WebURLRequest& request) { 946 blink::WebReferrerPolicy referrer_policy = blink::WebReferrerPolicyDefault; 947 WebString custom_user_agent; 948 949 if (request.extraData()) { 950 // This will only be called before willSendRequest, so only ExtraData 951 // members we have to copy here is on WebURLRequestExtraDataImpl. 952 webkit_glue::WebURLRequestExtraDataImpl* old_extra_data = 953 static_cast<webkit_glue::WebURLRequestExtraDataImpl*>( 954 request.extraData()); 955 956 referrer_policy = old_extra_data->referrer_policy(); 957 custom_user_agent = old_extra_data->custom_user_agent(); 958 } 959 960 bool was_after_preconnect_request = true; 961 // The args after |was_after_preconnect_request| are not used, and set to 962 // correct values at |willSendRequest|. 963 request.setExtraData(new webkit_glue::WebURLRequestExtraDataImpl( 964 referrer_policy, custom_user_agent, was_after_preconnect_request)); 965 } 966 967 void RenderFrameImpl::willSendRequest( 968 blink::WebFrame* frame, 969 unsigned identifier, 970 blink::WebURLRequest& request, 971 const blink::WebURLResponse& redirect_response) { 972 // The request my be empty during tests. 973 if (request.url().isEmpty()) 974 return; 975 976 WebFrame* top_frame = frame->top(); 977 if (!top_frame) 978 top_frame = frame; 979 WebDataSource* provisional_data_source = top_frame->provisionalDataSource(); 980 WebDataSource* top_data_source = top_frame->dataSource(); 981 WebDataSource* data_source = 982 provisional_data_source ? provisional_data_source : top_data_source; 983 984 PageTransition transition_type = PAGE_TRANSITION_LINK; 985 DocumentState* document_state = DocumentState::FromDataSource(data_source); 986 DCHECK(document_state); 987 InternalDocumentStateData* internal_data = 988 InternalDocumentStateData::FromDocumentState(document_state); 989 NavigationState* navigation_state = document_state->navigation_state(); 990 transition_type = navigation_state->transition_type(); 991 992 GURL request_url(request.url()); 993 GURL new_url; 994 if (GetContentClient()->renderer()->WillSendRequest( 995 frame, 996 transition_type, 997 request_url, 998 request.firstPartyForCookies(), 999 &new_url)) { 1000 request.setURL(WebURL(new_url)); 1001 } 1002 1003 if (internal_data->is_cache_policy_override_set()) 1004 request.setCachePolicy(internal_data->cache_policy_override()); 1005 1006 blink::WebReferrerPolicy referrer_policy; 1007 if (internal_data->is_referrer_policy_set()) { 1008 referrer_policy = internal_data->referrer_policy(); 1009 internal_data->clear_referrer_policy(); 1010 } else { 1011 referrer_policy = frame->document().referrerPolicy(); 1012 } 1013 1014 // The request's extra data may indicate that we should set a custom user 1015 // agent. This needs to be done here, after WebKit is through with setting the 1016 // user agent on its own. 1017 WebString custom_user_agent; 1018 bool was_after_preconnect_request = false; 1019 if (request.extraData()) { 1020 webkit_glue::WebURLRequestExtraDataImpl* old_extra_data = 1021 static_cast<webkit_glue::WebURLRequestExtraDataImpl*>( 1022 request.extraData()); 1023 custom_user_agent = old_extra_data->custom_user_agent(); 1024 was_after_preconnect_request = 1025 old_extra_data->was_after_preconnect_request(); 1026 1027 if (!custom_user_agent.isNull()) { 1028 if (custom_user_agent.isEmpty()) 1029 request.clearHTTPHeaderField("User-Agent"); 1030 else 1031 request.setHTTPHeaderField("User-Agent", custom_user_agent); 1032 } 1033 } 1034 1035 // Attach |should_replace_current_entry| state to requests so that, should 1036 // this navigation later require a request transfer, all state is preserved 1037 // when it is re-created in the new process. 1038 bool should_replace_current_entry = false; 1039 if (navigation_state->is_content_initiated()) { 1040 should_replace_current_entry = data_source->replacesCurrentHistoryItem(); 1041 } else { 1042 // If the navigation is browser-initiated, the NavigationState contains the 1043 // correct value instead of the WebDataSource. 1044 // 1045 // TODO(davidben): Avoid this awkward duplication of state. See comment on 1046 // NavigationState::should_replace_current_entry(). 1047 should_replace_current_entry = 1048 navigation_state->should_replace_current_entry(); 1049 } 1050 request.setExtraData( 1051 new RequestExtraData(referrer_policy, 1052 custom_user_agent, 1053 was_after_preconnect_request, 1054 routing_id_, 1055 (frame == top_frame), 1056 frame->identifier(), 1057 GURL(frame->document().securityOrigin().toString()), 1058 frame->parent() == top_frame, 1059 frame->parent() ? frame->parent()->identifier() : -1, 1060 navigation_state->allow_download(), 1061 transition_type, 1062 should_replace_current_entry, 1063 navigation_state->transferred_request_child_id(), 1064 navigation_state->transferred_request_request_id())); 1065 1066 DocumentState* top_document_state = 1067 DocumentState::FromDataSource(top_data_source); 1068 if (top_document_state) { 1069 // TODO(gavinp): separate out prefetching and prerender field trials 1070 // if the rel=prerender rel type is sticking around. 1071 if (request.targetType() == WebURLRequest::TargetIsPrefetch) 1072 top_document_state->set_was_prefetcher(true); 1073 1074 if (was_after_preconnect_request) 1075 top_document_state->set_was_after_preconnect_request(true); 1076 } 1077 1078 // This is an instance where we embed a copy of the routing id 1079 // into the data portion of the message. This can cause problems if we 1080 // don't register this id on the browser side, since the download manager 1081 // expects to find a RenderViewHost based off the id. 1082 request.setRequestorID(render_view_->GetRoutingID()); 1083 request.setHasUserGesture(WebUserGestureIndicator::isProcessingUserGesture()); 1084 1085 if (!navigation_state->extra_headers().empty()) { 1086 for (net::HttpUtil::HeadersIterator i( 1087 navigation_state->extra_headers().begin(), 1088 navigation_state->extra_headers().end(), "\n"); 1089 i.GetNext(); ) { 1090 request.setHTTPHeaderField(WebString::fromUTF8(i.name()), 1091 WebString::fromUTF8(i.values())); 1092 } 1093 } 1094 1095 if (!render_view_->renderer_preferences_.enable_referrers) 1096 request.clearHTTPHeaderField("Referer"); 1097 } 1098 1099 void RenderFrameImpl::didReceiveResponse( 1100 blink::WebFrame* frame, 1101 unsigned identifier, 1102 const blink::WebURLResponse& response) { 1103 // Only do this for responses that correspond to a provisional data source 1104 // of the top-most frame. If we have a provisional data source, then we 1105 // can't have any sub-resources yet, so we know that this response must 1106 // correspond to a frame load. 1107 if (!frame->provisionalDataSource() || frame->parent()) 1108 return; 1109 1110 // If we are in view source mode, then just let the user see the source of 1111 // the server's error page. 1112 if (frame->isViewSourceModeEnabled()) 1113 return; 1114 1115 DocumentState* document_state = 1116 DocumentState::FromDataSource(frame->provisionalDataSource()); 1117 int http_status_code = response.httpStatusCode(); 1118 1119 // Record page load flags. 1120 WebURLResponseExtraDataImpl* extra_data = 1121 RenderViewImpl::GetExtraDataFromResponse(response); 1122 if (extra_data) { 1123 document_state->set_was_fetched_via_spdy( 1124 extra_data->was_fetched_via_spdy()); 1125 document_state->set_was_npn_negotiated( 1126 extra_data->was_npn_negotiated()); 1127 document_state->set_npn_negotiated_protocol( 1128 extra_data->npn_negotiated_protocol()); 1129 document_state->set_was_alternate_protocol_available( 1130 extra_data->was_alternate_protocol_available()); 1131 document_state->set_connection_info( 1132 extra_data->connection_info()); 1133 document_state->set_was_fetched_via_proxy( 1134 extra_data->was_fetched_via_proxy()); 1135 } 1136 InternalDocumentStateData* internal_data = 1137 InternalDocumentStateData::FromDocumentState(document_state); 1138 internal_data->set_http_status_code(http_status_code); 1139 // Whether or not the http status code actually corresponds to an error is 1140 // only checked when the page is done loading, if |use_error_page| is 1141 // still true. 1142 internal_data->set_use_error_page(true); 1143 } 1144 1145 void RenderFrameImpl::didFinishResourceLoad(blink::WebFrame* frame, 1146 unsigned identifier) { 1147 // TODO(nasko): Move implementation here. Needed state: 1148 // * devtools_agent_ 1149 // Needed methods: 1150 // * LoadNavigationErrorPage 1151 render_view_->didFinishResourceLoad(frame, identifier); 1152 } 1153 1154 void RenderFrameImpl::didLoadResourceFromMemoryCache( 1155 blink::WebFrame* frame, 1156 const blink::WebURLRequest& request, 1157 const blink::WebURLResponse& response) { 1158 // The recipients of this message have no use for data: URLs: they don't 1159 // affect the page's insecure content list and are not in the disk cache. To 1160 // prevent large (1M+) data: URLs from crashing in the IPC system, we simply 1161 // filter them out here. 1162 GURL url(request.url()); 1163 if (url.SchemeIs("data")) 1164 return; 1165 1166 // Let the browser know we loaded a resource from the memory cache. This 1167 // message is needed to display the correct SSL indicators. 1168 render_view_->Send(new ViewHostMsg_DidLoadResourceFromMemoryCache( 1169 render_view_->GetRoutingID(), 1170 url, 1171 response.securityInfo(), 1172 request.httpMethod().utf8(), 1173 response.mimeType().utf8(), 1174 ResourceType::FromTargetType(request.targetType()))); 1175 } 1176 1177 void RenderFrameImpl::didDisplayInsecureContent(blink::WebFrame* frame) { 1178 render_view_->Send(new ViewHostMsg_DidDisplayInsecureContent( 1179 render_view_->GetRoutingID())); 1180 } 1181 1182 void RenderFrameImpl::didRunInsecureContent( 1183 blink::WebFrame* frame, 1184 const blink::WebSecurityOrigin& origin, 1185 const blink::WebURL& target) { 1186 render_view_->Send(new ViewHostMsg_DidRunInsecureContent( 1187 render_view_->GetRoutingID(), 1188 origin.toString().utf8(), 1189 target)); 1190 } 1191 1192 void RenderFrameImpl::didAbortLoading(blink::WebFrame* frame) { 1193 #if defined(ENABLE_PLUGINS) 1194 if (frame != render_view_->webview()->mainFrame()) 1195 return; 1196 PluginChannelHost::Broadcast( 1197 new PluginHostMsg_DidAbortLoading(render_view_->GetRoutingID())); 1198 #endif 1199 } 1200 1201 void RenderFrameImpl::didExhaustMemoryAvailableForScript( 1202 blink::WebFrame* frame) { 1203 render_view_->Send(new ViewHostMsg_JSOutOfMemory( 1204 render_view_->GetRoutingID())); 1205 } 1206 1207 void RenderFrameImpl::didCreateScriptContext(blink::WebFrame* frame, 1208 v8::Handle<v8::Context> context, 1209 int extension_group, 1210 int world_id) { 1211 GetContentClient()->renderer()->DidCreateScriptContext( 1212 frame, context, extension_group, world_id); 1213 } 1214 1215 void RenderFrameImpl::willReleaseScriptContext(blink::WebFrame* frame, 1216 v8::Handle<v8::Context> context, 1217 int world_id) { 1218 GetContentClient()->renderer()->WillReleaseScriptContext( 1219 frame, context, world_id); 1220 } 1221 1222 void RenderFrameImpl::didFirstVisuallyNonEmptyLayout(blink::WebFrame* frame) { 1223 render_view_->didFirstVisuallyNonEmptyLayout(frame); 1224 } 1225 1226 void RenderFrameImpl::didChangeContentsSize(blink::WebFrame* frame, 1227 const blink::WebSize& size) { 1228 // TODO(nasko): Move implementation here. Needed state: 1229 // * cached_has_main_frame_horizontal_scrollbar_ 1230 // * cached_has_main_frame_vertical_scrollbar_ 1231 render_view_->didChangeContentsSize(frame, size); 1232 } 1233 1234 void RenderFrameImpl::didChangeScrollOffset(blink::WebFrame* frame) { 1235 // TODO(nasko): Move implementation here. Needed methods: 1236 // * StartNavStateSyncTimerIfNecessary 1237 render_view_->didChangeScrollOffset(frame); 1238 } 1239 1240 void RenderFrameImpl::willInsertBody(blink::WebFrame* frame) { 1241 if (!frame->parent()) { 1242 render_view_->Send(new ViewHostMsg_WillInsertBody( 1243 render_view_->GetRoutingID())); 1244 } 1245 } 1246 1247 void RenderFrameImpl::reportFindInPageMatchCount(int request_id, 1248 int count, 1249 bool final_update) { 1250 int active_match_ordinal = -1; // -1 = don't update active match ordinal 1251 if (!count) 1252 active_match_ordinal = 0; 1253 1254 render_view_->Send(new ViewHostMsg_Find_Reply( 1255 render_view_->GetRoutingID(), request_id, count, 1256 gfx::Rect(), active_match_ordinal, final_update)); 1257 } 1258 1259 void RenderFrameImpl::reportFindInPageSelection( 1260 int request_id, 1261 int active_match_ordinal, 1262 const blink::WebRect& selection_rect) { 1263 render_view_->Send(new ViewHostMsg_Find_Reply( 1264 render_view_->GetRoutingID(), request_id, -1, selection_rect, 1265 active_match_ordinal, false)); 1266 } 1267 1268 void RenderFrameImpl::requestStorageQuota( 1269 blink::WebFrame* frame, 1270 blink::WebStorageQuotaType type, 1271 unsigned long long requested_size, 1272 blink::WebStorageQuotaCallbacks* callbacks) { 1273 DCHECK(frame); 1274 WebSecurityOrigin origin = frame->document().securityOrigin(); 1275 if (origin.isUnique()) { 1276 // Unique origins cannot store persistent state. 1277 callbacks->didFail(blink::WebStorageQuotaErrorAbort); 1278 return; 1279 } 1280 ChildThread::current()->quota_dispatcher()->RequestStorageQuota( 1281 render_view_->GetRoutingID(), GURL(origin.toString()), 1282 static_cast<quota::StorageType>(type), requested_size, 1283 QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(callbacks)); 1284 } 1285 1286 void RenderFrameImpl::willOpenSocketStream( 1287 blink::WebSocketStreamHandle* handle) { 1288 SocketStreamHandleData::AddToHandle(handle, render_view_->GetRoutingID()); 1289 } 1290 1291 void RenderFrameImpl::willStartUsingPeerConnectionHandler( 1292 blink::WebFrame* frame, 1293 blink::WebRTCPeerConnectionHandler* handler) { 1294 #if defined(ENABLE_WEBRTC) 1295 static_cast<RTCPeerConnectionHandler*>(handler)->associateWithFrame(frame); 1296 #endif 1297 } 1298 1299 bool RenderFrameImpl::willCheckAndDispatchMessageEvent( 1300 blink::WebFrame* sourceFrame, 1301 blink::WebFrame* targetFrame, 1302 blink::WebSecurityOrigin targetOrigin, 1303 blink::WebDOMMessageEvent event) { 1304 // TODO(nasko): Move implementation here. Needed state: 1305 // * is_swapped_out_ 1306 return render_view_->willCheckAndDispatchMessageEvent( 1307 sourceFrame, targetFrame, targetOrigin, event); 1308 } 1309 1310 blink::WebString RenderFrameImpl::userAgentOverride( 1311 blink::WebFrame* frame, 1312 const blink::WebURL& url) { 1313 if (!render_view_->webview() || !render_view_->webview()->mainFrame() || 1314 render_view_->renderer_preferences_.user_agent_override.empty()) { 1315 return blink::WebString(); 1316 } 1317 1318 // If we're in the middle of committing a load, the data source we need 1319 // will still be provisional. 1320 WebFrame* main_frame = render_view_->webview()->mainFrame(); 1321 WebDataSource* data_source = NULL; 1322 if (main_frame->provisionalDataSource()) 1323 data_source = main_frame->provisionalDataSource(); 1324 else 1325 data_source = main_frame->dataSource(); 1326 1327 InternalDocumentStateData* internal_data = data_source ? 1328 InternalDocumentStateData::FromDataSource(data_source) : NULL; 1329 if (internal_data && internal_data->is_overriding_user_agent()) 1330 return WebString::fromUTF8( 1331 render_view_->renderer_preferences_.user_agent_override); 1332 return blink::WebString(); 1333 } 1334 1335 blink::WebString RenderFrameImpl::doNotTrackValue(blink::WebFrame* frame) { 1336 if (render_view_->renderer_preferences_.enable_do_not_track) 1337 return WebString::fromUTF8("1"); 1338 return WebString(); 1339 } 1340 1341 bool RenderFrameImpl::allowWebGL(blink::WebFrame* frame, bool default_value) { 1342 if (!default_value) 1343 return false; 1344 1345 bool blocked = true; 1346 render_view_->Send(new ViewHostMsg_Are3DAPIsBlocked( 1347 render_view_->GetRoutingID(), 1348 GURL(frame->top()->document().securityOrigin().toString()), 1349 THREE_D_API_TYPE_WEBGL, 1350 &blocked)); 1351 return !blocked; 1352 } 1353 1354 void RenderFrameImpl::didLoseWebGLContext(blink::WebFrame* frame, 1355 int arb_robustness_status_code) { 1356 render_view_->Send(new ViewHostMsg_DidLose3DContext( 1357 GURL(frame->top()->document().securityOrigin().toString()), 1358 THREE_D_API_TYPE_WEBGL, 1359 arb_robustness_status_code)); 1360 } 1361 1362 void RenderFrameImpl::AddObserver(RenderFrameObserver* observer) { 1363 observers_.AddObserver(observer); 1364 } 1365 1366 void RenderFrameImpl::RemoveObserver(RenderFrameObserver* observer) { 1367 observer->RenderFrameGone(); 1368 observers_.RemoveObserver(observer); 1369 } 1370 1371 } // namespace content 1372