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/auto_reset.h"
11 #include "base/command_line.h"
12 #include "base/debug/alias.h"
13 #include "base/debug/dump_without_crashing.h"
14 #include "base/i18n/char_iterator.h"
15 #include "base/metrics/histogram.h"
16 #include "base/process/kill.h"
17 #include "base/process/process.h"
18 #include "base/strings/string16.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "base/time/time.h"
21 #include "content/child/appcache/appcache_dispatcher.h"
22 #include "content/child/plugin_messages.h"
23 #include "content/child/quota_dispatcher.h"
24 #include "content/child/request_extra_data.h"
25 #include "content/child/service_worker/service_worker_network_provider.h"
26 #include "content/child/service_worker/web_service_worker_provider_impl.h"
27 #include "content/child/web_socket_stream_handle_impl.h"
28 #include "content/child/webmessageportchannel_impl.h"
29 #include "content/child/websocket_bridge.h"
30 #include "content/common/clipboard_messages.h"
31 #include "content/common/frame_messages.h"
32 #include "content/common/input_messages.h"
33 #include "content/common/service_worker/service_worker_types.h"
34 #include "content/common/socket_stream_handle_data.h"
35 #include "content/common/swapped_out_messages.h"
36 #include "content/common/view_messages.h"
37 #include "content/public/common/bindings_policy.h"
38 #include "content/public/common/content_constants.h"
39 #include "content/public/common/content_switches.h"
40 #include "content/public/common/context_menu_params.h"
41 #include "content/public/common/url_constants.h"
42 #include "content/public/common/url_utils.h"
43 #include "content/public/renderer/content_renderer_client.h"
44 #include "content/public/renderer/context_menu_client.h"
45 #include "content/public/renderer/document_state.h"
46 #include "content/public/renderer/navigation_state.h"
47 #include "content/public/renderer/render_frame_observer.h"
48 #include "content/renderer/accessibility/renderer_accessibility.h"
49 #include "content/renderer/browser_plugin/browser_plugin.h"
50 #include "content/renderer/browser_plugin/browser_plugin_manager.h"
51 #include "content/renderer/child_frame_compositing_helper.h"
52 #include "content/renderer/context_menu_params_builder.h"
53 #include "content/renderer/devtools/devtools_agent.h"
54 #include "content/renderer/dom_automation_controller.h"
55 #include "content/renderer/geolocation_dispatcher.h"
56 #include "content/renderer/history_controller.h"
57 #include "content/renderer/history_serialization.h"
58 #include "content/renderer/image_loading_helper.h"
59 #include "content/renderer/ime_event_guard.h"
60 #include "content/renderer/internal_document_state_data.h"
61 #include "content/renderer/java/java_bridge_dispatcher.h"
62 #include "content/renderer/media/audio_renderer_mixer_manager.h"
63 #include "content/renderer/media/media_stream_dispatcher.h"
64 #include "content/renderer/media/media_stream_impl.h"
65 #include "content/renderer/media/media_stream_renderer_factory.h"
66 #include "content/renderer/media/render_media_log.h"
67 #include "content/renderer/media/webcontentdecryptionmodule_impl.h"
68 #include "content/renderer/media/webmediaplayer_impl.h"
69 #include "content/renderer/media/webmediaplayer_ms.h"
70 #include "content/renderer/media/webmediaplayer_params.h"
71 #include "content/renderer/notification_provider.h"
72 #include "content/renderer/npapi/plugin_channel_host.h"
73 #include "content/renderer/render_process.h"
74 #include "content/renderer/render_thread_impl.h"
75 #include "content/renderer/render_view_impl.h"
76 #include "content/renderer/render_widget_fullscreen_pepper.h"
77 #include "content/renderer/renderer_webapplicationcachehost_impl.h"
78 #include "content/renderer/renderer_webcolorchooser_impl.h"
79 #include "content/renderer/shared_worker_repository.h"
80 #include "content/renderer/v8_value_converter_impl.h"
81 #include "content/renderer/websharedworker_proxy.h"
82 #include "media/base/audio_renderer_mixer_input.h"
83 #include "net/base/data_url.h"
84 #include "net/base/net_errors.h"
85 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
86 #include "net/http/http_util.h"
87 #include "third_party/WebKit/public/platform/WebStorageQuotaCallbacks.h"
88 #include "third_party/WebKit/public/platform/WebString.h"
89 #include "third_party/WebKit/public/platform/WebURL.h"
90 #include "third_party/WebKit/public/platform/WebURLError.h"
91 #include "third_party/WebKit/public/platform/WebURLResponse.h"
92 #include "third_party/WebKit/public/platform/WebVector.h"
93 #include "third_party/WebKit/public/web/WebColorSuggestion.h"
94 #include "third_party/WebKit/public/web/WebDocument.h"
95 #include "third_party/WebKit/public/web/WebGlyphCache.h"
96 #include "third_party/WebKit/public/web/WebLocalFrame.h"
97 #include "third_party/WebKit/public/web/WebMediaStreamRegistry.h"
98 #include "third_party/WebKit/public/web/WebNavigationPolicy.h"
99 #include "third_party/WebKit/public/web/WebPlugin.h"
100 #include "third_party/WebKit/public/web/WebPluginParams.h"
101 #include "third_party/WebKit/public/web/WebRange.h"
102 #include "third_party/WebKit/public/web/WebScriptSource.h"
103 #include "third_party/WebKit/public/web/WebSearchableFormData.h"
104 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
105 #include "third_party/WebKit/public/web/WebSecurityPolicy.h"
106 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
107 #include "third_party/WebKit/public/web/WebView.h"
108 #include "webkit/child/weburlresponse_extradata_impl.h"
110 #if defined(ENABLE_PLUGINS)
111 #include "content/renderer/npapi/webplugin_impl.h"
112 #include "content/renderer/pepper/pepper_browser_connection.h"
113 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
114 #include "content/renderer/pepper/pepper_webplugin_impl.h"
115 #include "content/renderer/pepper/plugin_module.h"
118 #if defined(ENABLE_WEBRTC)
119 #include "content/renderer/media/rtc_peer_connection_handler.h"
122 #if defined(OS_ANDROID)
123 #include <cpu-features.h>
125 #include "content/common/gpu/client/context_provider_command_buffer.h"
126 #include "content/renderer/android/synchronous_compositor_factory.h"
127 #include "content/renderer/media/android/renderer_media_player_manager.h"
128 #include "content/renderer/media/android/stream_texture_factory_impl.h"
129 #include "content/renderer/media/android/webmediaplayer_android.h"
130 #include "content/renderer/media/crypto/renderer_cdm_manager.h"
133 using blink::WebContextMenuData
;
134 using blink::WebData
;
135 using blink::WebDataSource
;
136 using blink::WebDocument
;
137 using blink::WebElement
;
138 using blink::WebFrame
;
139 using blink::WebHistoryItem
;
140 using blink::WebHTTPBody
;
141 using blink::WebLocalFrame
;
142 using blink::WebMediaPlayer
;
143 using blink::WebMediaPlayerClient
;
144 using blink::WebNavigationPolicy
;
145 using blink::WebNavigationType
;
146 using blink::WebNode
;
147 using blink::WebPluginParams
;
148 using blink::WebRange
;
149 using blink::WebReferrerPolicy
;
150 using blink::WebScriptSource
;
151 using blink::WebSearchableFormData
;
152 using blink::WebSecurityOrigin
;
153 using blink::WebSecurityPolicy
;
154 using blink::WebServiceWorkerProvider
;
155 using blink::WebStorageQuotaCallbacks
;
156 using blink::WebString
;
158 using blink::WebURLError
;
159 using blink::WebURLRequest
;
160 using blink::WebURLResponse
;
161 using blink::WebUserGestureIndicator
;
162 using blink::WebVector
;
163 using blink::WebView
;
165 using base::TimeDelta
;
166 using webkit_glue::WebURLResponseExtraDataImpl
;
172 const char kDefaultAcceptHeader
[] =
173 "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/"
175 const char kAcceptHeader
[] = "Accept";
177 const size_t kExtraCharsBeforeAndAfterSelection
= 100;
179 typedef std::map
<int, RenderFrameImpl
*> RoutingIDFrameMap
;
180 static base::LazyInstance
<RoutingIDFrameMap
> g_routing_id_frame_map
=
181 LAZY_INSTANCE_INITIALIZER
;
183 typedef std::map
<blink::WebFrame
*, RenderFrameImpl
*> FrameMap
;
184 base::LazyInstance
<FrameMap
> g_frame_map
= LAZY_INSTANCE_INITIALIZER
;
186 int64
ExtractPostId(const WebHistoryItem
& item
) {
190 if (item
.httpBody().isNull())
193 return item
.httpBody().identifier();
196 WebURLResponseExtraDataImpl
* GetExtraDataFromResponse(
197 const WebURLResponse
& response
) {
198 return static_cast<WebURLResponseExtraDataImpl
*>(response
.extraData());
201 void GetRedirectChain(WebDataSource
* ds
, std::vector
<GURL
>* result
) {
202 // Replace any occurrences of swappedout:// with about:blank.
203 const WebURL
& blank_url
= GURL(url::kAboutBlankURL
);
204 WebVector
<WebURL
> urls
;
205 ds
->redirectChain(urls
);
206 result
->reserve(urls
.size());
207 for (size_t i
= 0; i
< urls
.size(); ++i
) {
208 if (urls
[i
] != GURL(kSwappedOutURL
))
209 result
->push_back(urls
[i
]);
211 result
->push_back(blank_url
);
215 // Returns the original request url. If there is no redirect, the original
216 // url is the same as ds->request()->url(). If the WebDataSource belongs to a
217 // frame was loaded by loadData, the original url will be ds->unreachableURL()
218 static GURL
GetOriginalRequestURL(WebDataSource
* ds
) {
219 // WebDataSource has unreachable URL means that the frame is loaded through
220 // blink::WebFrame::loadData(), and the base URL will be in the redirect
221 // chain. However, we never visited the baseURL. So in this case, we should
222 // use the unreachable URL as the original URL.
223 if (ds
->hasUnreachableURL())
224 return ds
->unreachableURL();
226 std::vector
<GURL
> redirects
;
227 GetRedirectChain(ds
, &redirects
);
228 if (!redirects
.empty())
229 return redirects
.at(0);
231 return ds
->originalRequest().url();
234 NOINLINE
static void CrashIntentionally() {
235 // NOTE(shess): Crash directly rather than using NOTREACHED() so
236 // that the signature is easier to triage in crash reports.
237 volatile int* zero
= NULL
;
241 #if defined(SYZYASAN)
242 NOINLINE
static void CorruptMemoryBlock() {
243 // NOTE(sebmarchand): We intentionally corrupt a memory block here in order to
244 // trigger an Address Sanitizer (ASAN) error report.
245 static const int kArraySize
= 5;
246 int* array
= new int[kArraySize
];
247 // Encapsulate the invalid memory access into a try-catch statement to prevent
248 // this function from being instrumented. This way the underflow won't be
249 // detected but the corruption will (as the allocator will still be hooked).
251 int dummy
= array
[-1]--;
252 // Make sure the assignments to the dummy value aren't optimized away.
253 base::debug::Alias(&array
);
254 } __except (EXCEPTION_EXECUTE_HANDLER
) {
260 #if defined(ADDRESS_SANITIZER) || defined(SYZYASAN)
261 NOINLINE
static void MaybeTriggerAsanError(const GURL
& url
) {
262 // NOTE(rogerm): We intentionally perform an invalid heap access here in
263 // order to trigger an Address Sanitizer (ASAN) error report.
264 static const char kCrashDomain
[] = "crash";
265 static const char kHeapOverflow
[] = "/heap-overflow";
266 static const char kHeapUnderflow
[] = "/heap-underflow";
267 static const char kUseAfterFree
[] = "/use-after-free";
268 #if defined(SYZYASAN)
269 static const char kCorruptHeapBlock
[] = "/corrupt-heap-block";
271 static const int kArraySize
= 5;
273 if (!url
.DomainIs(kCrashDomain
, sizeof(kCrashDomain
) - 1))
279 scoped_ptr
<int[]> array(new int[kArraySize
]);
280 std::string
crash_type(url
.path());
282 if (crash_type
== kHeapOverflow
) {
283 dummy
= array
[kArraySize
];
284 } else if (crash_type
== kHeapUnderflow
) {
286 } else if (crash_type
== kUseAfterFree
) {
287 int* dangling
= array
.get();
289 dummy
= dangling
[kArraySize
/ 2];
290 #if defined(SYZYASAN)
291 } else if (crash_type
== kCorruptHeapBlock
) {
292 CorruptMemoryBlock();
296 // Make sure the assignments to the dummy value aren't optimized away.
297 base::debug::Alias(&dummy
);
299 #endif // ADDRESS_SANITIZER || SYZYASAN
301 static void MaybeHandleDebugURL(const GURL
& url
) {
302 if (!url
.SchemeIs(kChromeUIScheme
))
304 if (url
== GURL(kChromeUICrashURL
)) {
305 CrashIntentionally();
306 } else if (url
== GURL(kChromeUIKillURL
)) {
307 base::KillProcess(base::GetCurrentProcessHandle(), 1, false);
308 } else if (url
== GURL(kChromeUIHangURL
)) {
310 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
312 } else if (url
== GURL(kChromeUIShorthangURL
)) {
313 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(20));
316 #if defined(ADDRESS_SANITIZER) || defined(SYZYASAN)
317 MaybeTriggerAsanError(url
);
318 #endif // ADDRESS_SANITIZER || SYZYASAN
321 // Returns false unless this is a top-level navigation.
322 static bool IsTopLevelNavigation(WebFrame
* frame
) {
323 return frame
->parent() == NULL
;
326 // Returns false unless this is a top-level navigation that crosses origins.
327 static bool IsNonLocalTopLevelNavigation(const GURL
& url
,
329 WebNavigationType type
,
331 if (!IsTopLevelNavigation(frame
))
334 // Navigations initiated within Webkit are not sent out to the external host
335 // in the following cases.
336 // 1. The url scheme is not http/https
337 // 2. The origin of the url and the opener is the same in which case the
338 // opener relationship is maintained.
339 // 3. Reloads/form submits/back forward navigations
340 if (!url
.SchemeIs(url::kHttpScheme
) && !url
.SchemeIs(url::kHttpsScheme
))
343 if (type
!= blink::WebNavigationTypeReload
&&
344 type
!= blink::WebNavigationTypeBackForward
&& !is_form_post
) {
345 // The opener relationship between the new window and the parent allows the
346 // new window to script the parent and vice versa. This is not allowed if
347 // the origins of the two domains are different. This can be treated as a
348 // top level navigation and routed back to the host.
349 blink::WebFrame
* opener
= frame
->opener();
353 if (url
.GetOrigin() != GURL(opener
->document().url()).GetOrigin())
361 static RenderFrameImpl
* (*g_create_render_frame_impl
)(RenderViewImpl
*, int32
) =
365 RenderFrameImpl
* RenderFrameImpl::Create(RenderViewImpl
* render_view
,
367 DCHECK(routing_id
!= MSG_ROUTING_NONE
);
369 if (g_create_render_frame_impl
)
370 return g_create_render_frame_impl(render_view
, routing_id
);
372 return new RenderFrameImpl(render_view
, routing_id
);
376 RenderFrameImpl
* RenderFrameImpl::FromRoutingID(int32 routing_id
) {
377 RoutingIDFrameMap::iterator iter
=
378 g_routing_id_frame_map
.Get().find(routing_id
);
379 if (iter
!= g_routing_id_frame_map
.Get().end())
385 RenderFrame
* RenderFrame::FromWebFrame(blink::WebFrame
* web_frame
) {
386 return RenderFrameImpl::FromWebFrame(web_frame
);
389 RenderFrameImpl
* RenderFrameImpl::FromWebFrame(blink::WebFrame
* web_frame
) {
390 FrameMap::iterator iter
= g_frame_map
.Get().find(web_frame
);
391 if (iter
!= g_frame_map
.Get().end())
397 void RenderFrameImpl::InstallCreateHook(
398 RenderFrameImpl
* (*create_render_frame_impl
)(RenderViewImpl
*, int32
)) {
399 CHECK(!g_create_render_frame_impl
);
400 g_create_render_frame_impl
= create_render_frame_impl
;
403 // RenderFrameImpl ----------------------------------------------------------
404 RenderFrameImpl::RenderFrameImpl(RenderViewImpl
* render_view
, int routing_id
)
406 render_view_(render_view
->AsWeakPtr()),
407 routing_id_(routing_id
),
408 is_swapped_out_(false),
409 render_frame_proxy_(NULL
),
410 is_detaching_(false),
412 selection_text_offset_(0),
413 selection_range_(gfx::Range::InvalidRange()),
414 handling_select_range_(false),
415 notification_provider_(NULL
),
416 web_user_media_client_(NULL
),
417 #if defined(OS_ANDROID)
418 media_player_manager_(NULL
),
421 geolocation_dispatcher_(NULL
),
422 weak_factory_(this) {
423 RenderThread::Get()->AddRoute(routing_id_
, this);
425 std::pair
<RoutingIDFrameMap::iterator
, bool> result
=
426 g_routing_id_frame_map
.Get().insert(std::make_pair(routing_id_
, this));
427 CHECK(result
.second
) << "Inserting a duplicate item.";
429 render_view_
->RegisterRenderFrame(this);
431 #if defined(OS_ANDROID)
432 new JavaBridgeDispatcher(this);
435 #if defined(ENABLE_NOTIFICATIONS)
436 notification_provider_
= new NotificationProvider(this);
440 RenderFrameImpl::~RenderFrameImpl() {
441 FOR_EACH_OBSERVER(RenderFrameObserver
, observers_
, RenderFrameGone());
442 FOR_EACH_OBSERVER(RenderFrameObserver
, observers_
, OnDestruct());
444 #if defined(VIDEO_HOLE)
445 if (media_player_manager_
)
446 render_view_
->UnregisterVideoHoleFrame(this);
447 #endif // defined(VIDEO_HOLE)
449 render_view_
->UnregisterRenderFrame(this);
450 g_routing_id_frame_map
.Get().erase(routing_id_
);
451 RenderThread::Get()->RemoveRoute(routing_id_
);
454 void RenderFrameImpl::SetWebFrame(blink::WebLocalFrame
* web_frame
) {
457 std::pair
<FrameMap::iterator
, bool> result
= g_frame_map
.Get().insert(
458 std::make_pair(web_frame
, this));
459 CHECK(result
.second
) << "Inserting a duplicate item.";
464 void RenderFrameImpl::Initialize() {
465 #if defined(ENABLE_PLUGINS)
466 new PepperBrowserConnection(this);
468 new SharedWorkerRepository(this);
470 if (!frame_
->parent())
471 new ImageLoadingHelper(this);
473 // We delay calling this until we have the WebFrame so that any observer or
474 // embedder can call GetWebFrame on any RenderFrame.
475 GetContentClient()->renderer()->RenderFrameCreated(this);
478 RenderWidget
* RenderFrameImpl::GetRenderWidget() {
479 return render_view_
.get();
482 #if defined(ENABLE_PLUGINS)
483 void RenderFrameImpl::PepperPluginCreated(RendererPpapiHost
* host
) {
484 FOR_EACH_OBSERVER(RenderFrameObserver
, observers_
,
485 DidCreatePepperPlugin(host
));
488 void RenderFrameImpl::PepperDidChangeCursor(
489 PepperPluginInstanceImpl
* instance
,
490 const blink::WebCursorInfo
& cursor
) {
491 // Update the cursor appearance immediately if the requesting plugin is the
492 // one which receives the last mouse event. Otherwise, the new cursor won't be
493 // picked up until the plugin gets the next input event. That is bad if, e.g.,
494 // the plugin would like to set an invisible cursor when there isn't any user
495 // input for a while.
496 if (instance
== render_view_
->pepper_last_mouse_event_target())
497 GetRenderWidget()->didChangeCursor(cursor
);
500 void RenderFrameImpl::PepperDidReceiveMouseEvent(
501 PepperPluginInstanceImpl
* instance
) {
502 render_view_
->set_pepper_last_mouse_event_target(instance
);
505 void RenderFrameImpl::PepperTextInputTypeChanged(
506 PepperPluginInstanceImpl
* instance
) {
507 if (instance
!= render_view_
->focused_pepper_plugin())
510 GetRenderWidget()->UpdateTextInputType();
511 if (render_view_
->renderer_accessibility())
512 render_view_
->renderer_accessibility()->FocusedNodeChanged(WebNode());
515 void RenderFrameImpl::PepperCaretPositionChanged(
516 PepperPluginInstanceImpl
* instance
) {
517 if (instance
!= render_view_
->focused_pepper_plugin())
519 GetRenderWidget()->UpdateSelectionBounds();
522 void RenderFrameImpl::PepperCancelComposition(
523 PepperPluginInstanceImpl
* instance
) {
524 if (instance
!= render_view_
->focused_pepper_plugin())
526 Send(new ViewHostMsg_ImeCancelComposition(render_view_
->GetRoutingID()));;
527 #if defined(OS_MACOSX) || defined(USE_AURA)
528 GetRenderWidget()->UpdateCompositionInfo(true);
532 void RenderFrameImpl::PepperSelectionChanged(
533 PepperPluginInstanceImpl
* instance
) {
534 if (instance
!= render_view_
->focused_pepper_plugin())
536 SyncSelectionIfRequired();
539 RenderWidgetFullscreenPepper
* RenderFrameImpl::CreatePepperFullscreenContainer(
540 PepperPluginInstanceImpl
* plugin
) {
542 if (render_view_
->webview() && render_view_
->webview()->mainFrame())
543 active_url
= GURL(render_view_
->webview()->mainFrame()->document().url());
544 RenderWidgetFullscreenPepper
* widget
= RenderWidgetFullscreenPepper::Create(
545 GetRenderWidget()->routing_id(), plugin
, active_url
,
546 GetRenderWidget()->screenInfo());
547 widget
->show(blink::WebNavigationPolicyIgnore
);
551 bool RenderFrameImpl::IsPepperAcceptingCompositionEvents() const {
552 if (!render_view_
->focused_pepper_plugin())
554 return render_view_
->focused_pepper_plugin()->
555 IsPluginAcceptingCompositionEvents();
558 void RenderFrameImpl::PluginCrashed(const base::FilePath
& plugin_path
,
559 base::ProcessId plugin_pid
) {
560 // TODO(jam): dispatch this IPC in RenderFrameHost and switch to use
561 // routing_id_ as a result.
562 Send(new FrameHostMsg_PluginCrashed(routing_id_
, plugin_path
, plugin_pid
));
565 void RenderFrameImpl::SimulateImeSetComposition(
566 const base::string16
& text
,
567 const std::vector
<blink::WebCompositionUnderline
>& underlines
,
570 render_view_
->OnImeSetComposition(
571 text
, underlines
, selection_start
, selection_end
);
574 void RenderFrameImpl::SimulateImeConfirmComposition(
575 const base::string16
& text
,
576 const gfx::Range
& replacement_range
) {
577 render_view_
->OnImeConfirmComposition(text
, replacement_range
, false);
581 void RenderFrameImpl::OnImeSetComposition(
582 const base::string16
& text
,
583 const std::vector
<blink::WebCompositionUnderline
>& underlines
,
586 // When a PPAPI plugin has focus, we bypass WebKit.
587 if (!IsPepperAcceptingCompositionEvents()) {
588 pepper_composition_text_
= text
;
590 // TODO(kinaba) currently all composition events are sent directly to
591 // plugins. Use DOM event mechanism after WebKit is made aware about
592 // plugins that support composition.
593 // The code below mimics the behavior of WebCore::Editor::setComposition.
595 // Empty -> nonempty: composition started.
596 if (pepper_composition_text_
.empty() && !text
.empty()) {
597 render_view_
->focused_pepper_plugin()->HandleCompositionStart(
600 // Nonempty -> empty: composition canceled.
601 if (!pepper_composition_text_
.empty() && text
.empty()) {
602 render_view_
->focused_pepper_plugin()->HandleCompositionEnd(
605 pepper_composition_text_
= text
;
606 // Nonempty: composition is ongoing.
607 if (!pepper_composition_text_
.empty()) {
608 render_view_
->focused_pepper_plugin()->HandleCompositionUpdate(
609 pepper_composition_text_
, underlines
, selection_start
,
615 void RenderFrameImpl::OnImeConfirmComposition(
616 const base::string16
& text
,
617 const gfx::Range
& replacement_range
,
618 bool keep_selection
) {
619 // When a PPAPI plugin has focus, we bypass WebKit.
620 // Here, text.empty() has a special meaning. It means to commit the last
621 // update of composition text (see
622 // RenderWidgetHost::ImeConfirmComposition()).
623 const base::string16
& last_text
= text
.empty() ? pepper_composition_text_
626 // last_text is empty only when both text and pepper_composition_text_ is.
628 if (last_text
.empty())
631 if (!IsPepperAcceptingCompositionEvents()) {
632 base::i18n::UTF16CharIterator
iterator(&last_text
);
634 while (iterator
.Advance()) {
635 blink::WebKeyboardEvent char_event
;
636 char_event
.type
= blink::WebInputEvent::Char
;
637 char_event
.timeStampSeconds
= base::Time::Now().ToDoubleT();
638 char_event
.modifiers
= 0;
639 char_event
.windowsKeyCode
= last_text
[i
];
640 char_event
.nativeKeyCode
= last_text
[i
];
642 const int32 char_start
= i
;
643 for (; i
< iterator
.array_pos(); ++i
) {
644 char_event
.text
[i
- char_start
] = last_text
[i
];
645 char_event
.unmodifiedText
[i
- char_start
] = last_text
[i
];
648 if (GetRenderWidget()->webwidget())
649 GetRenderWidget()->webwidget()->handleInputEvent(char_event
);
652 // Mimics the order of events sent by WebKit.
653 // See WebCore::Editor::setComposition() for the corresponding code.
654 render_view_
->focused_pepper_plugin()->HandleCompositionEnd(last_text
);
655 render_view_
->focused_pepper_plugin()->HandleTextInput(last_text
);
657 pepper_composition_text_
.clear();
660 #endif // ENABLE_PLUGINS
662 bool RenderFrameImpl::Send(IPC::Message
* message
) {
667 if (is_swapped_out_
|| render_view_
->is_swapped_out()) {
668 if (!SwappedOutMessages::CanSendWhileSwappedOut(message
)) {
672 // In most cases, send IPCs through the proxy when swapped out. In some
673 // calls the associated RenderViewImpl routing id is used to send
674 // messages, so don't use the proxy.
675 if (render_frame_proxy_
&& message
->routing_id() == routing_id_
)
676 return render_frame_proxy_
->Send(message
);
679 return RenderThread::Get()->Send(message
);
682 bool RenderFrameImpl::OnMessageReceived(const IPC::Message
& msg
) {
683 GetContentClient()->SetActiveURL(frame_
->document().url());
685 ObserverListBase
<RenderFrameObserver
>::Iterator
it(observers_
);
686 RenderFrameObserver
* observer
;
687 while ((observer
= it
.GetNext()) != NULL
) {
688 if (observer
->OnMessageReceived(msg
))
693 IPC_BEGIN_MESSAGE_MAP(RenderFrameImpl
, msg
)
694 IPC_MESSAGE_HANDLER(FrameMsg_Navigate
, OnNavigate
)
695 IPC_MESSAGE_HANDLER(FrameMsg_BeforeUnload
, OnBeforeUnload
)
696 IPC_MESSAGE_HANDLER(FrameMsg_SwapOut
, OnSwapOut
)
697 IPC_MESSAGE_HANDLER(FrameMsg_BuffersSwapped
, OnBuffersSwapped
)
698 IPC_MESSAGE_HANDLER_GENERIC(FrameMsg_CompositorFrameSwapped
,
699 OnCompositorFrameSwapped(msg
))
700 IPC_MESSAGE_HANDLER(FrameMsg_ChildFrameProcessGone
, OnChildFrameProcessGone
)
701 IPC_MESSAGE_HANDLER(FrameMsg_ContextMenuClosed
, OnContextMenuClosed
)
702 IPC_MESSAGE_HANDLER(FrameMsg_CustomContextMenuAction
,
703 OnCustomContextMenuAction
)
704 IPC_MESSAGE_HANDLER(InputMsg_Undo
, OnUndo
)
705 IPC_MESSAGE_HANDLER(InputMsg_Redo
, OnRedo
)
706 IPC_MESSAGE_HANDLER(InputMsg_Cut
, OnCut
)
707 IPC_MESSAGE_HANDLER(InputMsg_Copy
, OnCopy
)
708 IPC_MESSAGE_HANDLER(InputMsg_Paste
, OnPaste
)
709 IPC_MESSAGE_HANDLER(InputMsg_PasteAndMatchStyle
, OnPasteAndMatchStyle
)
710 IPC_MESSAGE_HANDLER(InputMsg_Delete
, OnDelete
)
711 IPC_MESSAGE_HANDLER(InputMsg_SelectAll
, OnSelectAll
)
712 IPC_MESSAGE_HANDLER(InputMsg_SelectRange
, OnSelectRange
)
713 IPC_MESSAGE_HANDLER(InputMsg_Unselect
, OnUnselect
)
714 IPC_MESSAGE_HANDLER(InputMsg_Replace
, OnReplace
)
715 IPC_MESSAGE_HANDLER(InputMsg_ReplaceMisspelling
, OnReplaceMisspelling
)
716 IPC_MESSAGE_HANDLER(FrameMsg_CSSInsertRequest
, OnCSSInsertRequest
)
717 IPC_MESSAGE_HANDLER(FrameMsg_JavaScriptExecuteRequest
,
718 OnJavaScriptExecuteRequest
)
719 IPC_MESSAGE_HANDLER(FrameMsg_SetEditableSelectionOffsets
,
720 OnSetEditableSelectionOffsets
)
721 IPC_MESSAGE_HANDLER(FrameMsg_SetCompositionFromExistingText
,
722 OnSetCompositionFromExistingText
)
723 IPC_MESSAGE_HANDLER(FrameMsg_ExtendSelectionAndDelete
,
724 OnExtendSelectionAndDelete
)
725 #if defined(OS_MACOSX)
726 IPC_MESSAGE_HANDLER(InputMsg_CopyToFindPboard
, OnCopyToFindPboard
)
728 IPC_MESSAGE_HANDLER(FrameMsg_Reload
, OnReload
)
729 IPC_END_MESSAGE_MAP()
734 void RenderFrameImpl::OnNavigate(const FrameMsg_Navigate_Params
& params
) {
735 MaybeHandleDebugURL(params
.url
);
736 if (!render_view_
->webview())
739 render_view_
->OnNavigate(params
);
741 bool is_reload
= RenderViewImpl::IsReload(params
);
742 WebURLRequest::CachePolicy cache_policy
=
743 WebURLRequest::UseProtocolCachePolicy
;
745 // If this is a stale back/forward (due to a recent navigation the browser
746 // didn't know about), ignore it.
747 if (render_view_
->IsBackForwardToStaleEntry(params
, is_reload
))
750 // Swap this renderer back in if necessary.
751 if (render_view_
->is_swapped_out_
) {
752 // We marked the view as hidden when swapping the view out, so be sure to
753 // reset the visibility state before navigating to the new URL.
754 render_view_
->webview()->setVisibilityState(
755 render_view_
->visibilityState(), false);
757 // If this is an attempt to reload while we are swapped out, we should not
758 // reload swappedout://, but the previous page, which is stored in
759 // params.state. Setting is_reload to false will treat this like a back
760 // navigation to accomplish that.
762 cache_policy
= WebURLRequest::ReloadIgnoringCacheData
;
764 // We refresh timezone when a view is swapped in since timezone
765 // can get out of sync when the system timezone is updated while
766 // the view is swapped out.
767 RenderThreadImpl::NotifyTimezoneChange();
769 render_view_
->SetSwappedOut(false);
770 is_swapped_out_
= false;
773 if (params
.should_clear_history_list
) {
774 CHECK_EQ(params
.pending_history_list_offset
, -1);
775 CHECK_EQ(params
.current_history_list_offset
, -1);
776 CHECK_EQ(params
.current_history_list_length
, 0);
778 render_view_
->history_list_offset_
= params
.current_history_list_offset
;
779 render_view_
->history_list_length_
= params
.current_history_list_length
;
780 if (render_view_
->history_list_length_
>= 0) {
781 render_view_
->history_page_ids_
.resize(
782 render_view_
->history_list_length_
, -1);
784 if (params
.pending_history_list_offset
>= 0 &&
785 params
.pending_history_list_offset
< render_view_
->history_list_length_
) {
786 render_view_
->history_page_ids_
[params
.pending_history_list_offset
] =
790 GetContentClient()->SetActiveURL(params
.url
);
792 WebFrame
* frame
= frame_
;
793 if (!params
.frame_to_navigate
.empty()) {
794 // TODO(nasko): Move this lookup to the browser process.
795 frame
= render_view_
->webview()->findFrameByName(
796 WebString::fromUTF8(params
.frame_to_navigate
));
797 CHECK(frame
) << "Invalid frame name passed: " << params
.frame_to_navigate
;
800 if (is_reload
&& !render_view_
->history_controller()->GetCurrentEntry()) {
801 // We cannot reload if we do not have any history state. This happens, for
802 // example, when recovering from a crash.
804 cache_policy
= WebURLRequest::ReloadIgnoringCacheData
;
807 render_view_
->pending_navigation_params_
.reset(
808 new FrameMsg_Navigate_Params(params
));
810 // If we are reloading, then WebKit will use the history state of the current
811 // page, so we should just ignore any given history state. Otherwise, if we
812 // have history state, then we need to navigate to it, which corresponds to a
813 // back/forward navigation event.
815 bool reload_original_url
=
816 (params
.navigation_type
==
817 FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL
);
818 bool ignore_cache
= (params
.navigation_type
==
819 FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE
);
821 if (reload_original_url
)
822 frame
->reloadWithOverrideURL(params
.url
, true);
824 frame
->reload(ignore_cache
);
825 } else if (params
.page_state
.IsValid()) {
826 // We must know the page ID of the page we are navigating back to.
827 DCHECK_NE(params
.page_id
, -1);
828 scoped_ptr
<HistoryEntry
> entry
=
829 PageStateToHistoryEntry(params
.page_state
);
831 // Ensure we didn't save the swapped out URL in UpdateState, since the
832 // browser should never be telling us to navigate to swappedout://.
833 CHECK(entry
->root().urlString() != WebString::fromUTF8(kSwappedOutURL
));
834 render_view_
->history_controller()->GoToEntry(entry
.Pass(), cache_policy
);
836 } else if (!params
.base_url_for_data_url
.is_empty()) {
837 // A loadData request with a specified base URL.
838 std::string mime_type
, charset
, data
;
839 if (net::DataURL::Parse(params
.url
, &mime_type
, &charset
, &data
)) {
841 WebData(data
.c_str(), data
.length()),
842 WebString::fromUTF8(mime_type
),
843 WebString::fromUTF8(charset
),
844 params
.base_url_for_data_url
,
845 params
.history_url_for_data_url
,
849 "Invalid URL passed: " << params
.url
.possibly_invalid_spec();
852 // Navigate to the given URL.
853 WebURLRequest
request(params
.url
);
855 // A session history navigation should have been accompanied by state.
856 CHECK_EQ(params
.page_id
, -1);
858 if (frame
->isViewSourceModeEnabled())
859 request
.setCachePolicy(WebURLRequest::ReturnCacheDataElseLoad
);
861 if (params
.referrer
.url
.is_valid()) {
862 WebString referrer
= WebSecurityPolicy::generateReferrerHeader(
863 params
.referrer
.policy
,
865 WebString::fromUTF8(params
.referrer
.url
.spec()));
866 if (!referrer
.isEmpty())
867 request
.setHTTPReferrer(referrer
, params
.referrer
.policy
);
870 if (!params
.extra_headers
.empty()) {
871 for (net::HttpUtil::HeadersIterator
i(params
.extra_headers
.begin(),
872 params
.extra_headers
.end(), "\n");
874 request
.addHTTPHeaderField(WebString::fromUTF8(i
.name()),
875 WebString::fromUTF8(i
.values()));
879 if (params
.is_post
) {
880 request
.setHTTPMethod(WebString::fromUTF8("POST"));
883 WebHTTPBody http_body
;
884 http_body
.initialize();
885 const char* data
= NULL
;
886 if (params
.browser_initiated_post_data
.size()) {
887 data
= reinterpret_cast<const char*>(
888 ¶ms
.browser_initiated_post_data
.front());
890 http_body
.appendData(
891 WebData(data
, params
.browser_initiated_post_data
.size()));
892 request
.setHTTPBody(http_body
);
895 frame
->loadRequest(request
);
897 // If this is a cross-process navigation, the browser process will send
898 // along the proper navigation start value.
899 if (!params
.browser_navigation_start
.is_null() &&
900 frame
->provisionalDataSource()) {
901 // browser_navigation_start is likely before this process existed, so we
902 // can't use InterProcessTimeTicksConverter. Instead, the best we can do
903 // is just ensure we don't report a bogus value in the future.
904 base::TimeTicks navigation_start
= std::min(
905 base::TimeTicks::Now(), params
.browser_navigation_start
);
906 double navigation_start_seconds
=
907 (navigation_start
- base::TimeTicks()).InSecondsF();
908 frame
->provisionalDataSource()->setNavigationStartTime(
909 navigation_start_seconds
);
913 // In case LoadRequest failed before DidCreateDataSource was called.
914 render_view_
->pending_navigation_params_
.reset();
917 void RenderFrameImpl::OnBeforeUnload() {
918 // TODO(creis): Right now, this is only called on the main frame. Make the
919 // browser process send dispatchBeforeUnloadEvent to every frame that needs
921 CHECK(!frame_
->parent());
923 base::TimeTicks before_unload_start_time
= base::TimeTicks::Now();
924 bool proceed
= frame_
->dispatchBeforeUnloadEvent();
925 base::TimeTicks before_unload_end_time
= base::TimeTicks::Now();
926 Send(new FrameHostMsg_BeforeUnload_ACK(routing_id_
, proceed
,
927 before_unload_start_time
,
928 before_unload_end_time
));
931 void RenderFrameImpl::OnSwapOut(int proxy_routing_id
) {
932 RenderFrameProxy
* proxy
= NULL
;
934 // Only run unload if we're not swapped out yet, but send the ack either way.
935 if (!is_swapped_out_
|| !render_view_
->is_swapped_out_
) {
936 // Swap this RenderFrame out so the frame can navigate to a page rendered by
937 // a different process. This involves running the unload handler and
938 // clearing the page. Once WasSwappedOut is called, we also allow this
939 // process to exit if there are no other active RenderFrames in it.
941 // Send an UpdateState message before we get swapped out. Create the
942 // RenderFrameProxy as well so its routing id is registered for receiving
944 render_view_
->SyncNavigationState();
945 proxy
= RenderFrameProxy::CreateFrameProxy(proxy_routing_id
, routing_id_
);
947 // Synchronously run the unload handler before sending the ACK.
948 // TODO(creis): Call dispatchUnloadEvent unconditionally here to support
949 // unload on subframes as well.
950 if (!frame_
->parent())
951 frame_
->dispatchUnloadEvent();
953 // Swap out and stop sending any IPC messages that are not ACKs.
954 if (!frame_
->parent())
955 render_view_
->SetSwappedOut(true);
956 is_swapped_out_
= true;
958 // Now that we're swapped out and filtering IPC messages, stop loading to
959 // ensure that no other in-progress navigation continues. We do this here
960 // to avoid sending a DidStopLoading message to the browser process.
961 // TODO(creis): Should we be stopping all frames here and using
962 // StopAltErrorPageFetcher with RenderView::OnStop, or just stopping this
964 if (!frame_
->parent())
965 render_view_
->OnStop();
967 frame_
->stopLoading();
969 // Let subframes know that the frame is now rendered remotely, for the
970 // purposes of compositing and input events.
971 if (frame_
->parent())
972 frame_
->setIsRemote(true);
974 // Replace the page with a blank dummy URL. The unload handler will not be
975 // run a second time, thanks to a check in FrameLoader::stopLoading.
976 // TODO(creis): Need to add a better way to do this that avoids running the
977 // beforeunload handler. For now, we just run it a second time silently.
978 render_view_
->NavigateToSwappedOutURL(frame_
);
980 if (frame_
->parent())
981 render_view_
->RegisterSwappedOutChildFrame(this);
983 // Let WebKit know that this view is hidden so it can drop resources and
985 // TODO(creis): Support this for subframes as well.
986 if (!frame_
->parent()) {
987 render_view_
->webview()->setVisibilityState(
988 blink::WebPageVisibilityStateHidden
, false);
992 // It is now safe to show modal dialogs again.
993 // TODO(creis): Deal with modal dialogs from subframes.
994 if (!frame_
->parent())
995 render_view_
->suppress_dialogs_until_swap_out_
= false;
997 Send(new FrameHostMsg_SwapOut_ACK(routing_id_
));
999 // Now that all of the cleanup is complete and the browser side is notified,
1000 // start using the RenderFrameProxy, if one is created.
1002 set_render_frame_proxy(proxy
);
1005 void RenderFrameImpl::OnBuffersSwapped(
1006 const FrameMsg_BuffersSwapped_Params
& params
) {
1007 if (!compositing_helper_
.get()) {
1008 compositing_helper_
=
1009 ChildFrameCompositingHelper::CreateCompositingHelperForRenderFrame(
1010 frame_
, this, routing_id_
);
1011 compositing_helper_
->EnableCompositing(true);
1013 compositing_helper_
->OnBuffersSwapped(
1016 params
.gpu_route_id
,
1018 render_view_
->GetWebView()->deviceScaleFactor());
1021 void RenderFrameImpl::OnCompositorFrameSwapped(const IPC::Message
& message
) {
1022 FrameMsg_CompositorFrameSwapped::Param param
;
1023 if (!FrameMsg_CompositorFrameSwapped::Read(&message
, ¶m
))
1025 scoped_ptr
<cc::CompositorFrame
> frame(new cc::CompositorFrame
);
1026 param
.a
.frame
.AssignTo(frame
.get());
1028 if (!compositing_helper_
.get()) {
1029 compositing_helper_
=
1030 ChildFrameCompositingHelper::CreateCompositingHelperForRenderFrame(
1031 frame_
, this, routing_id_
);
1032 compositing_helper_
->EnableCompositing(true);
1034 compositing_helper_
->OnCompositorFrameSwapped(frame
.Pass(),
1035 param
.a
.producing_route_id
,
1036 param
.a
.output_surface_id
,
1037 param
.a
.producing_host_id
,
1038 param
.a
.shared_memory_handle
);
1041 void RenderFrameImpl::OnContextMenuClosed(
1042 const CustomContextMenuContext
& custom_context
) {
1043 if (custom_context
.request_id
) {
1044 // External request, should be in our map.
1045 ContextMenuClient
* client
=
1046 pending_context_menus_
.Lookup(custom_context
.request_id
);
1048 client
->OnMenuClosed(custom_context
.request_id
);
1049 pending_context_menus_
.Remove(custom_context
.request_id
);
1052 // Internal request, forward to WebKit.
1053 context_menu_node_
.reset();
1057 void RenderFrameImpl::OnCustomContextMenuAction(
1058 const CustomContextMenuContext
& custom_context
,
1060 if (custom_context
.request_id
) {
1061 // External context menu request, look in our map.
1062 ContextMenuClient
* client
=
1063 pending_context_menus_
.Lookup(custom_context
.request_id
);
1065 client
->OnMenuAction(custom_context
.request_id
, action
);
1067 // Internal request, forward to WebKit.
1068 render_view_
->webview()->performCustomContextMenuAction(action
);
1072 void RenderFrameImpl::OnUndo() {
1073 frame_
->executeCommand(WebString::fromUTF8("Undo"), GetFocusedElement());
1076 void RenderFrameImpl::OnRedo() {
1077 frame_
->executeCommand(WebString::fromUTF8("Redo"), GetFocusedElement());
1080 void RenderFrameImpl::OnCut() {
1081 base::AutoReset
<bool> handling_select_range(&handling_select_range_
, true);
1082 frame_
->executeCommand(WebString::fromUTF8("Cut"), GetFocusedElement());
1085 void RenderFrameImpl::OnCopy() {
1086 base::AutoReset
<bool> handling_select_range(&handling_select_range_
, true);
1087 WebNode current_node
= context_menu_node_
.isNull() ?
1088 GetFocusedElement() : context_menu_node_
;
1089 frame_
->executeCommand(WebString::fromUTF8("Copy"), current_node
);
1092 void RenderFrameImpl::OnPaste() {
1093 base::AutoReset
<bool> handling_select_range(&handling_select_range_
, true);
1094 frame_
->executeCommand(WebString::fromUTF8("Paste"), GetFocusedElement());
1097 void RenderFrameImpl::OnPasteAndMatchStyle() {
1098 base::AutoReset
<bool> handling_select_range(&handling_select_range_
, true);
1099 frame_
->executeCommand(
1100 WebString::fromUTF8("PasteAndMatchStyle"), GetFocusedElement());
1103 #if defined(OS_MACOSX)
1104 void RenderFrameImpl::OnCopyToFindPboard() {
1105 // Since the find pasteboard supports only plain text, this can be simpler
1106 // than the |OnCopy()| case.
1107 if (frame_
->hasSelection()) {
1108 base::string16 selection
= frame_
->selectionAsText();
1109 RenderThread::Get()->Send(
1110 new ClipboardHostMsg_FindPboardWriteStringAsync(selection
));
1115 void RenderFrameImpl::OnDelete() {
1116 frame_
->executeCommand(WebString::fromUTF8("Delete"), GetFocusedElement());
1119 void RenderFrameImpl::OnSelectAll() {
1120 base::AutoReset
<bool> handling_select_range(&handling_select_range_
, true);
1121 frame_
->executeCommand(WebString::fromUTF8("SelectAll"), GetFocusedElement());
1124 void RenderFrameImpl::OnSelectRange(const gfx::Point
& start
,
1125 const gfx::Point
& end
) {
1126 // This IPC is dispatched by RenderWidgetHost, so use its routing id.
1127 Send(new ViewHostMsg_SelectRange_ACK(GetRenderWidget()->routing_id()));
1129 base::AutoReset
<bool> handling_select_range(&handling_select_range_
, true);
1130 frame_
->selectRange(start
, end
);
1133 void RenderFrameImpl::OnUnselect() {
1134 base::AutoReset
<bool> handling_select_range(&handling_select_range_
, true);
1135 frame_
->executeCommand(WebString::fromUTF8("Unselect"), GetFocusedElement());
1138 void RenderFrameImpl::OnReplace(const base::string16
& text
) {
1139 if (!frame_
->hasSelection())
1140 frame_
->selectWordAroundCaret();
1142 frame_
->replaceSelection(text
);
1145 void RenderFrameImpl::OnReplaceMisspelling(const base::string16
& text
) {
1146 if (!frame_
->hasSelection())
1149 frame_
->replaceMisspelledRange(text
);
1152 void RenderFrameImpl::OnCSSInsertRequest(const std::string
& css
) {
1153 frame_
->document().insertStyleSheet(WebString::fromUTF8(css
));
1156 void RenderFrameImpl::OnJavaScriptExecuteRequest(
1157 const base::string16
& jscript
,
1159 bool notify_result
) {
1160 TRACE_EVENT_INSTANT0("test_tracing", "OnJavaScriptExecuteRequest",
1161 TRACE_EVENT_SCOPE_THREAD
);
1163 v8::HandleScope
handle_scope(v8::Isolate::GetCurrent());
1164 v8::Handle
<v8::Value
> result
=
1165 frame_
->executeScriptAndReturnValue(WebScriptSource(jscript
));
1166 if (notify_result
) {
1167 base::ListValue list
;
1168 if (!result
.IsEmpty()) {
1169 v8::Local
<v8::Context
> context
= frame_
->mainWorldScriptContext();
1170 v8::Context::Scope
context_scope(context
);
1171 V8ValueConverterImpl converter
;
1172 converter
.SetDateAllowed(true);
1173 converter
.SetRegExpAllowed(true);
1174 base::Value
* result_value
= converter
.FromV8Value(result
, context
);
1175 list
.Set(0, result_value
? result_value
: base::Value::CreateNullValue());
1177 list
.Set(0, base::Value::CreateNullValue());
1179 Send(new FrameHostMsg_JavaScriptExecuteResponse(routing_id_
, id
, list
));
1183 void RenderFrameImpl::OnSetEditableSelectionOffsets(int start
, int end
) {
1184 base::AutoReset
<bool> handling_select_range(&handling_select_range_
, true);
1185 if (!GetRenderWidget()->ShouldHandleImeEvent())
1187 ImeEventGuard
guard(GetRenderWidget());
1188 frame_
->setEditableSelectionOffsets(start
, end
);
1191 void RenderFrameImpl::OnSetCompositionFromExistingText(
1193 const std::vector
<blink::WebCompositionUnderline
>& underlines
) {
1194 if (!GetRenderWidget()->ShouldHandleImeEvent())
1196 ImeEventGuard
guard(GetRenderWidget());
1197 frame_
->setCompositionFromExistingText(start
, end
, underlines
);
1200 void RenderFrameImpl::OnExtendSelectionAndDelete(int before
, int after
) {
1201 if (!GetRenderWidget()->ShouldHandleImeEvent())
1203 ImeEventGuard
guard(GetRenderWidget());
1204 frame_
->extendSelectionAndDelete(before
, after
);
1208 void RenderFrameImpl::OnReload(bool ignore_cache
) {
1209 frame_
->reload(ignore_cache
);
1212 bool RenderFrameImpl::ShouldUpdateSelectionTextFromContextMenuParams(
1213 const base::string16
& selection_text
,
1214 size_t selection_text_offset
,
1215 const gfx::Range
& selection_range
,
1216 const ContextMenuParams
& params
) {
1217 base::string16 trimmed_selection_text
;
1218 if (!selection_text
.empty() && !selection_range
.is_empty()) {
1219 const int start
= selection_range
.GetMin() - selection_text_offset
;
1220 const size_t length
= selection_range
.length();
1221 if (start
>= 0 && start
+ length
<= selection_text
.length()) {
1222 base::TrimWhitespace(selection_text
.substr(start
, length
), base::TRIM_ALL
,
1223 &trimmed_selection_text
);
1226 base::string16 trimmed_params_text
;
1227 base::TrimWhitespace(params
.selection_text
, base::TRIM_ALL
,
1228 &trimmed_params_text
);
1229 return trimmed_params_text
!= trimmed_selection_text
;
1232 bool RenderFrameImpl::RunJavaScriptMessage(JavaScriptMessageType type
,
1233 const base::string16
& message
,
1234 const base::string16
& default_value
,
1235 const GURL
& frame_url
,
1236 base::string16
* result
) {
1237 // Don't allow further dialogs if we are waiting to swap out, since the
1238 // PageGroupLoadDeferrer in our stack prevents it.
1239 if (render_view()->suppress_dialogs_until_swap_out_
)
1242 bool success
= false;
1243 base::string16 result_temp
;
1245 result
= &result_temp
;
1247 render_view()->SendAndRunNestedMessageLoop(
1248 new FrameHostMsg_RunJavaScriptMessage(
1249 routing_id_
, message
, default_value
, frame_url
, type
, &success
,
1254 void RenderFrameImpl::LoadNavigationErrorPage(
1255 const WebURLRequest
& failed_request
,
1256 const WebURLError
& error
,
1258 std::string error_html
;
1259 GetContentClient()->renderer()->GetNavigationErrorStrings(
1260 render_view(), frame_
, failed_request
, error
, &error_html
, NULL
);
1262 frame_
->loadHTMLString(error_html
,
1263 GURL(kUnreachableWebDataURL
),
1264 error
.unreachableURL
,
1268 void RenderFrameImpl::DidCommitCompositorFrame() {
1269 if (compositing_helper_
)
1270 compositing_helper_
->DidCommitCompositorFrame();
1272 RenderFrameObserver
, observers_
, DidCommitCompositorFrame());
1275 RenderView
* RenderFrameImpl::GetRenderView() {
1276 return render_view_
.get();
1279 int RenderFrameImpl::GetRoutingID() {
1283 blink::WebFrame
* RenderFrameImpl::GetWebFrame() {
1288 WebPreferences
& RenderFrameImpl::GetWebkitPreferences() {
1289 return render_view_
->GetWebkitPreferences();
1292 int RenderFrameImpl::ShowContextMenu(ContextMenuClient
* client
,
1293 const ContextMenuParams
& params
) {
1294 DCHECK(client
); // A null client means "internal" when we issue callbacks.
1295 ContextMenuParams
our_params(params
);
1296 our_params
.custom_context
.request_id
= pending_context_menus_
.Add(client
);
1297 Send(new FrameHostMsg_ContextMenu(routing_id_
, our_params
));
1298 return our_params
.custom_context
.request_id
;
1301 void RenderFrameImpl::CancelContextMenu(int request_id
) {
1302 DCHECK(pending_context_menus_
.Lookup(request_id
));
1303 pending_context_menus_
.Remove(request_id
);
1306 blink::WebNode
RenderFrameImpl::GetContextMenuNode() const {
1307 return context_menu_node_
;
1310 blink::WebPlugin
* RenderFrameImpl::CreatePlugin(
1311 blink::WebFrame
* frame
,
1312 const WebPluginInfo
& info
,
1313 const blink::WebPluginParams
& params
) {
1314 DCHECK_EQ(frame_
, frame
);
1315 #if defined(ENABLE_PLUGINS)
1316 bool pepper_plugin_was_registered
= false;
1317 scoped_refptr
<PluginModule
> pepper_module(PluginModule::Create(
1318 this, info
, &pepper_plugin_was_registered
));
1319 if (pepper_plugin_was_registered
) {
1320 if (pepper_module
.get()) {
1321 return new PepperWebPluginImpl(pepper_module
.get(), params
, this);
1324 #if defined(OS_CHROMEOS)
1325 LOG(WARNING
) << "Pepper module/plugin creation failed.";
1328 // TODO(jam): change to take RenderFrame.
1329 return new WebPluginImpl(frame
, params
, info
.path
, render_view_
, this);
1336 void RenderFrameImpl::LoadURLExternally(blink::WebLocalFrame
* frame
,
1337 const blink::WebURLRequest
& request
,
1338 blink::WebNavigationPolicy policy
) {
1339 DCHECK(!frame_
|| frame_
== frame
);
1340 loadURLExternally(frame
, request
, policy
, WebString());
1343 void RenderFrameImpl::ExecuteJavaScript(const base::string16
& javascript
) {
1344 OnJavaScriptExecuteRequest(javascript
, 0, false);
1347 void RenderFrameImpl::OnChildFrameProcessGone() {
1348 if (compositing_helper_
)
1349 compositing_helper_
->ChildFrameGone();
1352 // blink::WebFrameClient implementation ----------------------------------------
1354 blink::WebPlugin
* RenderFrameImpl::createPlugin(
1355 blink::WebLocalFrame
* frame
,
1356 const blink::WebPluginParams
& params
) {
1357 DCHECK_EQ(frame_
, frame
);
1358 blink::WebPlugin
* plugin
= NULL
;
1359 if (GetContentClient()->renderer()->OverrideCreatePlugin(
1360 this, frame
, params
, &plugin
)) {
1364 if (base::UTF16ToASCII(params
.mimeType
) == kBrowserPluginMimeType
) {
1365 return render_view_
->GetBrowserPluginManager()->CreateBrowserPlugin(
1366 render_view_
.get(), frame
, false);
1369 #if defined(ENABLE_PLUGINS)
1371 std::string mime_type
;
1373 Send(new FrameHostMsg_GetPluginInfo(
1374 routing_id_
, params
.url
, frame
->top()->document().url(),
1375 params
.mimeType
.utf8(), &found
, &info
, &mime_type
));
1379 if (info
.type
== content::WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN
) {
1380 return render_view_
->GetBrowserPluginManager()->CreateBrowserPlugin(
1381 render_view_
.get(), frame
, true);
1385 WebPluginParams params_to_use
= params
;
1386 params_to_use
.mimeType
= WebString::fromUTF8(mime_type
);
1387 return CreatePlugin(frame
, info
, params_to_use
);
1390 #endif // defined(ENABLE_PLUGINS)
1393 blink::WebMediaPlayer
* RenderFrameImpl::createMediaPlayer(
1394 blink::WebLocalFrame
* frame
,
1395 const blink::WebURL
& url
,
1396 blink::WebMediaPlayerClient
* client
) {
1397 blink::WebMediaStream
web_stream(
1398 blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(url
));
1399 if (!web_stream
.isNull())
1400 return CreateWebMediaPlayerForMediaStream(url
, client
);
1402 #if defined(OS_ANDROID)
1403 return CreateAndroidWebMediaPlayer(url
, client
);
1405 WebMediaPlayerParams
params(
1406 base::Bind(&ContentRendererClient::DeferMediaLoad
,
1407 base::Unretained(GetContentClient()->renderer()),
1408 static_cast<RenderFrame
*>(this)),
1409 RenderThreadImpl::current()->GetAudioRendererMixerManager()->CreateInput(
1410 render_view_
->routing_id_
, routing_id_
));
1411 return new WebMediaPlayerImpl(frame
, client
, weak_factory_
.GetWeakPtr(),
1413 #endif // defined(OS_ANDROID)
1416 blink::WebContentDecryptionModule
*
1417 RenderFrameImpl::createContentDecryptionModule(
1418 blink::WebLocalFrame
* frame
,
1419 const blink::WebSecurityOrigin
& security_origin
,
1420 const blink::WebString
& key_system
) {
1421 DCHECK(!frame_
|| frame_
== frame
);
1422 return WebContentDecryptionModuleImpl::Create(
1423 #if defined(ENABLE_PEPPER_CDMS)
1425 #elif defined(OS_ANDROID)
1432 blink::WebApplicationCacheHost
* RenderFrameImpl::createApplicationCacheHost(
1433 blink::WebLocalFrame
* frame
,
1434 blink::WebApplicationCacheHostClient
* client
) {
1435 if (!frame
|| !frame
->view())
1437 DCHECK(!frame_
|| frame_
== frame
);
1438 return new RendererWebApplicationCacheHostImpl(
1439 RenderViewImpl::FromWebView(frame
->view()), client
,
1440 RenderThreadImpl::current()->appcache_dispatcher()->backend_proxy());
1443 blink::WebWorkerPermissionClientProxy
*
1444 RenderFrameImpl::createWorkerPermissionClientProxy(
1445 blink::WebLocalFrame
* frame
) {
1446 if (!frame
|| !frame
->view())
1448 DCHECK(!frame_
|| frame_
== frame
);
1449 return GetContentClient()->renderer()->CreateWorkerPermissionClientProxy(
1453 blink::WebCookieJar
* RenderFrameImpl::cookieJar(blink::WebLocalFrame
* frame
) {
1454 DCHECK(!frame_
|| frame_
== frame
);
1455 return &cookie_jar_
;
1458 blink::WebServiceWorkerProvider
* RenderFrameImpl::createServiceWorkerProvider(
1459 blink::WebLocalFrame
* frame
) {
1460 DCHECK(!frame_
|| frame_
== frame
);
1461 // At this point we should have non-null data source.
1462 DCHECK(frame
->dataSource());
1463 if (!ChildThread::current())
1464 return NULL
; // May be null in some tests.
1465 ServiceWorkerNetworkProvider
* provider
=
1466 ServiceWorkerNetworkProvider::FromDocumentState(
1467 DocumentState::FromDataSource(frame
->dataSource()));
1468 return new WebServiceWorkerProviderImpl(
1469 ChildThread::current()->thread_safe_sender(),
1470 provider
? provider
->context() : NULL
);
1473 void RenderFrameImpl::didAccessInitialDocument(blink::WebLocalFrame
* frame
) {
1474 DCHECK(!frame_
|| frame_
== frame
);
1475 // Notify the browser process that it is no longer safe to show the pending
1476 // URL of the main frame, since a URL spoof is now possible.
1477 if (!frame
->parent() && render_view_
->page_id_
== -1)
1478 Send(new FrameHostMsg_DidAccessInitialDocument(routing_id_
));
1481 blink::WebFrame
* RenderFrameImpl::createChildFrame(
1482 blink::WebLocalFrame
* parent
,
1483 const blink::WebString
& name
) {
1484 // Synchronously notify the browser of a child frame creation to get the
1485 // routing_id for the RenderFrame.
1486 int child_routing_id
= MSG_ROUTING_NONE
;
1487 Send(new FrameHostMsg_CreateChildFrame(routing_id_
,
1488 base::UTF16ToUTF8(name
),
1489 &child_routing_id
));
1490 // Allocation of routing id failed, so we can't create a child frame. This can
1491 // happen if this RenderFrameImpl's IPCs are being filtered when in swapped
1493 if (child_routing_id
== MSG_ROUTING_NONE
) {
1494 #if !defined(OS_LINUX)
1495 // DumpWithoutCrashing() crashes on Linux in renderer processes when
1496 // breakpad and sandboxing are enabled: crbug.com/349600
1497 base::debug::Alias(parent
);
1498 base::debug::Alias(&routing_id_
);
1499 bool render_view_is_swapped_out
= GetRenderWidget()->is_swapped_out();
1500 base::debug::Alias(&render_view_is_swapped_out
);
1501 bool render_view_is_closing
= GetRenderWidget()->closing();
1502 base::debug::Alias(&render_view_is_closing
);
1503 base::debug::Alias(&is_swapped_out_
);
1504 base::debug::DumpWithoutCrashing();
1509 // Create the RenderFrame and WebLocalFrame, linking the two.
1510 RenderFrameImpl
* child_render_frame
= RenderFrameImpl::Create(
1511 render_view_
.get(), child_routing_id
);
1512 blink::WebLocalFrame
* web_frame
= WebLocalFrame::create(child_render_frame
);
1513 child_render_frame
->SetWebFrame(web_frame
);
1515 // Add the frame to the frame tree and initialize it.
1516 parent
->appendChild(web_frame
);
1517 child_render_frame
->Initialize();
1522 void RenderFrameImpl::didDisownOpener(blink::WebLocalFrame
* frame
) {
1523 DCHECK(!frame_
|| frame_
== frame
);
1524 // We only need to notify the browser if the active, top-level frame clears
1525 // its opener. We can ignore cases where a swapped out frame clears its
1526 // opener after hearing about it from the browser, and the browser does not
1527 // (yet) care about subframe openers.
1528 if (render_view_
->is_swapped_out_
|| frame
->parent())
1531 // Notify WebContents and all its swapped out RenderViews.
1532 Send(new FrameHostMsg_DidDisownOpener(routing_id_
));
1535 void RenderFrameImpl::frameDetached(blink::WebFrame
* frame
) {
1536 // NOTE: This function is called on the frame that is being detached and not
1537 // the parent frame. This is different from createChildFrame() which is
1538 // called on the parent frame.
1539 CHECK(!is_detaching_
);
1540 DCHECK(!frame_
|| frame_
== frame
);
1542 bool is_subframe
= !!frame
->parent();
1544 Send(new FrameHostMsg_Detach(routing_id_
));
1546 render_view_
->UnregisterSwappedOutChildFrame(this);
1548 // The |is_detaching_| flag disables Send(). FrameHostMsg_Detach must be
1549 // sent before setting |is_detaching_| to true. In contrast, Observers
1550 // should only be notified afterwards so they cannot call back into here and
1551 // have IPCs fired off.
1552 is_detaching_
= true;
1554 FOR_EACH_OBSERVER(RenderViewObserver
, render_view_
->observers(),
1555 FrameDetached(frame
));
1557 // We need to clean up subframes by removing them from the map and deleting
1558 // the RenderFrameImpl. In contrast, the main frame is owned by its
1559 // containing RenderViewHost (so that they have the same lifetime), so only
1560 // removal from the map is needed and no deletion.
1561 FrameMap::iterator it
= g_frame_map
.Get().find(frame
);
1562 CHECK(it
!= g_frame_map
.Get().end());
1563 CHECK_EQ(it
->second
, this);
1564 g_frame_map
.Get().erase(it
);
1567 frame
->parent()->removeChild(frame
);
1569 // |frame| is invalid after here.
1574 // Object is invalid after this point.
1578 void RenderFrameImpl::frameFocused() {
1579 Send(new FrameHostMsg_FrameFocused(routing_id_
));
1582 void RenderFrameImpl::willClose(blink::WebFrame
* frame
) {
1583 DCHECK(!frame_
|| frame_
== frame
);
1585 FOR_EACH_OBSERVER(RenderViewObserver
, render_view_
->observers(),
1586 FrameWillClose(frame
));
1589 void RenderFrameImpl::didChangeName(blink::WebLocalFrame
* frame
,
1590 const blink::WebString
& name
) {
1591 DCHECK(!frame_
|| frame_
== frame
);
1592 if (!render_view_
->renderer_preferences_
.report_frame_name_changes
)
1595 FOR_EACH_OBSERVER(RenderFrameObserver
, observers_
, DidChangeName(name
));
1598 void RenderFrameImpl::didMatchCSS(
1599 blink::WebLocalFrame
* frame
,
1600 const blink::WebVector
<blink::WebString
>& newly_matching_selectors
,
1601 const blink::WebVector
<blink::WebString
>& stopped_matching_selectors
) {
1602 DCHECK(!frame_
|| frame_
== frame
);
1604 FOR_EACH_OBSERVER(RenderViewObserver
, render_view_
->observers(),
1606 newly_matching_selectors
,
1607 stopped_matching_selectors
));
1610 bool RenderFrameImpl::shouldReportDetailedMessageForSource(
1611 const blink::WebString
& source
) {
1612 return GetContentClient()->renderer()->ShouldReportDetailedMessageForSource(
1616 void RenderFrameImpl::didAddMessageToConsole(
1617 const blink::WebConsoleMessage
& message
,
1618 const blink::WebString
& source_name
,
1619 unsigned source_line
,
1620 const blink::WebString
& stack_trace
) {
1621 logging::LogSeverity log_severity
= logging::LOG_VERBOSE
;
1622 switch (message
.level
) {
1623 case blink::WebConsoleMessage::LevelDebug
:
1624 log_severity
= logging::LOG_VERBOSE
;
1626 case blink::WebConsoleMessage::LevelLog
:
1627 case blink::WebConsoleMessage::LevelInfo
:
1628 log_severity
= logging::LOG_INFO
;
1630 case blink::WebConsoleMessage::LevelWarning
:
1631 log_severity
= logging::LOG_WARNING
;
1633 case blink::WebConsoleMessage::LevelError
:
1634 log_severity
= logging::LOG_ERROR
;
1640 if (shouldReportDetailedMessageForSource(source_name
)) {
1642 RenderFrameObserver
, observers_
,
1643 DetailedConsoleMessageAdded(message
.text
,
1647 static_cast<int32
>(log_severity
)));
1650 Send(new FrameHostMsg_AddMessageToConsole(routing_id_
,
1651 static_cast<int32
>(log_severity
),
1653 static_cast<int32
>(source_line
),
1657 void RenderFrameImpl::loadURLExternally(
1658 blink::WebLocalFrame
* frame
,
1659 const blink::WebURLRequest
& request
,
1660 blink::WebNavigationPolicy policy
,
1661 const blink::WebString
& suggested_name
) {
1662 DCHECK(!frame_
|| frame_
== frame
);
1663 Referrer
referrer(RenderViewImpl::GetReferrerFromRequest(frame
, request
));
1664 if (policy
== blink::WebNavigationPolicyDownload
) {
1665 render_view_
->Send(new ViewHostMsg_DownloadUrl(render_view_
->GetRoutingID(),
1666 request
.url(), referrer
,
1667 suggested_name
, false));
1668 } else if (policy
== blink::WebNavigationPolicyDownloadTo
) {
1669 render_view_
->Send(new ViewHostMsg_DownloadUrl(render_view_
->GetRoutingID(),
1670 request
.url(), referrer
,
1671 suggested_name
, true));
1673 OpenURL(frame
, request
.url(), referrer
, policy
);
1677 blink::WebNavigationPolicy
RenderFrameImpl::decidePolicyForNavigation(
1678 blink::WebLocalFrame
* frame
,
1679 blink::WebDataSource::ExtraData
* extra_data
,
1680 const blink::WebURLRequest
& request
,
1681 blink::WebNavigationType type
,
1682 blink::WebNavigationPolicy default_policy
,
1684 DCHECK(!frame_
|| frame_
== frame
);
1685 return DecidePolicyForNavigation(
1686 this, frame
, extra_data
, request
, type
, default_policy
, is_redirect
);
1689 blink::WebHistoryItem
RenderFrameImpl::historyItemForNewChildFrame(
1690 blink::WebFrame
* frame
) {
1691 DCHECK(!frame_
|| frame_
== frame
);
1692 return render_view_
->history_controller()->GetItemForNewChildFrame(this);
1695 void RenderFrameImpl::willSendSubmitEvent(blink::WebLocalFrame
* frame
,
1696 const blink::WebFormElement
& form
) {
1697 DCHECK(!frame_
|| frame_
== frame
);
1699 FOR_EACH_OBSERVER(RenderViewObserver
, render_view_
->observers(),
1700 WillSendSubmitEvent(frame
, form
));
1703 void RenderFrameImpl::willSubmitForm(blink::WebLocalFrame
* frame
,
1704 const blink::WebFormElement
& form
) {
1705 DCHECK(!frame_
|| frame_
== frame
);
1706 DocumentState
* document_state
=
1707 DocumentState::FromDataSource(frame
->provisionalDataSource());
1708 NavigationState
* navigation_state
= document_state
->navigation_state();
1709 InternalDocumentStateData
* internal_data
=
1710 InternalDocumentStateData::FromDocumentState(document_state
);
1712 if (PageTransitionCoreTypeIs(navigation_state
->transition_type(),
1713 PAGE_TRANSITION_LINK
)) {
1714 navigation_state
->set_transition_type(PAGE_TRANSITION_FORM_SUBMIT
);
1717 // Save these to be processed when the ensuing navigation is committed.
1718 WebSearchableFormData
web_searchable_form_data(form
);
1719 internal_data
->set_searchable_form_url(web_searchable_form_data
.url());
1720 internal_data
->set_searchable_form_encoding(
1721 web_searchable_form_data
.encoding().utf8());
1723 FOR_EACH_OBSERVER(RenderViewObserver
, render_view_
->observers(),
1724 WillSubmitForm(frame
, form
));
1727 void RenderFrameImpl::didCreateDataSource(blink::WebLocalFrame
* frame
,
1728 blink::WebDataSource
* datasource
) {
1729 DCHECK(!frame_
|| frame_
== frame
);
1731 // TODO(nasko): Move implementation here. Needed state:
1732 // * pending_navigation_params_
1735 // * PopulateDocumentStateFromPending
1736 // * CreateNavigationStateFromPending
1737 render_view_
->didCreateDataSource(frame
, datasource
);
1739 // Create the serviceworker's per-document network observing object.
1740 scoped_ptr
<ServiceWorkerNetworkProvider
>
1741 network_provider(new ServiceWorkerNetworkProvider());
1742 ServiceWorkerNetworkProvider::AttachToDocumentState(
1743 DocumentState::FromDataSource(datasource
),
1744 network_provider
.Pass());
1747 void RenderFrameImpl::didStartProvisionalLoad(blink::WebLocalFrame
* frame
) {
1748 DCHECK(!frame_
|| frame_
== frame
);
1749 WebDataSource
* ds
= frame
->provisionalDataSource();
1751 // In fast/loader/stop-provisional-loads.html, we abort the load before this
1752 // callback is invoked.
1756 DocumentState
* document_state
= DocumentState::FromDataSource(ds
);
1758 // We should only navigate to swappedout:// when is_swapped_out_ is true.
1759 CHECK((ds
->request().url() != GURL(kSwappedOutURL
)) ||
1761 render_view_
->is_swapped_out()) <<
1762 "Heard swappedout:// when not swapped out.";
1764 // Update the request time if WebKit has better knowledge of it.
1765 if (document_state
->request_time().is_null()) {
1766 double event_time
= ds
->triggeringEventTime();
1767 if (event_time
!= 0.0)
1768 document_state
->set_request_time(Time::FromDoubleT(event_time
));
1771 // Start time is only set after request time.
1772 document_state
->set_start_load_time(Time::Now());
1774 bool is_top_most
= !frame
->parent();
1776 render_view_
->set_navigation_gesture(
1777 WebUserGestureIndicator::isProcessingUserGesture() ?
1778 NavigationGestureUser
: NavigationGestureAuto
);
1779 } else if (ds
->replacesCurrentHistoryItem()) {
1780 // Subframe navigations that don't add session history items must be
1781 // marked with AUTO_SUBFRAME. See also didFailProvisionalLoad for how we
1782 // handle loading of error pages.
1783 document_state
->navigation_state()->set_transition_type(
1784 PAGE_TRANSITION_AUTO_SUBFRAME
);
1787 FOR_EACH_OBSERVER(RenderViewObserver
, render_view_
->observers(),
1788 DidStartProvisionalLoad(frame
));
1789 FOR_EACH_OBSERVER(RenderFrameObserver
, observers_
, DidStartProvisionalLoad());
1791 int parent_routing_id
= frame
->parent() ?
1792 FromWebFrame(frame
->parent())->GetRoutingID() : -1;
1793 Send(new FrameHostMsg_DidStartProvisionalLoadForFrame(
1794 routing_id_
, parent_routing_id
, ds
->request().url()));
1797 void RenderFrameImpl::didReceiveServerRedirectForProvisionalLoad(
1798 blink::WebLocalFrame
* frame
) {
1799 DCHECK(!frame_
|| frame_
== frame
);
1800 render_view_
->history_controller()->RemoveChildrenForRedirect(this);
1801 if (frame
->parent())
1803 // Received a redirect on the main frame.
1804 WebDataSource
* data_source
= frame
->provisionalDataSource();
1806 // Should only be invoked when we have a data source.
1810 std::vector
<GURL
> redirects
;
1811 GetRedirectChain(data_source
, &redirects
);
1812 if (redirects
.size() >= 2) {
1813 Send(new FrameHostMsg_DidRedirectProvisionalLoad(
1815 render_view_
->page_id_
,
1816 redirects
[redirects
.size() - 2],
1821 void RenderFrameImpl::didFailProvisionalLoad(blink::WebLocalFrame
* frame
,
1822 const blink::WebURLError
& error
) {
1823 DCHECK(!frame_
|| frame_
== frame
);
1824 WebDataSource
* ds
= frame
->provisionalDataSource();
1827 const WebURLRequest
& failed_request
= ds
->request();
1829 // Notify the browser that we failed a provisional load with an error.
1831 // Note: It is important this notification occur before DidStopLoading so the
1832 // SSL manager can react to the provisional load failure before being
1833 // notified the load stopped.
1835 FOR_EACH_OBSERVER(RenderViewObserver
, render_view_
->observers(),
1836 DidFailProvisionalLoad(frame
, error
));
1837 FOR_EACH_OBSERVER(RenderFrameObserver
, observers_
,
1838 DidFailProvisionalLoad(error
));
1840 bool show_repost_interstitial
=
1841 (error
.reason
== net::ERR_CACHE_MISS
&&
1842 EqualsASCII(failed_request
.httpMethod(), "POST"));
1844 FrameHostMsg_DidFailProvisionalLoadWithError_Params params
;
1845 params
.frame_unique_name
= frame
->uniqueName();
1846 params
.error_code
= error
.reason
;
1847 GetContentClient()->renderer()->GetNavigationErrorStrings(
1853 ¶ms
.error_description
);
1854 params
.url
= error
.unreachableURL
;
1855 params
.showing_repost_interstitial
= show_repost_interstitial
;
1856 Send(new FrameHostMsg_DidFailProvisionalLoadWithError(
1857 routing_id_
, params
));
1859 // Don't display an error page if this is simply a cancelled load. Aside
1860 // from being dumb, WebCore doesn't expect it and it will cause a crash.
1861 if (error
.reason
== net::ERR_ABORTED
)
1864 // Don't display "client blocked" error page if browser has asked us not to.
1865 if (error
.reason
== net::ERR_BLOCKED_BY_CLIENT
&&
1866 render_view_
->renderer_preferences_
.disable_client_blocked_error_page
) {
1870 // Allow the embedder to suppress an error page.
1871 if (GetContentClient()->renderer()->ShouldSuppressErrorPage(this,
1872 error
.unreachableURL
)) {
1876 if (RenderThreadImpl::current() &&
1877 RenderThreadImpl::current()->layout_test_mode()) {
1881 // Make sure we never show errors in view source mode.
1882 frame
->enableViewSourceMode(false);
1884 DocumentState
* document_state
= DocumentState::FromDataSource(ds
);
1885 NavigationState
* navigation_state
= document_state
->navigation_state();
1887 // If this is a failed back/forward/reload navigation, then we need to do a
1888 // 'replace' load. This is necessary to avoid messing up session history.
1889 // Otherwise, we do a normal load, which simulates a 'go' navigation as far
1890 // as session history is concerned.
1892 // AUTO_SUBFRAME loads should always be treated as loads that do not advance
1895 // TODO(davidben): This should also take the failed navigation's replacement
1896 // state into account, if a location.replace() failed.
1898 navigation_state
->pending_page_id() != -1 ||
1899 PageTransitionCoreTypeIs(navigation_state
->transition_type(),
1900 PAGE_TRANSITION_AUTO_SUBFRAME
);
1902 // If we failed on a browser initiated request, then make sure that our error
1903 // page load is regarded as the same browser initiated request.
1904 if (!navigation_state
->is_content_initiated()) {
1905 render_view_
->pending_navigation_params_
.reset(
1906 new FrameMsg_Navigate_Params
);
1907 render_view_
->pending_navigation_params_
->page_id
=
1908 navigation_state
->pending_page_id();
1909 render_view_
->pending_navigation_params_
->pending_history_list_offset
=
1910 navigation_state
->pending_history_list_offset();
1911 render_view_
->pending_navigation_params_
->should_clear_history_list
=
1912 navigation_state
->history_list_was_cleared();
1913 render_view_
->pending_navigation_params_
->transition
=
1914 navigation_state
->transition_type();
1915 render_view_
->pending_navigation_params_
->request_time
=
1916 document_state
->request_time();
1917 render_view_
->pending_navigation_params_
->should_replace_current_entry
=
1921 // Load an error page.
1922 LoadNavigationErrorPage(failed_request
, error
, replace
);
1925 void RenderFrameImpl::didCommitProvisionalLoad(
1926 blink::WebLocalFrame
* frame
,
1927 const blink::WebHistoryItem
& item
,
1928 blink::WebHistoryCommitType commit_type
) {
1929 DCHECK(!frame_
|| frame_
== frame
);
1930 DocumentState
* document_state
=
1931 DocumentState::FromDataSource(frame
->dataSource());
1932 NavigationState
* navigation_state
= document_state
->navigation_state();
1934 // When we perform a new navigation, we need to update the last committed
1935 // session history entry with state for the page we are leaving. Do this
1936 // before updating the HistoryController state.
1937 render_view_
->UpdateSessionHistory(frame
);
1939 render_view_
->history_controller()->UpdateForCommit(this, item
, commit_type
,
1940 navigation_state
->was_within_same_page());
1942 InternalDocumentStateData
* internal_data
=
1943 InternalDocumentStateData::FromDocumentState(document_state
);
1945 if (document_state
->commit_load_time().is_null())
1946 document_state
->set_commit_load_time(Time::Now());
1948 if (internal_data
->must_reset_scroll_and_scale_state()) {
1949 render_view_
->webview()->resetScrollAndScaleState();
1950 internal_data
->set_must_reset_scroll_and_scale_state(false);
1952 internal_data
->set_use_error_page(false);
1954 bool is_new_navigation
= commit_type
== blink::WebStandardCommit
;
1955 if (is_new_navigation
) {
1956 // We bump our Page ID to correspond with the new session history entry.
1957 render_view_
->page_id_
= render_view_
->next_page_id_
++;
1959 // Don't update history_page_ids_ (etc) for kSwappedOutURL, since
1960 // we don't want to forget the entry that was there, and since we will
1961 // never come back to kSwappedOutURL. Note that we have to call
1962 // UpdateSessionHistory and update page_id_ even in this case, so that
1963 // the current entry gets a state update and so that we don't send a
1964 // state update to the wrong entry when we swap back in.
1965 if (render_view_
->GetLoadingUrl(frame
) != GURL(kSwappedOutURL
)) {
1966 // Advance our offset in session history, applying the length limit.
1967 // There is now no forward history.
1968 render_view_
->history_list_offset_
++;
1969 if (render_view_
->history_list_offset_
>= kMaxSessionHistoryEntries
)
1970 render_view_
->history_list_offset_
= kMaxSessionHistoryEntries
- 1;
1971 render_view_
->history_list_length_
=
1972 render_view_
->history_list_offset_
+ 1;
1973 render_view_
->history_page_ids_
.resize(
1974 render_view_
->history_list_length_
, -1);
1975 render_view_
->history_page_ids_
[render_view_
->history_list_offset_
] =
1976 render_view_
->page_id_
;
1979 // Inspect the navigation_state on this frame to see if the navigation
1980 // corresponds to a session history navigation... Note: |frame| may or
1981 // may not be the toplevel frame, but for the case of capturing session
1982 // history, the first committed frame suffices. We keep track of whether
1983 // we've seen this commit before so that only capture session history once
1986 // Note that we need to check if the page ID changed. In the case of a
1987 // reload, the page ID doesn't change, and UpdateSessionHistory gets the
1988 // previous URL and the current page ID, which would be wrong.
1989 if (navigation_state
->pending_page_id() != -1 &&
1990 navigation_state
->pending_page_id() != render_view_
->page_id_
&&
1991 !navigation_state
->request_committed()) {
1992 // This is a successful session history navigation!
1993 render_view_
->page_id_
= navigation_state
->pending_page_id();
1995 render_view_
->history_list_offset_
=
1996 navigation_state
->pending_history_list_offset();
1998 // If the history list is valid, our list of page IDs should be correct.
1999 DCHECK(render_view_
->history_list_length_
<= 0 ||
2000 render_view_
->history_list_offset_
< 0 ||
2001 render_view_
->history_list_offset_
>=
2002 render_view_
->history_list_length_
||
2003 render_view_
->history_page_ids_
[render_view_
->history_list_offset_
]
2004 == render_view_
->page_id_
);
2008 render_view_
->FrameDidCommitProvisionalLoad(frame
, is_new_navigation
);
2009 FOR_EACH_OBSERVER(RenderFrameObserver
, observers_
,
2010 DidCommitProvisionalLoad(is_new_navigation
));
2012 // Remember that we've already processed this request, so we don't update
2013 // the session history again. We do this regardless of whether this is
2014 // a session history navigation, because if we attempted a session history
2015 // navigation without valid HistoryItem state, WebCore will think it is a
2017 navigation_state
->set_request_committed(true);
2021 // Check whether we have new encoding name.
2022 UpdateEncoding(frame
, frame
->view()->pageEncoding().utf8());
2025 void RenderFrameImpl::didClearWindowObject(blink::WebLocalFrame
* frame
) {
2026 DCHECK(!frame_
|| frame_
== frame
);
2027 // TODO(nasko): Move implementation here. Needed state:
2028 // * enabled_bindings_
2029 // * dom_automation_controller_
2030 // * stats_collection_controller_
2032 render_view_
->didClearWindowObject(frame
);
2034 if (render_view_
->GetEnabledBindings() & BINDINGS_POLICY_DOM_AUTOMATION
)
2035 DomAutomationController::Install(this, frame
);
2037 FOR_EACH_OBSERVER(RenderFrameObserver
, observers_
, DidClearWindowObject());
2040 void RenderFrameImpl::didCreateDocumentElement(blink::WebLocalFrame
* frame
) {
2041 DCHECK(!frame_
|| frame_
== frame
);
2043 // Notify the browser about non-blank documents loading in the top frame.
2044 GURL url
= frame
->document().url();
2045 if (url
.is_valid() && url
.spec() != url::kAboutBlankURL
) {
2046 // TODO(nasko): Check if webview()->mainFrame() is the same as the
2047 // frame->tree()->top().
2048 blink::WebFrame
* main_frame
= render_view_
->webview()->mainFrame();
2049 if (frame
== main_frame
) {
2050 // For now, don't remember plugin zoom values. We don't want to mix them
2051 // with normal web content (i.e. a fixed layout plugin would usually want
2053 render_view_
->Send(new ViewHostMsg_DocumentAvailableInMainFrame(
2054 render_view_
->GetRoutingID(),
2055 main_frame
->document().isPluginDocument()));
2059 FOR_EACH_OBSERVER(RenderViewObserver
, render_view_
->observers(),
2060 DidCreateDocumentElement(frame
));
2063 void RenderFrameImpl::didReceiveTitle(blink::WebLocalFrame
* frame
,
2064 const blink::WebString
& title
,
2065 blink::WebTextDirection direction
) {
2066 DCHECK(!frame_
|| frame_
== frame
);
2067 // Ignore all but top level navigations.
2068 if (!frame
->parent()) {
2069 base::string16 title16
= title
;
2070 base::debug::TraceLog::GetInstance()->UpdateProcessLabel(
2071 routing_id_
, base::UTF16ToUTF8(title16
));
2073 base::string16 shortened_title
= title16
.substr(0, kMaxTitleChars
);
2074 Send(new FrameHostMsg_UpdateTitle(routing_id_
,
2075 render_view_
->page_id_
,
2076 shortened_title
, direction
));
2079 // Also check whether we have new encoding name.
2080 UpdateEncoding(frame
, frame
->view()->pageEncoding().utf8());
2083 void RenderFrameImpl::didChangeIcon(blink::WebLocalFrame
* frame
,
2084 blink::WebIconURL::Type icon_type
) {
2085 DCHECK(!frame_
|| frame_
== frame
);
2086 // TODO(nasko): Investigate wheather implementation should move here.
2087 render_view_
->didChangeIcon(frame
, icon_type
);
2090 void RenderFrameImpl::didFinishDocumentLoad(blink::WebLocalFrame
* frame
) {
2091 DCHECK(!frame_
|| frame_
== frame
);
2092 WebDataSource
* ds
= frame
->dataSource();
2093 DocumentState
* document_state
= DocumentState::FromDataSource(ds
);
2094 document_state
->set_finish_document_load_time(Time::Now());
2096 Send(new FrameHostMsg_DidFinishDocumentLoad(routing_id_
));
2098 FOR_EACH_OBSERVER(RenderViewObserver
, render_view_
->observers(),
2099 DidFinishDocumentLoad(frame
));
2100 FOR_EACH_OBSERVER(RenderFrameObserver
, observers_
, DidFinishDocumentLoad());
2102 // Check whether we have new encoding name.
2103 UpdateEncoding(frame
, frame
->view()->pageEncoding().utf8());
2106 void RenderFrameImpl::didHandleOnloadEvents(blink::WebLocalFrame
* frame
) {
2107 DCHECK(!frame_
|| frame_
== frame
);
2108 if (!frame
->parent())
2109 Send(new FrameHostMsg_DocumentOnLoadCompleted(routing_id_
));
2112 void RenderFrameImpl::didFailLoad(blink::WebLocalFrame
* frame
,
2113 const blink::WebURLError
& error
) {
2114 DCHECK(!frame_
|| frame_
== frame
);
2115 // TODO(nasko): Move implementation here. No state needed.
2116 WebDataSource
* ds
= frame
->dataSource();
2119 FOR_EACH_OBSERVER(RenderViewObserver
, render_view_
->observers(),
2120 DidFailLoad(frame
, error
));
2122 const WebURLRequest
& failed_request
= ds
->request();
2123 base::string16 error_description
;
2124 GetContentClient()->renderer()->GetNavigationErrorStrings(
2130 &error_description
);
2131 Send(new FrameHostMsg_DidFailLoadWithError(routing_id_
,
2132 failed_request
.url(),
2134 error_description
));
2137 void RenderFrameImpl::didFinishLoad(blink::WebLocalFrame
* frame
) {
2138 DCHECK(!frame_
|| frame_
== frame
);
2139 WebDataSource
* ds
= frame
->dataSource();
2140 DocumentState
* document_state
= DocumentState::FromDataSource(ds
);
2141 if (document_state
->finish_load_time().is_null()) {
2142 if (!frame
->parent()) {
2143 TRACE_EVENT_INSTANT0("WebCore", "LoadFinished",
2144 TRACE_EVENT_SCOPE_PROCESS
);
2146 document_state
->set_finish_load_time(Time::Now());
2149 FOR_EACH_OBSERVER(RenderViewObserver
, render_view_
->observers(),
2150 DidFinishLoad(frame
));
2151 FOR_EACH_OBSERVER(RenderFrameObserver
, observers_
, DidFinishLoad());
2153 // Don't send this message while the frame is swapped out.
2154 if (is_swapped_out())
2157 Send(new FrameHostMsg_DidFinishLoad(routing_id_
,
2158 ds
->request().url()));
2161 void RenderFrameImpl::didNavigateWithinPage(blink::WebLocalFrame
* frame
,
2162 const blink::WebHistoryItem
& item
,
2163 blink::WebHistoryCommitType commit_type
) {
2164 DCHECK(!frame_
|| frame_
== frame
);
2165 // If this was a reference fragment navigation that we initiated, then we
2166 // could end up having a non-null pending navigation params. We just need to
2167 // update the ExtraData on the datasource so that others who read the
2168 // ExtraData will get the new NavigationState. Similarly, if we did not
2169 // initiate this navigation, then we need to take care to reset any pre-
2170 // existing navigation state to a content-initiated navigation state.
2171 // DidCreateDataSource conveniently takes care of this for us.
2172 didCreateDataSource(frame
, frame
->dataSource());
2174 DocumentState
* document_state
=
2175 DocumentState::FromDataSource(frame
->dataSource());
2176 NavigationState
* new_state
= document_state
->navigation_state();
2177 new_state
->set_was_within_same_page(true);
2179 didCommitProvisionalLoad(frame
, item
, commit_type
);
2182 void RenderFrameImpl::didUpdateCurrentHistoryItem(blink::WebLocalFrame
* frame
) {
2183 DCHECK(!frame_
|| frame_
== frame
);
2184 // TODO(nasko): Move implementation here. Needed methods:
2185 // * StartNavStateSyncTimerIfNecessary
2186 render_view_
->didUpdateCurrentHistoryItem(frame
);
2189 blink::WebNotificationPresenter
* RenderFrameImpl::notificationPresenter() {
2190 return notification_provider_
;
2193 void RenderFrameImpl::didChangeSelection(bool is_empty_selection
) {
2194 if (!GetRenderWidget()->handling_input_event() && !handling_select_range_
)
2197 if (is_empty_selection
)
2198 selection_text_
.clear();
2200 // UpdateTextInputType should be called before SyncSelectionIfRequired.
2201 // UpdateTextInputType may send TextInputTypeChanged to notify the focus
2202 // was changed, and SyncSelectionIfRequired may send SelectionChanged
2203 // to notify the selection was changed. Focus change should be notified
2204 // before selection change.
2205 GetRenderWidget()->UpdateTextInputType();
2206 SyncSelectionIfRequired();
2207 #if defined(OS_ANDROID)
2208 GetRenderWidget()->UpdateTextInputState(RenderWidget::NO_SHOW_IME
,
2209 RenderWidget::FROM_NON_IME
);
2213 blink::WebColorChooser
* RenderFrameImpl::createColorChooser(
2214 blink::WebColorChooserClient
* client
,
2215 const blink::WebColor
& initial_color
,
2216 const blink::WebVector
<blink::WebColorSuggestion
>& suggestions
) {
2217 RendererWebColorChooserImpl
* color_chooser
=
2218 new RendererWebColorChooserImpl(this, client
);
2219 std::vector
<content::ColorSuggestion
> color_suggestions
;
2220 for (size_t i
= 0; i
< suggestions
.size(); i
++) {
2221 color_suggestions
.push_back(content::ColorSuggestion(suggestions
[i
]));
2223 color_chooser
->Open(static_cast<SkColor
>(initial_color
), color_suggestions
);
2224 return color_chooser
;
2227 void RenderFrameImpl::runModalAlertDialog(const blink::WebString
& message
) {
2228 RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_ALERT
,
2231 frame_
->document().url(),
2235 bool RenderFrameImpl::runModalConfirmDialog(const blink::WebString
& message
) {
2236 return RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_CONFIRM
,
2239 frame_
->document().url(),
2243 bool RenderFrameImpl::runModalPromptDialog(
2244 const blink::WebString
& message
,
2245 const blink::WebString
& default_value
,
2246 blink::WebString
* actual_value
) {
2247 base::string16 result
;
2248 bool ok
= RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_PROMPT
,
2251 frame_
->document().url(),
2254 actual_value
->assign(result
);
2258 bool RenderFrameImpl::runModalBeforeUnloadDialog(
2260 const blink::WebString
& message
) {
2261 // If we are swapping out, we have already run the beforeunload handler.
2262 // TODO(creis): Fix OnSwapOut to clear the frame without running beforeunload
2263 // at all, to avoid running it twice.
2264 if (render_view()->is_swapped_out_
)
2267 // Don't allow further dialogs if we are waiting to swap out, since the
2268 // PageGroupLoadDeferrer in our stack prevents it.
2269 if (render_view()->suppress_dialogs_until_swap_out_
)
2272 bool success
= false;
2273 // This is an ignored return value, but is included so we can accept the same
2274 // response as RunJavaScriptMessage.
2275 base::string16 ignored_result
;
2276 render_view()->SendAndRunNestedMessageLoop(
2277 new FrameHostMsg_RunBeforeUnloadConfirm(
2278 routing_id_
, frame_
->document().url(), message
, is_reload
,
2279 &success
, &ignored_result
));
2283 void RenderFrameImpl::showContextMenu(const blink::WebContextMenuData
& data
) {
2284 ContextMenuParams params
= ContextMenuParamsBuilder::Build(data
);
2285 params
.source_type
= GetRenderWidget()->context_menu_source_type();
2286 if (params
.source_type
== ui::MENU_SOURCE_TOUCH_EDIT_MENU
) {
2287 params
.x
= GetRenderWidget()->touch_editing_context_menu_location().x();
2288 params
.y
= GetRenderWidget()->touch_editing_context_menu_location().y();
2290 GetRenderWidget()->OnShowHostContextMenu(¶ms
);
2292 // Plugins, e.g. PDF, don't currently update the render view when their
2293 // selected text changes, but the context menu params do contain the updated
2294 // selection. If that's the case, update the render view's state just prior
2295 // to showing the context menu.
2296 // TODO(asvitkine): http://crbug.com/152432
2297 if (ShouldUpdateSelectionTextFromContextMenuParams(
2298 selection_text_
, selection_text_offset_
, selection_range_
, params
)) {
2299 selection_text_
= params
.selection_text
;
2300 // TODO(asvitkine): Text offset and range is not available in this case.
2301 selection_text_offset_
= 0;
2302 selection_range_
= gfx::Range(0, selection_text_
.length());
2303 // This IPC is dispatched by RenderWidetHost, so use its routing ID.
2304 Send(new ViewHostMsg_SelectionChanged(
2305 GetRenderWidget()->routing_id(), selection_text_
,
2306 selection_text_offset_
, selection_range_
));
2309 // Serializing a GURL longer than kMaxURLChars will fail, so don't do
2310 // it. We replace it with an empty GURL so the appropriate items are disabled
2311 // in the context menu.
2312 // TODO(jcivelli): http://crbug.com/45160 This prevents us from saving large
2313 // data encoded images. We should have a way to save them.
2314 if (params
.src_url
.spec().size() > GetMaxURLChars())
2315 params
.src_url
= GURL();
2316 context_menu_node_
= data
.node
;
2318 #if defined(OS_ANDROID)
2319 gfx::Rect start_rect
;
2321 GetRenderWidget()->GetSelectionBounds(&start_rect
, &end_rect
);
2322 params
.selection_start
= gfx::Point(start_rect
.x(), start_rect
.bottom());
2323 params
.selection_end
= gfx::Point(end_rect
.right(), end_rect
.bottom());
2326 Send(new FrameHostMsg_ContextMenu(routing_id_
, params
));
2329 void RenderFrameImpl::clearContextMenu() {
2330 context_menu_node_
.reset();
2333 void RenderFrameImpl::willRequestAfterPreconnect(
2334 blink::WebLocalFrame
* frame
,
2335 blink::WebURLRequest
& request
) {
2336 DCHECK(!frame_
|| frame_
== frame
);
2337 // FIXME(kohei): This will never be set.
2338 WebString custom_user_agent
;
2340 DCHECK(!request
.extraData());
2342 bool was_after_preconnect_request
= true;
2343 // The args after |was_after_preconnect_request| are not used, and set to
2344 // correct values at |willSendRequest|.
2345 RequestExtraData
* extra_data
= new RequestExtraData();
2346 extra_data
->set_custom_user_agent(custom_user_agent
);
2347 extra_data
->set_was_after_preconnect_request(was_after_preconnect_request
);
2348 request
.setExtraData(extra_data
);
2351 void RenderFrameImpl::willSendRequest(
2352 blink::WebLocalFrame
* frame
,
2353 unsigned identifier
,
2354 blink::WebURLRequest
& request
,
2355 const blink::WebURLResponse
& redirect_response
) {
2356 DCHECK(!frame_
|| frame_
== frame
);
2357 // The request my be empty during tests.
2358 if (request
.url().isEmpty())
2361 // Set the first party for cookies url if it has not been set yet (new
2362 // requests). For redirects, it is updated by WebURLLoaderImpl.
2363 if (request
.firstPartyForCookies().isEmpty()) {
2364 if (request
.targetType() == blink::WebURLRequest::TargetIsMainFrame
) {
2365 request
.setFirstPartyForCookies(request
.url());
2367 request
.setFirstPartyForCookies(
2368 frame
->top()->document().firstPartyForCookies());
2372 WebFrame
* top_frame
= frame
->top();
2375 WebDataSource
* provisional_data_source
= top_frame
->provisionalDataSource();
2376 WebDataSource
* top_data_source
= top_frame
->dataSource();
2377 WebDataSource
* data_source
=
2378 provisional_data_source
? provisional_data_source
: top_data_source
;
2380 PageTransition transition_type
= PAGE_TRANSITION_LINK
;
2381 DocumentState
* document_state
= DocumentState::FromDataSource(data_source
);
2382 DCHECK(document_state
);
2383 InternalDocumentStateData
* internal_data
=
2384 InternalDocumentStateData::FromDocumentState(document_state
);
2385 NavigationState
* navigation_state
= document_state
->navigation_state();
2386 transition_type
= navigation_state
->transition_type();
2388 GURL
request_url(request
.url());
2390 if (GetContentClient()->renderer()->WillSendRequest(
2394 request
.firstPartyForCookies(),
2396 request
.setURL(WebURL(new_url
));
2399 if (internal_data
->is_cache_policy_override_set())
2400 request
.setCachePolicy(internal_data
->cache_policy_override());
2402 // The request's extra data may indicate that we should set a custom user
2403 // agent. This needs to be done here, after WebKit is through with setting the
2404 // user agent on its own.
2405 WebString custom_user_agent
;
2406 bool was_after_preconnect_request
= false;
2407 if (request
.extraData()) {
2408 RequestExtraData
* old_extra_data
=
2409 static_cast<RequestExtraData
*>(
2410 request
.extraData());
2411 custom_user_agent
= old_extra_data
->custom_user_agent();
2412 was_after_preconnect_request
=
2413 old_extra_data
->was_after_preconnect_request();
2415 if (!custom_user_agent
.isNull()) {
2416 if (custom_user_agent
.isEmpty())
2417 request
.clearHTTPHeaderField("User-Agent");
2419 request
.setHTTPHeaderField("User-Agent", custom_user_agent
);
2423 // Add the default accept header for frame request if it has not been set
2425 if ((request
.targetType() == blink::WebURLRequest::TargetIsMainFrame
||
2426 request
.targetType() == blink::WebURLRequest::TargetIsSubframe
) &&
2427 request
.httpHeaderField(WebString::fromUTF8(kAcceptHeader
)).isEmpty()) {
2428 request
.setHTTPHeaderField(WebString::fromUTF8(kAcceptHeader
),
2429 WebString::fromUTF8(kDefaultAcceptHeader
));
2432 // Attach |should_replace_current_entry| state to requests so that, should
2433 // this navigation later require a request transfer, all state is preserved
2434 // when it is re-created in the new process.
2435 bool should_replace_current_entry
= false;
2436 if (navigation_state
->is_content_initiated()) {
2437 should_replace_current_entry
= data_source
->replacesCurrentHistoryItem();
2439 // If the navigation is browser-initiated, the NavigationState contains the
2440 // correct value instead of the WebDataSource.
2442 // TODO(davidben): Avoid this awkward duplication of state. See comment on
2443 // NavigationState::should_replace_current_entry().
2444 should_replace_current_entry
=
2445 navigation_state
->should_replace_current_entry();
2448 int provider_id
= kInvalidServiceWorkerProviderId
;
2449 if (request
.targetType() == blink::WebURLRequest::TargetIsMainFrame
||
2450 request
.targetType() == blink::WebURLRequest::TargetIsSubframe
) {
2451 // |provisionalDataSource| may be null in some content::ResourceFetcher
2452 // use cases, we don't hook those requests.
2453 if (frame
->provisionalDataSource()) {
2454 ServiceWorkerNetworkProvider
* provider
=
2455 ServiceWorkerNetworkProvider::FromDocumentState(
2456 DocumentState::FromDataSource(frame
->provisionalDataSource()));
2457 provider_id
= provider
->provider_id();
2459 } else if (frame
->dataSource()) {
2460 ServiceWorkerNetworkProvider
* provider
=
2461 ServiceWorkerNetworkProvider::FromDocumentState(
2462 DocumentState::FromDataSource(frame
->dataSource()));
2463 provider_id
= provider
->provider_id();
2466 int parent_routing_id
= frame
->parent() ?
2467 FromWebFrame(frame
->parent())->GetRoutingID() : -1;
2468 RequestExtraData
* extra_data
= new RequestExtraData();
2469 extra_data
->set_visibility_state(render_view_
->visibilityState());
2470 extra_data
->set_custom_user_agent(custom_user_agent
);
2471 extra_data
->set_was_after_preconnect_request(was_after_preconnect_request
);
2472 extra_data
->set_render_frame_id(routing_id_
);
2473 extra_data
->set_is_main_frame(frame
== top_frame
);
2474 extra_data
->set_frame_origin(
2475 GURL(frame
->document().securityOrigin().toString()));
2476 extra_data
->set_parent_is_main_frame(frame
->parent() == top_frame
);
2477 extra_data
->set_parent_render_frame_id(parent_routing_id
);
2478 extra_data
->set_allow_download(navigation_state
->allow_download());
2479 extra_data
->set_transition_type(transition_type
);
2480 extra_data
->set_should_replace_current_entry(should_replace_current_entry
);
2481 extra_data
->set_transferred_request_child_id(
2482 navigation_state
->transferred_request_child_id());
2483 extra_data
->set_transferred_request_request_id(
2484 navigation_state
->transferred_request_request_id());
2485 extra_data
->set_service_worker_provider_id(provider_id
);
2486 request
.setExtraData(extra_data
);
2488 DocumentState
* top_document_state
=
2489 DocumentState::FromDataSource(top_data_source
);
2490 if (top_document_state
) {
2491 // TODO(gavinp): separate out prefetching and prerender field trials
2492 // if the rel=prerender rel type is sticking around.
2493 if (request
.targetType() == WebURLRequest::TargetIsPrefetch
)
2494 top_document_state
->set_was_prefetcher(true);
2496 if (was_after_preconnect_request
)
2497 top_document_state
->set_was_after_preconnect_request(true);
2500 // This is an instance where we embed a copy of the routing id
2501 // into the data portion of the message. This can cause problems if we
2502 // don't register this id on the browser side, since the download manager
2503 // expects to find a RenderViewHost based off the id.
2504 request
.setRequestorID(render_view_
->GetRoutingID());
2505 request
.setHasUserGesture(WebUserGestureIndicator::isProcessingUserGesture());
2507 if (!navigation_state
->extra_headers().empty()) {
2508 for (net::HttpUtil::HeadersIterator
i(
2509 navigation_state
->extra_headers().begin(),
2510 navigation_state
->extra_headers().end(), "\n");
2512 if (LowerCaseEqualsASCII(i
.name(), "referer")) {
2513 WebString referrer
= WebSecurityPolicy::generateReferrerHeader(
2514 blink::WebReferrerPolicyDefault
,
2516 WebString::fromUTF8(i
.values()));
2517 request
.setHTTPReferrer(referrer
, blink::WebReferrerPolicyDefault
);
2519 request
.setHTTPHeaderField(WebString::fromUTF8(i
.name()),
2520 WebString::fromUTF8(i
.values()));
2525 if (!render_view_
->renderer_preferences_
.enable_referrers
)
2526 request
.setHTTPReferrer(WebString(), blink::WebReferrerPolicyDefault
);
2529 void RenderFrameImpl::didReceiveResponse(
2530 blink::WebLocalFrame
* frame
,
2531 unsigned identifier
,
2532 const blink::WebURLResponse
& response
) {
2533 DCHECK(!frame_
|| frame_
== frame
);
2534 // Only do this for responses that correspond to a provisional data source
2535 // of the top-most frame. If we have a provisional data source, then we
2536 // can't have any sub-resources yet, so we know that this response must
2537 // correspond to a frame load.
2538 if (!frame
->provisionalDataSource() || frame
->parent())
2541 // If we are in view source mode, then just let the user see the source of
2542 // the server's error page.
2543 if (frame
->isViewSourceModeEnabled())
2546 DocumentState
* document_state
=
2547 DocumentState::FromDataSource(frame
->provisionalDataSource());
2548 int http_status_code
= response
.httpStatusCode();
2550 // Record page load flags.
2551 WebURLResponseExtraDataImpl
* extra_data
=
2552 GetExtraDataFromResponse(response
);
2554 document_state
->set_was_fetched_via_spdy(
2555 extra_data
->was_fetched_via_spdy());
2556 document_state
->set_was_npn_negotiated(
2557 extra_data
->was_npn_negotiated());
2558 document_state
->set_npn_negotiated_protocol(
2559 extra_data
->npn_negotiated_protocol());
2560 document_state
->set_was_alternate_protocol_available(
2561 extra_data
->was_alternate_protocol_available());
2562 document_state
->set_connection_info(
2563 extra_data
->connection_info());
2564 document_state
->set_was_fetched_via_proxy(
2565 extra_data
->was_fetched_via_proxy());
2567 InternalDocumentStateData
* internal_data
=
2568 InternalDocumentStateData::FromDocumentState(document_state
);
2569 internal_data
->set_http_status_code(http_status_code
);
2570 // Whether or not the http status code actually corresponds to an error is
2571 // only checked when the page is done loading, if |use_error_page| is
2573 internal_data
->set_use_error_page(true);
2576 void RenderFrameImpl::didFinishResourceLoad(blink::WebLocalFrame
* frame
,
2577 unsigned identifier
) {
2578 DCHECK(!frame_
|| frame_
== frame
);
2579 InternalDocumentStateData
* internal_data
=
2580 InternalDocumentStateData::FromDataSource(frame
->dataSource());
2581 if (!internal_data
->use_error_page())
2584 // Do not show error page when DevTools is attached.
2585 if (render_view_
->devtools_agent_
->IsAttached())
2588 // Display error page, if appropriate.
2589 std::string error_domain
= "http";
2590 int http_status_code
= internal_data
->http_status_code();
2591 if (GetContentClient()->renderer()->HasErrorPage(
2592 http_status_code
, &error_domain
)) {
2594 error
.unreachableURL
= frame
->document().url();
2595 error
.domain
= WebString::fromUTF8(error_domain
);
2596 error
.reason
= http_status_code
;
2597 LoadNavigationErrorPage(frame
->dataSource()->request(), error
, true);
2601 void RenderFrameImpl::didLoadResourceFromMemoryCache(
2602 blink::WebLocalFrame
* frame
,
2603 const blink::WebURLRequest
& request
,
2604 const blink::WebURLResponse
& response
) {
2605 DCHECK(!frame_
|| frame_
== frame
);
2606 // The recipients of this message have no use for data: URLs: they don't
2607 // affect the page's insecure content list and are not in the disk cache. To
2608 // prevent large (1M+) data: URLs from crashing in the IPC system, we simply
2609 // filter them out here.
2610 GURL
url(request
.url());
2611 if (url
.SchemeIs("data"))
2614 // Let the browser know we loaded a resource from the memory cache. This
2615 // message is needed to display the correct SSL indicators.
2616 render_view_
->Send(new ViewHostMsg_DidLoadResourceFromMemoryCache(
2617 render_view_
->GetRoutingID(),
2619 response
.securityInfo(),
2620 request
.httpMethod().utf8(),
2621 response
.mimeType().utf8(),
2622 ResourceType::FromTargetType(request
.targetType())));
2625 void RenderFrameImpl::didDisplayInsecureContent(blink::WebLocalFrame
* frame
) {
2626 DCHECK(!frame_
|| frame_
== frame
);
2627 render_view_
->Send(new ViewHostMsg_DidDisplayInsecureContent(
2628 render_view_
->GetRoutingID()));
2631 void RenderFrameImpl::didRunInsecureContent(
2632 blink::WebLocalFrame
* frame
,
2633 const blink::WebSecurityOrigin
& origin
,
2634 const blink::WebURL
& target
) {
2635 DCHECK(!frame_
|| frame_
== frame
);
2636 render_view_
->Send(new ViewHostMsg_DidRunInsecureContent(
2637 render_view_
->GetRoutingID(),
2638 origin
.toString().utf8(),
2642 void RenderFrameImpl::didAbortLoading(blink::WebLocalFrame
* frame
) {
2643 DCHECK(!frame_
|| frame_
== frame
);
2644 #if defined(ENABLE_PLUGINS)
2645 if (frame
!= render_view_
->webview()->mainFrame())
2647 PluginChannelHost::Broadcast(
2648 new PluginHostMsg_DidAbortLoading(render_view_
->GetRoutingID()));
2652 void RenderFrameImpl::didCreateScriptContext(blink::WebLocalFrame
* frame
,
2653 v8::Handle
<v8::Context
> context
,
2654 int extension_group
,
2656 DCHECK(!frame_
|| frame_
== frame
);
2657 GetContentClient()->renderer()->DidCreateScriptContext(
2658 frame
, context
, extension_group
, world_id
);
2661 void RenderFrameImpl::willReleaseScriptContext(blink::WebLocalFrame
* frame
,
2662 v8::Handle
<v8::Context
> context
,
2664 DCHECK(!frame_
|| frame_
== frame
);
2666 FOR_EACH_OBSERVER(RenderFrameObserver
,
2668 WillReleaseScriptContext(context
, world_id
));
2671 void RenderFrameImpl::didFirstVisuallyNonEmptyLayout(
2672 blink::WebLocalFrame
* frame
) {
2673 DCHECK(!frame_
|| frame_
== frame
);
2674 if (frame
->parent())
2677 InternalDocumentStateData
* data
=
2678 InternalDocumentStateData::FromDataSource(frame
->dataSource());
2679 data
->set_did_first_visually_non_empty_layout(true);
2681 #if defined(OS_ANDROID)
2682 GetRenderWidget()->DidChangeBodyBackgroundColor(
2683 render_view_
->webwidget_
->backgroundColor());
2687 void RenderFrameImpl::didChangeContentsSize(blink::WebLocalFrame
* frame
,
2688 const blink::WebSize
& size
) {
2689 DCHECK(!frame_
|| frame_
== frame
);
2690 #if defined(OS_MACOSX)
2691 if (frame
->parent())
2694 WebView
* frameView
= frame
->view();
2698 GetRenderWidget()->DidChangeScrollbarsForMainFrame(
2699 frame
->hasHorizontalScrollbar(),
2700 frame
->hasVerticalScrollbar());
2701 #endif // defined(OS_MACOSX)
2704 void RenderFrameImpl::didChangeScrollOffset(blink::WebLocalFrame
* frame
) {
2705 DCHECK(!frame_
|| frame_
== frame
);
2706 // TODO(nasko): Move implementation here. Needed methods:
2707 // * StartNavStateSyncTimerIfNecessary
2708 render_view_
->didChangeScrollOffset(frame
);
2711 void RenderFrameImpl::willInsertBody(blink::WebLocalFrame
* frame
) {
2712 DCHECK(!frame_
|| frame_
== frame
);
2713 if (!frame
->parent()) {
2714 render_view_
->Send(new ViewHostMsg_WillInsertBody(
2715 render_view_
->GetRoutingID()));
2719 void RenderFrameImpl::reportFindInPageMatchCount(int request_id
,
2721 bool final_update
) {
2722 int active_match_ordinal
= -1; // -1 = don't update active match ordinal
2724 active_match_ordinal
= 0;
2726 render_view_
->Send(new ViewHostMsg_Find_Reply(
2727 render_view_
->GetRoutingID(), request_id
, count
,
2728 gfx::Rect(), active_match_ordinal
, final_update
));
2731 void RenderFrameImpl::reportFindInPageSelection(
2733 int active_match_ordinal
,
2734 const blink::WebRect
& selection_rect
) {
2735 render_view_
->Send(new ViewHostMsg_Find_Reply(
2736 render_view_
->GetRoutingID(), request_id
, -1, selection_rect
,
2737 active_match_ordinal
, false));
2740 void RenderFrameImpl::requestStorageQuota(
2741 blink::WebLocalFrame
* frame
,
2742 blink::WebStorageQuotaType type
,
2743 unsigned long long requested_size
,
2744 blink::WebStorageQuotaCallbacks callbacks
) {
2745 DCHECK(!frame_
|| frame_
== frame
);
2746 WebSecurityOrigin origin
= frame
->document().securityOrigin();
2747 if (origin
.isUnique()) {
2748 // Unique origins cannot store persistent state.
2749 callbacks
.didFail(blink::WebStorageQuotaErrorAbort
);
2752 ChildThread::current()->quota_dispatcher()->RequestStorageQuota(
2753 render_view_
->GetRoutingID(), GURL(origin
.toString()),
2754 static_cast<quota::StorageType
>(type
), requested_size
,
2755 QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(callbacks
));
2758 void RenderFrameImpl::willOpenSocketStream(
2759 blink::WebSocketStreamHandle
* handle
) {
2760 WebSocketStreamHandleImpl
* impl
=
2761 static_cast<WebSocketStreamHandleImpl
*>(handle
);
2762 impl
->SetUserData(handle
, new SocketStreamHandleData(routing_id_
));
2765 void RenderFrameImpl::willOpenWebSocket(blink::WebSocketHandle
* handle
) {
2766 WebSocketBridge
* impl
= static_cast<WebSocketBridge
*>(handle
);
2767 impl
->set_render_frame_id(routing_id_
);
2770 blink::WebGeolocationClient
* RenderFrameImpl::geolocationClient() {
2771 if (!geolocation_dispatcher_
)
2772 geolocation_dispatcher_
= new GeolocationDispatcher(this);
2773 return geolocation_dispatcher_
;
2776 void RenderFrameImpl::willStartUsingPeerConnectionHandler(
2777 blink::WebLocalFrame
* frame
,
2778 blink::WebRTCPeerConnectionHandler
* handler
) {
2779 DCHECK(!frame_
|| frame_
== frame
);
2780 #if defined(ENABLE_WEBRTC)
2781 static_cast<RTCPeerConnectionHandler
*>(handler
)->associateWithFrame(frame
);
2785 blink::WebUserMediaClient
* RenderFrameImpl::userMediaClient() {
2786 // This can happen in tests, in which case it's OK to return NULL.
2787 if (!InitializeUserMediaClient())
2790 return web_user_media_client_
;
2793 blink::WebMIDIClient
* RenderFrameImpl::webMIDIClient() {
2794 return render_view_
->webMIDIClient();
2797 bool RenderFrameImpl::willCheckAndDispatchMessageEvent(
2798 blink::WebLocalFrame
* source_frame
,
2799 blink::WebFrame
* target_frame
,
2800 blink::WebSecurityOrigin target_origin
,
2801 blink::WebDOMMessageEvent event
) {
2802 DCHECK(!frame_
|| frame_
== target_frame
);
2804 if (!render_view_
->is_swapped_out_
)
2807 ViewMsg_PostMessage_Params params
;
2808 params
.data
= event
.data().toString();
2809 params
.source_origin
= event
.origin();
2810 if (!target_origin
.isNull())
2811 params
.target_origin
= target_origin
.toString();
2813 blink::WebMessagePortChannelArray channels
= event
.releaseChannels();
2814 if (!channels
.isEmpty()) {
2815 std::vector
<int> message_port_ids(channels
.size());
2816 // Extract the port IDs from the channel array.
2817 for (size_t i
= 0; i
< channels
.size(); ++i
) {
2818 WebMessagePortChannelImpl
* webchannel
=
2819 static_cast<WebMessagePortChannelImpl
*>(channels
[i
]);
2820 message_port_ids
[i
] = webchannel
->message_port_id();
2821 webchannel
->QueueMessages();
2822 DCHECK_NE(message_port_ids
[i
], MSG_ROUTING_NONE
);
2824 params
.message_port_ids
= message_port_ids
;
2827 // Include the routing ID for the source frame (if one exists), which the
2828 // browser process will translate into the routing ID for the equivalent
2829 // frame in the target process.
2830 params
.source_routing_id
= MSG_ROUTING_NONE
;
2832 RenderViewImpl
* source_view
=
2833 RenderViewImpl::FromWebView(source_frame
->view());
2835 params
.source_routing_id
= source_view
->routing_id();
2838 Send(new ViewHostMsg_RouteMessageEvent(render_view_
->routing_id_
, params
));
2842 blink::WebString
RenderFrameImpl::userAgentOverride(blink::WebLocalFrame
* frame
,
2843 const blink::WebURL
& url
) {
2844 DCHECK(!frame_
|| frame_
== frame
);
2845 if (!render_view_
->webview() || !render_view_
->webview()->mainFrame() ||
2846 render_view_
->renderer_preferences_
.user_agent_override
.empty()) {
2847 return blink::WebString();
2850 // If we're in the middle of committing a load, the data source we need
2851 // will still be provisional.
2852 WebFrame
* main_frame
= render_view_
->webview()->mainFrame();
2853 WebDataSource
* data_source
= NULL
;
2854 if (main_frame
->provisionalDataSource())
2855 data_source
= main_frame
->provisionalDataSource();
2857 data_source
= main_frame
->dataSource();
2859 InternalDocumentStateData
* internal_data
= data_source
?
2860 InternalDocumentStateData::FromDataSource(data_source
) : NULL
;
2861 if (internal_data
&& internal_data
->is_overriding_user_agent())
2862 return WebString::fromUTF8(
2863 render_view_
->renderer_preferences_
.user_agent_override
);
2864 return blink::WebString();
2867 blink::WebString
RenderFrameImpl::doNotTrackValue(blink::WebLocalFrame
* frame
) {
2868 DCHECK(!frame_
|| frame_
== frame
);
2869 if (render_view_
->renderer_preferences_
.enable_do_not_track
)
2870 return WebString::fromUTF8("1");
2874 bool RenderFrameImpl::allowWebGL(blink::WebLocalFrame
* frame
,
2875 bool default_value
) {
2876 DCHECK(!frame_
|| frame_
== frame
);
2880 bool blocked
= true;
2881 render_view_
->Send(new ViewHostMsg_Are3DAPIsBlocked(
2882 render_view_
->GetRoutingID(),
2883 GURL(frame
->top()->document().securityOrigin().toString()),
2884 THREE_D_API_TYPE_WEBGL
,
2889 void RenderFrameImpl::didLoseWebGLContext(blink::WebLocalFrame
* frame
,
2890 int arb_robustness_status_code
) {
2891 DCHECK(!frame_
|| frame_
== frame
);
2892 render_view_
->Send(new ViewHostMsg_DidLose3DContext(
2893 GURL(frame
->top()->document().securityOrigin().toString()),
2894 THREE_D_API_TYPE_WEBGL
,
2895 arb_robustness_status_code
));
2898 void RenderFrameImpl::forwardInputEvent(const blink::WebInputEvent
* event
) {
2899 Send(new FrameHostMsg_ForwardInputEvent(routing_id_
, event
));
2902 void RenderFrameImpl::initializeChildFrame(const blink::WebRect
& frame_rect
,
2903 float scale_factor
) {
2904 Send(new FrameHostMsg_InitializeChildFrame(
2905 routing_id_
, frame_rect
, scale_factor
));
2908 void RenderFrameImpl::DidPlay(blink::WebMediaPlayer
* player
) {
2909 Send(new FrameHostMsg_MediaPlayingNotification(
2910 routing_id_
, reinterpret_cast<int64
>(player
), player
->hasVideo(),
2911 player
->hasAudio()));
2914 void RenderFrameImpl::DidPause(blink::WebMediaPlayer
* player
) {
2915 Send(new FrameHostMsg_MediaPausedNotification(
2916 routing_id_
, reinterpret_cast<int64
>(player
)));
2919 void RenderFrameImpl::PlayerGone(blink::WebMediaPlayer
* player
) {
2923 void RenderFrameImpl::AddObserver(RenderFrameObserver
* observer
) {
2924 observers_
.AddObserver(observer
);
2927 void RenderFrameImpl::RemoveObserver(RenderFrameObserver
* observer
) {
2928 observer
->RenderFrameGone();
2929 observers_
.RemoveObserver(observer
);
2932 void RenderFrameImpl::OnStop() {
2933 FOR_EACH_OBSERVER(RenderFrameObserver
, observers_
, OnStop());
2936 void RenderFrameImpl::WasHidden() {
2937 FOR_EACH_OBSERVER(RenderFrameObserver
, observers_
, WasHidden());
2940 void RenderFrameImpl::WasShown() {
2941 FOR_EACH_OBSERVER(RenderFrameObserver
, observers_
, WasShown());
2944 bool RenderFrameImpl::IsHidden() {
2945 return GetRenderWidget()->is_hidden();
2948 // Tell the embedding application that the URL of the active page has changed.
2949 void RenderFrameImpl::UpdateURL(blink::WebFrame
* frame
) {
2950 DCHECK(!frame_
|| frame_
== frame
);
2951 WebDataSource
* ds
= frame
->dataSource();
2954 const WebURLRequest
& request
= ds
->request();
2955 const WebURLResponse
& response
= ds
->response();
2957 DocumentState
* document_state
= DocumentState::FromDataSource(ds
);
2958 NavigationState
* navigation_state
= document_state
->navigation_state();
2959 InternalDocumentStateData
* internal_data
=
2960 InternalDocumentStateData::FromDocumentState(document_state
);
2962 FrameHostMsg_DidCommitProvisionalLoad_Params params
;
2963 params
.http_status_code
= response
.httpStatusCode();
2964 params
.is_post
= false;
2965 params
.post_id
= -1;
2966 params
.page_id
= render_view_
->page_id_
;
2967 params
.frame_unique_name
= frame
->uniqueName();
2968 params
.socket_address
.set_host(response
.remoteIPAddress().utf8());
2969 params
.socket_address
.set_port(response
.remotePort());
2970 WebURLResponseExtraDataImpl
* extra_data
= GetExtraDataFromResponse(response
);
2972 params
.was_fetched_via_proxy
= extra_data
->was_fetched_via_proxy();
2973 params
.was_within_same_page
= navigation_state
->was_within_same_page();
2974 params
.security_info
= response
.securityInfo();
2976 // Set the URL to be displayed in the browser UI to the user.
2977 params
.url
= render_view_
->GetLoadingUrl(frame
);
2978 DCHECK(!is_swapped_out_
|| params
.url
== GURL(kSwappedOutURL
));
2980 if (frame
->document().baseURL() != params
.url
)
2981 params
.base_url
= frame
->document().baseURL();
2983 GetRedirectChain(ds
, ¶ms
.redirects
);
2984 params
.should_update_history
= !ds
->hasUnreachableURL() &&
2985 !response
.isMultipartPayload() && (response
.httpStatusCode() != 404);
2987 params
.searchable_form_url
= internal_data
->searchable_form_url();
2988 params
.searchable_form_encoding
= internal_data
->searchable_form_encoding();
2990 params
.gesture
= render_view_
->navigation_gesture_
;
2991 render_view_
->navigation_gesture_
= NavigationGestureUnknown
;
2993 // Make navigation state a part of the DidCommitProvisionalLoad message so
2994 // that commited entry has it at all times.
2995 HistoryEntry
* entry
= render_view_
->history_controller()->GetCurrentEntry();
2997 params
.page_state
= HistoryEntryToPageState(entry
);
2999 params
.page_state
= PageState::CreateFromURL(request
.url());
3001 if (!frame
->parent()) {
3002 // Top-level navigation.
3004 // Reset the zoom limits in case a plugin had changed them previously. This
3005 // will also call us back which will cause us to send a message to
3006 // update WebContentsImpl.
3007 render_view_
->webview()->zoomLimitsChanged(
3008 ZoomFactorToZoomLevel(kMinimumZoomFactor
),
3009 ZoomFactorToZoomLevel(kMaximumZoomFactor
));
3011 // Set zoom level, but don't do it for full-page plugin since they don't use
3012 // the same zoom settings.
3013 HostZoomLevels::iterator host_zoom
=
3014 render_view_
->host_zoom_levels_
.find(GURL(request
.url()));
3015 if (render_view_
->webview()->mainFrame()->document().isPluginDocument()) {
3016 // Reset the zoom levels for plugins.
3017 render_view_
->webview()->setZoomLevel(0);
3019 if (host_zoom
!= render_view_
->host_zoom_levels_
.end())
3020 render_view_
->webview()->setZoomLevel(host_zoom
->second
);
3023 if (host_zoom
!= render_view_
->host_zoom_levels_
.end()) {
3024 // This zoom level was merely recorded transiently for this load. We can
3025 // erase it now. If at some point we reload this page, the browser will
3026 // send us a new, up-to-date zoom level.
3027 render_view_
->host_zoom_levels_
.erase(host_zoom
);
3030 // Update contents MIME type for main frame.
3031 params
.contents_mime_type
= ds
->response().mimeType().utf8();
3033 params
.transition
= navigation_state
->transition_type();
3034 if (!PageTransitionIsMainFrame(params
.transition
)) {
3035 // If the main frame does a load, it should not be reported as a subframe
3036 // navigation. This can occur in the following case:
3037 // 1. You're on a site with frames.
3038 // 2. You do a subframe navigation. This is stored with transition type
3040 // 3. You navigate to some non-frame site, say, google.com.
3041 // 4. You navigate back to the page from step 2. Since it was initially
3042 // MANUAL_SUBFRAME, it will be that same transition type here.
3043 // We don't want that, because any navigation that changes the toplevel
3044 // frame should be tracked as a toplevel navigation (this allows us to
3045 // update the URL bar, etc).
3046 params
.transition
= PAGE_TRANSITION_LINK
;
3049 // If the page contained a client redirect (meta refresh, document.loc...),
3050 // set the referrer and transition appropriately.
3051 if (ds
->isClientRedirect()) {
3053 Referrer(params
.redirects
[0], ds
->request().referrerPolicy());
3054 params
.transition
= static_cast<PageTransition
>(
3055 params
.transition
| PAGE_TRANSITION_CLIENT_REDIRECT
);
3057 params
.referrer
= RenderViewImpl::GetReferrerFromRequest(
3058 frame
, ds
->request());
3061 base::string16 method
= request
.httpMethod();
3062 if (EqualsASCII(method
, "POST")) {
3063 params
.is_post
= true;
3064 params
.post_id
= ExtractPostId(entry
->root());
3067 // Send the user agent override back.
3068 params
.is_overriding_user_agent
= internal_data
->is_overriding_user_agent();
3070 // Track the URL of the original request. We use the first entry of the
3071 // redirect chain if it exists because the chain may have started in another
3073 params
.original_request_url
= GetOriginalRequestURL(ds
);
3075 params
.history_list_was_cleared
=
3076 navigation_state
->history_list_was_cleared();
3078 // Save some histogram data so we can compute the average memory used per
3079 // page load of the glyphs.
3080 UMA_HISTOGRAM_COUNTS_10000("Memory.GlyphPagesPerLoad",
3081 blink::WebGlyphCache::pageCount());
3083 // This message needs to be sent before any of allowScripts(),
3084 // allowImages(), allowPlugins() is called for the new page, so that when
3085 // these functions send a ViewHostMsg_ContentBlocked message, it arrives
3086 // after the FrameHostMsg_DidCommitProvisionalLoad message.
3087 Send(new FrameHostMsg_DidCommitProvisionalLoad(routing_id_
, params
));
3089 // Subframe navigation: the type depends on whether this navigation
3090 // generated a new session history entry. When they do generate a session
3091 // history entry, it means the user initiated the navigation and we should
3092 // mark it as such. This test checks if this is the first time UpdateURL
3093 // has been called since WillNavigateToURL was called to initiate the load.
3094 if (render_view_
->page_id_
> render_view_
->last_page_id_sent_to_browser_
)
3095 params
.transition
= PAGE_TRANSITION_MANUAL_SUBFRAME
;
3097 params
.transition
= PAGE_TRANSITION_AUTO_SUBFRAME
;
3099 DCHECK(!navigation_state
->history_list_was_cleared());
3100 params
.history_list_was_cleared
= false;
3102 // Don't send this message while the subframe is swapped out.
3103 if (!is_swapped_out())
3104 Send(new FrameHostMsg_DidCommitProvisionalLoad(routing_id_
, params
));
3107 render_view_
->last_page_id_sent_to_browser_
=
3108 std::max(render_view_
->last_page_id_sent_to_browser_
,
3109 render_view_
->page_id_
);
3111 // If we end up reusing this WebRequest (for example, due to a #ref click),
3112 // we don't want the transition type to persist. Just clear it.
3113 navigation_state
->set_transition_type(PAGE_TRANSITION_LINK
);
3116 WebElement
RenderFrameImpl::GetFocusedElement() {
3117 WebDocument doc
= frame_
->document();
3119 return doc
.focusedElement();
3121 return WebElement();
3124 void RenderFrameImpl::didStartLoading(bool to_different_document
) {
3125 render_view_
->FrameDidStartLoading(frame_
);
3126 Send(new FrameHostMsg_DidStartLoading(routing_id_
, to_different_document
));
3129 void RenderFrameImpl::didStopLoading() {
3130 render_view_
->FrameDidStopLoading(frame_
);
3131 Send(new FrameHostMsg_DidStopLoading(routing_id_
));
3134 void RenderFrameImpl::didChangeLoadProgress(double load_progress
) {
3135 Send(new FrameHostMsg_DidChangeLoadProgress(routing_id_
, load_progress
));
3138 WebNavigationPolicy
RenderFrameImpl::DecidePolicyForNavigation(
3139 RenderFrame
* render_frame
,
3141 WebDataSource::ExtraData
* extraData
,
3142 const WebURLRequest
& request
,
3143 WebNavigationType type
,
3144 WebNavigationPolicy default_policy
,
3147 // The handlenavigation API is deprecated and will be removed once
3148 // crbug.com/325351 is resolved.
3149 if (request
.url() != GURL(kSwappedOutURL
) &&
3150 GetContentClient()->renderer()->HandleNavigation(
3152 static_cast<DocumentState
*>(extraData
),
3153 render_view_
->opener_id_
,
3159 return blink::WebNavigationPolicyIgnore
;
3163 Referrer
referrer(RenderViewImpl::GetReferrerFromRequest(frame
, request
));
3165 if (is_swapped_out_
|| render_view_
->is_swapped_out()) {
3166 if (request
.url() != GURL(kSwappedOutURL
)) {
3167 // Targeted links may try to navigate a swapped out frame. Allow the
3168 // browser process to navigate the tab instead. Note that it is also
3169 // possible for non-targeted navigations (from this view) to arrive
3170 // here just after we are swapped out. It's ok to send them to the
3171 // browser, as long as they're for the top level frame.
3172 // TODO(creis): Ensure this supports targeted form submissions when
3173 // fixing http://crbug.com/101395.
3174 if (frame
->parent() == NULL
) {
3175 OpenURL(frame
, request
.url(), referrer
, default_policy
);
3176 return blink::WebNavigationPolicyIgnore
; // Suppress the load here.
3179 // We should otherwise ignore in-process iframe navigations, if they
3180 // arrive just after we are swapped out.
3181 return blink::WebNavigationPolicyIgnore
;
3184 // Allow kSwappedOutURL to complete.
3185 return default_policy
;
3188 // Webkit is asking whether to navigate to a new URL.
3189 // This is fine normally, except if we're showing UI from one security
3190 // context and they're trying to navigate to a different context.
3191 const GURL
& url
= request
.url();
3193 // A content initiated navigation may have originated from a link-click,
3194 // script, drag-n-drop operation, etc.
3195 bool is_content_initiated
= static_cast<DocumentState
*>(extraData
)->
3196 navigation_state()->is_content_initiated();
3199 // If --enable-strict-site-isolation or --site-per-process is enabled, send
3200 // all top-level navigations to the browser to let it swap processes when
3201 // crossing site boundaries. This is currently expected to break some script
3202 // calls and navigations, such as form submissions.
3203 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
3204 bool force_swap_due_to_flag
=
3205 command_line
.HasSwitch(switches::kEnableStrictSiteIsolation
) ||
3206 command_line
.HasSwitch(switches::kSitePerProcess
);
3207 if (force_swap_due_to_flag
&&
3208 !frame
->parent() && (is_content_initiated
|| is_redirect
)) {
3209 WebString origin_str
= frame
->document().securityOrigin().toString();
3210 GURL
frame_url(origin_str
.utf8().data());
3211 // TODO(cevans): revisit whether this site check is still necessary once
3212 // crbug.com/101395 is fixed.
3213 bool same_domain_or_host
=
3214 net::registry_controlled_domains::SameDomainOrHost(
3217 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES
);
3218 if (!same_domain_or_host
|| frame_url
.scheme() != url
.scheme()) {
3219 OpenURL(frame
, url
, referrer
, default_policy
);
3220 return blink::WebNavigationPolicyIgnore
;
3224 // If the browser is interested, then give it a chance to look at the request.
3225 if (is_content_initiated
) {
3226 bool is_form_post
= ((type
== blink::WebNavigationTypeFormSubmitted
) ||
3227 (type
== blink::WebNavigationTypeFormResubmitted
)) &&
3228 EqualsASCII(request
.httpMethod(), "POST");
3229 bool browser_handles_request
=
3230 render_view_
->renderer_preferences_
3231 .browser_handles_non_local_top_level_requests
3232 && IsNonLocalTopLevelNavigation(url
, frame
, type
, is_form_post
);
3233 if (!browser_handles_request
) {
3234 browser_handles_request
= IsTopLevelNavigation(frame
) &&
3235 render_view_
->renderer_preferences_
3236 .browser_handles_all_top_level_requests
;
3239 if (browser_handles_request
) {
3240 // Reset these counters as the RenderView could be reused for the next
3242 render_view_
->page_id_
= -1;
3243 render_view_
->last_page_id_sent_to_browser_
= -1;
3244 OpenURL(frame
, url
, referrer
, default_policy
);
3245 return blink::WebNavigationPolicyIgnore
; // Suppress the load here.
3249 // Use the frame's original request's URL rather than the document's URL for
3250 // subsequent checks. For a popup, the document's URL may become the opener
3251 // window's URL if the opener has called document.write().
3252 // See http://crbug.com/93517.
3253 GURL
old_url(frame
->dataSource()->request().url());
3255 // Detect when we're crossing a permission-based boundary (e.g. into or out of
3256 // an extension or app origin, leaving a WebUI page, etc). We only care about
3257 // top-level navigations (not iframes). But we sometimes navigate to
3258 // about:blank to clear a tab, and we want to still allow that.
3260 // Note: this is known to break POST submissions when crossing process
3261 // boundaries until http://crbug.com/101395 is fixed. This is better for
3262 // security than loading a WebUI, extension or app page in the wrong process.
3263 // POST requests don't work because this mechanism does not preserve form
3264 // POST data. We will need to send the request's httpBody data up to the
3265 // browser process, and issue a special POST navigation in WebKit (via
3266 // FrameLoader::loadFrameRequest). See ResourceDispatcher and WebURLLoaderImpl
3267 // for examples of how to send the httpBody data.
3268 if (!frame
->parent() && is_content_initiated
&&
3269 !url
.SchemeIs(url::kAboutScheme
)) {
3270 bool send_referrer
= false;
3272 // All navigations to or from WebUI URLs or within WebUI-enabled
3273 // RenderProcesses must be handled by the browser process so that the
3274 // correct bindings and data sources can be registered.
3275 // Similarly, navigations to view-source URLs or within ViewSource mode
3276 // must be handled by the browser process (except for reloads - those are
3277 // safe to leave within the renderer).
3278 // Lastly, access to file:// URLs from non-file:// URL pages must be
3279 // handled by the browser so that ordinary renderer processes don't get
3280 // blessed with file permissions.
3281 int cumulative_bindings
= RenderProcess::current()->GetEnabledBindings();
3282 bool is_initial_navigation
= render_view_
->page_id_
== -1;
3283 bool should_fork
= HasWebUIScheme(url
) || HasWebUIScheme(old_url
) ||
3284 (cumulative_bindings
& BINDINGS_POLICY_WEB_UI
) ||
3285 url
.SchemeIs(kViewSourceScheme
) ||
3286 (frame
->isViewSourceModeEnabled() &&
3287 type
!= blink::WebNavigationTypeReload
);
3289 if (!should_fork
&& url
.SchemeIs(url::kFileScheme
)) {
3290 // Fork non-file to file opens. Check the opener URL if this is the
3291 // initial navigation in a newly opened window.
3292 GURL
source_url(old_url
);
3293 if (is_initial_navigation
&& source_url
.is_empty() && frame
->opener())
3294 source_url
= frame
->opener()->top()->document().url();
3295 DCHECK(!source_url
.is_empty());
3296 should_fork
= !source_url
.SchemeIs(url::kFileScheme
);
3300 // Give the embedder a chance.
3301 should_fork
= GetContentClient()->renderer()->ShouldFork(
3302 frame
, url
, request
.httpMethod().utf8(), is_initial_navigation
,
3303 is_redirect
, &send_referrer
);
3308 frame
, url
, send_referrer
? referrer
: Referrer(), default_policy
);
3309 return blink::WebNavigationPolicyIgnore
; // Suppress the load here.
3313 // Detect when a page is "forking" a new tab that can be safely rendered in
3314 // its own process. This is done by sites like Gmail that try to open links
3315 // in new windows without script connections back to the original page. We
3316 // treat such cases as browser navigations (in which we will create a new
3317 // renderer for a cross-site navigation), rather than WebKit navigations.
3319 // We use the following heuristic to decide whether to fork a new page in its
3321 // The parent page must open a new tab to about:blank, set the new tab's
3322 // window.opener to null, and then redirect the tab to a cross-site URL using
3325 // TODO(creis): Deprecate this logic once we can rely on rel=noreferrer
3328 // Must start from a tab showing about:blank, which is later redirected.
3329 old_url
== GURL(url::kAboutBlankURL
) &&
3330 // Must be the first real navigation of the tab.
3331 render_view_
->historyBackListCount() < 1 &&
3332 render_view_
->historyForwardListCount() < 1 &&
3333 // The parent page must have set the child's window.opener to null before
3334 // redirecting to the desired URL.
3335 frame
->opener() == NULL
&&
3336 // Must be a top-level frame.
3337 frame
->parent() == NULL
&&
3338 // Must not have issued the request from this page.
3339 is_content_initiated
&&
3340 // Must be targeted at the current tab.
3341 default_policy
== blink::WebNavigationPolicyCurrentTab
&&
3342 // Must be a JavaScript navigation, which appears as "other".
3343 type
== blink::WebNavigationTypeOther
;
3346 // Open the URL via the browser, not via WebKit.
3347 OpenURL(frame
, url
, Referrer(), default_policy
);
3348 return blink::WebNavigationPolicyIgnore
;
3351 return default_policy
;
3354 void RenderFrameImpl::OpenURL(WebFrame
* frame
,
3356 const Referrer
& referrer
,
3357 WebNavigationPolicy policy
) {
3358 DCHECK_EQ(frame_
, frame
);
3360 FrameHostMsg_OpenURL_Params params
;
3362 params
.referrer
= referrer
;
3363 params
.disposition
= RenderViewImpl::NavigationPolicyToDisposition(policy
);
3364 WebDataSource
* ds
= frame
->provisionalDataSource();
3366 DocumentState
* document_state
= DocumentState::FromDataSource(ds
);
3367 NavigationState
* navigation_state
= document_state
->navigation_state();
3368 if (navigation_state
->is_content_initiated()) {
3369 params
.should_replace_current_entry
= ds
->replacesCurrentHistoryItem();
3371 // This is necessary to preserve the should_replace_current_entry value on
3372 // cross-process redirects, in the event it was set by a previous process.
3374 // TODO(davidben): Avoid this awkward duplication of state. See comment on
3375 // NavigationState::should_replace_current_entry().
3376 params
.should_replace_current_entry
=
3377 navigation_state
->should_replace_current_entry();
3380 params
.should_replace_current_entry
= false;
3382 params
.user_gesture
= WebUserGestureIndicator::isProcessingUserGesture();
3383 if (GetContentClient()->renderer()->AllowPopup())
3384 params
.user_gesture
= true;
3386 if (policy
== blink::WebNavigationPolicyNewBackgroundTab
||
3387 policy
== blink::WebNavigationPolicyNewForegroundTab
||
3388 policy
== blink::WebNavigationPolicyNewWindow
||
3389 policy
== blink::WebNavigationPolicyNewPopup
) {
3390 WebUserGestureIndicator::consumeUserGesture();
3393 Send(new FrameHostMsg_OpenURL(routing_id_
, params
));
3396 void RenderFrameImpl::UpdateEncoding(WebFrame
* frame
,
3397 const std::string
& encoding_name
) {
3398 // Only update main frame's encoding_name.
3399 if (!frame
->parent())
3400 Send(new FrameHostMsg_UpdateEncoding(routing_id_
, encoding_name
));
3403 void RenderFrameImpl::SyncSelectionIfRequired() {
3404 base::string16 text
;
3407 #if defined(ENABLE_PLUGINS)
3408 if (render_view_
->focused_pepper_plugin_
) {
3409 render_view_
->focused_pepper_plugin_
->GetSurroundingText(&text
, &range
);
3410 offset
= 0; // Pepper API does not support offset reporting.
3411 // TODO(kinaba): cut as needed.
3415 size_t location
, length
;
3416 if (!GetRenderWidget()->webwidget()->caretOrSelectionRange(
3417 &location
, &length
)) {
3421 range
= gfx::Range(location
, location
+ length
);
3423 if (GetRenderWidget()->webwidget()->textInputInfo().type
!=
3424 blink::WebTextInputTypeNone
) {
3425 // If current focused element is editable, we will send 100 more chars
3426 // before and after selection. It is for input method surrounding text
3428 if (location
> kExtraCharsBeforeAndAfterSelection
)
3429 offset
= location
- kExtraCharsBeforeAndAfterSelection
;
3432 length
= location
+ length
- offset
+ kExtraCharsBeforeAndAfterSelection
;
3433 WebRange webrange
= WebRange::fromDocumentRange(frame_
, offset
, length
);
3434 if (!webrange
.isNull())
3435 text
= WebRange::fromDocumentRange(
3436 frame_
, offset
, length
).toPlainText();
3439 text
= frame_
->selectionAsText();
3440 // http://crbug.com/101435
3441 // In some case, frame->selectionAsText() returned text's length is not
3442 // equal to the length returned from webwidget()->caretOrSelectionRange().
3443 // So we have to set the range according to text.length().
3444 range
.set_end(range
.start() + text
.length());
3448 // Sometimes we get repeated didChangeSelection calls from webkit when
3449 // the selection hasn't actually changed. We don't want to report these
3450 // because it will cause us to continually claim the X clipboard.
3451 if (selection_text_offset_
!= offset
||
3452 selection_range_
!= range
||
3453 selection_text_
!= text
) {
3454 selection_text_
= text
;
3455 selection_text_offset_
= offset
;
3456 selection_range_
= range
;
3457 // This IPC is dispatched by RenderWidetHost, so use its routing ID.
3458 Send(new ViewHostMsg_SelectionChanged(
3459 GetRenderWidget()->routing_id(), text
, offset
, range
));
3461 GetRenderWidget()->UpdateSelectionBounds();
3464 bool RenderFrameImpl::InitializeUserMediaClient() {
3465 if (web_user_media_client_
)
3468 if (!RenderThreadImpl::current()) // Will be NULL during unit tests.
3471 #if defined(OS_ANDROID)
3472 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableWebRTC
))
3476 #if defined(ENABLE_WEBRTC)
3477 if (!render_view_
->media_stream_dispatcher_
) {
3478 render_view_
->media_stream_dispatcher_
=
3479 new MediaStreamDispatcher(render_view_
.get());
3482 MediaStreamImpl
* media_stream_impl
= new MediaStreamImpl(
3484 render_view_
->media_stream_dispatcher_
,
3485 RenderThreadImpl::current()->GetPeerConnectionDependencyFactory());
3486 web_user_media_client_
= media_stream_impl
;
3493 WebMediaPlayer
* RenderFrameImpl::CreateWebMediaPlayerForMediaStream(
3494 const blink::WebURL
& url
,
3495 WebMediaPlayerClient
* client
) {
3496 #if defined(ENABLE_WEBRTC)
3497 #if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL)
3499 (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON
) != 0;
3500 UMA_HISTOGRAM_BOOLEAN("Platform.WebRtcNEONFound", found_neon
);
3501 #endif // defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL)
3502 return new WebMediaPlayerMS(frame_
, client
, weak_factory_
.GetWeakPtr(),
3503 new RenderMediaLog(),
3504 CreateRendererFactory());
3507 #endif // defined(ENABLE_WEBRTC)
3510 scoped_ptr
<MediaStreamRendererFactory
>
3511 RenderFrameImpl::CreateRendererFactory() {
3512 #if defined(ENABLE_WEBRTC)
3513 return scoped_ptr
<MediaStreamRendererFactory
>(
3514 new MediaStreamRendererFactory());
3516 return scoped_ptr
<MediaStreamRendererFactory
>(
3517 static_cast<MediaStreamRendererFactory
*>(NULL
));
3521 #if defined(OS_ANDROID)
3523 WebMediaPlayer
* RenderFrameImpl::CreateAndroidWebMediaPlayer(
3524 const blink::WebURL
& url
,
3525 WebMediaPlayerClient
* client
) {
3526 GpuChannelHost
* gpu_channel_host
=
3527 RenderThreadImpl::current()->EstablishGpuChannelSync(
3528 CAUSE_FOR_GPU_LAUNCH_VIDEODECODEACCELERATOR_INITIALIZE
);
3529 if (!gpu_channel_host
) {
3530 LOG(ERROR
) << "Failed to establish GPU channel for media player";
3534 scoped_refptr
<StreamTextureFactory
> stream_texture_factory
;
3535 if (GetRenderWidget()->UsingSynchronousRendererCompositor()) {
3536 SynchronousCompositorFactory
* factory
=
3537 SynchronousCompositorFactory::GetInstance();
3538 stream_texture_factory
= factory
->CreateStreamTextureFactory(
3539 render_view_
->routing_id_
);
3541 scoped_refptr
<webkit::gpu::ContextProviderWebContext
> context_provider
=
3542 RenderThreadImpl::current()->SharedMainThreadContextProvider();
3544 if (!context_provider
.get()) {
3545 LOG(ERROR
) << "Failed to get context3d for media player";
3549 stream_texture_factory
= StreamTextureFactoryImpl::Create(
3550 context_provider
, gpu_channel_host
, routing_id_
);
3553 return new WebMediaPlayerAndroid(
3556 weak_factory_
.GetWeakPtr(),
3557 GetMediaPlayerManager(),
3559 stream_texture_factory
,
3560 RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy(),
3561 new RenderMediaLog());
3564 RendererMediaPlayerManager
* RenderFrameImpl::GetMediaPlayerManager() {
3565 if (!media_player_manager_
) {
3566 media_player_manager_
= new RendererMediaPlayerManager(this);
3567 #if defined(VIDEO_HOLE)
3568 render_view_
->RegisterVideoHoleFrame(this);
3569 #endif // defined(VIDEO_HOLE)
3571 return media_player_manager_
;
3574 RendererCdmManager
* RenderFrameImpl::GetCdmManager() {
3576 cdm_manager_
= new RendererCdmManager(this);
3577 return cdm_manager_
;
3580 #endif // defined(OS_ANDROID)
3582 } // namespace content