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"
10 #include "base/command_line.h"
11 #include "base/debug/alias.h"
12 #include "base/i18n/char_iterator.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/time/time.h"
15 #include "content/child/appcache/appcache_dispatcher.h"
16 #include "content/child/plugin_messages.h"
17 #include "content/child/quota_dispatcher.h"
18 #include "content/child/request_extra_data.h"
19 #include "content/child/service_worker/web_service_worker_provider_impl.h"
20 #include "content/common/frame_messages.h"
21 #include "content/common/socket_stream_handle_data.h"
22 #include "content/common/swapped_out_messages.h"
23 #include "content/common/view_messages.h"
24 #include "content/public/common/content_constants.h"
25 #include "content/public/common/content_switches.h"
26 #include "content/public/common/url_constants.h"
27 #include "content/public/renderer/content_renderer_client.h"
28 #include "content/public/renderer/document_state.h"
29 #include "content/public/renderer/navigation_state.h"
30 #include "content/public/renderer/render_frame_observer.h"
31 #include "content/renderer/accessibility/renderer_accessibility.h"
32 #include "content/renderer/browser_plugin/browser_plugin.h"
33 #include "content/renderer/browser_plugin/browser_plugin_manager.h"
34 #include "content/renderer/internal_document_state_data.h"
35 #include "content/renderer/npapi/plugin_channel_host.h"
36 #include "content/renderer/render_thread_impl.h"
37 #include "content/renderer/render_view_impl.h"
38 #include "content/renderer/render_widget_fullscreen_pepper.h"
39 #include "content/renderer/renderer_webapplicationcachehost_impl.h"
40 #include "content/renderer/shared_worker_repository.h"
41 #include "content/renderer/websharedworker_proxy.h"
42 #include "net/base/net_errors.h"
43 #include "net/http/http_util.h"
44 #include "third_party/WebKit/public/platform/WebStorageQuotaCallbacks.h"
45 #include "third_party/WebKit/public/platform/WebString.h"
46 #include "third_party/WebKit/public/platform/WebURL.h"
47 #include "third_party/WebKit/public/platform/WebURLError.h"
48 #include "third_party/WebKit/public/platform/WebURLResponse.h"
49 #include "third_party/WebKit/public/platform/WebVector.h"
50 #include "third_party/WebKit/public/web/WebDocument.h"
51 #include "third_party/WebKit/public/web/WebFrame.h"
52 #include "third_party/WebKit/public/web/WebNavigationPolicy.h"
53 #include "third_party/WebKit/public/web/WebPlugin.h"
54 #include "third_party/WebKit/public/web/WebPluginParams.h"
55 #include "third_party/WebKit/public/web/WebSearchableFormData.h"
56 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
57 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
58 #include "third_party/WebKit/public/web/WebView.h"
59 #include "webkit/child/weburlresponse_extradata_impl.h"
61 #if defined(ENABLE_PLUGINS)
62 #include "content/renderer/npapi/webplugin_impl.h"
63 #include "content/renderer/pepper/pepper_browser_connection.h"
64 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
65 #include "content/renderer/pepper/pepper_webplugin_impl.h"
66 #include "content/renderer/pepper/plugin_module.h"
69 #if defined(ENABLE_WEBRTC)
70 #include "content/renderer/media/rtc_peer_connection_handler.h"
73 using blink::WebDataSource
;
74 using blink::WebDocument
;
75 using blink::WebFrame
;
76 using blink::WebNavigationPolicy
;
77 using blink::WebPluginParams
;
78 using blink::WebReferrerPolicy
;
79 using blink::WebSearchableFormData
;
80 using blink::WebSecurityOrigin
;
81 using blink::WebServiceWorkerProvider
;
82 using blink::WebStorageQuotaCallbacks
;
83 using blink::WebString
;
85 using blink::WebURLError
;
86 using blink::WebURLRequest
;
87 using blink::WebURLResponse
;
88 using blink::WebUserGestureIndicator
;
89 using blink::WebVector
;
92 using base::TimeDelta
;
93 using webkit_glue::WebURLResponseExtraDataImpl
;
99 typedef std::map
<blink::WebFrame
*, RenderFrameImpl
*> FrameMap
;
100 base::LazyInstance
<FrameMap
> g_frame_map
= LAZY_INSTANCE_INITIALIZER
;
104 static RenderFrameImpl
* (*g_create_render_frame_impl
)(RenderViewImpl
*, int32
) =
108 RenderFrameImpl
* RenderFrameImpl::Create(RenderViewImpl
* render_view
,
110 DCHECK(routing_id
!= MSG_ROUTING_NONE
);
112 if (g_create_render_frame_impl
)
113 return g_create_render_frame_impl(render_view
, routing_id
);
115 return new RenderFrameImpl(render_view
, routing_id
);
118 RenderFrameImpl
* RenderFrameImpl::FindByWebFrame(blink::WebFrame
* web_frame
) {
119 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess
)) {
120 FrameMap::iterator iter
= g_frame_map
.Get().find(web_frame
);
121 if (iter
!= g_frame_map
.Get().end())
129 void RenderFrameImpl::InstallCreateHook(
130 RenderFrameImpl
* (*create_render_frame_impl
)(RenderViewImpl
*, int32
)) {
131 CHECK(!g_create_render_frame_impl
);
132 g_create_render_frame_impl
= create_render_frame_impl
;
135 // RenderFrameImpl ----------------------------------------------------------
136 RenderFrameImpl::RenderFrameImpl(RenderViewImpl
* render_view
, int routing_id
)
138 render_view_(render_view
),
139 routing_id_(routing_id
),
140 is_swapped_out_(false),
141 is_detaching_(false),
143 RenderThread::Get()->AddRoute(routing_id_
, this);
144 #if defined(ENABLE_PLUGINS)
145 new PepperBrowserConnection(this);
147 new SharedWorkerRepository(this);
149 GetContentClient()->renderer()->RenderFrameCreated(this);
152 RenderFrameImpl::~RenderFrameImpl() {
153 FOR_EACH_OBSERVER(RenderFrameObserver
, observers_
, RenderFrameGone());
154 FOR_EACH_OBSERVER(RenderFrameObserver
, observers_
, OnDestruct());
155 RenderThread::Get()->RemoveRoute(routing_id_
);
158 // TODO(nasko): Overload the delete operator to overwrite the freed
159 // RenderFrameImpl object and help detect potential use-after-free bug.
160 // See https://crbug.com/245126#c34.
161 void RenderFrameImpl::operator delete(void* ptr
) {
162 memset(ptr
, 0xAF, sizeof(RenderFrameImpl
));
165 void RenderFrameImpl::MainWebFrameCreated(blink::WebFrame
* frame
) {
166 std::pair
<FrameMap::iterator
, bool> result
= g_frame_map
.Get().insert(
167 std::make_pair(frame
, this));
168 CHECK(result
.second
) << "Inserting a duplicate item.";
170 FOR_EACH_OBSERVER(RenderFrameObserver
, observers_
,
171 WebFrameCreated(frame
));
174 void RenderFrameImpl::SetWebFrame(blink::WebFrame
* web_frame
) {
176 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess
))
180 RenderWidget
* RenderFrameImpl::GetRenderWidget() {
184 #if defined(ENABLE_PLUGINS)
185 void RenderFrameImpl::PepperPluginCreated(RendererPpapiHost
* host
) {
186 FOR_EACH_OBSERVER(RenderFrameObserver
, observers_
,
187 DidCreatePepperPlugin(host
));
190 void RenderFrameImpl::PepperInstanceCreated(
191 PepperPluginInstanceImpl
* instance
) {
192 active_pepper_instances_
.insert(instance
);
195 void RenderFrameImpl::PepperInstanceDeleted(
196 PepperPluginInstanceImpl
* instance
) {
197 active_pepper_instances_
.erase(instance
);
199 if (render_view_
->pepper_last_mouse_event_target() == instance
)
200 render_view_
->set_pepper_last_mouse_event_target(NULL
);
201 if (render_view_
->focused_pepper_plugin() == instance
)
202 PepperFocusChanged(instance
, false);
205 void RenderFrameImpl::PepperDidChangeCursor(
206 PepperPluginInstanceImpl
* instance
,
207 const blink::WebCursorInfo
& cursor
) {
208 // Update the cursor appearance immediately if the requesting plugin is the
209 // one which receives the last mouse event. Otherwise, the new cursor won't be
210 // picked up until the plugin gets the next input event. That is bad if, e.g.,
211 // the plugin would like to set an invisible cursor when there isn't any user
212 // input for a while.
213 if (instance
== render_view_
->pepper_last_mouse_event_target())
214 GetRenderWidget()->didChangeCursor(cursor
);
217 void RenderFrameImpl::PepperDidReceiveMouseEvent(
218 PepperPluginInstanceImpl
* instance
) {
219 render_view_
->set_pepper_last_mouse_event_target(instance
);
222 void RenderFrameImpl::PepperFocusChanged(PepperPluginInstanceImpl
* instance
,
225 render_view_
->set_focused_pepper_plugin(instance
);
226 else if (render_view_
->focused_pepper_plugin() == instance
)
227 render_view_
->set_focused_pepper_plugin(NULL
);
229 GetRenderWidget()->UpdateTextInputType();
230 GetRenderWidget()->UpdateSelectionBounds();
233 void RenderFrameImpl::PepperTextInputTypeChanged(
234 PepperPluginInstanceImpl
* instance
) {
235 if (instance
!= render_view_
->focused_pepper_plugin())
238 GetRenderWidget()->UpdateTextInputType();
239 if (render_view_
->renderer_accessibility()) {
240 render_view_
->renderer_accessibility()->FocusedNodeChanged(
245 void RenderFrameImpl::PepperCaretPositionChanged(
246 PepperPluginInstanceImpl
* instance
) {
247 if (instance
!= render_view_
->focused_pepper_plugin())
249 GetRenderWidget()->UpdateSelectionBounds();
252 void RenderFrameImpl::PepperCancelComposition(
253 PepperPluginInstanceImpl
* instance
) {
254 if (instance
!= render_view_
->focused_pepper_plugin())
256 Send(new ViewHostMsg_ImeCancelComposition(render_view_
->GetRoutingID()));;
257 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
258 GetRenderWidget()->UpdateCompositionInfo(true);
262 void RenderFrameImpl::PepperSelectionChanged(
263 PepperPluginInstanceImpl
* instance
) {
264 if (instance
!= render_view_
->focused_pepper_plugin())
266 render_view_
->SyncSelectionIfRequired();
269 RenderWidgetFullscreenPepper
* RenderFrameImpl::CreatePepperFullscreenContainer(
270 PepperPluginInstanceImpl
* plugin
) {
272 if (render_view_
->webview() && render_view_
->webview()->mainFrame())
273 active_url
= GURL(render_view_
->webview()->mainFrame()->document().url());
274 RenderWidgetFullscreenPepper
* widget
= RenderWidgetFullscreenPepper::Create(
275 GetRenderWidget()->routing_id(), plugin
, active_url
,
276 GetRenderWidget()->screenInfo());
277 widget
->show(blink::WebNavigationPolicyIgnore
);
281 bool RenderFrameImpl::IsPepperAcceptingCompositionEvents() const {
282 if (!render_view_
->focused_pepper_plugin())
284 return render_view_
->focused_pepper_plugin()->
285 IsPluginAcceptingCompositionEvents();
288 void RenderFrameImpl::PluginCrashed(const base::FilePath
& plugin_path
,
289 base::ProcessId plugin_pid
) {
290 // TODO(jam): dispatch this IPC in RenderFrameHost and switch to use
291 // routing_id_ as a result.
292 Send(new FrameHostMsg_PluginCrashed(routing_id_
, plugin_path
, plugin_pid
));
295 void RenderFrameImpl::DidInitiatePaint() {
296 // Notify all instances that we painted. The same caveats apply as for
297 // ViewFlushedPaint regarding instances closing themselves, so we take
298 // similar precautions.
299 PepperPluginSet plugins
= active_pepper_instances_
;
300 for (PepperPluginSet::iterator i
= plugins
.begin(); i
!= plugins
.end(); ++i
) {
301 if (active_pepper_instances_
.find(*i
) != active_pepper_instances_
.end())
302 (*i
)->ViewInitiatedPaint();
306 void RenderFrameImpl::DidFlushPaint() {
307 // Notify all instances that we flushed. This will call into the plugin, and
308 // we it may ask to close itself as a result. This will, in turn, modify our
309 // set, possibly invalidating the iterator. So we iterate on a copy that
310 // won't change out from under us.
311 PepperPluginSet plugins
= active_pepper_instances_
;
312 for (PepperPluginSet::iterator i
= plugins
.begin(); i
!= plugins
.end(); ++i
) {
313 // The copy above makes sure our iterator is never invalid if some plugins
314 // are destroyed. But some plugin may decide to close all of its views in
315 // response to a paint in one of them, so we need to make sure each one is
316 // still "current" before using it.
318 // It's possible that a plugin was destroyed, but another one was created
319 // with the same address. In this case, we'll call ViewFlushedPaint on that
320 // new plugin. But that's OK for this particular case since we're just
321 // notifying all of our instances that the view flushed, and the new one is
322 // one of our instances.
324 // What about the case where a new one is created in a callback at a new
325 // address and we don't issue the callback? We're still OK since this
326 // callback is used for flush callbacks and we could not have possibly
327 // started a new paint for the new plugin while processing a previous paint
328 // for an existing one.
329 if (active_pepper_instances_
.find(*i
) != active_pepper_instances_
.end())
330 (*i
)->ViewFlushedPaint();
334 PepperPluginInstanceImpl
* RenderFrameImpl::GetBitmapForOptimizedPluginPaint(
335 const gfx::Rect
& paint_bounds
,
339 float* scale_factor
) {
340 for (PepperPluginSet::iterator i
= active_pepper_instances_
.begin();
341 i
!= active_pepper_instances_
.end(); ++i
) {
342 PepperPluginInstanceImpl
* instance
= *i
;
343 // In Flash fullscreen , the plugin contents should be painted onto the
344 // fullscreen widget instead of the web page.
345 if (!instance
->FlashIsFullscreenOrPending() &&
346 instance
->GetBitmapForOptimizedPluginPaint(paint_bounds
, dib
, location
,
353 void RenderFrameImpl::PageVisibilityChanged(bool shown
) {
354 // Inform PPAPI plugins that their page is no longer visible.
355 for (PepperPluginSet::iterator i
= active_pepper_instances_
.begin();
356 i
!= active_pepper_instances_
.end(); ++i
)
357 (*i
)->PageVisibilityChanged(shown
);
360 void RenderFrameImpl::OnSetFocus(bool enable
) {
361 // Notify all Pepper plugins.
362 for (PepperPluginSet::iterator i
= active_pepper_instances_
.begin();
363 i
!= active_pepper_instances_
.end(); ++i
)
364 (*i
)->SetContentAreaFocus(enable
);
367 void RenderFrameImpl::WillHandleMouseEvent(const blink::WebMouseEvent
& event
) {
368 // This method is called for every mouse event that the render view receives.
369 // And then the mouse event is forwarded to WebKit, which dispatches it to the
370 // event target. Potentially a Pepper plugin will receive the event.
371 // In order to tell whether a plugin gets the last mouse event and which it
372 // is, we set |pepper_last_mouse_event_target_| to NULL here. If a plugin gets
373 // the event, it will notify us via DidReceiveMouseEvent() and set itself as
374 // |pepper_last_mouse_event_target_|.
375 render_view_
->set_pepper_last_mouse_event_target(NULL
);
378 void RenderFrameImpl::SimulateImeSetComposition(
379 const base::string16
& text
,
380 const std::vector
<blink::WebCompositionUnderline
>& underlines
,
383 render_view_
->OnImeSetComposition(
384 text
, underlines
, selection_start
, selection_end
);
387 void RenderFrameImpl::SimulateImeConfirmComposition(
388 const base::string16
& text
,
389 const gfx::Range
& replacement_range
) {
390 render_view_
->OnImeConfirmComposition(text
, replacement_range
, false);
394 void RenderFrameImpl::OnImeSetComposition(
395 const base::string16
& text
,
396 const std::vector
<blink::WebCompositionUnderline
>& underlines
,
399 // When a PPAPI plugin has focus, we bypass WebKit.
400 if (!IsPepperAcceptingCompositionEvents()) {
401 pepper_composition_text_
= text
;
403 // TODO(kinaba) currently all composition events are sent directly to
404 // plugins. Use DOM event mechanism after WebKit is made aware about
405 // plugins that support composition.
406 // The code below mimics the behavior of WebCore::Editor::setComposition.
408 // Empty -> nonempty: composition started.
409 if (pepper_composition_text_
.empty() && !text
.empty()) {
410 render_view_
->focused_pepper_plugin()->HandleCompositionStart(
413 // Nonempty -> empty: composition canceled.
414 if (!pepper_composition_text_
.empty() && text
.empty()) {
415 render_view_
->focused_pepper_plugin()->HandleCompositionEnd(
418 pepper_composition_text_
= text
;
419 // Nonempty: composition is ongoing.
420 if (!pepper_composition_text_
.empty()) {
421 render_view_
->focused_pepper_plugin()->HandleCompositionUpdate(
422 pepper_composition_text_
, underlines
, selection_start
,
428 void RenderFrameImpl::OnImeConfirmComposition(
429 const base::string16
& text
,
430 const gfx::Range
& replacement_range
,
431 bool keep_selection
) {
432 // When a PPAPI plugin has focus, we bypass WebKit.
433 // Here, text.empty() has a special meaning. It means to commit the last
434 // update of composition text (see
435 // RenderWidgetHost::ImeConfirmComposition()).
436 const base::string16
& last_text
= text
.empty() ? pepper_composition_text_
439 // last_text is empty only when both text and pepper_composition_text_ is.
441 if (last_text
.empty())
444 if (!IsPepperAcceptingCompositionEvents()) {
445 base::i18n::UTF16CharIterator
iterator(&last_text
);
447 while (iterator
.Advance()) {
448 blink::WebKeyboardEvent char_event
;
449 char_event
.type
= blink::WebInputEvent::Char
;
450 char_event
.timeStampSeconds
= base::Time::Now().ToDoubleT();
451 char_event
.modifiers
= 0;
452 char_event
.windowsKeyCode
= last_text
[i
];
453 char_event
.nativeKeyCode
= last_text
[i
];
455 const int32 char_start
= i
;
456 for (; i
< iterator
.array_pos(); ++i
) {
457 char_event
.text
[i
- char_start
] = last_text
[i
];
458 char_event
.unmodifiedText
[i
- char_start
] = last_text
[i
];
461 if (GetRenderWidget()->webwidget())
462 GetRenderWidget()->webwidget()->handleInputEvent(char_event
);
465 // Mimics the order of events sent by WebKit.
466 // See WebCore::Editor::setComposition() for the corresponding code.
467 render_view_
->focused_pepper_plugin()->HandleCompositionEnd(last_text
);
468 render_view_
->focused_pepper_plugin()->HandleTextInput(last_text
);
470 pepper_composition_text_
.clear();
473 #endif // ENABLE_PLUGINS
475 bool RenderFrameImpl::Send(IPC::Message
* message
) {
477 ((is_swapped_out_
|| render_view_
->is_swapped_out()) &&
478 !SwappedOutMessages::CanSendWhileSwappedOut(message
))) {
483 return RenderThread::Get()->Send(message
);
486 bool RenderFrameImpl::OnMessageReceived(const IPC::Message
& msg
) {
487 ObserverListBase
<RenderFrameObserver
>::Iterator
it(observers_
);
488 RenderFrameObserver
* observer
;
489 while ((observer
= it
.GetNext()) != NULL
) {
490 if (observer
->OnMessageReceived(msg
))
495 bool msg_is_ok
= true;
496 IPC_BEGIN_MESSAGE_MAP_EX(RenderFrameImpl
, msg
, msg_is_ok
)
497 IPC_MESSAGE_HANDLER(FrameMsg_SwapOut
, OnSwapOut
)
498 IPC_END_MESSAGE_MAP_EX()
501 // The message had a handler, but its deserialization failed.
502 // Kill the renderer to avoid potential spoofing attacks.
503 CHECK(false) << "Unable to deserialize message in RenderFrameImpl.";
509 void RenderFrameImpl::OnSwapOut() {
510 // Only run unload if we're not swapped out yet, but send the ack either way.
511 if (!is_swapped_out_
) {
512 // Swap this RenderView out so the tab can navigate to a page rendered by a
513 // different process. This involves running the unload handler and clearing
514 // the page. Once WasSwappedOut is called, we also allow this process to
515 // exit if there are no other active RenderViews in it.
517 // Send an UpdateState message before we get swapped out.
518 render_view_
->SyncNavigationState();
520 // Synchronously run the unload handler before sending the ACK.
521 // TODO(creis): Add a WebFrame::dispatchUnloadEvent and call it here.
523 // Swap out and stop sending any IPC messages that are not ACKs.
524 is_swapped_out_
= true;
526 // Now that we're swapped out and filtering IPC messages, stop loading to
527 // ensure that no other in-progress navigation continues. We do this here
528 // to avoid sending a DidStopLoading message to the browser process.
529 // TODO(creis): Should we be stopping all frames here and using
530 // StopAltErrorPageFetcher with RenderView::OnStop, or just stopping this
532 frame_
->stopLoading();
534 // Replace the page with a blank dummy URL. The unload handler will not be
535 // run a second time, thanks to a check in FrameLoader::stopLoading.
536 // TODO(creis): Need to add a better way to do this that avoids running the
537 // beforeunload handler. For now, we just run it a second time silently.
538 render_view_
->NavigateToSwappedOutURL(frame_
);
541 Send(new FrameHostMsg_SwapOut_ACK(routing_id_
));
544 RenderView
* RenderFrameImpl::GetRenderView() {
548 int RenderFrameImpl::GetRoutingID() {
552 WebPreferences
& RenderFrameImpl::GetWebkitPreferences() {
553 return render_view_
->GetWebkitPreferences();
556 int RenderFrameImpl::ShowContextMenu(ContextMenuClient
* client
,
557 const ContextMenuParams
& params
) {
558 return render_view_
->ShowContextMenu(client
, params
);
561 void RenderFrameImpl::CancelContextMenu(int request_id
) {
562 return render_view_
->CancelContextMenu(request_id
);
565 blink::WebPlugin
* RenderFrameImpl::CreatePlugin(
566 blink::WebFrame
* frame
,
567 const WebPluginInfo
& info
,
568 const blink::WebPluginParams
& params
) {
569 #if defined(ENABLE_PLUGINS)
570 bool pepper_plugin_was_registered
= false;
571 scoped_refptr
<PluginModule
> pepper_module(PluginModule::Create(
572 this, info
, &pepper_plugin_was_registered
));
573 if (pepper_plugin_was_registered
) {
574 if (pepper_module
.get()) {
575 return new PepperWebPluginImpl(pepper_module
.get(), params
, this);
578 #if defined(OS_CHROMEOS)
579 LOG(WARNING
) << "Pepper module/plugin creation failed.";
582 // TODO(jam): change to take RenderFrame.
583 return new WebPluginImpl(frame
, params
, info
.path
, render_view_
->AsWeakPtr(),
591 void RenderFrameImpl::LoadURLExternally(
592 blink::WebFrame
* frame
,
593 const blink::WebURLRequest
& request
,
594 blink::WebNavigationPolicy policy
) {
595 loadURLExternally(frame
, request
, policy
);
598 // blink::WebFrameClient implementation ----------------------------------------
600 blink::WebPlugin
* RenderFrameImpl::createPlugin(
601 blink::WebFrame
* frame
,
602 const blink::WebPluginParams
& params
) {
603 blink::WebPlugin
* plugin
= NULL
;
604 if (GetContentClient()->renderer()->OverrideCreatePlugin(
605 this, frame
, params
, &plugin
)) {
609 if (UTF16ToASCII(params
.mimeType
) == kBrowserPluginMimeType
) {
610 return render_view_
->GetBrowserPluginManager()->CreateBrowserPlugin(
611 render_view_
, frame
);
614 #if defined(ENABLE_PLUGINS)
616 std::string mime_type
;
618 Send(new FrameHostMsg_GetPluginInfo(
619 routing_id_
, params
.url
, frame
->top()->document().url(),
620 params
.mimeType
.utf8(), &found
, &info
, &mime_type
));
624 WebPluginParams params_to_use
= params
;
625 params_to_use
.mimeType
= WebString::fromUTF8(mime_type
);
626 return CreatePlugin(frame
, info
, params_to_use
);
629 #endif // defined(ENABLE_PLUGINS)
632 blink::WebMediaPlayer
* RenderFrameImpl::createMediaPlayer(
633 blink::WebFrame
* frame
,
634 const blink::WebURL
& url
,
635 blink::WebMediaPlayerClient
* client
) {
636 // TODO(nasko): Moving the implementation here involves moving a few media
637 // related client objects here or referencing them in the RenderView. Needs
638 // more work to understand where the proper place for those objects is.
639 return render_view_
->CreateMediaPlayer(this, frame
, url
, client
);
642 blink::WebApplicationCacheHost
* RenderFrameImpl::createApplicationCacheHost(
643 blink::WebFrame
* frame
,
644 blink::WebApplicationCacheHostClient
* client
) {
645 if (!frame
|| !frame
->view())
647 return new RendererWebApplicationCacheHostImpl(
648 RenderViewImpl::FromWebView(frame
->view()), client
,
649 RenderThreadImpl::current()->appcache_dispatcher()->backend_proxy());
652 blink::WebWorkerPermissionClientProxy
*
653 RenderFrameImpl::createWorkerPermissionClientProxy(WebFrame
* frame
) {
654 if (!frame
|| !frame
->view())
656 return GetContentClient()->renderer()->CreateWorkerPermissionClientProxy(
660 blink::WebCookieJar
* RenderFrameImpl::cookieJar(blink::WebFrame
* frame
) {
664 blink::WebServiceWorkerProvider
* RenderFrameImpl::createServiceWorkerProvider(
665 blink::WebFrame
* frame
,
666 blink::WebServiceWorkerProviderClient
* client
) {
667 return new WebServiceWorkerProviderImpl(
668 ChildThread::current()->thread_safe_sender(),
669 make_scoped_ptr(client
));
672 void RenderFrameImpl::didAccessInitialDocument(blink::WebFrame
* frame
) {
673 render_view_
->didAccessInitialDocument(frame
);
676 blink::WebFrame
* RenderFrameImpl::createChildFrame(
677 blink::WebFrame
* parent
,
678 const blink::WebString
& name
) {
679 long long child_frame_identifier
= WebFrame::generateEmbedderIdentifier();
680 // Synchronously notify the browser of a child frame creation to get the
681 // routing_id for the RenderFrame.
682 int routing_id
= MSG_ROUTING_NONE
;
683 Send(new FrameHostMsg_CreateChildFrame(routing_id_
,
684 parent
->identifier(),
685 child_frame_identifier
,
686 base::UTF16ToUTF8(name
),
688 CHECK_NE(routing_id
, MSG_ROUTING_NONE
);
689 RenderFrameImpl
* child_render_frame
= RenderFrameImpl::Create(render_view_
,
691 // TODO(nasko): Over-conservative check for debugging.
692 CHECK(child_render_frame
);
693 blink::WebFrame
* web_frame
= WebFrame::create(child_render_frame
,
694 child_frame_identifier
);
695 // TODO(nasko): Over-conservative check for debugging.
697 child_render_frame
->SetWebFrame(web_frame
);
699 std::pair
<FrameMap::iterator
, bool> result
= g_frame_map
.Get().insert(
700 std::make_pair(web_frame
, child_render_frame
));
701 CHECK(result
.second
) << "Inserting a duplicate item.";
703 FOR_EACH_OBSERVER(RenderFrameObserver
, observers_
,
704 WebFrameCreated(web_frame
));
708 void RenderFrameImpl::didDisownOpener(blink::WebFrame
* frame
) {
709 render_view_
->didDisownOpener(frame
);
712 void RenderFrameImpl::frameDetached(blink::WebFrame
* frame
) {
713 // NOTE: This function is called on the frame that is being detached and not
714 // the parent frame. This is different from createChildFrame() which is
715 // called on the parent frame.
716 CHECK(!is_detaching_
);
717 // TODO(nasko): Remove all debug::Alias lines after diagnosing failures.
718 base::debug::Alias(frame
);
720 bool is_subframe
= !!frame
->parent();
721 base::debug::Alias(&is_subframe
);
723 int64 parent_frame_id
= -1;
724 base::debug::Alias(&parent_frame_id
);
726 parent_frame_id
= frame
->parent()->identifier();
728 Send(new FrameHostMsg_Detach(routing_id_
, parent_frame_id
,
729 frame
->identifier()));
731 // The |is_detaching_| flag disables Send(). FrameHostMsg_Detach must be
732 // sent before setting |is_detaching_| to true. In contrast, Observers
733 // should only be notified afterwards so they cannot call back into here and
734 // have IPCs fired off.
735 is_detaching_
= true;
737 // Call back to RenderViewImpl for observers to be notified.
738 // TODO(nasko): Remove once we have RenderFrameObserver.
739 render_view_
->frameDetached(frame
);
741 // We need to clean up subframes by removing them from the map and deleting
742 // the RenderFrameImpl. In contrast, the main frame is owned by its
743 // containing RenderViewHost (so that they have the same lifetime), so only
744 // removal from the map is needed and no deletion.
745 FrameMap::iterator it
= g_frame_map
.Get().find(frame
);
746 CHECK(it
!= g_frame_map
.Get().end());
747 CHECK_EQ(it
->second
, this);
748 g_frame_map
.Get().erase(it
);
750 // |frame| is invalid after here.
755 // Object is invalid after this point.
759 void RenderFrameImpl::willClose(blink::WebFrame
* frame
) {
760 // Call back to RenderViewImpl for observers to be notified.
761 // TODO(nasko): Remove once we have RenderFrameObserver.
762 render_view_
->willClose(frame
);
765 void RenderFrameImpl::didChangeName(blink::WebFrame
* frame
,
766 const blink::WebString
& name
) {
767 if (!render_view_
->renderer_preferences_
.report_frame_name_changes
)
771 new ViewHostMsg_UpdateFrameName(render_view_
->GetRoutingID(),
774 base::UTF16ToUTF8(name
)));
777 void RenderFrameImpl::didMatchCSS(
778 blink::WebFrame
* frame
,
779 const blink::WebVector
<blink::WebString
>& newly_matching_selectors
,
780 const blink::WebVector
<blink::WebString
>& stopped_matching_selectors
) {
781 render_view_
->didMatchCSS(
782 frame
, newly_matching_selectors
, stopped_matching_selectors
);
785 void RenderFrameImpl::loadURLExternally(blink::WebFrame
* frame
,
786 const blink::WebURLRequest
& request
,
787 blink::WebNavigationPolicy policy
) {
788 loadURLExternally(frame
, request
, policy
, WebString());
791 void RenderFrameImpl::loadURLExternally(
792 blink::WebFrame
* frame
,
793 const blink::WebURLRequest
& request
,
794 blink::WebNavigationPolicy policy
,
795 const blink::WebString
& suggested_name
) {
796 Referrer
referrer(RenderViewImpl::GetReferrerFromRequest(frame
, request
));
797 if (policy
== blink::WebNavigationPolicyDownload
) {
798 render_view_
->Send(new ViewHostMsg_DownloadUrl(render_view_
->GetRoutingID(),
799 request
.url(), referrer
,
802 render_view_
->OpenURL(frame
, request
.url(), referrer
, policy
);
806 blink::WebNavigationPolicy
RenderFrameImpl::decidePolicyForNavigation(
807 blink::WebFrame
* frame
,
808 blink::WebDataSource::ExtraData
* extra_data
,
809 const blink::WebURLRequest
& request
,
810 blink::WebNavigationType type
,
811 blink::WebNavigationPolicy default_policy
,
813 return render_view_
->DecidePolicyForNavigation(
814 this, frame
, extra_data
, request
, type
, default_policy
, is_redirect
);
817 blink::WebNavigationPolicy
RenderFrameImpl::decidePolicyForNavigation(
818 blink::WebFrame
* frame
,
819 const blink::WebURLRequest
& request
,
820 blink::WebNavigationType type
,
821 blink::WebNavigationPolicy default_policy
,
823 return decidePolicyForNavigation(frame
,
824 frame
->provisionalDataSource()->extraData(),
825 request
, type
, default_policy
, is_redirect
);
828 void RenderFrameImpl::willSendSubmitEvent(blink::WebFrame
* frame
,
829 const blink::WebFormElement
& form
) {
830 // Call back to RenderViewImpl for observers to be notified.
831 // TODO(nasko): Remove once we have RenderFrameObserver.
832 render_view_
->willSendSubmitEvent(frame
, form
);
835 void RenderFrameImpl::willSubmitForm(blink::WebFrame
* frame
,
836 const blink::WebFormElement
& form
) {
837 DocumentState
* document_state
=
838 DocumentState::FromDataSource(frame
->provisionalDataSource());
839 NavigationState
* navigation_state
= document_state
->navigation_state();
840 InternalDocumentStateData
* internal_data
=
841 InternalDocumentStateData::FromDocumentState(document_state
);
843 if (PageTransitionCoreTypeIs(navigation_state
->transition_type(),
844 PAGE_TRANSITION_LINK
)) {
845 navigation_state
->set_transition_type(PAGE_TRANSITION_FORM_SUBMIT
);
848 // Save these to be processed when the ensuing navigation is committed.
849 WebSearchableFormData
web_searchable_form_data(form
);
850 internal_data
->set_searchable_form_url(web_searchable_form_data
.url());
851 internal_data
->set_searchable_form_encoding(
852 web_searchable_form_data
.encoding().utf8());
854 // Call back to RenderViewImpl for observers to be notified.
855 // TODO(nasko): Remove once we have RenderFrameObserver.
856 render_view_
->willSubmitForm(frame
, form
);
859 void RenderFrameImpl::didCreateDataSource(blink::WebFrame
* frame
,
860 blink::WebDataSource
* datasource
) {
861 // TODO(nasko): Move implementation here. Needed state:
862 // * pending_navigation_params_
865 // * PopulateDocumentStateFromPending
866 // * CreateNavigationStateFromPending
867 render_view_
->didCreateDataSource(frame
, datasource
);
870 void RenderFrameImpl::didStartProvisionalLoad(blink::WebFrame
* frame
) {
871 WebDataSource
* ds
= frame
->provisionalDataSource();
873 // In fast/loader/stop-provisional-loads.html, we abort the load before this
874 // callback is invoked.
878 DocumentState
* document_state
= DocumentState::FromDataSource(ds
);
880 // We should only navigate to swappedout:// when is_swapped_out_ is true.
881 CHECK((ds
->request().url() != GURL(kSwappedOutURL
)) ||
883 render_view_
->is_swapped_out()) <<
884 "Heard swappedout:// when not swapped out.";
886 // Update the request time if WebKit has better knowledge of it.
887 if (document_state
->request_time().is_null()) {
888 double event_time
= ds
->triggeringEventTime();
889 if (event_time
!= 0.0)
890 document_state
->set_request_time(Time::FromDoubleT(event_time
));
893 // Start time is only set after request time.
894 document_state
->set_start_load_time(Time::Now());
896 bool is_top_most
= !frame
->parent();
898 render_view_
->set_navigation_gesture(
899 WebUserGestureIndicator::isProcessingUserGesture() ?
900 NavigationGestureUser
: NavigationGestureAuto
);
901 } else if (ds
->replacesCurrentHistoryItem()) {
902 // Subframe navigations that don't add session history items must be
903 // marked with AUTO_SUBFRAME. See also didFailProvisionalLoad for how we
904 // handle loading of error pages.
905 document_state
->navigation_state()->set_transition_type(
906 PAGE_TRANSITION_AUTO_SUBFRAME
);
910 RenderViewObserver
, render_view_
->observers(),
911 DidStartProvisionalLoad(frame
));
913 Send(new FrameHostMsg_DidStartProvisionalLoadForFrame(
914 routing_id_
, frame
->identifier(),
915 frame
->parent() ? frame
->parent()->identifier() : -1,
916 is_top_most
, ds
->request().url()));
919 void RenderFrameImpl::didReceiveServerRedirectForProvisionalLoad(
920 blink::WebFrame
* frame
) {
921 // TODO(nasko): Move implementation here. Needed state:
923 render_view_
->didReceiveServerRedirectForProvisionalLoad(frame
);
926 void RenderFrameImpl::didFailProvisionalLoad(
927 blink::WebFrame
* frame
,
928 const blink::WebURLError
& error
) {
929 WebDataSource
* ds
= frame
->provisionalDataSource();
932 const WebURLRequest
& failed_request
= ds
->request();
934 // Call out to RenderViewImpl, so observers are notified.
935 render_view_
->didFailProvisionalLoad(frame
, error
);
937 bool show_repost_interstitial
=
938 (error
.reason
== net::ERR_CACHE_MISS
&&
939 EqualsASCII(failed_request
.httpMethod(), "POST"));
941 FrameHostMsg_DidFailProvisionalLoadWithError_Params params
;
942 params
.frame_id
= frame
->identifier();
943 params
.frame_unique_name
= frame
->uniqueName();
944 params
.is_main_frame
= !frame
->parent();
945 params
.error_code
= error
.reason
;
946 GetContentClient()->renderer()->GetNavigationErrorStrings(
950 render_view_
->renderer_preferences_
.accept_languages
,
952 ¶ms
.error_description
);
953 params
.url
= error
.unreachableURL
;
954 params
.showing_repost_interstitial
= show_repost_interstitial
;
955 Send(new FrameHostMsg_DidFailProvisionalLoadWithError(
956 routing_id_
, params
));
958 // Don't display an error page if this is simply a cancelled load. Aside
959 // from being dumb, WebCore doesn't expect it and it will cause a crash.
960 if (error
.reason
== net::ERR_ABORTED
)
963 // Don't display "client blocked" error page if browser has asked us not to.
964 if (error
.reason
== net::ERR_BLOCKED_BY_CLIENT
&&
965 render_view_
->renderer_preferences_
.disable_client_blocked_error_page
) {
969 // Allow the embedder to suppress an error page.
970 if (GetContentClient()->renderer()->ShouldSuppressErrorPage(
971 error
.unreachableURL
)) {
975 if (RenderThreadImpl::current() &&
976 RenderThreadImpl::current()->layout_test_mode()) {
980 // Make sure we never show errors in view source mode.
981 frame
->enableViewSourceMode(false);
983 DocumentState
* document_state
= DocumentState::FromDataSource(ds
);
984 NavigationState
* navigation_state
= document_state
->navigation_state();
986 // If this is a failed back/forward/reload navigation, then we need to do a
987 // 'replace' load. This is necessary to avoid messing up session history.
988 // Otherwise, we do a normal load, which simulates a 'go' navigation as far
989 // as session history is concerned.
991 // AUTO_SUBFRAME loads should always be treated as loads that do not advance
994 // TODO(davidben): This should also take the failed navigation's replacement
995 // state into account, if a location.replace() failed.
997 navigation_state
->pending_page_id() != -1 ||
998 PageTransitionCoreTypeIs(navigation_state
->transition_type(),
999 PAGE_TRANSITION_AUTO_SUBFRAME
);
1001 // If we failed on a browser initiated request, then make sure that our error
1002 // page load is regarded as the same browser initiated request.
1003 if (!navigation_state
->is_content_initiated()) {
1004 render_view_
->pending_navigation_params_
.reset(new ViewMsg_Navigate_Params
);
1005 render_view_
->pending_navigation_params_
->page_id
=
1006 navigation_state
->pending_page_id();
1007 render_view_
->pending_navigation_params_
->pending_history_list_offset
=
1008 navigation_state
->pending_history_list_offset();
1009 render_view_
->pending_navigation_params_
->should_clear_history_list
=
1010 navigation_state
->history_list_was_cleared();
1011 render_view_
->pending_navigation_params_
->transition
=
1012 navigation_state
->transition_type();
1013 render_view_
->pending_navigation_params_
->request_time
=
1014 document_state
->request_time();
1015 render_view_
->pending_navigation_params_
->should_replace_current_entry
=
1019 // Provide the user with a more helpful error page?
1020 if (render_view_
->MaybeLoadAlternateErrorPage(frame
, error
, replace
))
1023 // Fallback to a local error page.
1024 render_view_
->LoadNavigationErrorPage(
1025 frame
, failed_request
, error
, std::string(), replace
);
1028 void RenderFrameImpl::didCommitProvisionalLoad(blink::WebFrame
* frame
,
1029 bool is_new_navigation
) {
1030 // TODO(nasko): Move implementation here. Needed state:
1033 // * history_list_offset_
1034 // * history_list_length_
1035 // * history_page_ids_
1038 // * UpdateSessionHistory
1040 render_view_
->didCommitProvisionalLoad(frame
, is_new_navigation
);
1042 FOR_EACH_OBSERVER(RenderFrameObserver
, observers_
,
1043 DidCommitProvisionalLoad(frame
, is_new_navigation
));
1046 void RenderFrameImpl::didClearWindowObject(blink::WebFrame
* frame
) {
1047 // TODO(nasko): Move implementation here. Needed state:
1048 // * enabled_bindings_
1049 // * dom_automation_controller_
1050 // * stats_collection_controller_
1051 render_view_
->didClearWindowObject(frame
);
1054 void RenderFrameImpl::didCreateDocumentElement(blink::WebFrame
* frame
) {
1055 // Notify the browser about non-blank documents loading in the top frame.
1056 GURL url
= frame
->document().url();
1057 if (url
.is_valid() && url
.spec() != kAboutBlankURL
) {
1058 // TODO(nasko): Check if webview()->mainFrame() is the same as the
1059 // frame->tree()->top().
1060 if (frame
== render_view_
->webview()->mainFrame()) {
1061 render_view_
->Send(new ViewHostMsg_DocumentAvailableInMainFrame(
1062 render_view_
->GetRoutingID()));
1066 // Call back to RenderViewImpl for observers to be notified.
1067 // TODO(nasko): Remove once we have RenderFrameObserver.
1068 render_view_
->didCreateDocumentElement(frame
);
1071 void RenderFrameImpl::didReceiveTitle(blink::WebFrame
* frame
,
1072 const blink::WebString
& title
,
1073 blink::WebTextDirection direction
) {
1074 // TODO(nasko): Investigate wheather implementation should move here.
1075 render_view_
->didReceiveTitle(frame
, title
, direction
);
1078 void RenderFrameImpl::didChangeIcon(blink::WebFrame
* frame
,
1079 blink::WebIconURL::Type icon_type
) {
1080 // TODO(nasko): Investigate wheather implementation should move here.
1081 render_view_
->didChangeIcon(frame
, icon_type
);
1084 void RenderFrameImpl::didFinishDocumentLoad(blink::WebFrame
* frame
) {
1085 // TODO(nasko): Move implementation here. No state needed, just observers
1086 // notification in before updating encoding.
1087 render_view_
->didFinishDocumentLoad(frame
);
1090 void RenderFrameImpl::didHandleOnloadEvents(blink::WebFrame
* frame
) {
1091 // TODO(nasko): Move implementation here. Needed state:
1093 render_view_
->didHandleOnloadEvents(frame
);
1096 void RenderFrameImpl::didFailLoad(blink::WebFrame
* frame
,
1097 const blink::WebURLError
& error
) {
1098 // TODO(nasko): Move implementation here. No state needed.
1099 render_view_
->didFailLoad(frame
, error
);
1102 void RenderFrameImpl::didFinishLoad(blink::WebFrame
* frame
) {
1103 // TODO(nasko): Move implementation here. No state needed, just observers
1104 // notification before sending message to the browser process.
1105 render_view_
->didFinishLoad(frame
);
1108 void RenderFrameImpl::didNavigateWithinPage(blink::WebFrame
* frame
,
1109 bool is_new_navigation
) {
1110 // TODO(nasko): Move implementation here. No state needed, just observers
1111 // notification before sending message to the browser process.
1112 render_view_
->didNavigateWithinPage(frame
, is_new_navigation
);
1115 void RenderFrameImpl::didUpdateCurrentHistoryItem(blink::WebFrame
* frame
) {
1116 // TODO(nasko): Move implementation here. Needed methods:
1117 // * StartNavStateSyncTimerIfNecessary
1118 render_view_
->didUpdateCurrentHistoryItem(frame
);
1121 void RenderFrameImpl::willRequestAfterPreconnect(
1122 blink::WebFrame
* frame
,
1123 blink::WebURLRequest
& request
) {
1124 blink::WebReferrerPolicy referrer_policy
= frame
->document().referrerPolicy();
1125 // FIXME(kohei): This will never be set.
1126 WebString custom_user_agent
;
1128 DCHECK(!request
.extraData());
1130 bool was_after_preconnect_request
= true;
1131 // The args after |was_after_preconnect_request| are not used, and set to
1132 // correct values at |willSendRequest|.
1133 request
.setExtraData(new webkit_glue::WebURLRequestExtraDataImpl(
1134 referrer_policy
, custom_user_agent
, was_after_preconnect_request
));
1137 void RenderFrameImpl::willSendRequest(
1138 blink::WebFrame
* frame
,
1139 unsigned identifier
,
1140 blink::WebURLRequest
& request
,
1141 const blink::WebURLResponse
& redirect_response
) {
1142 // The request my be empty during tests.
1143 if (request
.url().isEmpty())
1146 WebFrame
* top_frame
= frame
->top();
1149 WebDataSource
* provisional_data_source
= top_frame
->provisionalDataSource();
1150 WebDataSource
* top_data_source
= top_frame
->dataSource();
1151 WebDataSource
* data_source
=
1152 provisional_data_source
? provisional_data_source
: top_data_source
;
1154 PageTransition transition_type
= PAGE_TRANSITION_LINK
;
1155 DocumentState
* document_state
= DocumentState::FromDataSource(data_source
);
1156 DCHECK(document_state
);
1157 InternalDocumentStateData
* internal_data
=
1158 InternalDocumentStateData::FromDocumentState(document_state
);
1159 NavigationState
* navigation_state
= document_state
->navigation_state();
1160 transition_type
= navigation_state
->transition_type();
1162 GURL
request_url(request
.url());
1164 if (GetContentClient()->renderer()->WillSendRequest(
1168 request
.firstPartyForCookies(),
1170 request
.setURL(WebURL(new_url
));
1173 if (internal_data
->is_cache_policy_override_set())
1174 request
.setCachePolicy(internal_data
->cache_policy_override());
1176 blink::WebReferrerPolicy referrer_policy
;
1177 if (internal_data
->is_referrer_policy_set()) {
1178 referrer_policy
= internal_data
->referrer_policy();
1180 referrer_policy
= frame
->document().referrerPolicy();
1183 // The request's extra data may indicate that we should set a custom user
1184 // agent. This needs to be done here, after WebKit is through with setting the
1185 // user agent on its own.
1186 WebString custom_user_agent
;
1187 bool was_after_preconnect_request
= false;
1188 if (request
.extraData()) {
1189 webkit_glue::WebURLRequestExtraDataImpl
* old_extra_data
=
1190 static_cast<webkit_glue::WebURLRequestExtraDataImpl
*>(
1191 request
.extraData());
1192 custom_user_agent
= old_extra_data
->custom_user_agent();
1193 was_after_preconnect_request
=
1194 old_extra_data
->was_after_preconnect_request();
1196 if (!custom_user_agent
.isNull()) {
1197 if (custom_user_agent
.isEmpty())
1198 request
.clearHTTPHeaderField("User-Agent");
1200 request
.setHTTPHeaderField("User-Agent", custom_user_agent
);
1204 // Attach |should_replace_current_entry| state to requests so that, should
1205 // this navigation later require a request transfer, all state is preserved
1206 // when it is re-created in the new process.
1207 bool should_replace_current_entry
= false;
1208 if (navigation_state
->is_content_initiated()) {
1209 should_replace_current_entry
= data_source
->replacesCurrentHistoryItem();
1211 // If the navigation is browser-initiated, the NavigationState contains the
1212 // correct value instead of the WebDataSource.
1214 // TODO(davidben): Avoid this awkward duplication of state. See comment on
1215 // NavigationState::should_replace_current_entry().
1216 should_replace_current_entry
=
1217 navigation_state
->should_replace_current_entry();
1219 request
.setExtraData(
1220 new RequestExtraData(referrer_policy
,
1222 was_after_preconnect_request
,
1224 (frame
== top_frame
),
1225 frame
->identifier(),
1226 GURL(frame
->document().securityOrigin().toString()),
1227 frame
->parent() == top_frame
,
1228 frame
->parent() ? frame
->parent()->identifier() : -1,
1229 navigation_state
->allow_download(),
1231 should_replace_current_entry
,
1232 navigation_state
->transferred_request_child_id(),
1233 navigation_state
->transferred_request_request_id()));
1235 DocumentState
* top_document_state
=
1236 DocumentState::FromDataSource(top_data_source
);
1237 if (top_document_state
) {
1238 // TODO(gavinp): separate out prefetching and prerender field trials
1239 // if the rel=prerender rel type is sticking around.
1240 if (request
.targetType() == WebURLRequest::TargetIsPrefetch
)
1241 top_document_state
->set_was_prefetcher(true);
1243 if (was_after_preconnect_request
)
1244 top_document_state
->set_was_after_preconnect_request(true);
1247 // This is an instance where we embed a copy of the routing id
1248 // into the data portion of the message. This can cause problems if we
1249 // don't register this id on the browser side, since the download manager
1250 // expects to find a RenderViewHost based off the id.
1251 request
.setRequestorID(render_view_
->GetRoutingID());
1252 request
.setHasUserGesture(WebUserGestureIndicator::isProcessingUserGesture());
1254 if (!navigation_state
->extra_headers().empty()) {
1255 for (net::HttpUtil::HeadersIterator
i(
1256 navigation_state
->extra_headers().begin(),
1257 navigation_state
->extra_headers().end(), "\n");
1259 request
.setHTTPHeaderField(WebString::fromUTF8(i
.name()),
1260 WebString::fromUTF8(i
.values()));
1264 if (!render_view_
->renderer_preferences_
.enable_referrers
)
1265 request
.clearHTTPHeaderField("Referer");
1268 void RenderFrameImpl::didReceiveResponse(
1269 blink::WebFrame
* frame
,
1270 unsigned identifier
,
1271 const blink::WebURLResponse
& response
) {
1272 // Only do this for responses that correspond to a provisional data source
1273 // of the top-most frame. If we have a provisional data source, then we
1274 // can't have any sub-resources yet, so we know that this response must
1275 // correspond to a frame load.
1276 if (!frame
->provisionalDataSource() || frame
->parent())
1279 // If we are in view source mode, then just let the user see the source of
1280 // the server's error page.
1281 if (frame
->isViewSourceModeEnabled())
1284 DocumentState
* document_state
=
1285 DocumentState::FromDataSource(frame
->provisionalDataSource());
1286 int http_status_code
= response
.httpStatusCode();
1288 // Record page load flags.
1289 WebURLResponseExtraDataImpl
* extra_data
=
1290 RenderViewImpl::GetExtraDataFromResponse(response
);
1292 document_state
->set_was_fetched_via_spdy(
1293 extra_data
->was_fetched_via_spdy());
1294 document_state
->set_was_npn_negotiated(
1295 extra_data
->was_npn_negotiated());
1296 document_state
->set_npn_negotiated_protocol(
1297 extra_data
->npn_negotiated_protocol());
1298 document_state
->set_was_alternate_protocol_available(
1299 extra_data
->was_alternate_protocol_available());
1300 document_state
->set_connection_info(
1301 extra_data
->connection_info());
1302 document_state
->set_was_fetched_via_proxy(
1303 extra_data
->was_fetched_via_proxy());
1305 InternalDocumentStateData
* internal_data
=
1306 InternalDocumentStateData::FromDocumentState(document_state
);
1307 internal_data
->set_http_status_code(http_status_code
);
1308 // Whether or not the http status code actually corresponds to an error is
1309 // only checked when the page is done loading, if |use_error_page| is
1311 internal_data
->set_use_error_page(true);
1314 void RenderFrameImpl::didFinishResourceLoad(blink::WebFrame
* frame
,
1315 unsigned identifier
) {
1316 // TODO(nasko): Move implementation here. Needed state:
1317 // * devtools_agent_
1319 // * LoadNavigationErrorPage
1320 render_view_
->didFinishResourceLoad(frame
, identifier
);
1323 void RenderFrameImpl::didLoadResourceFromMemoryCache(
1324 blink::WebFrame
* frame
,
1325 const blink::WebURLRequest
& request
,
1326 const blink::WebURLResponse
& response
) {
1327 // The recipients of this message have no use for data: URLs: they don't
1328 // affect the page's insecure content list and are not in the disk cache. To
1329 // prevent large (1M+) data: URLs from crashing in the IPC system, we simply
1330 // filter them out here.
1331 GURL
url(request
.url());
1332 if (url
.SchemeIs("data"))
1335 // Let the browser know we loaded a resource from the memory cache. This
1336 // message is needed to display the correct SSL indicators.
1337 render_view_
->Send(new ViewHostMsg_DidLoadResourceFromMemoryCache(
1338 render_view_
->GetRoutingID(),
1340 response
.securityInfo(),
1341 request
.httpMethod().utf8(),
1342 response
.mimeType().utf8(),
1343 ResourceType::FromTargetType(request
.targetType())));
1346 void RenderFrameImpl::didDisplayInsecureContent(blink::WebFrame
* frame
) {
1347 render_view_
->Send(new ViewHostMsg_DidDisplayInsecureContent(
1348 render_view_
->GetRoutingID()));
1351 void RenderFrameImpl::didRunInsecureContent(
1352 blink::WebFrame
* frame
,
1353 const blink::WebSecurityOrigin
& origin
,
1354 const blink::WebURL
& target
) {
1355 render_view_
->Send(new ViewHostMsg_DidRunInsecureContent(
1356 render_view_
->GetRoutingID(),
1357 origin
.toString().utf8(),
1361 void RenderFrameImpl::didAbortLoading(blink::WebFrame
* frame
) {
1362 #if defined(ENABLE_PLUGINS)
1363 if (frame
!= render_view_
->webview()->mainFrame())
1365 PluginChannelHost::Broadcast(
1366 new PluginHostMsg_DidAbortLoading(render_view_
->GetRoutingID()));
1370 void RenderFrameImpl::didExhaustMemoryAvailableForScript(
1371 blink::WebFrame
* frame
) {
1372 render_view_
->Send(new ViewHostMsg_JSOutOfMemory(
1373 render_view_
->GetRoutingID()));
1376 void RenderFrameImpl::didCreateScriptContext(blink::WebFrame
* frame
,
1377 v8::Handle
<v8::Context
> context
,
1378 int extension_group
,
1380 GetContentClient()->renderer()->DidCreateScriptContext(
1381 frame
, context
, extension_group
, world_id
);
1384 void RenderFrameImpl::willReleaseScriptContext(blink::WebFrame
* frame
,
1385 v8::Handle
<v8::Context
> context
,
1387 GetContentClient()->renderer()->WillReleaseScriptContext(
1388 frame
, context
, world_id
);
1391 void RenderFrameImpl::didFirstVisuallyNonEmptyLayout(blink::WebFrame
* frame
) {
1392 render_view_
->didFirstVisuallyNonEmptyLayout(frame
);
1395 void RenderFrameImpl::didChangeContentsSize(blink::WebFrame
* frame
,
1396 const blink::WebSize
& size
) {
1397 // TODO(nasko): Move implementation here. Needed state:
1398 // * cached_has_main_frame_horizontal_scrollbar_
1399 // * cached_has_main_frame_vertical_scrollbar_
1400 render_view_
->didChangeContentsSize(frame
, size
);
1403 void RenderFrameImpl::didChangeScrollOffset(blink::WebFrame
* frame
) {
1404 // TODO(nasko): Move implementation here. Needed methods:
1405 // * StartNavStateSyncTimerIfNecessary
1406 render_view_
->didChangeScrollOffset(frame
);
1409 void RenderFrameImpl::willInsertBody(blink::WebFrame
* frame
) {
1410 if (!frame
->parent()) {
1411 render_view_
->Send(new ViewHostMsg_WillInsertBody(
1412 render_view_
->GetRoutingID()));
1416 void RenderFrameImpl::reportFindInPageMatchCount(int request_id
,
1418 bool final_update
) {
1419 int active_match_ordinal
= -1; // -1 = don't update active match ordinal
1421 active_match_ordinal
= 0;
1423 render_view_
->Send(new ViewHostMsg_Find_Reply(
1424 render_view_
->GetRoutingID(), request_id
, count
,
1425 gfx::Rect(), active_match_ordinal
, final_update
));
1428 void RenderFrameImpl::reportFindInPageSelection(
1430 int active_match_ordinal
,
1431 const blink::WebRect
& selection_rect
) {
1432 render_view_
->Send(new ViewHostMsg_Find_Reply(
1433 render_view_
->GetRoutingID(), request_id
, -1, selection_rect
,
1434 active_match_ordinal
, false));
1437 void RenderFrameImpl::requestStorageQuota(
1438 blink::WebFrame
* frame
,
1439 blink::WebStorageQuotaType type
,
1440 unsigned long long requested_size
,
1441 blink::WebStorageQuotaCallbacks
* callbacks
) {
1443 WebSecurityOrigin origin
= frame
->document().securityOrigin();
1444 if (origin
.isUnique()) {
1445 // Unique origins cannot store persistent state.
1446 callbacks
->didFail(blink::WebStorageQuotaErrorAbort
);
1449 ChildThread::current()->quota_dispatcher()->RequestStorageQuota(
1450 render_view_
->GetRoutingID(), GURL(origin
.toString()),
1451 static_cast<quota::StorageType
>(type
), requested_size
,
1452 QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(callbacks
));
1455 void RenderFrameImpl::willOpenSocketStream(
1456 blink::WebSocketStreamHandle
* handle
) {
1457 SocketStreamHandleData::AddToHandle(handle
, routing_id_
);
1460 void RenderFrameImpl::willStartUsingPeerConnectionHandler(
1461 blink::WebFrame
* frame
,
1462 blink::WebRTCPeerConnectionHandler
* handler
) {
1463 #if defined(ENABLE_WEBRTC)
1464 static_cast<RTCPeerConnectionHandler
*>(handler
)->associateWithFrame(frame
);
1468 bool RenderFrameImpl::willCheckAndDispatchMessageEvent(
1469 blink::WebFrame
* sourceFrame
,
1470 blink::WebFrame
* targetFrame
,
1471 blink::WebSecurityOrigin targetOrigin
,
1472 blink::WebDOMMessageEvent event
) {
1473 // TODO(nasko): Move implementation here. Needed state:
1474 // * is_swapped_out_
1475 return render_view_
->willCheckAndDispatchMessageEvent(
1476 sourceFrame
, targetFrame
, targetOrigin
, event
);
1479 blink::WebString
RenderFrameImpl::userAgentOverride(
1480 blink::WebFrame
* frame
,
1481 const blink::WebURL
& url
) {
1482 if (!render_view_
->webview() || !render_view_
->webview()->mainFrame() ||
1483 render_view_
->renderer_preferences_
.user_agent_override
.empty()) {
1484 return blink::WebString();
1487 // If we're in the middle of committing a load, the data source we need
1488 // will still be provisional.
1489 WebFrame
* main_frame
= render_view_
->webview()->mainFrame();
1490 WebDataSource
* data_source
= NULL
;
1491 if (main_frame
->provisionalDataSource())
1492 data_source
= main_frame
->provisionalDataSource();
1494 data_source
= main_frame
->dataSource();
1496 InternalDocumentStateData
* internal_data
= data_source
?
1497 InternalDocumentStateData::FromDataSource(data_source
) : NULL
;
1498 if (internal_data
&& internal_data
->is_overriding_user_agent())
1499 return WebString::fromUTF8(
1500 render_view_
->renderer_preferences_
.user_agent_override
);
1501 return blink::WebString();
1504 blink::WebString
RenderFrameImpl::doNotTrackValue(blink::WebFrame
* frame
) {
1505 if (render_view_
->renderer_preferences_
.enable_do_not_track
)
1506 return WebString::fromUTF8("1");
1510 bool RenderFrameImpl::allowWebGL(blink::WebFrame
* frame
, bool default_value
) {
1514 bool blocked
= true;
1515 render_view_
->Send(new ViewHostMsg_Are3DAPIsBlocked(
1516 render_view_
->GetRoutingID(),
1517 GURL(frame
->top()->document().securityOrigin().toString()),
1518 THREE_D_API_TYPE_WEBGL
,
1523 void RenderFrameImpl::didLoseWebGLContext(blink::WebFrame
* frame
,
1524 int arb_robustness_status_code
) {
1525 render_view_
->Send(new ViewHostMsg_DidLose3DContext(
1526 GURL(frame
->top()->document().securityOrigin().toString()),
1527 THREE_D_API_TYPE_WEBGL
,
1528 arb_robustness_status_code
));
1531 void RenderFrameImpl::AddObserver(RenderFrameObserver
* observer
) {
1532 observers_
.AddObserver(observer
);
1535 void RenderFrameImpl::RemoveObserver(RenderFrameObserver
* observer
) {
1536 observer
->RenderFrameGone();
1537 observers_
.RemoveObserver(observer
);
1540 } // namespace content