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 "base/strings/utf_string_conversions.h" 8 #include "base/time/time.h" 9 #include "content/child/appcache/appcache_dispatcher.h" 10 #include "content/child/fileapi/file_system_dispatcher.h" 11 #include "content/child/fileapi/webfilesystem_callback_adapters.h" 12 #include "content/child/quota_dispatcher.h" 13 #include "content/child/request_extra_data.h" 14 #include "content/common/socket_stream_handle_data.h" 15 #include "content/common/view_messages.h" 16 #include "content/public/common/content_constants.h" 17 #include "content/public/common/url_constants.h" 18 #include "content/public/renderer/content_renderer_client.h" 19 #include "content/public/renderer/document_state.h" 20 #include "content/public/renderer/navigation_state.h" 21 #include "content/public/renderer/password_form_conversion_utils.h" 22 #include "content/renderer/browser_plugin/browser_plugin.h" 23 #include "content/renderer/browser_plugin/browser_plugin_manager.h" 24 #include "content/renderer/internal_document_state_data.h" 25 #include "content/renderer/media/rtc_peer_connection_handler.h" 26 #include "content/renderer/render_thread_impl.h" 27 #include "content/renderer/render_view_impl.h" 28 #include "content/renderer/renderer_webapplicationcachehost_impl.h" 29 #include "content/renderer/websharedworker_proxy.h" 30 #include "net/base/net_errors.h" 31 #include "net/http/http_util.h" 32 #include "third_party/WebKit/public/platform/WebString.h" 33 #include "third_party/WebKit/public/platform/WebURL.h" 34 #include "third_party/WebKit/public/platform/WebURLError.h" 35 #include "third_party/WebKit/public/platform/WebURLResponse.h" 36 #include "third_party/WebKit/public/platform/WebVector.h" 37 #include "third_party/WebKit/public/web/WebDocument.h" 38 #include "third_party/WebKit/public/web/WebFileSystemCallbacks.h" 39 #include "third_party/WebKit/public/web/WebFrame.h" 40 #include "third_party/WebKit/public/web/WebNavigationPolicy.h" 41 #include "third_party/WebKit/public/web/WebPlugin.h" 42 #include "third_party/WebKit/public/web/WebPluginParams.h" 43 #include "third_party/WebKit/public/web/WebSearchableFormData.h" 44 #include "third_party/WebKit/public/web/WebSecurityOrigin.h" 45 #include "third_party/WebKit/public/web/WebStorageQuotaCallbacks.h" 46 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" 47 #include "third_party/WebKit/public/web/WebView.h" 48 #include "webkit/child/weburlresponse_extradata_impl.h" 49 50 using WebKit::WebDataSource; 51 using WebKit::WebDocument; 52 using WebKit::WebFileSystemCallbacks; 53 using WebKit::WebFrame; 54 using WebKit::WebNavigationPolicy; 55 using WebKit::WebPluginParams; 56 using WebKit::WebReferrerPolicy; 57 using WebKit::WebSearchableFormData; 58 using WebKit::WebSecurityOrigin; 59 using WebKit::WebStorageQuotaCallbacks; 60 using WebKit::WebString; 61 using WebKit::WebURL; 62 using WebKit::WebURLError; 63 using WebKit::WebURLRequest; 64 using WebKit::WebURLResponse; 65 using WebKit::WebUserGestureIndicator; 66 using WebKit::WebVector; 67 using WebKit::WebView; 68 using base::Time; 69 using base::TimeDelta; 70 using webkit_glue::WebURLResponseExtraDataImpl; 71 72 namespace content { 73 74 static RenderFrameImpl* (*g_create_render_frame_impl)(RenderViewImpl*, int32) = 75 NULL; 76 77 // static 78 RenderFrameImpl* RenderFrameImpl::Create(RenderViewImpl* render_view, 79 int32 routing_id) { 80 DCHECK(routing_id != MSG_ROUTING_NONE); 81 82 RenderFrameImpl* render_frame = NULL; 83 if (g_create_render_frame_impl) 84 render_frame = g_create_render_frame_impl(render_view, routing_id); 85 else 86 render_frame = new RenderFrameImpl(render_view, routing_id); 87 88 return render_frame; 89 } 90 91 // static 92 void RenderFrameImpl::InstallCreateHook( 93 RenderFrameImpl* (*create_render_frame_impl)(RenderViewImpl*, int32)) { 94 CHECK(!g_create_render_frame_impl); 95 g_create_render_frame_impl = create_render_frame_impl; 96 } 97 98 // RenderFrameImpl ---------------------------------------------------------- 99 RenderFrameImpl::RenderFrameImpl(RenderViewImpl* render_view, int routing_id) 100 : render_view_(render_view), 101 routing_id_(routing_id) { 102 } 103 104 RenderFrameImpl::~RenderFrameImpl() { 105 } 106 107 int RenderFrameImpl::GetRoutingID() const { 108 // TODO(nasko): Until we register RenderFrameHost in the browser process as 109 // a listener, we must route all messages to the RenderViewHost, so use the 110 // routing id of the RenderView for now. 111 return render_view_->GetRoutingID(); 112 } 113 114 bool RenderFrameImpl::Send(IPC::Message* message) { 115 // TODO(nasko): Move away from using the RenderView's Send method once we 116 // have enough infrastructure and state to make the right checks here. 117 return render_view_->Send(message); 118 } 119 120 bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) { 121 // Pass the message up to the RenderView, until we have enough 122 // infrastructure to start processing messages in this object. 123 return render_view_->OnMessageReceived(msg); 124 } 125 126 // WebKit::WebFrameClient implementation ------------------------------------- 127 128 WebKit::WebPlugin* RenderFrameImpl::createPlugin( 129 WebKit::WebFrame* frame, 130 const WebKit::WebPluginParams& params) { 131 WebKit::WebPlugin* plugin = NULL; 132 if (GetContentClient()->renderer()->OverrideCreatePlugin( 133 render_view_, frame, params, &plugin)) { 134 return plugin; 135 } 136 137 #if defined(ENABLE_PLUGINS) 138 if (UTF16ToASCII(params.mimeType) == kBrowserPluginMimeType) { 139 return render_view_->GetBrowserPluginManager()->CreateBrowserPlugin( 140 render_view_, frame, params); 141 } 142 143 WebPluginInfo info; 144 std::string mime_type; 145 bool found = render_view_->GetPluginInfo( 146 params.url, frame->top()->document().url(), params.mimeType.utf8(), 147 &info, &mime_type); 148 if (!found) 149 return NULL; 150 151 WebPluginParams params_to_use = params; 152 params_to_use.mimeType = WebString::fromUTF8(mime_type); 153 return render_view_->CreatePlugin(frame, info, params_to_use); 154 #else 155 return NULL; 156 #endif // defined(ENABLE_PLUGINS) 157 } 158 159 WebKit::WebSharedWorker* RenderFrameImpl::createSharedWorker( 160 WebKit::WebFrame* frame, 161 const WebKit::WebURL& url, 162 const WebKit::WebString& name, 163 unsigned long long document_id) { 164 int route_id = MSG_ROUTING_NONE; 165 bool exists = false; 166 bool url_mismatch = false; 167 ViewHostMsg_CreateWorker_Params params; 168 params.url = url; 169 params.name = name; 170 params.document_id = document_id; 171 params.render_view_route_id = GetRoutingID(); 172 params.route_id = MSG_ROUTING_NONE; 173 params.script_resource_appcache_id = 0; 174 Send(new ViewHostMsg_LookupSharedWorker( 175 params, &exists, &route_id, &url_mismatch)); 176 if (url_mismatch) { 177 return NULL; 178 } else { 179 return new WebSharedWorkerProxy(RenderThreadImpl::current(), 180 document_id, 181 exists, 182 route_id, 183 GetRoutingID()); 184 } 185 } 186 187 WebKit::WebMediaPlayer* RenderFrameImpl::createMediaPlayer( 188 WebKit::WebFrame* frame, 189 const WebKit::WebURL& url, 190 WebKit::WebMediaPlayerClient* client) { 191 // TODO(nasko): Moving the implementation here involves moving a few media 192 // related client objects here or referencing them in the RenderView. Needs 193 // more work to understand where the proper place for those objects is. 194 return render_view_->createMediaPlayer(frame, url, client); 195 } 196 197 WebKit::WebApplicationCacheHost* RenderFrameImpl::createApplicationCacheHost( 198 WebKit::WebFrame* frame, 199 WebKit::WebApplicationCacheHostClient* client) { 200 if (!frame || !frame->view()) 201 return NULL; 202 return new RendererWebApplicationCacheHostImpl( 203 RenderViewImpl::FromWebView(frame->view()), client, 204 RenderThreadImpl::current()->appcache_dispatcher()->backend_proxy()); 205 } 206 207 WebKit::WebCookieJar* RenderFrameImpl::cookieJar(WebKit::WebFrame* frame) { 208 return render_view_->cookieJar(frame); 209 } 210 211 void RenderFrameImpl::didAccessInitialDocument(WebKit::WebFrame* frame) { 212 render_view_->didAccessInitialDocument(frame); 213 } 214 215 void RenderFrameImpl::didCreateFrame(WebKit::WebFrame* parent, 216 WebKit::WebFrame* child) { 217 Send(new ViewHostMsg_FrameAttached(GetRoutingID(), parent->identifier(), 218 child->identifier(), UTF16ToUTF8(child->assignedName()))); 219 } 220 221 void RenderFrameImpl::didDisownOpener(WebKit::WebFrame* frame) { 222 render_view_->didDisownOpener(frame); 223 } 224 225 void RenderFrameImpl::frameDetached(WebKit::WebFrame* frame) { 226 int64 parent_frame_id = -1; 227 if (frame->parent()) 228 parent_frame_id = frame->parent()->identifier(); 229 230 Send(new ViewHostMsg_FrameDetached(GetRoutingID(), parent_frame_id, 231 frame->identifier())); 232 233 // Call back to RenderViewImpl for observers to be notified. 234 // TODO(nasko): Remove once we have RenderFrameObserver. 235 render_view_->frameDetached(frame); 236 } 237 238 void RenderFrameImpl::willClose(WebKit::WebFrame* frame) { 239 // Call back to RenderViewImpl for observers to be notified. 240 // TODO(nasko): Remove once we have RenderFrameObserver. 241 render_view_->willClose(frame); 242 } 243 244 void RenderFrameImpl::didChangeName(WebKit::WebFrame* frame, 245 const WebKit::WebString& name) { 246 if (!render_view_->renderer_preferences_.report_frame_name_changes) 247 return; 248 249 Send(new ViewHostMsg_UpdateFrameName(GetRoutingID(), 250 frame->identifier(), 251 !frame->parent(), 252 UTF16ToUTF8(name))); 253 } 254 255 void RenderFrameImpl::loadURLExternally(WebKit::WebFrame* frame, 256 const WebKit::WebURLRequest& request, 257 WebKit::WebNavigationPolicy policy) { 258 loadURLExternally(frame, request, policy, WebString()); 259 } 260 261 void RenderFrameImpl::loadURLExternally( 262 WebKit::WebFrame* frame, 263 const WebKit::WebURLRequest& request, 264 WebKit::WebNavigationPolicy policy, 265 const WebKit::WebString& suggested_name) { 266 Referrer referrer(RenderViewImpl::GetReferrerFromRequest(frame, request)); 267 if (policy == WebKit::WebNavigationPolicyDownload) { 268 Send(new ViewHostMsg_DownloadUrl(GetRoutingID(), request.url(), referrer, 269 suggested_name)); 270 } else { 271 render_view_->OpenURL(frame, request.url(), referrer, policy); 272 } 273 } 274 275 WebKit::WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation( 276 WebKit::WebFrame* frame, 277 WebKit::WebDataSource::ExtraData* extra_data, 278 const WebKit::WebURLRequest& request, 279 WebKit::WebNavigationType type, 280 WebKit::WebNavigationPolicy default_policy, 281 bool is_redirect) { 282 return render_view_->decidePolicyForNavigation( 283 frame, extra_data, request, type, default_policy, is_redirect); 284 } 285 286 WebKit::WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation( 287 WebKit::WebFrame* frame, 288 const WebKit::WebURLRequest& request, 289 WebKit::WebNavigationType type, 290 WebKit::WebNavigationPolicy default_policy, 291 bool is_redirect) { 292 return render_view_->decidePolicyForNavigation( 293 frame, request, type, default_policy, is_redirect); 294 } 295 296 bool RenderFrameImpl::shouldAbortNavigationAfterUrlResolve(const WebURL& base, 297 const WebString& fragment, 298 const WebURL& result) { 299 return render_view_->shouldAbortNavigationAfterUrlResolve(base, fragment, result); 300 } 301 302 void RenderFrameImpl::willSendSubmitEvent(WebKit::WebFrame* frame, 303 const WebKit::WebFormElement& form) { 304 // Some login forms have onSubmit handlers that put a hash of the password 305 // into a hidden field and then clear the password. (Issue 28910.) 306 // This method gets called before any of those handlers run, so save away 307 // a copy of the password in case it gets lost. 308 DocumentState* document_state = 309 DocumentState::FromDataSource(frame->dataSource()); 310 document_state->set_password_form_data(CreatePasswordForm(form)); 311 } 312 313 void RenderFrameImpl::willSubmitForm(WebKit::WebFrame* frame, 314 const WebKit::WebFormElement& form) { 315 DocumentState* document_state = 316 DocumentState::FromDataSource(frame->provisionalDataSource()); 317 NavigationState* navigation_state = document_state->navigation_state(); 318 InternalDocumentStateData* internal_data = 319 InternalDocumentStateData::FromDocumentState(document_state); 320 321 if (PageTransitionCoreTypeIs(navigation_state->transition_type(), 322 PAGE_TRANSITION_LINK)) { 323 navigation_state->set_transition_type(PAGE_TRANSITION_FORM_SUBMIT); 324 } 325 326 // Save these to be processed when the ensuing navigation is committed. 327 WebSearchableFormData web_searchable_form_data(form); 328 internal_data->set_searchable_form_url(web_searchable_form_data.url()); 329 internal_data->set_searchable_form_encoding( 330 web_searchable_form_data.encoding().utf8()); 331 scoped_ptr<PasswordForm> password_form_data = 332 CreatePasswordForm(form); 333 334 // In order to save the password that the user actually typed and not one 335 // that may have gotten transformed by the site prior to submit, recover it 336 // from the form contents already stored by |willSendSubmitEvent| into the 337 // dataSource's NavigationState (as opposed to the provisionalDataSource's, 338 // which is what we're storing into now.) 339 if (password_form_data) { 340 DocumentState* old_document_state = 341 DocumentState::FromDataSource(frame->dataSource()); 342 if (old_document_state) { 343 PasswordForm* old_form_data = old_document_state->password_form_data(); 344 if (old_form_data && old_form_data->action == password_form_data->action) 345 password_form_data->password_value = old_form_data->password_value; 346 } 347 } 348 349 document_state->set_password_form_data(password_form_data.Pass()); 350 351 // Call back to RenderViewImpl for observers to be notified. 352 // TODO(nasko): Remove once we have RenderFrameObserver. 353 render_view_->willSubmitForm(frame, form); 354 } 355 356 void RenderFrameImpl::didCreateDataSource(WebKit::WebFrame* frame, 357 WebKit::WebDataSource* datasource) { 358 // TODO(nasko): Move implementation here. Needed state: 359 // * pending_navigation_params_ 360 // * webview 361 // Needed methods: 362 // * PopulateDocumentStateFromPending 363 // * CreateNavigationStateFromPending 364 render_view_->didCreateDataSource(frame, datasource); 365 } 366 367 void RenderFrameImpl::didStartProvisionalLoad(WebKit::WebFrame* frame) { 368 // TODO(nasko): Move implementation here. Needed state: 369 // * is_swapped_out_ 370 // * navigation_gesture_ 371 // * completed_client_redirect_src_ 372 render_view_->didStartProvisionalLoad(frame); 373 } 374 375 void RenderFrameImpl::didReceiveServerRedirectForProvisionalLoad( 376 WebKit::WebFrame* frame) { 377 // TODO(nasko): Move implementation here. Needed state: 378 // * page_id_ 379 render_view_->didReceiveServerRedirectForProvisionalLoad(frame); 380 } 381 382 void RenderFrameImpl::didFailProvisionalLoad( 383 WebKit::WebFrame* frame, 384 const WebKit::WebURLError& error) { 385 // TODO(nasko): Move implementation here. Needed state: 386 // * page_id_ 387 // * pending_navigation_params_ 388 // Needed methods 389 // * MaybeLoadAlternateErrorPage 390 // * LoadNavigationErrorPage 391 render_view_->didFailProvisionalLoad(frame, error); 392 } 393 394 void RenderFrameImpl::didCommitProvisionalLoad(WebKit::WebFrame* frame, 395 bool is_new_navigation) { 396 // TODO(nasko): Move implementation here. Needed state: 397 // * page_id_ 398 // * next_page_id_ 399 // * history_list_offset_ 400 // * history_list_length_ 401 // * history_page_ids_ 402 // Needed methods 403 // * webview 404 // * UpdateSessionHistory 405 // * GetLoadingUrl 406 render_view_->didCommitProvisionalLoad(frame, is_new_navigation); 407 } 408 409 void RenderFrameImpl::didClearWindowObject(WebKit::WebFrame* frame) { 410 // TODO(nasko): Move implementation here. Needed state: 411 // * enabled_bindings_ 412 // * dom_automation_controller_ 413 // * stats_collection_controller_ 414 render_view_->didClearWindowObject(frame); 415 } 416 417 void RenderFrameImpl::didCreateDocumentElement(WebKit::WebFrame* frame) { 418 // Notify the browser about non-blank documents loading in the top frame. 419 GURL url = frame->document().url(); 420 if (url.is_valid() && url.spec() != kAboutBlankURL) { 421 // TODO(nasko): Check if webview()->mainFrame() is the same as the 422 // frame->tree()->top(). 423 if (frame == render_view_->webview()->mainFrame()) 424 Send(new ViewHostMsg_DocumentAvailableInMainFrame(GetRoutingID())); 425 } 426 427 // Call back to RenderViewImpl for observers to be notified. 428 // TODO(nasko): Remove once we have RenderFrameObserver. 429 render_view_->didCreateDocumentElement(frame); 430 } 431 432 void RenderFrameImpl::didReceiveTitle(WebKit::WebFrame* frame, 433 const WebKit::WebString& title, 434 WebKit::WebTextDirection direction) { 435 // TODO(nasko): Investigate wheather implementation should move here. 436 render_view_->didReceiveTitle(frame, title, direction); 437 } 438 439 void RenderFrameImpl::didChangeIcon(WebKit::WebFrame* frame, 440 WebKit::WebIconURL::Type icon_type) { 441 // TODO(nasko): Investigate wheather implementation should move here. 442 render_view_->didChangeIcon(frame, icon_type); 443 } 444 445 void RenderFrameImpl::didFinishDocumentLoad(WebKit::WebFrame* frame) { 446 // TODO(nasko): Move implementation here. No state needed, just observers 447 // notification in before updating encoding. 448 render_view_->didFinishDocumentLoad(frame); 449 } 450 451 void RenderFrameImpl::didHandleOnloadEvents(WebKit::WebFrame* frame) { 452 // TODO(nasko): Move implementation here. Needed state: 453 // * page_id_ 454 render_view_->didHandleOnloadEvents(frame); 455 } 456 457 void RenderFrameImpl::didFailLoad(WebKit::WebFrame* frame, 458 const WebKit::WebURLError& error) { 459 // TODO(nasko): Move implementation here. No state needed. 460 render_view_->didFailLoad(frame, error); 461 } 462 463 void RenderFrameImpl::didFinishLoad(WebKit::WebFrame* frame) { 464 // TODO(nasko): Move implementation here. No state needed, just observers 465 // notification before sending message to the browser process. 466 render_view_->didFinishLoad(frame); 467 } 468 469 void RenderFrameImpl::didNavigateWithinPage(WebKit::WebFrame* frame, 470 bool is_new_navigation) { 471 // TODO(nasko): Move implementation here. No state needed, just observers 472 // notification before sending message to the browser process. 473 render_view_->didNavigateWithinPage(frame, is_new_navigation); 474 } 475 476 void RenderFrameImpl::didUpdateCurrentHistoryItem(WebKit::WebFrame* frame) { 477 // TODO(nasko): Move implementation here. Needed methods: 478 // * StartNavStateSyncTimerIfNecessary 479 render_view_->didUpdateCurrentHistoryItem(frame); 480 } 481 482 void RenderFrameImpl::willRequestAfterPreconnect( 483 WebKit::WebFrame* frame, 484 WebKit::WebURLRequest& request) { 485 WebKit::WebReferrerPolicy referrer_policy = WebKit::WebReferrerPolicyDefault; 486 WebString custom_user_agent; 487 488 if (request.extraData()) { 489 // This will only be called before willSendRequest, so only ExtraData 490 // members we have to copy here is on WebURLRequestExtraDataImpl. 491 webkit_glue::WebURLRequestExtraDataImpl* old_extra_data = 492 static_cast<webkit_glue::WebURLRequestExtraDataImpl*>( 493 request.extraData()); 494 495 referrer_policy = old_extra_data->referrer_policy(); 496 custom_user_agent = old_extra_data->custom_user_agent(); 497 } 498 499 bool was_after_preconnect_request = true; 500 // The args after |was_after_preconnect_request| are not used, and set to 501 // correct values at |willSendRequest|. 502 request.setExtraData(new webkit_glue::WebURLRequestExtraDataImpl( 503 referrer_policy, custom_user_agent, was_after_preconnect_request)); 504 } 505 506 void RenderFrameImpl::willSendRequest( 507 WebKit::WebFrame* frame, 508 unsigned identifier, 509 WebKit::WebURLRequest& request, 510 const WebKit::WebURLResponse& redirect_response) { 511 // The request my be empty during tests. 512 if (request.url().isEmpty()) 513 return; 514 515 WebFrame* top_frame = frame->top(); 516 if (!top_frame) 517 top_frame = frame; 518 WebDataSource* provisional_data_source = top_frame->provisionalDataSource(); 519 WebDataSource* top_data_source = top_frame->dataSource(); 520 WebDataSource* data_source = 521 provisional_data_source ? provisional_data_source : top_data_source; 522 523 PageTransition transition_type = PAGE_TRANSITION_LINK; 524 DocumentState* document_state = DocumentState::FromDataSource(data_source); 525 DCHECK(document_state); 526 InternalDocumentStateData* internal_data = 527 InternalDocumentStateData::FromDocumentState(document_state); 528 NavigationState* navigation_state = document_state->navigation_state(); 529 transition_type = navigation_state->transition_type(); 530 531 GURL request_url(request.url()); 532 GURL new_url; 533 if (GetContentClient()->renderer()->WillSendRequest( 534 frame, 535 transition_type, 536 request_url, 537 request.firstPartyForCookies(), 538 &new_url)) { 539 request.setURL(WebURL(new_url)); 540 } 541 542 if (internal_data->is_cache_policy_override_set()) 543 request.setCachePolicy(internal_data->cache_policy_override()); 544 545 WebKit::WebReferrerPolicy referrer_policy; 546 if (internal_data->is_referrer_policy_set()) { 547 referrer_policy = internal_data->referrer_policy(); 548 internal_data->clear_referrer_policy(); 549 } else { 550 referrer_policy = frame->document().referrerPolicy(); 551 } 552 553 // The request's extra data may indicate that we should set a custom user 554 // agent. This needs to be done here, after WebKit is through with setting the 555 // user agent on its own. 556 WebString custom_user_agent; 557 bool was_after_preconnect_request = false; 558 if (request.extraData()) { 559 webkit_glue::WebURLRequestExtraDataImpl* old_extra_data = 560 static_cast<webkit_glue::WebURLRequestExtraDataImpl*>( 561 request.extraData()); 562 custom_user_agent = old_extra_data->custom_user_agent(); 563 was_after_preconnect_request = 564 old_extra_data->was_after_preconnect_request(); 565 566 if (!custom_user_agent.isNull()) { 567 if (custom_user_agent.isEmpty()) 568 request.clearHTTPHeaderField("User-Agent"); 569 else 570 request.setHTTPHeaderField("User-Agent", custom_user_agent); 571 } 572 } 573 574 request.setExtraData( 575 new RequestExtraData(referrer_policy, 576 custom_user_agent, 577 was_after_preconnect_request, 578 (frame == top_frame), 579 frame->identifier(), 580 frame->parent() == top_frame, 581 frame->parent() ? frame->parent()->identifier() : -1, 582 navigation_state->allow_download(), 583 transition_type, 584 navigation_state->transferred_request_child_id(), 585 navigation_state->transferred_request_request_id())); 586 587 DocumentState* top_document_state = 588 DocumentState::FromDataSource(top_data_source); 589 if (top_document_state) { 590 // TODO(gavinp): separate out prefetching and prerender field trials 591 // if the rel=prerender rel type is sticking around. 592 if (request.targetType() == WebURLRequest::TargetIsPrefetch) 593 top_document_state->set_was_prefetcher(true); 594 595 if (was_after_preconnect_request) 596 top_document_state->set_was_after_preconnect_request(true); 597 } 598 599 // This is an instance where we embed a copy of the routing id 600 // into the data portion of the message. This can cause problems if we 601 // don't register this id on the browser side, since the download manager 602 // expects to find a RenderViewHost based off the id. 603 request.setRequestorID(GetRoutingID()); 604 request.setHasUserGesture(WebUserGestureIndicator::isProcessingUserGesture()); 605 606 // Forked for WebView, http://crbug.com/306873 607 // Only add the extra headers on the navigation state if the request is for 608 // the main frame. This emulates the old WebView's behaviour where these 609 // headers don't apply to other resource loads. 610 if (!navigation_state->extra_headers().empty() && 611 request.targetType() == WebURLRequest::TargetIsMainFrame) { 612 for (net::HttpUtil::HeadersIterator i( 613 navigation_state->extra_headers().begin(), 614 navigation_state->extra_headers().end(), "\n"); 615 i.GetNext(); ) { 616 request.setHTTPHeaderField(WebString::fromUTF8(i.name()), 617 WebString::fromUTF8(i.values())); 618 } 619 } 620 621 if (!render_view_->renderer_preferences_.enable_referrers) 622 request.clearHTTPHeaderField("Referer"); 623 } 624 625 void RenderFrameImpl::didReceiveResponse( 626 WebKit::WebFrame* frame, 627 unsigned identifier, 628 const WebKit::WebURLResponse& response) { 629 // Only do this for responses that correspond to a provisional data source 630 // of the top-most frame. If we have a provisional data source, then we 631 // can't have any sub-resources yet, so we know that this response must 632 // correspond to a frame load. 633 if (!frame->provisionalDataSource() || frame->parent()) 634 return; 635 636 // If we are in view source mode, then just let the user see the source of 637 // the server's error page. 638 if (frame->isViewSourceModeEnabled()) 639 return; 640 641 DocumentState* document_state = 642 DocumentState::FromDataSource(frame->provisionalDataSource()); 643 int http_status_code = response.httpStatusCode(); 644 645 // Record page load flags. 646 WebURLResponseExtraDataImpl* extra_data = 647 RenderViewImpl::GetExtraDataFromResponse(response); 648 if (extra_data) { 649 document_state->set_was_fetched_via_spdy( 650 extra_data->was_fetched_via_spdy()); 651 document_state->set_was_npn_negotiated( 652 extra_data->was_npn_negotiated()); 653 document_state->set_npn_negotiated_protocol( 654 extra_data->npn_negotiated_protocol()); 655 document_state->set_was_alternate_protocol_available( 656 extra_data->was_alternate_protocol_available()); 657 document_state->set_connection_info( 658 extra_data->connection_info()); 659 document_state->set_was_fetched_via_proxy( 660 extra_data->was_fetched_via_proxy()); 661 } 662 InternalDocumentStateData* internal_data = 663 InternalDocumentStateData::FromDocumentState(document_state); 664 internal_data->set_http_status_code(http_status_code); 665 // Whether or not the http status code actually corresponds to an error is 666 // only checked when the page is done loading, if |use_error_page| is 667 // still true. 668 internal_data->set_use_error_page(true); 669 } 670 671 void RenderFrameImpl::didFinishResourceLoad(WebKit::WebFrame* frame, 672 unsigned identifier) { 673 // TODO(nasko): Move implementation here. Needed state: 674 // * devtools_agent_ 675 // Needed methods: 676 // * LoadNavigationErrorPage 677 render_view_->didFinishResourceLoad(frame, identifier); 678 } 679 680 void RenderFrameImpl::didLoadResourceFromMemoryCache( 681 WebKit::WebFrame* frame, 682 const WebKit::WebURLRequest& request, 683 const WebKit::WebURLResponse& response) { 684 // The recipients of this message have no use for data: URLs: they don't 685 // affect the page's insecure content list and are not in the disk cache. To 686 // prevent large (1M+) data: URLs from crashing in the IPC system, we simply 687 // filter them out here. 688 GURL url(request.url()); 689 if (url.SchemeIs("data")) 690 return; 691 692 // Let the browser know we loaded a resource from the memory cache. This 693 // message is needed to display the correct SSL indicators. 694 Send(new ViewHostMsg_DidLoadResourceFromMemoryCache( 695 GetRoutingID(), 696 url, 697 response.securityInfo(), 698 request.httpMethod().utf8(), 699 response.mimeType().utf8(), 700 ResourceType::FromTargetType(request.targetType()))); 701 } 702 703 void RenderFrameImpl::didDisplayInsecureContent(WebKit::WebFrame* frame) { 704 Send(new ViewHostMsg_DidDisplayInsecureContent(GetRoutingID())); 705 } 706 707 void RenderFrameImpl::didRunInsecureContent( 708 WebKit::WebFrame* frame, 709 const WebKit::WebSecurityOrigin& origin, 710 const WebKit::WebURL& target) { 711 Send(new ViewHostMsg_DidRunInsecureContent( 712 GetRoutingID(), 713 origin.toString().utf8(), 714 target)); 715 } 716 717 void RenderFrameImpl::didExhaustMemoryAvailableForScript( 718 WebKit::WebFrame* frame) { 719 Send(new ViewHostMsg_JSOutOfMemory(GetRoutingID())); 720 } 721 722 void RenderFrameImpl::didCreateScriptContext(WebKit::WebFrame* frame, 723 v8::Handle<v8::Context> context, 724 int extension_group, 725 int world_id) { 726 GetContentClient()->renderer()->DidCreateScriptContext( 727 frame, context, extension_group, world_id); 728 } 729 730 void RenderFrameImpl::willReleaseScriptContext(WebKit::WebFrame* frame, 731 v8::Handle<v8::Context> context, 732 int world_id) { 733 GetContentClient()->renderer()->WillReleaseScriptContext( 734 frame, context, world_id); 735 } 736 737 void RenderFrameImpl::didFirstVisuallyNonEmptyLayout(WebKit::WebFrame* frame) { 738 render_view_->didFirstVisuallyNonEmptyLayout(frame); 739 } 740 741 void RenderFrameImpl::didChangeContentsSize(WebKit::WebFrame* frame, 742 const WebKit::WebSize& size) { 743 // TODO(nasko): Move implementation here. Needed state: 744 // * cached_has_main_frame_horizontal_scrollbar_ 745 // * cached_has_main_frame_vertical_scrollbar_ 746 render_view_->didChangeContentsSize(frame, size); 747 } 748 749 void RenderFrameImpl::didChangeScrollOffset(WebKit::WebFrame* frame) { 750 // TODO(nasko): Move implementation here. Needed methods: 751 // * StartNavStateSyncTimerIfNecessary 752 render_view_->didChangeScrollOffset(frame); 753 } 754 755 void RenderFrameImpl::willInsertBody(WebKit::WebFrame* frame) { 756 if (!frame->parent()) 757 Send(new ViewHostMsg_WillInsertBody(GetRoutingID())); 758 } 759 760 void RenderFrameImpl::reportFindInPageMatchCount(int request_id, 761 int count, 762 bool final_update) { 763 int active_match_ordinal = -1; // -1 = don't update active match ordinal 764 if (!count) 765 active_match_ordinal = 0; 766 767 Send(new ViewHostMsg_Find_Reply(GetRoutingID(), 768 request_id, 769 count, 770 gfx::Rect(), 771 active_match_ordinal, 772 final_update)); 773 } 774 775 void RenderFrameImpl::reportFindInPageSelection( 776 int request_id, 777 int active_match_ordinal, 778 const WebKit::WebRect& selection_rect) { 779 Send(new ViewHostMsg_Find_Reply(GetRoutingID(), 780 request_id, 781 -1, 782 selection_rect, 783 active_match_ordinal, 784 false)); 785 } 786 787 void RenderFrameImpl::openFileSystem( 788 WebKit::WebFrame* frame, 789 WebKit::WebFileSystemType type, 790 long long size, 791 bool create, 792 WebKit::WebFileSystemCallbacks* callbacks) { 793 DCHECK(callbacks); 794 795 WebSecurityOrigin origin = frame->document().securityOrigin(); 796 if (origin.isUnique()) { 797 // Unique origins cannot store persistent state. 798 callbacks->didFail(WebKit::WebFileErrorAbort); 799 return; 800 } 801 802 ChildThread::current()->file_system_dispatcher()->OpenFileSystem( 803 GURL(origin.toString()), static_cast<fileapi::FileSystemType>(type), 804 size, create, 805 base::Bind(&OpenFileSystemCallbackAdapter, callbacks), 806 base::Bind(&FileStatusCallbackAdapter, callbacks)); 807 } 808 809 void RenderFrameImpl::deleteFileSystem( 810 WebKit::WebFrame* frame, 811 WebKit::WebFileSystemType type, 812 WebKit::WebFileSystemCallbacks* callbacks) { 813 DCHECK(callbacks); 814 815 WebSecurityOrigin origin = frame->document().securityOrigin(); 816 if (origin.isUnique()) { 817 // Unique origins cannot store persistent state. 818 callbacks->didSucceed(); 819 return; 820 } 821 822 ChildThread::current()->file_system_dispatcher()->DeleteFileSystem( 823 GURL(origin.toString()), 824 static_cast<fileapi::FileSystemType>(type), 825 base::Bind(&FileStatusCallbackAdapter, callbacks)); 826 } 827 828 void RenderFrameImpl::requestStorageQuota( 829 WebKit::WebFrame* frame, 830 WebKit::WebStorageQuotaType type, 831 unsigned long long requested_size, 832 WebKit::WebStorageQuotaCallbacks* callbacks) { 833 DCHECK(frame); 834 WebSecurityOrigin origin = frame->document().securityOrigin(); 835 if (origin.isUnique()) { 836 // Unique origins cannot store persistent state. 837 callbacks->didFail(WebKit::WebStorageQuotaErrorAbort); 838 return; 839 } 840 ChildThread::current()->quota_dispatcher()->RequestStorageQuota( 841 GetRoutingID(), GURL(origin.toString()), 842 static_cast<quota::StorageType>(type), requested_size, 843 QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(callbacks)); 844 } 845 846 void RenderFrameImpl::willOpenSocketStream( 847 WebKit::WebSocketStreamHandle* handle) { 848 SocketStreamHandleData::AddToHandle(handle, GetRoutingID()); 849 } 850 851 void RenderFrameImpl::willStartUsingPeerConnectionHandler( 852 WebKit::WebFrame* frame, 853 WebKit::WebRTCPeerConnectionHandler* handler) { 854 #if defined(ENABLE_WEBRTC) 855 static_cast<RTCPeerConnectionHandler*>(handler)->associateWithFrame(frame); 856 #endif 857 } 858 859 bool RenderFrameImpl::willCheckAndDispatchMessageEvent( 860 WebKit::WebFrame* sourceFrame, 861 WebKit::WebFrame* targetFrame, 862 WebKit::WebSecurityOrigin targetOrigin, 863 WebKit::WebDOMMessageEvent event) { 864 // TODO(nasko): Move implementation here. Needed state: 865 // * is_swapped_out_ 866 return render_view_->willCheckAndDispatchMessageEvent( 867 sourceFrame, targetFrame, targetOrigin, event); 868 } 869 870 WebKit::WebString RenderFrameImpl::userAgentOverride( 871 WebKit::WebFrame* frame, 872 const WebKit::WebURL& url) { 873 if (!render_view_->webview() || !render_view_->webview()->mainFrame() || 874 render_view_->renderer_preferences_.user_agent_override.empty()) { 875 return WebKit::WebString(); 876 } 877 878 // If we're in the middle of committing a load, the data source we need 879 // will still be provisional. 880 WebFrame* main_frame = render_view_->webview()->mainFrame(); 881 WebDataSource* data_source = NULL; 882 if (main_frame->provisionalDataSource()) 883 data_source = main_frame->provisionalDataSource(); 884 else 885 data_source = main_frame->dataSource(); 886 887 InternalDocumentStateData* internal_data = data_source ? 888 InternalDocumentStateData::FromDataSource(data_source) : NULL; 889 if (internal_data && internal_data->is_overriding_user_agent()) 890 return WebString::fromUTF8( 891 render_view_->renderer_preferences_.user_agent_override); 892 return WebKit::WebString(); 893 } 894 895 WebKit::WebString RenderFrameImpl::doNotTrackValue(WebKit::WebFrame* frame) { 896 if (render_view_->renderer_preferences_.enable_do_not_track) 897 return WebString::fromUTF8("1"); 898 return WebString(); 899 } 900 901 bool RenderFrameImpl::allowWebGL(WebKit::WebFrame* frame, bool default_value) { 902 if (!default_value) 903 return false; 904 905 bool blocked = true; 906 Send(new ViewHostMsg_Are3DAPIsBlocked( 907 GetRoutingID(), 908 GURL(frame->top()->document().securityOrigin().toString()), 909 THREE_D_API_TYPE_WEBGL, 910 &blocked)); 911 return !blocked; 912 } 913 914 void RenderFrameImpl::didLoseWebGLContext(WebKit::WebFrame* frame, 915 int arb_robustness_status_code) { 916 Send(new ViewHostMsg_DidLose3DContext( 917 GURL(frame->top()->document().securityOrigin().toString()), 918 THREE_D_API_TYPE_WEBGL, 919 arb_robustness_status_code)); 920 } 921 922 } // namespace content 923