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