Refactor management of overview window copy lifetime into a separate class.
[chromium-blink-merge.git] / content / renderer / render_frame_impl.cc
blob91475d361fb56c3dfd6899a76adb83a956970995
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 "base/command_line.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "base/time/time.h"
10 #include "content/child/appcache/appcache_dispatcher.h"
11 #include "content/child/plugin_messages.h"
12 #include "content/child/quota_dispatcher.h"
13 #include "content/child/request_extra_data.h"
14 #include "content/common/frame_messages.h"
15 #include "content/common/socket_stream_handle_data.h"
16 #include "content/common/swapped_out_messages.h"
17 #include "content/common/view_messages.h"
18 #include "content/public/common/content_constants.h"
19 #include "content/public/common/content_switches.h"
20 #include "content/public/common/url_constants.h"
21 #include "content/public/renderer/content_renderer_client.h"
22 #include "content/public/renderer/document_state.h"
23 #include "content/public/renderer/navigation_state.h"
24 #include "content/renderer/browser_plugin/browser_plugin.h"
25 #include "content/renderer/browser_plugin/browser_plugin_manager.h"
26 #include "content/renderer/internal_document_state_data.h"
27 #include "content/renderer/npapi/plugin_channel_host.h"
28 #include "content/renderer/render_thread_impl.h"
29 #include "content/renderer/render_view_impl.h"
30 #include "content/renderer/renderer_webapplicationcachehost_impl.h"
31 #include "content/renderer/websharedworker_proxy.h"
32 #include "net/base/net_errors.h"
33 #include "net/http/http_util.h"
34 #include "third_party/WebKit/public/platform/WebString.h"
35 #include "third_party/WebKit/public/platform/WebURL.h"
36 #include "third_party/WebKit/public/platform/WebURLError.h"
37 #include "third_party/WebKit/public/platform/WebURLResponse.h"
38 #include "third_party/WebKit/public/platform/WebVector.h"
39 #include "third_party/WebKit/public/web/WebDocument.h"
40 #include "third_party/WebKit/public/web/WebFrame.h"
41 #include "third_party/WebKit/public/web/WebNavigationPolicy.h"
42 #include "third_party/WebKit/public/web/WebPlugin.h"
43 #include "third_party/WebKit/public/web/WebPluginParams.h"
44 #include "third_party/WebKit/public/web/WebSearchableFormData.h"
45 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
46 #include "third_party/WebKit/public/web/WebStorageQuotaCallbacks.h"
47 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
48 #include "third_party/WebKit/public/web/WebView.h"
49 #include "webkit/child/weburlresponse_extradata_impl.h"
51 #if defined(ENABLE_WEBRTC)
52 #include "content/renderer/media/rtc_peer_connection_handler.h"
53 #endif
55 using WebKit::WebDataSource;
56 using WebKit::WebDocument;
57 using WebKit::WebFrame;
58 using WebKit::WebNavigationPolicy;
59 using WebKit::WebPluginParams;
60 using WebKit::WebReferrerPolicy;
61 using WebKit::WebSearchableFormData;
62 using WebKit::WebSecurityOrigin;
63 using WebKit::WebStorageQuotaCallbacks;
64 using WebKit::WebString;
65 using WebKit::WebURL;
66 using WebKit::WebURLError;
67 using WebKit::WebURLRequest;
68 using WebKit::WebURLResponse;
69 using WebKit::WebUserGestureIndicator;
70 using WebKit::WebVector;
71 using WebKit::WebView;
72 using base::Time;
73 using base::TimeDelta;
74 using webkit_glue::WebURLResponseExtraDataImpl;
76 namespace content {
78 namespace {
80 typedef std::map<WebKit::WebFrame*, RenderFrameImpl*> FrameMap;
81 base::LazyInstance<FrameMap> g_child_frame_map = LAZY_INSTANCE_INITIALIZER;
83 } // namespace
85 static RenderFrameImpl* (*g_create_render_frame_impl)(RenderViewImpl*, int32) =
86 NULL;
88 // static
89 RenderFrameImpl* RenderFrameImpl::Create(RenderViewImpl* render_view,
90 int32 routing_id) {
91 DCHECK(routing_id != MSG_ROUTING_NONE);
93 if (g_create_render_frame_impl)
94 return g_create_render_frame_impl(render_view, routing_id);
95 else
96 return new RenderFrameImpl(render_view, routing_id);
99 // static
100 void RenderFrameImpl::InstallCreateHook(
101 RenderFrameImpl* (*create_render_frame_impl)(RenderViewImpl*, int32)) {
102 CHECK(!g_create_render_frame_impl);
103 g_create_render_frame_impl = create_render_frame_impl;
106 // RenderFrameImpl ----------------------------------------------------------
107 RenderFrameImpl::RenderFrameImpl(RenderViewImpl* render_view, int routing_id)
108 : render_view_(render_view),
109 routing_id_(routing_id),
110 is_swapped_out_(false),
111 is_detaching_(false) {
114 RenderFrameImpl::~RenderFrameImpl() {
117 int RenderFrameImpl::GetRoutingID() const {
118 return routing_id_;
121 bool RenderFrameImpl::Send(IPC::Message* message) {
122 if (is_detaching_ ||
123 ((is_swapped_out_ || render_view_->is_swapped_out()) &&
124 !SwappedOutMessages::CanSendWhileSwappedOut(message))) {
125 delete message;
126 return false;
129 return RenderThread::Get()->Send(message);
132 bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
133 // TODO(ajwong): Fill in with message handlers as various components
134 // are migrated over to understand frames.
135 return false;
138 // WebKit::WebFrameClient implementation -------------------------------------
140 WebKit::WebPlugin* RenderFrameImpl::createPlugin(
141 WebKit::WebFrame* frame,
142 const WebKit::WebPluginParams& params) {
143 WebKit::WebPlugin* plugin = NULL;
144 if (GetContentClient()->renderer()->OverrideCreatePlugin(
145 render_view_, frame, params, &plugin)) {
146 return plugin;
149 #if defined(ENABLE_PLUGINS)
150 if (UTF16ToASCII(params.mimeType) == kBrowserPluginMimeType) {
151 return render_view_->GetBrowserPluginManager()->CreateBrowserPlugin(
152 render_view_, frame, params);
155 WebPluginInfo info;
156 std::string mime_type;
157 bool found = render_view_->GetPluginInfo(
158 params.url, frame->top()->document().url(), params.mimeType.utf8(),
159 &info, &mime_type);
160 if (!found)
161 return NULL;
163 WebPluginParams params_to_use = params;
164 params_to_use.mimeType = WebString::fromUTF8(mime_type);
165 return render_view_->CreatePlugin(frame, info, params_to_use);
166 #else
167 return NULL;
168 #endif // defined(ENABLE_PLUGINS)
171 WebKit::WebSharedWorker* RenderFrameImpl::createSharedWorker(
172 WebKit::WebFrame* frame,
173 const WebKit::WebURL& url,
174 const WebKit::WebString& name,
175 unsigned long long document_id) {
176 int route_id = MSG_ROUTING_NONE;
177 bool exists = false;
178 bool url_mismatch = false;
179 ViewHostMsg_CreateWorker_Params params;
180 params.url = url;
181 params.name = name;
182 params.document_id = document_id;
183 params.render_view_route_id = render_view_->GetRoutingID();
184 params.route_id = MSG_ROUTING_NONE;
185 params.script_resource_appcache_id = 0;
186 render_view_->Send(new ViewHostMsg_LookupSharedWorker(
187 params, &exists, &route_id, &url_mismatch));
188 if (url_mismatch) {
189 return NULL;
190 } else {
191 return new WebSharedWorkerProxy(RenderThreadImpl::current(),
192 document_id,
193 exists,
194 route_id,
195 render_view_->GetRoutingID());
199 WebKit::WebMediaPlayer* RenderFrameImpl::createMediaPlayer(
200 WebKit::WebFrame* frame,
201 const WebKit::WebURL& url,
202 WebKit::WebMediaPlayerClient* client) {
203 // TODO(nasko): Moving the implementation here involves moving a few media
204 // related client objects here or referencing them in the RenderView. Needs
205 // more work to understand where the proper place for those objects is.
206 return render_view_->createMediaPlayer(frame, url, client);
209 WebKit::WebApplicationCacheHost* RenderFrameImpl::createApplicationCacheHost(
210 WebKit::WebFrame* frame,
211 WebKit::WebApplicationCacheHostClient* client) {
212 if (!frame || !frame->view())
213 return NULL;
214 return new RendererWebApplicationCacheHostImpl(
215 RenderViewImpl::FromWebView(frame->view()), client,
216 RenderThreadImpl::current()->appcache_dispatcher()->backend_proxy());
219 WebKit::WebCookieJar* RenderFrameImpl::cookieJar(WebKit::WebFrame* frame) {
220 return render_view_->cookieJar(frame);
223 void RenderFrameImpl::didAccessInitialDocument(WebKit::WebFrame* frame) {
224 render_view_->didAccessInitialDocument(frame);
227 WebKit::WebFrame* RenderFrameImpl::createChildFrame(
228 WebKit::WebFrame* parent,
229 const WebKit::WebString& name) {
230 RenderFrameImpl* child_render_frame = this;
231 long long child_frame_identifier = WebFrame::generateEmbedderIdentifier();
232 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) {
233 // Synchronously notify the browser of a child frame creation to get the
234 // routing_id for the RenderFrame.
235 int routing_id;
236 Send(new FrameHostMsg_CreateChildFrame(GetRoutingID(),
237 parent->identifier(),
238 child_frame_identifier,
239 UTF16ToUTF8(name),
240 &routing_id));
241 child_render_frame = RenderFrameImpl::Create(render_view_, routing_id);
244 WebKit::WebFrame* web_frame = WebFrame::create(child_render_frame,
245 child_frame_identifier);
247 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) {
248 g_child_frame_map.Get().insert(
249 std::make_pair(web_frame, child_render_frame));
252 return web_frame;
255 void RenderFrameImpl::didDisownOpener(WebKit::WebFrame* frame) {
256 render_view_->didDisownOpener(frame);
259 void RenderFrameImpl::frameDetached(WebKit::WebFrame* frame) {
260 // Currently multiple WebCore::Frames can send frameDetached to a single
261 // RenderFrameImpl. This is legacy behavior from when RenderViewImpl served
262 // as a shared WebFrameClient for multiple Webcore::Frame objects. It also
263 // prevents this class from entering the |is_detaching_| state because
264 // even though one WebCore::Frame may have detached itself, others will
265 // still need to use this object.
266 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) {
267 // TODO(ajwong): Add CHECK(!is_detaching_) once we guarantee each
268 // RenderFrameImpl is only used by one WebCore::Frame.
269 is_detaching_ = true;
272 int64 parent_frame_id = -1;
273 if (frame->parent())
274 parent_frame_id = frame->parent()->identifier();
276 render_view_->Send(new FrameHostMsg_Detach(GetRoutingID(), parent_frame_id,
277 frame->identifier()));
279 // Call back to RenderViewImpl for observers to be notified.
280 // TODO(nasko): Remove once we have RenderFrameObserver.
281 render_view_->frameDetached(frame);
283 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) {
284 FrameMap::iterator it = g_child_frame_map.Get().find(frame);
285 DCHECK(it != g_child_frame_map.Get().end());
286 DCHECK_EQ(it->second, this);
287 delete it->second;
288 g_child_frame_map.Get().erase(it);
291 frame->close();
294 void RenderFrameImpl::willClose(WebKit::WebFrame* frame) {
295 // Call back to RenderViewImpl for observers to be notified.
296 // TODO(nasko): Remove once we have RenderFrameObserver.
297 render_view_->willClose(frame);
300 void RenderFrameImpl::didChangeName(WebKit::WebFrame* frame,
301 const WebKit::WebString& name) {
302 if (!render_view_->renderer_preferences_.report_frame_name_changes)
303 return;
305 render_view_->Send(
306 new ViewHostMsg_UpdateFrameName(render_view_->GetRoutingID(),
307 frame->identifier(),
308 !frame->parent(),
309 UTF16ToUTF8(name)));
312 void RenderFrameImpl::didMatchCSS(
313 WebKit::WebFrame* frame,
314 const WebKit::WebVector<WebKit::WebString>& newly_matching_selectors,
315 const WebKit::WebVector<WebKit::WebString>& stopped_matching_selectors) {
316 render_view_->didMatchCSS(
317 frame, newly_matching_selectors, stopped_matching_selectors);
320 void RenderFrameImpl::loadURLExternally(WebKit::WebFrame* frame,
321 const WebKit::WebURLRequest& request,
322 WebKit::WebNavigationPolicy policy) {
323 loadURLExternally(frame, request, policy, WebString());
326 void RenderFrameImpl::loadURLExternally(
327 WebKit::WebFrame* frame,
328 const WebKit::WebURLRequest& request,
329 WebKit::WebNavigationPolicy policy,
330 const WebKit::WebString& suggested_name) {
331 Referrer referrer(RenderViewImpl::GetReferrerFromRequest(frame, request));
332 if (policy == WebKit::WebNavigationPolicyDownload) {
333 render_view_->Send(new ViewHostMsg_DownloadUrl(render_view_->GetRoutingID(),
334 request.url(), referrer,
335 suggested_name));
336 } else {
337 render_view_->OpenURL(frame, request.url(), referrer, policy);
341 WebKit::WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation(
342 WebKit::WebFrame* frame,
343 WebKit::WebDataSource::ExtraData* extra_data,
344 const WebKit::WebURLRequest& request,
345 WebKit::WebNavigationType type,
346 WebKit::WebNavigationPolicy default_policy,
347 bool is_redirect) {
348 return render_view_->decidePolicyForNavigation(
349 frame, extra_data, request, type, default_policy, is_redirect);
352 WebKit::WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation(
353 WebKit::WebFrame* frame,
354 const WebKit::WebURLRequest& request,
355 WebKit::WebNavigationType type,
356 WebKit::WebNavigationPolicy default_policy,
357 bool is_redirect) {
358 return render_view_->decidePolicyForNavigation(
359 frame, request, type, default_policy, is_redirect);
362 void RenderFrameImpl::willSendSubmitEvent(WebKit::WebFrame* frame,
363 const WebKit::WebFormElement& form) {
364 // Call back to RenderViewImpl for observers to be notified.
365 // TODO(nasko): Remove once we have RenderFrameObserver.
366 render_view_->willSendSubmitEvent(frame, form);
369 void RenderFrameImpl::willSubmitForm(WebKit::WebFrame* frame,
370 const WebKit::WebFormElement& form) {
371 DocumentState* document_state =
372 DocumentState::FromDataSource(frame->provisionalDataSource());
373 NavigationState* navigation_state = document_state->navigation_state();
374 InternalDocumentStateData* internal_data =
375 InternalDocumentStateData::FromDocumentState(document_state);
377 if (PageTransitionCoreTypeIs(navigation_state->transition_type(),
378 PAGE_TRANSITION_LINK)) {
379 navigation_state->set_transition_type(PAGE_TRANSITION_FORM_SUBMIT);
382 // Save these to be processed when the ensuing navigation is committed.
383 WebSearchableFormData web_searchable_form_data(form);
384 internal_data->set_searchable_form_url(web_searchable_form_data.url());
385 internal_data->set_searchable_form_encoding(
386 web_searchable_form_data.encoding().utf8());
388 // Call back to RenderViewImpl for observers to be notified.
389 // TODO(nasko): Remove once we have RenderFrameObserver.
390 render_view_->willSubmitForm(frame, form);
393 void RenderFrameImpl::didCreateDataSource(WebKit::WebFrame* frame,
394 WebKit::WebDataSource* datasource) {
395 // TODO(nasko): Move implementation here. Needed state:
396 // * pending_navigation_params_
397 // * webview
398 // Needed methods:
399 // * PopulateDocumentStateFromPending
400 // * CreateNavigationStateFromPending
401 render_view_->didCreateDataSource(frame, datasource);
404 void RenderFrameImpl::didStartProvisionalLoad(WebKit::WebFrame* frame) {
405 WebDataSource* ds = frame->provisionalDataSource();
407 // In fast/loader/stop-provisional-loads.html, we abort the load before this
408 // callback is invoked.
409 if (!ds)
410 return;
412 DocumentState* document_state = DocumentState::FromDataSource(ds);
414 // We should only navigate to swappedout:// when is_swapped_out_ is true.
415 CHECK((ds->request().url() != GURL(kSwappedOutURL)) ||
416 render_view_->is_swapped_out()) <<
417 "Heard swappedout:// when not swapped out.";
419 // Update the request time if WebKit has better knowledge of it.
420 if (document_state->request_time().is_null()) {
421 double event_time = ds->triggeringEventTime();
422 if (event_time != 0.0)
423 document_state->set_request_time(Time::FromDoubleT(event_time));
426 // Start time is only set after request time.
427 document_state->set_start_load_time(Time::Now());
429 bool is_top_most = !frame->parent();
430 if (is_top_most) {
431 render_view_->set_navigation_gesture(
432 WebUserGestureIndicator::isProcessingUserGesture() ?
433 NavigationGestureUser : NavigationGestureAuto);
434 } else if (ds->replacesCurrentHistoryItem()) {
435 // Subframe navigations that don't add session history items must be
436 // marked with AUTO_SUBFRAME. See also didFailProvisionalLoad for how we
437 // handle loading of error pages.
438 document_state->navigation_state()->set_transition_type(
439 PAGE_TRANSITION_AUTO_SUBFRAME);
442 FOR_EACH_OBSERVER(
443 RenderViewObserver, render_view_->observers(),
444 DidStartProvisionalLoad(frame));
446 Send(new FrameHostMsg_DidStartProvisionalLoadForFrame(
447 routing_id_, frame->identifier(),
448 frame->parent() ? frame->parent()->identifier() : -1,
449 is_top_most, ds->request().url()));
452 void RenderFrameImpl::didReceiveServerRedirectForProvisionalLoad(
453 WebKit::WebFrame* frame) {
454 // TODO(nasko): Move implementation here. Needed state:
455 // * page_id_
456 render_view_->didReceiveServerRedirectForProvisionalLoad(frame);
459 void RenderFrameImpl::didFailProvisionalLoad(
460 WebKit::WebFrame* frame,
461 const WebKit::WebURLError& error) {
462 // TODO(nasko): Move implementation here. Needed state:
463 // * page_id_
464 // * pending_navigation_params_
465 // Needed methods
466 // * MaybeLoadAlternateErrorPage
467 // * LoadNavigationErrorPage
468 render_view_->didFailProvisionalLoad(frame, error);
471 void RenderFrameImpl::didCommitProvisionalLoad(WebKit::WebFrame* frame,
472 bool is_new_navigation) {
473 // TODO(nasko): Move implementation here. Needed state:
474 // * page_id_
475 // * next_page_id_
476 // * history_list_offset_
477 // * history_list_length_
478 // * history_page_ids_
479 // Needed methods
480 // * webview
481 // * UpdateSessionHistory
482 // * GetLoadingUrl
483 render_view_->didCommitProvisionalLoad(frame, is_new_navigation);
486 void RenderFrameImpl::didClearWindowObject(WebKit::WebFrame* frame) {
487 // TODO(nasko): Move implementation here. Needed state:
488 // * enabled_bindings_
489 // * dom_automation_controller_
490 // * stats_collection_controller_
491 render_view_->didClearWindowObject(frame);
494 void RenderFrameImpl::didCreateDocumentElement(WebKit::WebFrame* frame) {
495 // Notify the browser about non-blank documents loading in the top frame.
496 GURL url = frame->document().url();
497 if (url.is_valid() && url.spec() != kAboutBlankURL) {
498 // TODO(nasko): Check if webview()->mainFrame() is the same as the
499 // frame->tree()->top().
500 if (frame == render_view_->webview()->mainFrame()) {
501 render_view_->Send(new ViewHostMsg_DocumentAvailableInMainFrame(
502 render_view_->GetRoutingID()));
506 // Call back to RenderViewImpl for observers to be notified.
507 // TODO(nasko): Remove once we have RenderFrameObserver.
508 render_view_->didCreateDocumentElement(frame);
511 void RenderFrameImpl::didReceiveTitle(WebKit::WebFrame* frame,
512 const WebKit::WebString& title,
513 WebKit::WebTextDirection direction) {
514 // TODO(nasko): Investigate wheather implementation should move here.
515 render_view_->didReceiveTitle(frame, title, direction);
518 void RenderFrameImpl::didChangeIcon(WebKit::WebFrame* frame,
519 WebKit::WebIconURL::Type icon_type) {
520 // TODO(nasko): Investigate wheather implementation should move here.
521 render_view_->didChangeIcon(frame, icon_type);
524 void RenderFrameImpl::didFinishDocumentLoad(WebKit::WebFrame* frame) {
525 // TODO(nasko): Move implementation here. No state needed, just observers
526 // notification in before updating encoding.
527 render_view_->didFinishDocumentLoad(frame);
530 void RenderFrameImpl::didHandleOnloadEvents(WebKit::WebFrame* frame) {
531 // TODO(nasko): Move implementation here. Needed state:
532 // * page_id_
533 render_view_->didHandleOnloadEvents(frame);
536 void RenderFrameImpl::didFailLoad(WebKit::WebFrame* frame,
537 const WebKit::WebURLError& error) {
538 // TODO(nasko): Move implementation here. No state needed.
539 render_view_->didFailLoad(frame, error);
542 void RenderFrameImpl::didFinishLoad(WebKit::WebFrame* frame) {
543 // TODO(nasko): Move implementation here. No state needed, just observers
544 // notification before sending message to the browser process.
545 render_view_->didFinishLoad(frame);
548 void RenderFrameImpl::didNavigateWithinPage(WebKit::WebFrame* frame,
549 bool is_new_navigation) {
550 // TODO(nasko): Move implementation here. No state needed, just observers
551 // notification before sending message to the browser process.
552 render_view_->didNavigateWithinPage(frame, is_new_navigation);
555 void RenderFrameImpl::didUpdateCurrentHistoryItem(WebKit::WebFrame* frame) {
556 // TODO(nasko): Move implementation here. Needed methods:
557 // * StartNavStateSyncTimerIfNecessary
558 render_view_->didUpdateCurrentHistoryItem(frame);
561 void RenderFrameImpl::willRequestAfterPreconnect(
562 WebKit::WebFrame* frame,
563 WebKit::WebURLRequest& request) {
564 WebKit::WebReferrerPolicy referrer_policy = WebKit::WebReferrerPolicyDefault;
565 WebString custom_user_agent;
567 if (request.extraData()) {
568 // This will only be called before willSendRequest, so only ExtraData
569 // members we have to copy here is on WebURLRequestExtraDataImpl.
570 webkit_glue::WebURLRequestExtraDataImpl* old_extra_data =
571 static_cast<webkit_glue::WebURLRequestExtraDataImpl*>(
572 request.extraData());
574 referrer_policy = old_extra_data->referrer_policy();
575 custom_user_agent = old_extra_data->custom_user_agent();
578 bool was_after_preconnect_request = true;
579 // The args after |was_after_preconnect_request| are not used, and set to
580 // correct values at |willSendRequest|.
581 request.setExtraData(new webkit_glue::WebURLRequestExtraDataImpl(
582 referrer_policy, custom_user_agent, was_after_preconnect_request));
585 void RenderFrameImpl::willSendRequest(
586 WebKit::WebFrame* frame,
587 unsigned identifier,
588 WebKit::WebURLRequest& request,
589 const WebKit::WebURLResponse& redirect_response) {
590 // The request my be empty during tests.
591 if (request.url().isEmpty())
592 return;
594 WebFrame* top_frame = frame->top();
595 if (!top_frame)
596 top_frame = frame;
597 WebDataSource* provisional_data_source = top_frame->provisionalDataSource();
598 WebDataSource* top_data_source = top_frame->dataSource();
599 WebDataSource* data_source =
600 provisional_data_source ? provisional_data_source : top_data_source;
602 PageTransition transition_type = PAGE_TRANSITION_LINK;
603 DocumentState* document_state = DocumentState::FromDataSource(data_source);
604 DCHECK(document_state);
605 InternalDocumentStateData* internal_data =
606 InternalDocumentStateData::FromDocumentState(document_state);
607 NavigationState* navigation_state = document_state->navigation_state();
608 transition_type = navigation_state->transition_type();
610 GURL request_url(request.url());
611 GURL new_url;
612 if (GetContentClient()->renderer()->WillSendRequest(
613 frame,
614 transition_type,
615 request_url,
616 request.firstPartyForCookies(),
617 &new_url)) {
618 request.setURL(WebURL(new_url));
621 if (internal_data->is_cache_policy_override_set())
622 request.setCachePolicy(internal_data->cache_policy_override());
624 WebKit::WebReferrerPolicy referrer_policy;
625 if (internal_data->is_referrer_policy_set()) {
626 referrer_policy = internal_data->referrer_policy();
627 internal_data->clear_referrer_policy();
628 } else {
629 referrer_policy = frame->document().referrerPolicy();
632 // The request's extra data may indicate that we should set a custom user
633 // agent. This needs to be done here, after WebKit is through with setting the
634 // user agent on its own.
635 WebString custom_user_agent;
636 bool was_after_preconnect_request = false;
637 if (request.extraData()) {
638 webkit_glue::WebURLRequestExtraDataImpl* old_extra_data =
639 static_cast<webkit_glue::WebURLRequestExtraDataImpl*>(
640 request.extraData());
641 custom_user_agent = old_extra_data->custom_user_agent();
642 was_after_preconnect_request =
643 old_extra_data->was_after_preconnect_request();
645 if (!custom_user_agent.isNull()) {
646 if (custom_user_agent.isEmpty())
647 request.clearHTTPHeaderField("User-Agent");
648 else
649 request.setHTTPHeaderField("User-Agent", custom_user_agent);
653 request.setExtraData(
654 new RequestExtraData(referrer_policy,
655 custom_user_agent,
656 was_after_preconnect_request,
657 (frame == top_frame),
658 frame->identifier(),
659 GURL(frame->document().securityOrigin().toString()),
660 frame->parent() == top_frame,
661 frame->parent() ? frame->parent()->identifier() : -1,
662 navigation_state->allow_download(),
663 transition_type,
664 navigation_state->transferred_request_child_id(),
665 navigation_state->transferred_request_request_id()));
667 DocumentState* top_document_state =
668 DocumentState::FromDataSource(top_data_source);
669 if (top_document_state) {
670 // TODO(gavinp): separate out prefetching and prerender field trials
671 // if the rel=prerender rel type is sticking around.
672 if (request.targetType() == WebURLRequest::TargetIsPrefetch)
673 top_document_state->set_was_prefetcher(true);
675 if (was_after_preconnect_request)
676 top_document_state->set_was_after_preconnect_request(true);
679 // This is an instance where we embed a copy of the routing id
680 // into the data portion of the message. This can cause problems if we
681 // don't register this id on the browser side, since the download manager
682 // expects to find a RenderViewHost based off the id.
683 request.setRequestorID(render_view_->GetRoutingID());
684 request.setHasUserGesture(WebUserGestureIndicator::isProcessingUserGesture());
686 if (!navigation_state->extra_headers().empty()) {
687 for (net::HttpUtil::HeadersIterator i(
688 navigation_state->extra_headers().begin(),
689 navigation_state->extra_headers().end(), "\n");
690 i.GetNext(); ) {
691 request.setHTTPHeaderField(WebString::fromUTF8(i.name()),
692 WebString::fromUTF8(i.values()));
696 if (!render_view_->renderer_preferences_.enable_referrers)
697 request.clearHTTPHeaderField("Referer");
700 void RenderFrameImpl::didReceiveResponse(
701 WebKit::WebFrame* frame,
702 unsigned identifier,
703 const WebKit::WebURLResponse& response) {
704 // Only do this for responses that correspond to a provisional data source
705 // of the top-most frame. If we have a provisional data source, then we
706 // can't have any sub-resources yet, so we know that this response must
707 // correspond to a frame load.
708 if (!frame->provisionalDataSource() || frame->parent())
709 return;
711 // If we are in view source mode, then just let the user see the source of
712 // the server's error page.
713 if (frame->isViewSourceModeEnabled())
714 return;
716 DocumentState* document_state =
717 DocumentState::FromDataSource(frame->provisionalDataSource());
718 int http_status_code = response.httpStatusCode();
720 // Record page load flags.
721 WebURLResponseExtraDataImpl* extra_data =
722 RenderViewImpl::GetExtraDataFromResponse(response);
723 if (extra_data) {
724 document_state->set_was_fetched_via_spdy(
725 extra_data->was_fetched_via_spdy());
726 document_state->set_was_npn_negotiated(
727 extra_data->was_npn_negotiated());
728 document_state->set_npn_negotiated_protocol(
729 extra_data->npn_negotiated_protocol());
730 document_state->set_was_alternate_protocol_available(
731 extra_data->was_alternate_protocol_available());
732 document_state->set_connection_info(
733 extra_data->connection_info());
734 document_state->set_was_fetched_via_proxy(
735 extra_data->was_fetched_via_proxy());
737 InternalDocumentStateData* internal_data =
738 InternalDocumentStateData::FromDocumentState(document_state);
739 internal_data->set_http_status_code(http_status_code);
740 // Whether or not the http status code actually corresponds to an error is
741 // only checked when the page is done loading, if |use_error_page| is
742 // still true.
743 internal_data->set_use_error_page(true);
746 void RenderFrameImpl::didFinishResourceLoad(WebKit::WebFrame* frame,
747 unsigned identifier) {
748 // TODO(nasko): Move implementation here. Needed state:
749 // * devtools_agent_
750 // Needed methods:
751 // * LoadNavigationErrorPage
752 render_view_->didFinishResourceLoad(frame, identifier);
755 void RenderFrameImpl::didLoadResourceFromMemoryCache(
756 WebKit::WebFrame* frame,
757 const WebKit::WebURLRequest& request,
758 const WebKit::WebURLResponse& response) {
759 // The recipients of this message have no use for data: URLs: they don't
760 // affect the page's insecure content list and are not in the disk cache. To
761 // prevent large (1M+) data: URLs from crashing in the IPC system, we simply
762 // filter them out here.
763 GURL url(request.url());
764 if (url.SchemeIs("data"))
765 return;
767 // Let the browser know we loaded a resource from the memory cache. This
768 // message is needed to display the correct SSL indicators.
769 render_view_->Send(new ViewHostMsg_DidLoadResourceFromMemoryCache(
770 render_view_->GetRoutingID(),
771 url,
772 response.securityInfo(),
773 request.httpMethod().utf8(),
774 response.mimeType().utf8(),
775 ResourceType::FromTargetType(request.targetType())));
778 void RenderFrameImpl::didDisplayInsecureContent(WebKit::WebFrame* frame) {
779 render_view_->Send(new ViewHostMsg_DidDisplayInsecureContent(
780 render_view_->GetRoutingID()));
783 void RenderFrameImpl::didRunInsecureContent(
784 WebKit::WebFrame* frame,
785 const WebKit::WebSecurityOrigin& origin,
786 const WebKit::WebURL& target) {
787 render_view_->Send(new ViewHostMsg_DidRunInsecureContent(
788 render_view_->GetRoutingID(),
789 origin.toString().utf8(),
790 target));
793 void RenderFrameImpl::didAbortLoading(WebKit::WebFrame* frame) {
794 #if defined(ENABLE_PLUGINS)
795 if (frame != render_view_->webview()->mainFrame())
796 return;
797 PluginChannelHost::Broadcast(
798 new PluginHostMsg_DidAbortLoading(render_view_->GetRoutingID()));
799 #endif
802 void RenderFrameImpl::didExhaustMemoryAvailableForScript(
803 WebKit::WebFrame* frame) {
804 render_view_->Send(new ViewHostMsg_JSOutOfMemory(
805 render_view_->GetRoutingID()));
808 void RenderFrameImpl::didCreateScriptContext(WebKit::WebFrame* frame,
809 v8::Handle<v8::Context> context,
810 int extension_group,
811 int world_id) {
812 GetContentClient()->renderer()->DidCreateScriptContext(
813 frame, context, extension_group, world_id);
816 void RenderFrameImpl::willReleaseScriptContext(WebKit::WebFrame* frame,
817 v8::Handle<v8::Context> context,
818 int world_id) {
819 GetContentClient()->renderer()->WillReleaseScriptContext(
820 frame, context, world_id);
823 void RenderFrameImpl::didFirstVisuallyNonEmptyLayout(WebKit::WebFrame* frame) {
824 render_view_->didFirstVisuallyNonEmptyLayout(frame);
827 void RenderFrameImpl::didChangeContentsSize(WebKit::WebFrame* frame,
828 const WebKit::WebSize& size) {
829 // TODO(nasko): Move implementation here. Needed state:
830 // * cached_has_main_frame_horizontal_scrollbar_
831 // * cached_has_main_frame_vertical_scrollbar_
832 render_view_->didChangeContentsSize(frame, size);
835 void RenderFrameImpl::didChangeScrollOffset(WebKit::WebFrame* frame) {
836 // TODO(nasko): Move implementation here. Needed methods:
837 // * StartNavStateSyncTimerIfNecessary
838 render_view_->didChangeScrollOffset(frame);
841 void RenderFrameImpl::willInsertBody(WebKit::WebFrame* frame) {
842 if (!frame->parent()) {
843 render_view_->Send(new ViewHostMsg_WillInsertBody(
844 render_view_->GetRoutingID()));
848 void RenderFrameImpl::reportFindInPageMatchCount(int request_id,
849 int count,
850 bool final_update) {
851 int active_match_ordinal = -1; // -1 = don't update active match ordinal
852 if (!count)
853 active_match_ordinal = 0;
855 render_view_->Send(new ViewHostMsg_Find_Reply(
856 render_view_->GetRoutingID(), request_id, count,
857 gfx::Rect(), active_match_ordinal, final_update));
860 void RenderFrameImpl::reportFindInPageSelection(
861 int request_id,
862 int active_match_ordinal,
863 const WebKit::WebRect& selection_rect) {
864 render_view_->Send(new ViewHostMsg_Find_Reply(
865 render_view_->GetRoutingID(), request_id, -1, selection_rect,
866 active_match_ordinal, false));
869 void RenderFrameImpl::requestStorageQuota(
870 WebKit::WebFrame* frame,
871 WebKit::WebStorageQuotaType type,
872 unsigned long long requested_size,
873 WebKit::WebStorageQuotaCallbacks* callbacks) {
874 DCHECK(frame);
875 WebSecurityOrigin origin = frame->document().securityOrigin();
876 if (origin.isUnique()) {
877 // Unique origins cannot store persistent state.
878 callbacks->didFail(WebKit::WebStorageQuotaErrorAbort);
879 return;
881 ChildThread::current()->quota_dispatcher()->RequestStorageQuota(
882 render_view_->GetRoutingID(), GURL(origin.toString()),
883 static_cast<quota::StorageType>(type), requested_size,
884 QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(callbacks));
887 void RenderFrameImpl::willOpenSocketStream(
888 WebKit::WebSocketStreamHandle* handle) {
889 SocketStreamHandleData::AddToHandle(handle, render_view_->GetRoutingID());
892 void RenderFrameImpl::willStartUsingPeerConnectionHandler(
893 WebKit::WebFrame* frame,
894 WebKit::WebRTCPeerConnectionHandler* handler) {
895 #if defined(ENABLE_WEBRTC)
896 static_cast<RTCPeerConnectionHandler*>(handler)->associateWithFrame(frame);
897 #endif
900 bool RenderFrameImpl::willCheckAndDispatchMessageEvent(
901 WebKit::WebFrame* sourceFrame,
902 WebKit::WebFrame* targetFrame,
903 WebKit::WebSecurityOrigin targetOrigin,
904 WebKit::WebDOMMessageEvent event) {
905 // TODO(nasko): Move implementation here. Needed state:
906 // * is_swapped_out_
907 return render_view_->willCheckAndDispatchMessageEvent(
908 sourceFrame, targetFrame, targetOrigin, event);
911 WebKit::WebString RenderFrameImpl::userAgentOverride(
912 WebKit::WebFrame* frame,
913 const WebKit::WebURL& url) {
914 if (!render_view_->webview() || !render_view_->webview()->mainFrame() ||
915 render_view_->renderer_preferences_.user_agent_override.empty()) {
916 return WebKit::WebString();
919 // If we're in the middle of committing a load, the data source we need
920 // will still be provisional.
921 WebFrame* main_frame = render_view_->webview()->mainFrame();
922 WebDataSource* data_source = NULL;
923 if (main_frame->provisionalDataSource())
924 data_source = main_frame->provisionalDataSource();
925 else
926 data_source = main_frame->dataSource();
928 InternalDocumentStateData* internal_data = data_source ?
929 InternalDocumentStateData::FromDataSource(data_source) : NULL;
930 if (internal_data && internal_data->is_overriding_user_agent())
931 return WebString::fromUTF8(
932 render_view_->renderer_preferences_.user_agent_override);
933 return WebKit::WebString();
936 WebKit::WebString RenderFrameImpl::doNotTrackValue(WebKit::WebFrame* frame) {
937 if (render_view_->renderer_preferences_.enable_do_not_track)
938 return WebString::fromUTF8("1");
939 return WebString();
942 bool RenderFrameImpl::allowWebGL(WebKit::WebFrame* frame, bool default_value) {
943 if (!default_value)
944 return false;
946 bool blocked = true;
947 render_view_->Send(new ViewHostMsg_Are3DAPIsBlocked(
948 render_view_->GetRoutingID(),
949 GURL(frame->top()->document().securityOrigin().toString()),
950 THREE_D_API_TYPE_WEBGL,
951 &blocked));
952 return !blocked;
955 void RenderFrameImpl::didLoseWebGLContext(WebKit::WebFrame* frame,
956 int arb_robustness_status_code) {
957 render_view_->Send(new ViewHostMsg_DidLose3DContext(
958 GURL(frame->top()->document().securityOrigin().toString()),
959 THREE_D_API_TYPE_WEBGL,
960 arb_robustness_status_code));
963 } // namespace content