Get foreground tab on Android
[chromium-blink-merge.git] / content / renderer / render_frame_impl.cc
blob6231d5939010210cac92f67cb1e184f3d6bc5c89
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/render_frame_impl.h"
7 #include <map>
8 #include <string>
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/time/time.h"
12 #include "content/child/appcache/appcache_dispatcher.h"
13 #include "content/child/plugin_messages.h"
14 #include "content/child/quota_dispatcher.h"
15 #include "content/child/request_extra_data.h"
16 #include "content/child/service_worker/web_service_worker_provider_impl.h"
17 #include "content/common/frame_messages.h"
18 #include "content/common/socket_stream_handle_data.h"
19 #include "content/common/swapped_out_messages.h"
20 #include "content/common/view_messages.h"
21 #include "content/public/common/content_constants.h"
22 #include "content/public/common/content_switches.h"
23 #include "content/public/common/url_constants.h"
24 #include "content/public/renderer/content_renderer_client.h"
25 #include "content/public/renderer/document_state.h"
26 #include "content/public/renderer/navigation_state.h"
27 #include "content/renderer/browser_plugin/browser_plugin.h"
28 #include "content/renderer/browser_plugin/browser_plugin_manager.h"
29 #include "content/renderer/internal_document_state_data.h"
30 #include "content/renderer/npapi/plugin_channel_host.h"
31 #include "content/renderer/render_thread_impl.h"
32 #include "content/renderer/render_view_impl.h"
33 #include "content/renderer/renderer_webapplicationcachehost_impl.h"
34 #include "content/renderer/websharedworker_proxy.h"
35 #include "net/base/net_errors.h"
36 #include "net/http/http_util.h"
37 #include "third_party/WebKit/public/platform/WebStorageQuotaCallbacks.h"
38 #include "third_party/WebKit/public/platform/WebString.h"
39 #include "third_party/WebKit/public/platform/WebURL.h"
40 #include "third_party/WebKit/public/platform/WebURLError.h"
41 #include "third_party/WebKit/public/platform/WebURLResponse.h"
42 #include "third_party/WebKit/public/platform/WebVector.h"
43 #include "third_party/WebKit/public/web/WebDocument.h"
44 #include "third_party/WebKit/public/web/WebFrame.h"
45 #include "third_party/WebKit/public/web/WebNavigationPolicy.h"
46 #include "third_party/WebKit/public/web/WebPlugin.h"
47 #include "third_party/WebKit/public/web/WebPluginParams.h"
48 #include "third_party/WebKit/public/web/WebSearchableFormData.h"
49 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
50 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
51 #include "third_party/WebKit/public/web/WebView.h"
52 #include "webkit/child/weburlresponse_extradata_impl.h"
54 #if defined(ENABLE_WEBRTC)
55 #include "content/renderer/media/rtc_peer_connection_handler.h"
56 #endif
58 using blink::WebDataSource;
59 using blink::WebDocument;
60 using blink::WebFrame;
61 using blink::WebNavigationPolicy;
62 using blink::WebPluginParams;
63 using blink::WebReferrerPolicy;
64 using blink::WebSearchableFormData;
65 using blink::WebSecurityOrigin;
66 using blink::WebServiceWorkerProvider;
67 using blink::WebStorageQuotaCallbacks;
68 using blink::WebString;
69 using blink::WebURL;
70 using blink::WebURLError;
71 using blink::WebURLRequest;
72 using blink::WebURLResponse;
73 using blink::WebUserGestureIndicator;
74 using blink::WebVector;
75 using blink::WebView;
76 using base::Time;
77 using base::TimeDelta;
78 using webkit_glue::WebURLResponseExtraDataImpl;
80 namespace content {
82 namespace {
84 typedef std::map<blink::WebFrame*, RenderFrameImpl*> FrameMap;
85 base::LazyInstance<FrameMap> g_child_frame_map = LAZY_INSTANCE_INITIALIZER;
87 } // namespace
89 static RenderFrameImpl* (*g_create_render_frame_impl)(RenderViewImpl*, int32) =
90 NULL;
92 // static
93 RenderFrameImpl* RenderFrameImpl::Create(RenderViewImpl* render_view,
94 int32 routing_id) {
95 DCHECK(routing_id != MSG_ROUTING_NONE);
97 if (g_create_render_frame_impl)
98 return g_create_render_frame_impl(render_view, routing_id);
99 else
100 return new RenderFrameImpl(render_view, routing_id);
103 // static
104 void RenderFrameImpl::InstallCreateHook(
105 RenderFrameImpl* (*create_render_frame_impl)(RenderViewImpl*, int32)) {
106 CHECK(!g_create_render_frame_impl);
107 g_create_render_frame_impl = create_render_frame_impl;
110 // RenderFrameImpl ----------------------------------------------------------
111 RenderFrameImpl::RenderFrameImpl(RenderViewImpl* render_view, int routing_id)
112 : render_view_(render_view),
113 routing_id_(routing_id),
114 is_swapped_out_(false),
115 is_detaching_(false) {
118 RenderFrameImpl::~RenderFrameImpl() {
121 int RenderFrameImpl::GetRoutingID() const {
122 return routing_id_;
125 bool RenderFrameImpl::Send(IPC::Message* message) {
126 if (is_detaching_ ||
127 ((is_swapped_out_ || render_view_->is_swapped_out()) &&
128 !SwappedOutMessages::CanSendWhileSwappedOut(message))) {
129 delete message;
130 return false;
133 return RenderThread::Get()->Send(message);
136 bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
137 // TODO(ajwong): Fill in with message handlers as various components
138 // are migrated over to understand frames.
139 return false;
142 // blink::WebFrameClient implementation -------------------------------------
144 blink::WebPlugin* RenderFrameImpl::createPlugin(
145 blink::WebFrame* frame,
146 const blink::WebPluginParams& params) {
147 blink::WebPlugin* plugin = NULL;
148 if (GetContentClient()->renderer()->OverrideCreatePlugin(
149 render_view_, frame, params, &plugin)) {
150 return plugin;
153 #if defined(ENABLE_PLUGINS)
154 if (UTF16ToASCII(params.mimeType) == kBrowserPluginMimeType) {
155 return render_view_->GetBrowserPluginManager()->CreateBrowserPlugin(
156 render_view_, frame, params);
159 WebPluginInfo info;
160 std::string mime_type;
161 bool found = render_view_->GetPluginInfo(
162 params.url, frame->top()->document().url(), params.mimeType.utf8(),
163 &info, &mime_type);
164 if (!found)
165 return NULL;
167 WebPluginParams params_to_use = params;
168 params_to_use.mimeType = WebString::fromUTF8(mime_type);
169 return render_view_->CreatePlugin(frame, info, params_to_use);
170 #else
171 return NULL;
172 #endif // defined(ENABLE_PLUGINS)
175 blink::WebMediaPlayer* RenderFrameImpl::createMediaPlayer(
176 blink::WebFrame* frame,
177 const blink::WebURL& url,
178 blink::WebMediaPlayerClient* client) {
179 // TODO(nasko): Moving the implementation here involves moving a few media
180 // related client objects here or referencing them in the RenderView. Needs
181 // more work to understand where the proper place for those objects is.
182 return render_view_->createMediaPlayer(frame, url, client);
185 blink::WebApplicationCacheHost* RenderFrameImpl::createApplicationCacheHost(
186 blink::WebFrame* frame,
187 blink::WebApplicationCacheHostClient* client) {
188 if (!frame || !frame->view())
189 return NULL;
190 return new RendererWebApplicationCacheHostImpl(
191 RenderViewImpl::FromWebView(frame->view()), client,
192 RenderThreadImpl::current()->appcache_dispatcher()->backend_proxy());
195 blink::WebWorkerPermissionClientProxy*
196 RenderFrameImpl::createWorkerPermissionClientProxy(WebFrame* frame) {
197 if (!frame || !frame->view())
198 return NULL;
199 return GetContentClient()->renderer()->CreateWorkerPermissionClientProxy(
200 RenderViewImpl::FromWebView(frame->view()), frame);
203 blink::WebCookieJar* RenderFrameImpl::cookieJar(blink::WebFrame* frame) {
204 return render_view_->cookieJar(frame);
207 blink::WebServiceWorkerProvider* RenderFrameImpl::createServiceWorkerProvider(
208 blink::WebFrame* frame,
209 blink::WebServiceWorkerProviderClient* client) {
210 return new WebServiceWorkerProviderImpl(
211 ChildThread::current()->thread_safe_sender(),
212 make_scoped_ptr(client));
215 void RenderFrameImpl::didAccessInitialDocument(blink::WebFrame* frame) {
216 render_view_->didAccessInitialDocument(frame);
219 blink::WebFrame* RenderFrameImpl::createChildFrame(
220 blink::WebFrame* parent,
221 const blink::WebString& name) {
222 long long child_frame_identifier = WebFrame::generateEmbedderIdentifier();
223 // Synchronously notify the browser of a child frame creation to get the
224 // routing_id for the RenderFrame.
225 int routing_id = MSG_ROUTING_NONE;
226 Send(new FrameHostMsg_CreateChildFrame(GetRoutingID(),
227 parent->identifier(),
228 child_frame_identifier,
229 UTF16ToUTF8(name),
230 &routing_id));
231 if (routing_id == MSG_ROUTING_NONE)
232 return NULL;
233 RenderFrameImpl* child_render_frame = RenderFrameImpl::Create(render_view_,
234 routing_id);
236 blink::WebFrame* web_frame = WebFrame::create(child_render_frame,
237 child_frame_identifier);
239 g_child_frame_map.Get().insert(
240 std::make_pair(web_frame, child_render_frame));
242 return web_frame;
245 void RenderFrameImpl::didDisownOpener(blink::WebFrame* frame) {
246 render_view_->didDisownOpener(frame);
249 void RenderFrameImpl::frameDetached(blink::WebFrame* frame) {
250 // NOTE: This function is called on the frame that is being detached and not
251 // the parent frame. This is different from createChildFrame() which is
252 // called on the parent frame.
253 CHECK(!is_detaching_);
255 bool is_subframe = !!frame->parent();
256 int64 parent_frame_id = -1;
257 if (is_subframe)
258 parent_frame_id = frame->parent()->identifier();
260 Send(new FrameHostMsg_Detach(GetRoutingID(), parent_frame_id,
261 frame->identifier()));
263 // The |is_detaching_| flag disables Send(). FrameHostMsg_Detach must be
264 // sent before setting |is_detaching_| to true. In contrast, Observers
265 // should only be notified afterwards so they cannot call back into and
266 // have IPCs fired off.
267 is_detaching_ = true;
269 // Call back to RenderViewImpl for observers to be notified.
270 // TODO(nasko): Remove once we have RenderFrameObserver.
271 render_view_->frameDetached(frame);
273 // We need to clean up subframes by removing them from the map and deleting
274 // the RenderFrameImpl. In contrast, the main frame is owned by its
275 // containing RenderViewHost (so that they have the same lifetime), so it does
276 // not require any cleanup here.
277 if (is_subframe) {
278 FrameMap::iterator it = g_child_frame_map.Get().find(frame);
279 DCHECK(it != g_child_frame_map.Get().end());
280 DCHECK_EQ(it->second, this);
281 g_child_frame_map.Get().erase(it);
284 // |frame| is invalid after here.
285 frame->close();
287 if (is_subframe) {
288 delete this;
289 // Object is invalid after this point.
293 void RenderFrameImpl::willClose(blink::WebFrame* frame) {
294 // Call back to RenderViewImpl for observers to be notified.
295 // TODO(nasko): Remove once we have RenderFrameObserver.
296 render_view_->willClose(frame);
299 void RenderFrameImpl::didChangeName(blink::WebFrame* frame,
300 const blink::WebString& name) {
301 if (!render_view_->renderer_preferences_.report_frame_name_changes)
302 return;
304 render_view_->Send(
305 new ViewHostMsg_UpdateFrameName(render_view_->GetRoutingID(),
306 frame->identifier(),
307 !frame->parent(),
308 UTF16ToUTF8(name)));
311 void RenderFrameImpl::didMatchCSS(
312 blink::WebFrame* frame,
313 const blink::WebVector<blink::WebString>& newly_matching_selectors,
314 const blink::WebVector<blink::WebString>& stopped_matching_selectors) {
315 render_view_->didMatchCSS(
316 frame, newly_matching_selectors, stopped_matching_selectors);
319 void RenderFrameImpl::loadURLExternally(blink::WebFrame* frame,
320 const blink::WebURLRequest& request,
321 blink::WebNavigationPolicy policy) {
322 loadURLExternally(frame, request, policy, WebString());
325 void RenderFrameImpl::loadURLExternally(
326 blink::WebFrame* frame,
327 const blink::WebURLRequest& request,
328 blink::WebNavigationPolicy policy,
329 const blink::WebString& suggested_name) {
330 Referrer referrer(RenderViewImpl::GetReferrerFromRequest(frame, request));
331 if (policy == blink::WebNavigationPolicyDownload) {
332 render_view_->Send(new ViewHostMsg_DownloadUrl(render_view_->GetRoutingID(),
333 request.url(), referrer,
334 suggested_name));
335 } else {
336 render_view_->OpenURL(frame, request.url(), referrer, policy);
340 blink::WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation(
341 blink::WebFrame* frame,
342 blink::WebDataSource::ExtraData* extra_data,
343 const blink::WebURLRequest& request,
344 blink::WebNavigationType type,
345 blink::WebNavigationPolicy default_policy,
346 bool is_redirect) {
347 return render_view_->decidePolicyForNavigation(
348 frame, extra_data, request, type, default_policy, is_redirect);
351 blink::WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation(
352 blink::WebFrame* frame,
353 const blink::WebURLRequest& request,
354 blink::WebNavigationType type,
355 blink::WebNavigationPolicy default_policy,
356 bool is_redirect) {
357 return render_view_->decidePolicyForNavigation(
358 frame, request, type, default_policy, is_redirect);
361 void RenderFrameImpl::willSendSubmitEvent(blink::WebFrame* frame,
362 const blink::WebFormElement& form) {
363 // Call back to RenderViewImpl for observers to be notified.
364 // TODO(nasko): Remove once we have RenderFrameObserver.
365 render_view_->willSendSubmitEvent(frame, form);
368 void RenderFrameImpl::willSubmitForm(blink::WebFrame* frame,
369 const blink::WebFormElement& form) {
370 DocumentState* document_state =
371 DocumentState::FromDataSource(frame->provisionalDataSource());
372 NavigationState* navigation_state = document_state->navigation_state();
373 InternalDocumentStateData* internal_data =
374 InternalDocumentStateData::FromDocumentState(document_state);
376 if (PageTransitionCoreTypeIs(navigation_state->transition_type(),
377 PAGE_TRANSITION_LINK)) {
378 navigation_state->set_transition_type(PAGE_TRANSITION_FORM_SUBMIT);
381 // Save these to be processed when the ensuing navigation is committed.
382 WebSearchableFormData web_searchable_form_data(form);
383 internal_data->set_searchable_form_url(web_searchable_form_data.url());
384 internal_data->set_searchable_form_encoding(
385 web_searchable_form_data.encoding().utf8());
387 // Call back to RenderViewImpl for observers to be notified.
388 // TODO(nasko): Remove once we have RenderFrameObserver.
389 render_view_->willSubmitForm(frame, form);
392 void RenderFrameImpl::didCreateDataSource(blink::WebFrame* frame,
393 blink::WebDataSource* datasource) {
394 // TODO(nasko): Move implementation here. Needed state:
395 // * pending_navigation_params_
396 // * webview
397 // Needed methods:
398 // * PopulateDocumentStateFromPending
399 // * CreateNavigationStateFromPending
400 render_view_->didCreateDataSource(frame, datasource);
403 void RenderFrameImpl::didStartProvisionalLoad(blink::WebFrame* frame) {
404 WebDataSource* ds = frame->provisionalDataSource();
406 // In fast/loader/stop-provisional-loads.html, we abort the load before this
407 // callback is invoked.
408 if (!ds)
409 return;
411 DocumentState* document_state = DocumentState::FromDataSource(ds);
413 // We should only navigate to swappedout:// when is_swapped_out_ is true.
414 CHECK((ds->request().url() != GURL(kSwappedOutURL)) ||
415 render_view_->is_swapped_out()) <<
416 "Heard swappedout:// when not swapped out.";
418 // Update the request time if WebKit has better knowledge of it.
419 if (document_state->request_time().is_null()) {
420 double event_time = ds->triggeringEventTime();
421 if (event_time != 0.0)
422 document_state->set_request_time(Time::FromDoubleT(event_time));
425 // Start time is only set after request time.
426 document_state->set_start_load_time(Time::Now());
428 bool is_top_most = !frame->parent();
429 if (is_top_most) {
430 render_view_->set_navigation_gesture(
431 WebUserGestureIndicator::isProcessingUserGesture() ?
432 NavigationGestureUser : NavigationGestureAuto);
433 } else if (ds->replacesCurrentHistoryItem()) {
434 // Subframe navigations that don't add session history items must be
435 // marked with AUTO_SUBFRAME. See also didFailProvisionalLoad for how we
436 // handle loading of error pages.
437 document_state->navigation_state()->set_transition_type(
438 PAGE_TRANSITION_AUTO_SUBFRAME);
441 FOR_EACH_OBSERVER(
442 RenderViewObserver, render_view_->observers(),
443 DidStartProvisionalLoad(frame));
445 Send(new FrameHostMsg_DidStartProvisionalLoadForFrame(
446 routing_id_, frame->identifier(),
447 frame->parent() ? frame->parent()->identifier() : -1,
448 is_top_most, ds->request().url()));
451 void RenderFrameImpl::didReceiveServerRedirectForProvisionalLoad(
452 blink::WebFrame* frame) {
453 // TODO(nasko): Move implementation here. Needed state:
454 // * page_id_
455 render_view_->didReceiveServerRedirectForProvisionalLoad(frame);
458 void RenderFrameImpl::didFailProvisionalLoad(
459 blink::WebFrame* frame,
460 const blink::WebURLError& error) {
461 // TODO(nasko): Move implementation here. Needed state:
462 // * page_id_
463 // * pending_navigation_params_
464 // Needed methods
465 // * MaybeLoadAlternateErrorPage
466 // * LoadNavigationErrorPage
467 render_view_->didFailProvisionalLoad(frame, error);
470 void RenderFrameImpl::didCommitProvisionalLoad(blink::WebFrame* frame,
471 bool is_new_navigation) {
472 // TODO(nasko): Move implementation here. Needed state:
473 // * page_id_
474 // * next_page_id_
475 // * history_list_offset_
476 // * history_list_length_
477 // * history_page_ids_
478 // Needed methods
479 // * webview
480 // * UpdateSessionHistory
481 // * GetLoadingUrl
482 render_view_->didCommitProvisionalLoad(frame, is_new_navigation);
485 void RenderFrameImpl::didClearWindowObject(blink::WebFrame* frame) {
486 // TODO(nasko): Move implementation here. Needed state:
487 // * enabled_bindings_
488 // * dom_automation_controller_
489 // * stats_collection_controller_
490 render_view_->didClearWindowObject(frame);
493 void RenderFrameImpl::didCreateDocumentElement(blink::WebFrame* frame) {
494 // Notify the browser about non-blank documents loading in the top frame.
495 GURL url = frame->document().url();
496 if (url.is_valid() && url.spec() != kAboutBlankURL) {
497 // TODO(nasko): Check if webview()->mainFrame() is the same as the
498 // frame->tree()->top().
499 if (frame == render_view_->webview()->mainFrame()) {
500 render_view_->Send(new ViewHostMsg_DocumentAvailableInMainFrame(
501 render_view_->GetRoutingID()));
505 // Call back to RenderViewImpl for observers to be notified.
506 // TODO(nasko): Remove once we have RenderFrameObserver.
507 render_view_->didCreateDocumentElement(frame);
510 void RenderFrameImpl::didReceiveTitle(blink::WebFrame* frame,
511 const blink::WebString& title,
512 blink::WebTextDirection direction) {
513 // TODO(nasko): Investigate wheather implementation should move here.
514 render_view_->didReceiveTitle(frame, title, direction);
517 void RenderFrameImpl::didChangeIcon(blink::WebFrame* frame,
518 blink::WebIconURL::Type icon_type) {
519 // TODO(nasko): Investigate wheather implementation should move here.
520 render_view_->didChangeIcon(frame, icon_type);
523 void RenderFrameImpl::didFinishDocumentLoad(blink::WebFrame* frame) {
524 // TODO(nasko): Move implementation here. No state needed, just observers
525 // notification in before updating encoding.
526 render_view_->didFinishDocumentLoad(frame);
529 void RenderFrameImpl::didHandleOnloadEvents(blink::WebFrame* frame) {
530 // TODO(nasko): Move implementation here. Needed state:
531 // * page_id_
532 render_view_->didHandleOnloadEvents(frame);
535 void RenderFrameImpl::didFailLoad(blink::WebFrame* frame,
536 const blink::WebURLError& error) {
537 // TODO(nasko): Move implementation here. No state needed.
538 render_view_->didFailLoad(frame, error);
541 void RenderFrameImpl::didFinishLoad(blink::WebFrame* frame) {
542 // TODO(nasko): Move implementation here. No state needed, just observers
543 // notification before sending message to the browser process.
544 render_view_->didFinishLoad(frame);
547 void RenderFrameImpl::didNavigateWithinPage(blink::WebFrame* frame,
548 bool is_new_navigation) {
549 // TODO(nasko): Move implementation here. No state needed, just observers
550 // notification before sending message to the browser process.
551 render_view_->didNavigateWithinPage(frame, is_new_navigation);
554 void RenderFrameImpl::didUpdateCurrentHistoryItem(blink::WebFrame* frame) {
555 // TODO(nasko): Move implementation here. Needed methods:
556 // * StartNavStateSyncTimerIfNecessary
557 render_view_->didUpdateCurrentHistoryItem(frame);
560 void RenderFrameImpl::willRequestAfterPreconnect(
561 blink::WebFrame* frame,
562 blink::WebURLRequest& request) {
563 blink::WebReferrerPolicy referrer_policy = blink::WebReferrerPolicyDefault;
564 WebString custom_user_agent;
566 if (request.extraData()) {
567 // This will only be called before willSendRequest, so only ExtraData
568 // members we have to copy here is on WebURLRequestExtraDataImpl.
569 webkit_glue::WebURLRequestExtraDataImpl* old_extra_data =
570 static_cast<webkit_glue::WebURLRequestExtraDataImpl*>(
571 request.extraData());
573 referrer_policy = old_extra_data->referrer_policy();
574 custom_user_agent = old_extra_data->custom_user_agent();
577 bool was_after_preconnect_request = true;
578 // The args after |was_after_preconnect_request| are not used, and set to
579 // correct values at |willSendRequest|.
580 request.setExtraData(new webkit_glue::WebURLRequestExtraDataImpl(
581 referrer_policy, custom_user_agent, was_after_preconnect_request));
584 void RenderFrameImpl::willSendRequest(
585 blink::WebFrame* frame,
586 unsigned identifier,
587 blink::WebURLRequest& request,
588 const blink::WebURLResponse& redirect_response) {
589 // The request my be empty during tests.
590 if (request.url().isEmpty())
591 return;
593 WebFrame* top_frame = frame->top();
594 if (!top_frame)
595 top_frame = frame;
596 WebDataSource* provisional_data_source = top_frame->provisionalDataSource();
597 WebDataSource* top_data_source = top_frame->dataSource();
598 WebDataSource* data_source =
599 provisional_data_source ? provisional_data_source : top_data_source;
601 PageTransition transition_type = PAGE_TRANSITION_LINK;
602 DocumentState* document_state = DocumentState::FromDataSource(data_source);
603 DCHECK(document_state);
604 InternalDocumentStateData* internal_data =
605 InternalDocumentStateData::FromDocumentState(document_state);
606 NavigationState* navigation_state = document_state->navigation_state();
607 transition_type = navigation_state->transition_type();
609 GURL request_url(request.url());
610 GURL new_url;
611 if (GetContentClient()->renderer()->WillSendRequest(
612 frame,
613 transition_type,
614 request_url,
615 request.firstPartyForCookies(),
616 &new_url)) {
617 request.setURL(WebURL(new_url));
620 if (internal_data->is_cache_policy_override_set())
621 request.setCachePolicy(internal_data->cache_policy_override());
623 blink::WebReferrerPolicy referrer_policy;
624 if (internal_data->is_referrer_policy_set()) {
625 referrer_policy = internal_data->referrer_policy();
626 internal_data->clear_referrer_policy();
627 } else {
628 referrer_policy = frame->document().referrerPolicy();
631 // The request's extra data may indicate that we should set a custom user
632 // agent. This needs to be done here, after WebKit is through with setting the
633 // user agent on its own.
634 WebString custom_user_agent;
635 bool was_after_preconnect_request = false;
636 if (request.extraData()) {
637 webkit_glue::WebURLRequestExtraDataImpl* old_extra_data =
638 static_cast<webkit_glue::WebURLRequestExtraDataImpl*>(
639 request.extraData());
640 custom_user_agent = old_extra_data->custom_user_agent();
641 was_after_preconnect_request =
642 old_extra_data->was_after_preconnect_request();
644 if (!custom_user_agent.isNull()) {
645 if (custom_user_agent.isEmpty())
646 request.clearHTTPHeaderField("User-Agent");
647 else
648 request.setHTTPHeaderField("User-Agent", custom_user_agent);
652 // Attach |should_replace_current_entry| state to requests so that, should
653 // this navigation later require a request transfer, all state is preserved
654 // when it is re-created in the new process.
655 bool should_replace_current_entry = false;
656 if (navigation_state->is_content_initiated()) {
657 should_replace_current_entry = data_source->replacesCurrentHistoryItem();
658 } else {
659 // If the navigation is browser-initiated, the NavigationState contains the
660 // correct value instead of the WebDataSource.
662 // TODO(davidben): Avoid this awkward duplication of state. See comment on
663 // NavigationState::should_replace_current_entry().
664 should_replace_current_entry =
665 navigation_state->should_replace_current_entry();
667 request.setExtraData(
668 new RequestExtraData(referrer_policy,
669 custom_user_agent,
670 was_after_preconnect_request,
671 (frame == top_frame),
672 frame->identifier(),
673 GURL(frame->document().securityOrigin().toString()),
674 frame->parent() == top_frame,
675 frame->parent() ? frame->parent()->identifier() : -1,
676 navigation_state->allow_download(),
677 transition_type,
678 should_replace_current_entry,
679 navigation_state->transferred_request_child_id(),
680 navigation_state->transferred_request_request_id()));
682 DocumentState* top_document_state =
683 DocumentState::FromDataSource(top_data_source);
684 if (top_document_state) {
685 // TODO(gavinp): separate out prefetching and prerender field trials
686 // if the rel=prerender rel type is sticking around.
687 if (request.targetType() == WebURLRequest::TargetIsPrefetch)
688 top_document_state->set_was_prefetcher(true);
690 if (was_after_preconnect_request)
691 top_document_state->set_was_after_preconnect_request(true);
694 // This is an instance where we embed a copy of the routing id
695 // into the data portion of the message. This can cause problems if we
696 // don't register this id on the browser side, since the download manager
697 // expects to find a RenderViewHost based off the id.
698 request.setRequestorID(render_view_->GetRoutingID());
699 request.setHasUserGesture(WebUserGestureIndicator::isProcessingUserGesture());
701 if (!navigation_state->extra_headers().empty()) {
702 for (net::HttpUtil::HeadersIterator i(
703 navigation_state->extra_headers().begin(),
704 navigation_state->extra_headers().end(), "\n");
705 i.GetNext(); ) {
706 request.setHTTPHeaderField(WebString::fromUTF8(i.name()),
707 WebString::fromUTF8(i.values()));
711 if (!render_view_->renderer_preferences_.enable_referrers)
712 request.clearHTTPHeaderField("Referer");
715 void RenderFrameImpl::didReceiveResponse(
716 blink::WebFrame* frame,
717 unsigned identifier,
718 const blink::WebURLResponse& response) {
719 // Only do this for responses that correspond to a provisional data source
720 // of the top-most frame. If we have a provisional data source, then we
721 // can't have any sub-resources yet, so we know that this response must
722 // correspond to a frame load.
723 if (!frame->provisionalDataSource() || frame->parent())
724 return;
726 // If we are in view source mode, then just let the user see the source of
727 // the server's error page.
728 if (frame->isViewSourceModeEnabled())
729 return;
731 DocumentState* document_state =
732 DocumentState::FromDataSource(frame->provisionalDataSource());
733 int http_status_code = response.httpStatusCode();
735 // Record page load flags.
736 WebURLResponseExtraDataImpl* extra_data =
737 RenderViewImpl::GetExtraDataFromResponse(response);
738 if (extra_data) {
739 document_state->set_was_fetched_via_spdy(
740 extra_data->was_fetched_via_spdy());
741 document_state->set_was_npn_negotiated(
742 extra_data->was_npn_negotiated());
743 document_state->set_npn_negotiated_protocol(
744 extra_data->npn_negotiated_protocol());
745 document_state->set_was_alternate_protocol_available(
746 extra_data->was_alternate_protocol_available());
747 document_state->set_connection_info(
748 extra_data->connection_info());
749 document_state->set_was_fetched_via_proxy(
750 extra_data->was_fetched_via_proxy());
752 InternalDocumentStateData* internal_data =
753 InternalDocumentStateData::FromDocumentState(document_state);
754 internal_data->set_http_status_code(http_status_code);
755 // Whether or not the http status code actually corresponds to an error is
756 // only checked when the page is done loading, if |use_error_page| is
757 // still true.
758 internal_data->set_use_error_page(true);
761 void RenderFrameImpl::didFinishResourceLoad(blink::WebFrame* frame,
762 unsigned identifier) {
763 // TODO(nasko): Move implementation here. Needed state:
764 // * devtools_agent_
765 // Needed methods:
766 // * LoadNavigationErrorPage
767 render_view_->didFinishResourceLoad(frame, identifier);
770 void RenderFrameImpl::didLoadResourceFromMemoryCache(
771 blink::WebFrame* frame,
772 const blink::WebURLRequest& request,
773 const blink::WebURLResponse& response) {
774 // The recipients of this message have no use for data: URLs: they don't
775 // affect the page's insecure content list and are not in the disk cache. To
776 // prevent large (1M+) data: URLs from crashing in the IPC system, we simply
777 // filter them out here.
778 GURL url(request.url());
779 if (url.SchemeIs("data"))
780 return;
782 // Let the browser know we loaded a resource from the memory cache. This
783 // message is needed to display the correct SSL indicators.
784 render_view_->Send(new ViewHostMsg_DidLoadResourceFromMemoryCache(
785 render_view_->GetRoutingID(),
786 url,
787 response.securityInfo(),
788 request.httpMethod().utf8(),
789 response.mimeType().utf8(),
790 ResourceType::FromTargetType(request.targetType())));
793 void RenderFrameImpl::didDisplayInsecureContent(blink::WebFrame* frame) {
794 render_view_->Send(new ViewHostMsg_DidDisplayInsecureContent(
795 render_view_->GetRoutingID()));
798 void RenderFrameImpl::didRunInsecureContent(
799 blink::WebFrame* frame,
800 const blink::WebSecurityOrigin& origin,
801 const blink::WebURL& target) {
802 render_view_->Send(new ViewHostMsg_DidRunInsecureContent(
803 render_view_->GetRoutingID(),
804 origin.toString().utf8(),
805 target));
808 void RenderFrameImpl::didAbortLoading(blink::WebFrame* frame) {
809 #if defined(ENABLE_PLUGINS)
810 if (frame != render_view_->webview()->mainFrame())
811 return;
812 PluginChannelHost::Broadcast(
813 new PluginHostMsg_DidAbortLoading(render_view_->GetRoutingID()));
814 #endif
817 void RenderFrameImpl::didExhaustMemoryAvailableForScript(
818 blink::WebFrame* frame) {
819 render_view_->Send(new ViewHostMsg_JSOutOfMemory(
820 render_view_->GetRoutingID()));
823 void RenderFrameImpl::didCreateScriptContext(blink::WebFrame* frame,
824 v8::Handle<v8::Context> context,
825 int extension_group,
826 int world_id) {
827 GetContentClient()->renderer()->DidCreateScriptContext(
828 frame, context, extension_group, world_id);
831 void RenderFrameImpl::willReleaseScriptContext(blink::WebFrame* frame,
832 v8::Handle<v8::Context> context,
833 int world_id) {
834 GetContentClient()->renderer()->WillReleaseScriptContext(
835 frame, context, world_id);
838 void RenderFrameImpl::didFirstVisuallyNonEmptyLayout(blink::WebFrame* frame) {
839 render_view_->didFirstVisuallyNonEmptyLayout(frame);
842 void RenderFrameImpl::didChangeContentsSize(blink::WebFrame* frame,
843 const blink::WebSize& size) {
844 // TODO(nasko): Move implementation here. Needed state:
845 // * cached_has_main_frame_horizontal_scrollbar_
846 // * cached_has_main_frame_vertical_scrollbar_
847 render_view_->didChangeContentsSize(frame, size);
850 void RenderFrameImpl::didChangeScrollOffset(blink::WebFrame* frame) {
851 // TODO(nasko): Move implementation here. Needed methods:
852 // * StartNavStateSyncTimerIfNecessary
853 render_view_->didChangeScrollOffset(frame);
856 void RenderFrameImpl::willInsertBody(blink::WebFrame* frame) {
857 if (!frame->parent()) {
858 render_view_->Send(new ViewHostMsg_WillInsertBody(
859 render_view_->GetRoutingID()));
863 void RenderFrameImpl::reportFindInPageMatchCount(int request_id,
864 int count,
865 bool final_update) {
866 int active_match_ordinal = -1; // -1 = don't update active match ordinal
867 if (!count)
868 active_match_ordinal = 0;
870 render_view_->Send(new ViewHostMsg_Find_Reply(
871 render_view_->GetRoutingID(), request_id, count,
872 gfx::Rect(), active_match_ordinal, final_update));
875 void RenderFrameImpl::reportFindInPageSelection(
876 int request_id,
877 int active_match_ordinal,
878 const blink::WebRect& selection_rect) {
879 render_view_->Send(new ViewHostMsg_Find_Reply(
880 render_view_->GetRoutingID(), request_id, -1, selection_rect,
881 active_match_ordinal, false));
884 void RenderFrameImpl::requestStorageQuota(
885 blink::WebFrame* frame,
886 blink::WebStorageQuotaType type,
887 unsigned long long requested_size,
888 blink::WebStorageQuotaCallbacks* callbacks) {
889 DCHECK(frame);
890 WebSecurityOrigin origin = frame->document().securityOrigin();
891 if (origin.isUnique()) {
892 // Unique origins cannot store persistent state.
893 callbacks->didFail(blink::WebStorageQuotaErrorAbort);
894 return;
896 ChildThread::current()->quota_dispatcher()->RequestStorageQuota(
897 render_view_->GetRoutingID(), GURL(origin.toString()),
898 static_cast<quota::StorageType>(type), requested_size,
899 QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(callbacks));
902 void RenderFrameImpl::willOpenSocketStream(
903 blink::WebSocketStreamHandle* handle) {
904 SocketStreamHandleData::AddToHandle(handle, render_view_->GetRoutingID());
907 void RenderFrameImpl::willStartUsingPeerConnectionHandler(
908 blink::WebFrame* frame,
909 blink::WebRTCPeerConnectionHandler* handler) {
910 #if defined(ENABLE_WEBRTC)
911 static_cast<RTCPeerConnectionHandler*>(handler)->associateWithFrame(frame);
912 #endif
915 bool RenderFrameImpl::willCheckAndDispatchMessageEvent(
916 blink::WebFrame* sourceFrame,
917 blink::WebFrame* targetFrame,
918 blink::WebSecurityOrigin targetOrigin,
919 blink::WebDOMMessageEvent event) {
920 // TODO(nasko): Move implementation here. Needed state:
921 // * is_swapped_out_
922 return render_view_->willCheckAndDispatchMessageEvent(
923 sourceFrame, targetFrame, targetOrigin, event);
926 blink::WebString RenderFrameImpl::userAgentOverride(
927 blink::WebFrame* frame,
928 const blink::WebURL& url) {
929 if (!render_view_->webview() || !render_view_->webview()->mainFrame() ||
930 render_view_->renderer_preferences_.user_agent_override.empty()) {
931 return blink::WebString();
934 // If we're in the middle of committing a load, the data source we need
935 // will still be provisional.
936 WebFrame* main_frame = render_view_->webview()->mainFrame();
937 WebDataSource* data_source = NULL;
938 if (main_frame->provisionalDataSource())
939 data_source = main_frame->provisionalDataSource();
940 else
941 data_source = main_frame->dataSource();
943 InternalDocumentStateData* internal_data = data_source ?
944 InternalDocumentStateData::FromDataSource(data_source) : NULL;
945 if (internal_data && internal_data->is_overriding_user_agent())
946 return WebString::fromUTF8(
947 render_view_->renderer_preferences_.user_agent_override);
948 return blink::WebString();
951 blink::WebString RenderFrameImpl::doNotTrackValue(blink::WebFrame* frame) {
952 if (render_view_->renderer_preferences_.enable_do_not_track)
953 return WebString::fromUTF8("1");
954 return WebString();
957 bool RenderFrameImpl::allowWebGL(blink::WebFrame* frame, bool default_value) {
958 if (!default_value)
959 return false;
961 bool blocked = true;
962 render_view_->Send(new ViewHostMsg_Are3DAPIsBlocked(
963 render_view_->GetRoutingID(),
964 GURL(frame->top()->document().securityOrigin().toString()),
965 THREE_D_API_TYPE_WEBGL,
966 &blocked));
967 return !blocked;
970 void RenderFrameImpl::didLoseWebGLContext(blink::WebFrame* frame,
971 int arb_robustness_status_code) {
972 render_view_->Send(new ViewHostMsg_DidLose3DContext(
973 GURL(frame->top()->document().securityOrigin().toString()),
974 THREE_D_API_TYPE_WEBGL,
975 arb_robustness_status_code));
978 } // namespace content