1 // Copyright (c) 2012 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_view_impl.h"
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/command_line.h"
13 #include "base/compiler_specific.h"
14 #include "base/debug/trace_event.h"
15 #include "base/json/json_reader.h"
16 #include "base/json/json_writer.h"
17 #include "base/lazy_instance.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/message_loop_proxy.h"
20 #include "base/metrics/histogram.h"
21 #include "base/path_service.h"
22 #include "base/process_util.h"
23 #include "base/string_number_conversions.h"
24 #include "base/string_piece.h"
25 #include "base/string_split.h"
26 #include "base/string_util.h"
27 #include "base/sys_string_conversions.h"
28 #include "base/time.h"
29 #include "base/utf_string_conversions.h"
30 #include "cc/output_surface.h"
31 #include "cc/switches.h"
32 #include "content/common/appcache/appcache_dispatcher.h"
33 #include "content/common/child_thread.h"
34 #include "content/common/clipboard_messages.h"
35 #include "content/common/content_constants_internal.h"
36 #include "content/common/database_messages.h"
37 #include "content/common/drag_messages.h"
38 #include "content/common/fileapi/file_system_dispatcher.h"
39 #include "content/common/fileapi/webfilesystem_callback_dispatcher.h"
40 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
41 #include "content/common/intents_messages.h"
42 #include "content/common/java_bridge_messages.h"
43 #include "content/common/pepper_messages.h"
44 #include "content/common/pepper_plugin_registry.h"
45 #include "content/common/quota_dispatcher.h"
46 #include "content/common/request_extra_data.h"
47 #include "content/common/socket_stream_handle_data.h"
48 #include "content/common/ssl_status_serialization.h"
49 #include "content/common/view_messages.h"
50 #include "content/common/webmessageportchannel_impl.h"
51 #include "content/public/common/bindings_policy.h"
52 #include "content/public/common/content_client.h"
53 #include "content/public/common/content_constants.h"
54 #include "content/public/common/content_switches.h"
55 #include "content/public/common/context_menu_params.h"
56 #include "content/public/common/file_chooser_params.h"
57 #include "content/public/common/ssl_status.h"
58 #include "content/public/common/three_d_api_types.h"
59 #include "content/public/common/url_constants.h"
60 #include "content/public/renderer/content_renderer_client.h"
61 #include "content/public/renderer/context_menu_client.h"
62 #include "content/public/renderer/document_state.h"
63 #include "content/public/renderer/navigation_state.h"
64 #include "content/public/renderer/password_form_conversion_utils.h"
65 #include "content/public/renderer/render_view_observer.h"
66 #include "content/public/renderer/render_view_visitor.h"
67 #include "content/renderer/browser_plugin/browser_plugin.h"
68 #include "content/renderer/browser_plugin/browser_plugin_manager.h"
69 #include "content/renderer/browser_plugin/browser_plugin_manager_impl.h"
70 #include "content/renderer/device_orientation_dispatcher.h"
71 #include "content/renderer/devtools_agent.h"
72 #include "content/renderer/disambiguation_popup_helper.h"
73 #include "content/renderer/dom_automation_controller.h"
74 #include "content/renderer/dom_storage/webstoragenamespace_impl.h"
75 #include "content/renderer/do_not_track_bindings.h"
76 #include "content/renderer/external_popup_menu.h"
77 #include "content/renderer/favicon_helper.h"
78 #include "content/renderer/geolocation_dispatcher.h"
79 #include "content/renderer/gpu/compositor_thread.h"
80 #include "content/renderer/gpu/compositor_output_surface.h"
81 #include "content/renderer/gpu/compositor_software_output_device_gl_adapter.h"
82 #include "content/renderer/idle_user_detector.h"
83 #include "content/renderer/input_tag_speech_dispatcher.h"
84 #include "content/renderer/java/java_bridge_dispatcher.h"
85 #include "content/renderer/load_progress_tracker.h"
86 #include "content/renderer/media/media_stream_dependency_factory.h"
87 #include "content/renderer/media/media_stream_dispatcher.h"
88 #include "content/renderer/media/media_stream_impl.h"
89 #include "content/renderer/media/render_audiosourceprovider.h"
90 #include "content/renderer/media/render_media_log.h"
91 #include "content/renderer/media/renderer_gpu_video_decoder_factories.h"
92 #include "content/renderer/media/rtc_peer_connection_handler.h"
93 #include "content/renderer/mhtml_generator.h"
94 #include "content/renderer/notification_provider.h"
95 #include "content/renderer/pepper/pepper_plugin_delegate_impl.h"
96 #include "content/renderer/plugin_channel_host.h"
97 #include "content/renderer/render_process.h"
98 #include "content/renderer/render_thread_impl.h"
99 #include "content/renderer/render_view_impl_params.h"
100 #include "content/renderer/render_view_mouse_lock_dispatcher.h"
101 #include "content/renderer/render_widget_fullscreen_pepper.h"
102 #include "content/renderer/renderer_accessibility.h"
103 #include "content/renderer/renderer_accessibility_complete.h"
104 #include "content/renderer/renderer_accessibility_focus_only.h"
105 #include "content/renderer/renderer_date_time_picker.h"
106 #include "content/renderer/renderer_webapplicationcachehost_impl.h"
107 #include "content/renderer/renderer_webcolorchooser_impl.h"
108 #include "content/renderer/speech_recognition_dispatcher.h"
109 #include "content/renderer/text_input_client_observer.h"
110 #include "content/renderer/v8_value_converter_impl.h"
111 #include "content/renderer/web_intents_host.h"
112 #include "content/renderer/web_ui_extension.h"
113 #include "content/renderer/web_ui_extension_data.h"
114 #include "content/renderer/webplugin_delegate_proxy.h"
115 #include "content/renderer/websharedworker_proxy.h"
116 #include "media/base/filter_collection.h"
117 #include "media/base/media_switches.h"
118 #include "media/base/message_loop_factory.h"
119 #include "media/filters/audio_renderer_impl.h"
120 #include "media/filters/gpu_video_decoder.h"
121 #include "net/base/data_url.h"
122 #include "net/base/escape.h"
123 #include "net/base/net_errors.h"
124 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
125 #include "net/http/http_util.h"
126 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAccessibilityObject.h"
127 #include "third_party/WebKit/Source/WebKit/chromium/public/WebColorName.h"
128 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDOMEvent.h"
129 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDOMMessageEvent.h"
130 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h"
131 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDateTimeChooserCompletion.h"
132 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDateTimeChooserParams.h"
133 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
134 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
135 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFileChooserParams.h"
136 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFileSystemCallbacks.h"
137 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFindOptions.h"
138 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFormControlElement.h"
139 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFormElement.h"
140 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
141 #include "third_party/WebKit/Source/WebKit/chromium/public/WebHelperPlugin.h"
142 #include "third_party/WebKit/Source/WebKit/chromium/public/WebHistoryItem.h"
143 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h"
144 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
145 #include "third_party/WebKit/Source/WebKit/chromium/public/WebIntent.h"
146 #include "third_party/WebKit/Source/WebKit/chromium/public/WebIntentRequest.h"
147 #include "third_party/WebKit/Source/WebKit/chromium/public/WebIntentServiceInfo.h"
148 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayerAction.h"
149 #include "third_party/WebKit/Source/WebKit/chromium/public/WebMessagePortChannel.h"
150 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNodeList.h"
151 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPageSerializer.h"
152 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPlugin.h"
153 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginAction.h"
154 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h"
155 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginDocument.h"
156 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginParams.h"
157 #include "third_party/WebKit/Source/WebKit/chromium/public/WebRange.h"
158 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h"
159 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSearchableFormData.h"
160 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
161 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityPolicy.h"
162 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSettings.h"
163 #include "third_party/WebKit/Source/WebKit/chromium/public/WebStorageQuotaCallbacks.h"
164 #include "third_party/WebKit/Source/WebKit/chromium/public/WebUserMediaClient.h"
165 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
166 #include "third_party/WebKit/Source/WebKit/chromium/public/WebWindowFeatures.h"
167 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCString.h"
168 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebDragData.h"
169 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebGraphicsContext3D.h"
170 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebHTTPBody.h"
171 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebImage.h"
172 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebPoint.h"
173 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h"
174 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSerializedScriptValue.h"
175 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h"
176 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSocketStreamHandle.h"
177 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
178 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h"
179 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLError.h"
180 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLRequest.h"
181 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLResponse.h"
182 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebVector.h"
183 #include "third_party/skia/include/core/SkBitmap.h"
184 #include "ui/base/dialogs/selected_file_info.h"
185 #include "ui/base/ui_base_switches.h"
186 #include "ui/gfx/native_widget_types.h"
187 #include "ui/gfx/point.h"
188 #include "ui/gfx/rect.h"
189 #include "ui/gfx/size_conversions.h"
190 #include "v8/include/v8.h"
191 #include "webkit/appcache/web_application_cache_host_impl.h"
192 #include "webkit/base/file_path_string_conversions.h"
193 #include "webkit/dom_storage/dom_storage_types.h"
194 #include "webkit/glue/alt_error_page_resource_fetcher.h"
195 #include "webkit/glue/dom_operations.h"
196 #include "webkit/glue/glue_serialize.h"
197 #include "webkit/glue/web_intent_service_data.h"
198 #include "webkit/glue/webdropdata.h"
199 #include "webkit/glue/webkit_constants.h"
200 #include "webkit/glue/webkit_glue.h"
201 #include "webkit/glue/weburlresponse_extradata_impl.h"
202 #include "webkit/gpu/webgraphicscontext3d_in_process_impl.h"
203 #include "webkit/media/webmediaplayer_impl.h"
204 #include "webkit/media/webmediaplayer_ms.h"
205 #include "webkit/plugins/npapi/plugin_list.h"
206 #include "webkit/plugins/npapi/webplugin_delegate.h"
207 #include "webkit/plugins/npapi/webplugin_delegate_impl.h"
208 #include "webkit/plugins/npapi/webplugin_impl.h"
210 #if defined(OS_ANDROID)
211 #include "content/common/android/device_info.h"
212 #include "content/renderer/android/address_detector.h"
213 #include "content/renderer/android/content_detector.h"
214 #include "content/renderer/android/email_detector.h"
215 #include "content/renderer/android/phone_number_detector.h"
216 #include "content/renderer/media/stream_texture_factory_impl_android.h"
217 #include "content/renderer/media/webmediaplayer_proxy_impl_android.h"
218 #include "third_party/WebKit/Source/WebKit/chromium/public/WebHitTestResult.h"
219 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebFloatPoint.h"
220 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebFloatRect.h"
221 #include "ui/gfx/rect_f.h"
222 #include "webkit/media/android/media_player_bridge_manager_impl.h"
223 #include "webkit/media/android/webmediaplayer_android.h"
224 #include "webkit/media/android/webmediaplayer_impl_android.h"
225 #include "webkit/media/android/webmediaplayer_in_process_android.h"
226 #include "webkit/media/android/webmediaplayer_manager_android.h"
227 #elif defined(OS_WIN)
228 // TODO(port): these files are currently Windows only because they concern:
230 #include "ui/native_theme/native_theme_win.h"
231 #elif defined(USE_X11)
232 #include "third_party/WebKit/Source/WebKit/chromium/public/default/WebRenderTheme.h"
233 #include "ui/native_theme/native_theme.h"
234 #elif defined(OS_MACOSX)
235 #include "skia/ext/skia_utils_mac.h"
238 using WebKit::WebAccessibilityNotification
;
239 using WebKit::WebAccessibilityObject
;
240 using WebKit::WebApplicationCacheHost
;
241 using WebKit::WebApplicationCacheHostClient
;
242 using WebKit::WebCString
;
243 using WebKit::WebColor
;
244 using WebKit::WebColorName
;
245 using WebKit::WebConsoleMessage
;
246 using WebKit::WebContextMenuData
;
247 using WebKit::WebCookieJar
;
248 using WebKit::WebData
;
249 using WebKit::WebDataSource
;
250 using WebKit::WebDocument
;
251 using WebKit::WebDOMEvent
;
252 using WebKit::WebDOMMessageEvent
;
253 using WebKit::WebDragData
;
254 using WebKit::WebDragOperation
;
255 using WebKit::WebDragOperationsMask
;
256 using WebKit::WebEditingAction
;
257 using WebKit::WebElement
;
258 using WebKit::WebExternalPopupMenu
;
259 using WebKit::WebExternalPopupMenuClient
;
260 using WebKit::WebFileChooserCompletion
;
261 using WebKit::WebFileSystem
;
262 using WebKit::WebFileSystemCallbacks
;
263 using WebKit::WebFindOptions
;
264 using WebKit::WebFormControlElement
;
265 using WebKit::WebFormElement
;
266 using WebKit::WebFrame
;
267 using WebKit::WebGestureEvent
;
268 using WebKit::WebGraphicsContext3D
;
269 using WebKit::WebHistoryItem
;
270 using WebKit::WebHTTPBody
;
271 using WebKit::WebIconURL
;
272 using WebKit::WebImage
;
273 using WebKit::WebInputElement
;
274 using WebKit::WebInputEvent
;
275 using WebKit::WebIntentRequest
;
276 using WebKit::WebIntentServiceInfo
;
277 using WebKit::WebMediaPlayer
;
278 using WebKit::WebMediaPlayerAction
;
279 using WebKit::WebMediaPlayerClient
;
280 using WebKit::WebMouseEvent
;
281 using WebKit::WebNavigationPolicy
;
282 using WebKit::WebNavigationType
;
283 using WebKit::WebNode
;
284 using WebKit::WebPageSerializer
;
285 using WebKit::WebPageSerializerClient
;
286 using WebKit::WebPeerConnection00Handler
;
287 using WebKit::WebPeerConnection00HandlerClient
;
288 using WebKit::WebPeerConnectionHandler
;
289 using WebKit::WebPeerConnectionHandlerClient
;
290 using WebKit::WebPlugin
;
291 using WebKit::WebPluginAction
;
292 using WebKit::WebPluginContainer
;
293 using WebKit::WebPluginDocument
;
294 using WebKit::WebPluginParams
;
295 using WebKit::WebPoint
;
296 using WebKit::WebPopupMenuInfo
;
297 using WebKit::WebRange
;
298 using WebKit::WebRect
;
299 using WebKit::WebReferrerPolicy
;
300 using WebKit::WebScriptSource
;
301 using WebKit::WebSearchableFormData
;
302 using WebKit::WebSecurityOrigin
;
303 using WebKit::WebSecurityPolicy
;
304 using WebKit::WebSerializedScriptValue
;
305 using WebKit::WebSettings
;
306 using WebKit::WebSharedWorker
;
307 using WebKit::WebSize
;
308 using WebKit::WebSocketStreamHandle
;
309 using WebKit::WebStorageNamespace
;
310 using WebKit::WebStorageQuotaCallbacks
;
311 using WebKit::WebStorageQuotaError
;
312 using WebKit::WebStorageQuotaType
;
313 using WebKit::WebString
;
314 using WebKit::WebTextAffinity
;
315 using WebKit::WebTextDirection
;
316 using WebKit::WebTouchEvent
;
317 using WebKit::WebURL
;
318 using WebKit::WebURLError
;
319 using WebKit::WebURLRequest
;
320 using WebKit::WebURLResponse
;
321 using WebKit::WebVector
;
322 using WebKit::WebView
;
323 using WebKit::WebWidget
;
324 using WebKit::WebWindowFeatures
;
325 using appcache::WebApplicationCacheHostImpl
;
327 using base::TimeDelta
;
329 using webkit_glue::AltErrorPageResourceFetcher
;
330 using webkit_glue::ResourceFetcher
;
331 using webkit_glue::WebPreferences
;
332 using webkit_glue::WebURLResponseExtraDataImpl
;
334 #if defined(OS_ANDROID)
335 using WebKit::WebContentDetectionResult
;
336 using WebKit::WebFloatPoint
;
337 using WebKit::WebFloatRect
;
338 using WebKit::WebHitTestResult
;
343 //-----------------------------------------------------------------------------
345 typedef std::map
<WebKit::WebView
*, RenderViewImpl
*> ViewMap
;
346 static base::LazyInstance
<ViewMap
> g_view_map
= LAZY_INSTANCE_INITIALIZER
;
347 typedef std::map
<int32
, RenderViewImpl
*> RoutingIDViewMap
;
348 static base::LazyInstance
<RoutingIDViewMap
> g_routing_id_view_map
=
349 LAZY_INSTANCE_INITIALIZER
;
351 // Time, in seconds, we delay before sending content state changes (such as form
352 // state and scroll position) to the browser. We delay sending changes to avoid
353 // spamming the browser.
354 // To avoid having tab/session restore require sending a message to get the
355 // current content state during tab closing we use a shorter timeout for the
356 // foreground renderer. This means there is a small window of time from which
357 // content state is modified and not sent to session restore, but this is
358 // better than having to wake up all renderers during shutdown.
359 static const int kDelaySecondsForContentStateSyncHidden
= 5;
360 static const int kDelaySecondsForContentStateSync
= 1;
362 static const size_t kExtraCharsBeforeAndAfterSelection
= 100;
364 // The maximum number of popups that can be spawned from one page.
365 static const int kMaximumNumberOfUnacknowledgedPopups
= 25;
367 static const float kScalingIncrement
= 0.1f
;
369 static const float kScalingIncrementForGesture
= 0.01f
;
371 #if defined(OS_ANDROID)
372 // Delay between tapping in content and launching the associated android intent.
373 // Used to allow users see what has been recognized as content.
374 static const size_t kContentIntentDelayMilliseconds
= 700;
377 static RenderViewImpl
* (*g_create_render_view_impl
)(RenderViewImplParams
*) =
380 static WebKit::WebFrame
* FindFrameByID(WebKit::WebFrame
* root
, int frame_id
) {
381 for (WebFrame
* frame
= root
; frame
; frame
= frame
->traverseNext(false)) {
382 if (frame
->identifier() == frame_id
)
388 static void GetRedirectChain(WebDataSource
* ds
, std::vector
<GURL
>* result
) {
389 // Replace any occurrences of swappedout:// with about:blank.
390 const WebURL
& blank_url
= GURL(chrome::kAboutBlankURL
);
391 WebVector
<WebURL
> urls
;
392 ds
->redirectChain(urls
);
393 result
->reserve(urls
.size());
394 for (size_t i
= 0; i
< urls
.size(); ++i
) {
395 if (urls
[i
] != GURL(kSwappedOutURL
))
396 result
->push_back(urls
[i
]);
398 result
->push_back(blank_url
);
402 // If |data_source| is non-null and has a DocumentState associated with it,
403 // the AltErrorPageResourceFetcher is reset.
404 static void StopAltErrorPageFetcher(WebDataSource
* data_source
) {
406 DocumentState
* document_state
= DocumentState::FromDataSource(data_source
);
408 document_state
->set_alt_error_page_fetcher(NULL
);
412 static bool IsReload(const ViewMsg_Navigate_Params
& params
) {
414 params
.navigation_type
== ViewMsg_Navigate_Type::RELOAD
||
415 params
.navigation_type
== ViewMsg_Navigate_Type::RELOAD_IGNORING_CACHE
||
416 params
.navigation_type
==
417 ViewMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL
;
420 static WebReferrerPolicy
GetReferrerPolicyFromRequest(
422 const WebURLRequest
& request
) {
423 return request
.extraData() ?
424 static_cast<RequestExtraData
*>(request
.extraData())->referrer_policy() :
425 frame
->document().referrerPolicy();
428 static WebURLResponseExtraDataImpl
* GetExtraDataFromResponse(
429 const WebURLResponse
& response
) {
430 return static_cast<WebURLResponseExtraDataImpl
*>(
431 response
.extraData());
434 NOINLINE
static void CrashIntentionally() {
435 // NOTE(shess): Crash directly rather than using NOTREACHED() so
436 // that the signature is easier to triage in crash reports.
437 volatile int* zero
= NULL
;
441 static void MaybeHandleDebugURL(const GURL
& url
) {
442 if (!url
.SchemeIs(chrome::kChromeUIScheme
))
444 if (url
== GURL(chrome::kChromeUICrashURL
)) {
445 CrashIntentionally();
446 } else if (url
== GURL(chrome::kChromeUIKillURL
)) {
447 base::KillProcess(base::GetCurrentProcessHandle(), 1, false);
448 } else if (url
== GURL(chrome::kChromeUIHangURL
)) {
450 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
452 } else if (url
== GURL(kChromeUIShorthangURL
)) {
453 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(20));
457 // Returns false unless this is a top-level navigation.
458 static bool IsTopLevelNavigation(WebFrame
* frame
) {
459 return frame
->parent() == NULL
;
462 // Returns false unless this is a top-level navigation that crosses origins.
463 static bool IsNonLocalTopLevelNavigation(const GURL
& url
,
465 WebNavigationType type
) {
466 if (!IsTopLevelNavigation(frame
))
469 // Navigations initiated within Webkit are not sent out to the external host
470 // in the following cases.
471 // 1. The url scheme is not http/https
472 // 2. The origin of the url and the opener is the same in which case the
473 // opener relationship is maintained.
474 // 3. Reloads/form submits/back forward navigations
475 if (!url
.SchemeIs(chrome::kHttpScheme
) && !url
.SchemeIs(chrome::kHttpsScheme
))
478 // Not interested in reloads/form submits/resubmits/back forward navigations.
479 if (type
!= WebKit::WebNavigationTypeReload
&&
480 type
!= WebKit::WebNavigationTypeFormSubmitted
&&
481 type
!= WebKit::WebNavigationTypeFormResubmitted
&&
482 type
!= WebKit::WebNavigationTypeBackForward
) {
483 // The opener relationship between the new window and the parent allows the
484 // new window to script the parent and vice versa. This is not allowed if
485 // the origins of the two domains are different. This can be treated as a
486 // top level navigation and routed back to the host.
487 WebKit::WebFrame
* opener
= frame
->opener();
492 if (url
.GetOrigin() != GURL(opener
->document().url()).GetOrigin())
498 static void NotifyTimezoneChange(WebKit::WebFrame
* frame
) {
499 v8::HandleScope handle_scope
;
500 v8::Context::Scope
context_scope(frame
->mainWorldScriptContext());
501 v8::Date::DateTimeConfigurationChangeNotification();
502 WebKit::WebFrame
* child
= frame
->firstChild();
503 for (; child
; child
= child
->nextSibling())
504 NotifyTimezoneChange(child
);
507 ///////////////////////////////////////////////////////////////////////////////
509 struct RenderViewImpl::PendingFileChooser
{
510 PendingFileChooser(const FileChooserParams
& p
, WebFileChooserCompletion
* c
)
514 FileChooserParams params
;
515 WebFileChooserCompletion
* completion
; // MAY BE NULL to skip callback.
520 class WebWidgetLockTarget
: public MouseLockDispatcher::LockTarget
{
522 explicit WebWidgetLockTarget(WebKit::WebWidget
* webwidget
)
523 : webwidget_(webwidget
) {}
525 virtual void OnLockMouseACK(bool succeeded
) OVERRIDE
{
527 webwidget_
->didAcquirePointerLock();
529 webwidget_
->didNotAcquirePointerLock();
532 virtual void OnMouseLockLost() OVERRIDE
{
533 webwidget_
->didLosePointerLock();
536 virtual bool HandleMouseLockedInputEvent(
537 const WebKit::WebMouseEvent
&event
) OVERRIDE
{
538 // The WebWidget handles mouse lock in WebKit's handleInputEvent().
543 WebKit::WebWidget
* webwidget_
;
546 int64
ExtractPostId(const WebHistoryItem
& item
) {
550 if (item
.httpBody().isNull())
553 return item
.httpBody().identifier();
558 RenderViewImpl::RenderViewImpl(RenderViewImplParams
* params
)
559 : RenderWidget(WebKit::WebPopupTypeNone
,
561 params
->swapped_out
),
562 webkit_preferences_(params
->webkit_prefs
),
563 send_content_state_immediately_(false),
564 enabled_bindings_(0),
565 send_preferred_size_changes_(false),
567 navigation_gesture_(NavigationGestureUnknown
),
568 opened_by_user_gesture_(true),
569 opener_suppressed_(false),
571 last_page_id_sent_to_browser_(-1),
572 next_page_id_(params
->next_page_id
),
573 history_list_offset_(-1),
574 history_list_length_(0),
575 target_url_status_(TARGET_NONE
),
576 selection_text_offset_(0),
577 cached_is_main_frame_pinned_to_left_(false),
578 cached_is_main_frame_pinned_to_right_(false),
579 cached_has_main_frame_horizontal_scrollbar_(false),
580 cached_has_main_frame_vertical_scrollbar_(false),
581 ALLOW_THIS_IN_INITIALIZER_LIST(cookie_jar_(this)),
582 geolocation_dispatcher_(NULL
),
583 input_tag_speech_dispatcher_(NULL
),
584 speech_recognition_dispatcher_(NULL
),
585 device_orientation_dispatcher_(NULL
),
586 media_stream_dispatcher_(NULL
),
587 browser_plugin_manager_(NULL
),
588 media_stream_impl_(NULL
),
589 devtools_agent_(NULL
),
590 accessibility_mode_(AccessibilityModeOff
),
591 renderer_accessibility_(NULL
),
592 java_bridge_dispatcher_(NULL
),
593 mouse_lock_dispatcher_(NULL
),
594 favicon_helper_(NULL
),
595 #if defined(OS_ANDROID)
596 body_background_color_(SK_ColorWHITE
),
597 update_frame_info_scheduled_(false),
598 expected_content_intent_id_(0),
599 media_player_proxy_(NULL
),
600 synchronous_find_active_match_ordinal_(-1),
601 ALLOW_THIS_IN_INITIALIZER_LIST(
602 load_progress_tracker_(new LoadProgressTracker(this))),
604 session_storage_namespace_id_(params
->session_storage_namespace_id
),
605 handling_select_range_(false),
606 next_snapshot_id_(0),
608 focused_plugin_id_(-1),
610 updating_frame_tree_(false),
611 pending_frame_tree_update_(false),
612 target_process_id_(0),
613 target_routing_id_(0) {
614 #if defined(ENABLE_PLUGINS)
615 pepper_helper_
.reset(new PepperPluginDelegateImpl(this));
617 pepper_helper_
.reset(new RenderViewPepperHelper());
619 set_throttle_input_events(params
->renderer_prefs
.throttle_input_events
);
620 routing_id_
= params
->routing_id
;
621 surface_id_
= params
->surface_id
;
622 if (params
->opener_id
!= MSG_ROUTING_NONE
&& params
->is_renderer_created
)
623 opener_id_
= params
->opener_id
;
625 // Ensure we start with a valid next_page_id_ from the browser.
626 DCHECK_GE(next_page_id_
, 0);
628 #if defined(ENABLE_NOTIFICATIONS)
629 notification_provider_
= new NotificationProvider(this);
631 notification_provider_
= NULL
;
634 webwidget_
= WebView::create(this);
635 webwidget_mouse_lock_target_
.reset(new WebWidgetLockTarget(webwidget_
));
637 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
639 #if defined(OS_ANDROID)
640 scoped_ptr
<DeviceInfo
> device_info(new DeviceInfo());
642 const std::string region_code
=
643 command_line
.HasSwitch(switches::kNetworkCountryIso
)
644 ? command_line
.GetSwitchValueASCII(switches::kNetworkCountryIso
)
645 : device_info
->GetNetworkCountryIso();
646 content_detectors_
.push_back(linked_ptr
<ContentDetector
>(
647 new AddressDetector()));
648 content_detectors_
.push_back(linked_ptr
<ContentDetector
>(
649 new PhoneNumberDetector(region_code
)));
650 content_detectors_
.push_back(linked_ptr
<ContentDetector
>(
651 new EmailDetector()));
654 if (params
->counter
) {
655 shared_popup_counter_
= params
->counter
;
656 // Only count this if it isn't swapped out upon creation.
657 if (!params
->swapped_out
)
658 shared_popup_counter_
->data
++;
659 decrement_shared_popup_at_destruction_
= true;
661 shared_popup_counter_
= new SharedRenderViewCounter(0);
662 decrement_shared_popup_at_destruction_
= false;
665 RenderThread::Get()->AddRoute(routing_id_
, this);
666 // Take a reference on behalf of the RenderThread. This will be balanced
667 // when we receive ViewMsg_ClosePage.
670 // If this is a popup, we must wait for the CreatingNew_ACK message before
671 // completing initialization. Otherwise, we can finish it now.
672 if (opener_id_
== MSG_ROUTING_NONE
) {
677 g_view_map
.Get().insert(std::make_pair(webview(), this));
678 g_routing_id_view_map
.Get().insert(std::make_pair(routing_id_
, this));
679 webview()->setDeviceScaleFactor(device_scale_factor_
);
680 webkit_preferences_
.Apply(webview());
681 webview()->initializeMainFrame(this);
683 if (command_line
.HasSwitch(switches::kEnableTouchDragDrop
))
684 webview()->settings()->setTouchDragDropEnabled(true);
686 if (!params
->frame_name
.empty())
687 webview()->mainFrame()->setName(params
->frame_name
);
688 webview()->settings()->setMinimumTimerInterval(
689 is_hidden() ? webkit_glue::kBackgroundTabTimerInterval
:
690 webkit_glue::kForegroundTabTimerInterval
);
692 OnSetRendererPrefs(params
->renderer_prefs
);
694 #if defined(ENABLE_WEBRTC)
695 if (!media_stream_dispatcher_
)
696 media_stream_dispatcher_
= new MediaStreamDispatcher(this);
699 new MHTMLGenerator(this);
700 #if defined(OS_MACOSX)
701 new TextInputClientObserver(this);
702 #endif // defined(OS_MACOSX)
704 #if defined(OS_ANDROID)
705 media_player_manager_
.reset(
706 new webkit_media::WebMediaPlayerManagerAndroid());
709 // The next group of objects all implement RenderViewObserver, so are deleted
710 // along with the RenderView automatically.
711 devtools_agent_
= new DevToolsAgent(this);
712 mouse_lock_dispatcher_
= new RenderViewMouseLockDispatcher(this);
713 intents_host_
= new WebIntentsHost(this);
714 favicon_helper_
= new FaviconHelper(this);
716 // Create renderer_accessibility_ if needed.
717 OnSetAccessibilityMode(params
->accessibility_mode
);
719 new IdleUserDetector(this);
721 if (command_line
.HasSwitch(switches::kDomAutomationController
))
722 enabled_bindings_
|= BINDINGS_POLICY_DOM_AUTOMATION
;
724 ProcessViewLayoutFlags(command_line
);
726 GetContentClient()->renderer()->RenderViewCreated(this);
728 // If we have an opener_id but we weren't created by a renderer, then
729 // it's the browser asking us to set our opener to another RenderView.
730 if (params
->opener_id
!= MSG_ROUTING_NONE
&& !params
->is_renderer_created
) {
731 RenderViewImpl
* opener_view
= FromRoutingID(params
->opener_id
);
733 webview()->mainFrame()->setOpener(opener_view
->webview()->mainFrame());
736 // If we are initially swapped out, navigate to kSwappedOutURL.
737 // This ensures we are in a unique origin that others cannot script.
739 NavigateToSwappedOutURL(webview()->mainFrame());
742 RenderViewImpl::~RenderViewImpl() {
743 history_page_ids_
.clear();
745 if (decrement_shared_popup_at_destruction_
)
746 shared_popup_counter_
->data
--;
748 // If file chooser is still waiting for answer, dispatch empty answer.
749 while (!file_chooser_completions_
.empty()) {
750 if (file_chooser_completions_
.front()->completion
) {
751 file_chooser_completions_
.front()->completion
->didChooseFile(
752 WebVector
<WebString
>());
754 file_chooser_completions_
.pop_front();
757 #if defined(OS_MACOSX)
758 // Destroy all fake plugin window handles on the browser side.
759 while (!fake_plugin_window_handles_
.empty()) {
760 // Make sure no NULL plugin window handles were inserted into this list.
761 DCHECK(*fake_plugin_window_handles_
.begin());
762 // DestroyFakePluginWindowHandle modifies fake_plugin_window_handles_.
763 DestroyFakePluginWindowHandle(*fake_plugin_window_handles_
.begin());
768 // Make sure we are no longer referenced by the ViewMap or RoutingIDViewMap.
769 ViewMap
* views
= g_view_map
.Pointer();
770 for (ViewMap::iterator it
= views
->begin(); it
!= views
->end(); ++it
)
771 DCHECK_NE(this, it
->second
) << "Failed to call Close?";
772 RoutingIDViewMap
* routing_id_views
= g_routing_id_view_map
.Pointer();
773 for (RoutingIDViewMap::iterator it
= routing_id_views
->begin();
774 it
!= routing_id_views
->end(); ++it
)
775 DCHECK_NE(this, it
->second
) << "Failed to call Close?";
778 FOR_EACH_OBSERVER(RenderViewObserver
, observers_
, RenderViewGone());
779 FOR_EACH_OBSERVER(RenderViewObserver
, observers_
, OnDestruct());
783 RenderViewImpl
* RenderViewImpl::FromWebView(WebView
* webview
) {
784 ViewMap
* views
= g_view_map
.Pointer();
785 ViewMap::iterator it
= views
->find(webview
);
786 return it
== views
->end() ? NULL
: it
->second
;
790 RenderView
* RenderView::FromWebView(WebKit::WebView
* webview
) {
791 return RenderViewImpl::FromWebView(webview
);
795 RenderViewImpl
* RenderViewImpl::FromRoutingID(int32 routing_id
) {
796 RoutingIDViewMap
* views
= g_routing_id_view_map
.Pointer();
797 RoutingIDViewMap::iterator it
= views
->find(routing_id
);
798 return it
== views
->end() ? NULL
: it
->second
;
802 RenderView
* RenderView::FromRoutingID(int routing_id
) {
803 return RenderViewImpl::FromRoutingID(routing_id
);
807 void RenderView::ForEach(RenderViewVisitor
* visitor
) {
808 ViewMap
* views
= g_view_map
.Pointer();
809 for (ViewMap::iterator it
= views
->begin(); it
!= views
->end(); ++it
) {
810 if (!visitor
->Visit(it
->second
))
816 RenderViewImpl
* RenderViewImpl::Create(
818 const RendererPreferences
& renderer_prefs
,
819 const WebPreferences
& webkit_prefs
,
820 SharedRenderViewCounter
* counter
,
823 int64 session_storage_namespace_id
,
824 const string16
& frame_name
,
825 bool is_renderer_created
,
828 const WebKit::WebScreenInfo
& screen_info
,
829 AccessibilityMode accessibility_mode
) {
830 DCHECK(routing_id
!= MSG_ROUTING_NONE
);
831 RenderViewImplParams
params(
838 session_storage_namespace_id
,
845 if (g_create_render_view_impl
)
846 return g_create_render_view_impl(¶ms
);
847 return new RenderViewImpl(¶ms
);
851 void RenderViewImpl::InstallCreateHook(
852 RenderViewImpl
* (*create_render_view_impl
)(RenderViewImplParams
*)) {
853 CHECK(!g_create_render_view_impl
);
854 g_create_render_view_impl
= create_render_view_impl
;
857 void RenderViewImpl::AddObserver(RenderViewObserver
* observer
) {
858 observers_
.AddObserver(observer
);
861 void RenderViewImpl::RemoveObserver(RenderViewObserver
* observer
) {
862 observer
->RenderViewGone();
863 observers_
.RemoveObserver(observer
);
866 WebKit::WebView
* RenderViewImpl::webview() const {
867 return static_cast<WebKit::WebView
*>(webwidget());
870 void RenderViewImpl::PluginCrashed(const FilePath
& plugin_path
) {
871 Send(new ViewHostMsg_CrashedPlugin(routing_id_
, plugin_path
));
874 void RenderViewImpl::RegisterPluginDelegate(WebPluginDelegateProxy
* delegate
) {
875 plugin_delegates_
.insert(delegate
);
876 // If the renderer is visible, set initial visibility and focus state.
878 #if defined(OS_MACOSX)
879 delegate
->SetContainerVisibility(true);
880 if (webview() && webview()->isActive())
881 delegate
->SetWindowFocus(true);
884 // Plugins start assuming the content has focus (so that they work in
885 // environments where RenderView isn't hosting them), so we always have to
886 // set the initial state. See webplugin_delegate_impl.h for details.
887 delegate
->SetContentAreaFocus(has_focus());
890 void RenderViewImpl::UnregisterPluginDelegate(
891 WebPluginDelegateProxy
* delegate
) {
892 plugin_delegates_
.erase(delegate
);
895 bool RenderViewImpl::GetPluginInfo(const GURL
& url
,
896 const GURL
& page_url
,
897 const std::string
& mime_type
,
898 webkit::WebPluginInfo
* plugin_info
,
899 std::string
* actual_mime_type
) {
901 Send(new ViewHostMsg_GetPluginInfo(
902 routing_id_
, url
, page_url
, mime_type
, &found
, plugin_info
,
907 void RenderViewImpl::TransferActiveWheelFlingAnimation(
908 const WebKit::WebActiveWheelFlingParameters
& params
) {
910 webview()->transferActiveWheelFlingAnimation(params
);
913 bool RenderViewImpl::HasIMETextFocus() {
914 return GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE
;
917 bool RenderViewImpl::OnMessageReceived(const IPC::Message
& message
) {
918 WebFrame
* main_frame
= webview() ? webview()->mainFrame() : NULL
;
920 GetContentClient()->SetActiveURL(main_frame
->document().url());
922 ObserverListBase
<RenderViewObserver
>::Iterator
it(observers_
);
923 RenderViewObserver
* observer
;
924 while ((observer
= it
.GetNext()) != NULL
)
925 if (observer
->OnMessageReceived(message
))
929 bool msg_is_ok
= true;
930 IPC_BEGIN_MESSAGE_MAP_EX(RenderViewImpl
, message
, msg_is_ok
)
931 IPC_MESSAGE_HANDLER(ViewMsg_Navigate
, OnNavigate
)
932 IPC_MESSAGE_HANDLER(ViewMsg_Stop
, OnStop
)
933 IPC_MESSAGE_HANDLER(ViewMsg_ReloadFrame
, OnReloadFrame
)
934 IPC_MESSAGE_HANDLER(ViewMsg_Undo
, OnUndo
)
935 IPC_MESSAGE_HANDLER(ViewMsg_Redo
, OnRedo
)
936 IPC_MESSAGE_HANDLER(ViewMsg_Cut
, OnCut
)
937 IPC_MESSAGE_HANDLER(ViewMsg_Copy
, OnCopy
)
938 IPC_MESSAGE_HANDLER(ViewMsg_Paste
, OnPaste
)
939 IPC_MESSAGE_HANDLER(ViewMsg_PasteAndMatchStyle
, OnPasteAndMatchStyle
)
940 IPC_MESSAGE_HANDLER(ViewMsg_Replace
, OnReplace
)
941 IPC_MESSAGE_HANDLER(ViewMsg_Delete
, OnDelete
)
942 IPC_MESSAGE_HANDLER(ViewMsg_SelectAll
, OnSelectAll
)
943 IPC_MESSAGE_HANDLER(ViewMsg_Unselect
, OnUnselect
)
944 IPC_MESSAGE_HANDLER(ViewMsg_SetEditableSelectionOffsets
,
945 OnSetEditableSelectionOffsets
)
946 IPC_MESSAGE_HANDLER(ViewMsg_SetCompositionFromExistingText
,
947 OnSetCompositionFromExistingText
)
948 IPC_MESSAGE_HANDLER(ViewMsg_ExtendSelectionAndDelete
,
949 OnExtendSelectionAndDelete
)
950 IPC_MESSAGE_HANDLER(ViewMsg_SelectRange
, OnSelectRange
)
951 IPC_MESSAGE_HANDLER(ViewMsg_CopyImageAt
, OnCopyImageAt
)
952 IPC_MESSAGE_HANDLER(ViewMsg_ExecuteEditCommand
, OnExecuteEditCommand
)
953 IPC_MESSAGE_HANDLER(ViewMsg_Find
, OnFind
)
954 IPC_MESSAGE_HANDLER(ViewMsg_StopFinding
, OnStopFinding
)
955 IPC_MESSAGE_HANDLER(ViewMsg_Zoom
, OnZoom
)
956 IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevel
, OnSetZoomLevel
)
957 IPC_MESSAGE_HANDLER(ViewMsg_ZoomFactor
, OnZoomFactor
)
958 IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevelForLoadingURL
,
959 OnSetZoomLevelForLoadingURL
)
960 IPC_MESSAGE_HANDLER(ViewMsg_SetPageEncoding
, OnSetPageEncoding
)
961 IPC_MESSAGE_HANDLER(ViewMsg_ResetPageEncodingToDefault
,
962 OnResetPageEncodingToDefault
)
963 IPC_MESSAGE_HANDLER(ViewMsg_ScriptEvalRequest
, OnScriptEvalRequest
)
964 IPC_MESSAGE_HANDLER(ViewMsg_PostMessageEvent
, OnPostMessageEvent
)
965 IPC_MESSAGE_HANDLER(ViewMsg_CSSInsertRequest
, OnCSSInsertRequest
)
966 IPC_MESSAGE_HANDLER(DragMsg_TargetDragEnter
, OnDragTargetDragEnter
)
967 IPC_MESSAGE_HANDLER(DragMsg_TargetDragOver
, OnDragTargetDragOver
)
968 IPC_MESSAGE_HANDLER(DragMsg_TargetDragLeave
, OnDragTargetDragLeave
)
969 IPC_MESSAGE_HANDLER(DragMsg_TargetDrop
, OnDragTargetDrop
)
970 IPC_MESSAGE_HANDLER(DragMsg_SourceEndedOrMoved
, OnDragSourceEndedOrMoved
)
971 IPC_MESSAGE_HANDLER(DragMsg_SourceSystemDragEnded
,
972 OnDragSourceSystemDragEnded
)
973 IPC_MESSAGE_HANDLER(ViewMsg_AllowBindings
, OnAllowBindings
)
974 IPC_MESSAGE_HANDLER(ViewMsg_SetInitialFocus
, OnSetInitialFocus
)
975 IPC_MESSAGE_HANDLER(ViewMsg_ScrollFocusedEditableNodeIntoRect
,
976 OnScrollFocusedEditableNodeIntoRect
)
977 IPC_MESSAGE_HANDLER(ViewMsg_UpdateTargetURL_ACK
, OnUpdateTargetURLAck
)
978 IPC_MESSAGE_HANDLER(ViewMsg_UpdateWebPreferences
, OnUpdateWebPreferences
)
979 IPC_MESSAGE_HANDLER(ViewMsg_TimezoneChange
, OnUpdateTimezone
)
980 IPC_MESSAGE_HANDLER(ViewMsg_SetAltErrorPageURL
, OnSetAltErrorPageURL
)
981 IPC_MESSAGE_HANDLER(ViewMsg_EnumerateDirectoryResponse
,
982 OnEnumerateDirectoryResponse
)
983 IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse
, OnFileChooserResponse
)
984 IPC_MESSAGE_HANDLER(ViewMsg_ShouldClose
, OnShouldClose
)
985 IPC_MESSAGE_HANDLER(ViewMsg_SwapOut
, OnSwapOut
)
986 IPC_MESSAGE_HANDLER(ViewMsg_ClosePage
, OnClosePage
)
987 IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged
, OnThemeChanged
)
988 IPC_MESSAGE_HANDLER(ViewMsg_DisassociateFromPopupCount
,
989 OnDisassociateFromPopupCount
)
990 IPC_MESSAGE_HANDLER(ViewMsg_MoveOrResizeStarted
, OnMoveOrResizeStarted
)
991 IPC_MESSAGE_HANDLER(ViewMsg_ClearFocusedNode
, OnClearFocusedNode
)
992 IPC_MESSAGE_HANDLER(ViewMsg_SetBackground
, OnSetBackground
)
993 IPC_MESSAGE_HANDLER(ViewMsg_EnablePreferredSizeChangedMode
,
994 OnEnablePreferredSizeChangedMode
)
995 IPC_MESSAGE_HANDLER(ViewMsg_EnableAutoResize
, OnEnableAutoResize
)
996 IPC_MESSAGE_HANDLER(ViewMsg_DisableAutoResize
, OnDisableAutoResize
)
997 IPC_MESSAGE_HANDLER(ViewMsg_DisableScrollbarsForSmallWindows
,
998 OnDisableScrollbarsForSmallWindows
)
999 IPC_MESSAGE_HANDLER(ViewMsg_SetRendererPrefs
, OnSetRendererPrefs
)
1000 IPC_MESSAGE_HANDLER(ViewMsg_MediaPlayerActionAt
, OnMediaPlayerActionAt
)
1001 IPC_MESSAGE_HANDLER(ViewMsg_OrientationChangeEvent
,
1002 OnOrientationChangeEvent
)
1003 IPC_MESSAGE_HANDLER(ViewMsg_PluginActionAt
, OnPluginActionAt
)
1004 IPC_MESSAGE_HANDLER(ViewMsg_SetActive
, OnSetActive
)
1005 IPC_MESSAGE_HANDLER(ViewMsg_SetNavigationStartTime
,
1006 OnSetNavigationStartTime
)
1007 IPC_MESSAGE_HANDLER(ViewMsg_SetEditCommandsForNextKeyEvent
,
1008 OnSetEditCommandsForNextKeyEvent
)
1009 IPC_MESSAGE_HANDLER(ViewMsg_CustomContextMenuAction
,
1010 OnCustomContextMenuAction
)
1011 IPC_MESSAGE_HANDLER(ViewMsg_AsyncOpenFile_ACK
, OnAsyncFileOpened
)
1012 IPC_MESSAGE_HANDLER(ViewMsg_PpapiBrokerChannelCreated
,
1013 OnPpapiBrokerChannelCreated
)
1014 IPC_MESSAGE_HANDLER(ViewMsg_PpapiBrokerPermissionResult
,
1015 OnPpapiBrokerPermissionResult
)
1016 IPC_MESSAGE_HANDLER(ViewMsg_GetAllSavableResourceLinksForCurrentPage
,
1017 OnGetAllSavableResourceLinksForCurrentPage
)
1018 IPC_MESSAGE_HANDLER(
1019 ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks
,
1020 OnGetSerializedHtmlDataForCurrentPageWithLocalLinks
)
1021 IPC_MESSAGE_HANDLER(ViewMsg_ContextMenuClosed
, OnContextMenuClosed
)
1022 // TODO(viettrungluu): Move to a separate message filter.
1023 IPC_MESSAGE_HANDLER(ViewMsg_SetHistoryLengthAndPrune
,
1024 OnSetHistoryLengthAndPrune
)
1025 IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode
, OnEnableViewSourceMode
)
1026 IPC_MESSAGE_HANDLER(JavaBridgeMsg_Init
, OnJavaBridgeInit
)
1027 IPC_MESSAGE_HANDLER(ViewMsg_SetAccessibilityMode
, OnSetAccessibilityMode
)
1028 IPC_MESSAGE_HANDLER(ViewMsg_DisownOpener
, OnDisownOpener
)
1029 IPC_MESSAGE_HANDLER(ViewMsg_UpdateFrameTree
, OnUpdatedFrameTree
)
1030 #if defined(OS_ANDROID)
1031 IPC_MESSAGE_HANDLER(ViewMsg_ActivateNearestFindResult
,
1032 OnActivateNearestFindResult
)
1033 IPC_MESSAGE_HANDLER(ViewMsg_FindMatchRects
, OnFindMatchRects
)
1034 IPC_MESSAGE_HANDLER(ViewMsg_SelectPopupMenuItems
, OnSelectPopupMenuItems
)
1035 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewMsg_SynchronousFind
, OnSynchronousFind
)
1036 IPC_MESSAGE_HANDLER(ViewMsg_UndoScrollFocusedEditableNodeIntoView
,
1037 OnUndoScrollFocusedEditableNodeIntoRect
)
1038 #elif defined(OS_MACOSX)
1039 IPC_MESSAGE_HANDLER(ViewMsg_CopyToFindPboard
, OnCopyToFindPboard
)
1040 IPC_MESSAGE_HANDLER(ViewMsg_PluginImeCompositionCompleted
,
1041 OnPluginImeCompositionCompleted
)
1042 IPC_MESSAGE_HANDLER(ViewMsg_SelectPopupMenuItem
, OnSelectPopupMenuItem
)
1043 IPC_MESSAGE_HANDLER(ViewMsg_SetInLiveResize
, OnSetInLiveResize
)
1044 IPC_MESSAGE_HANDLER(ViewMsg_SetWindowVisibility
, OnSetWindowVisibility
)
1045 IPC_MESSAGE_HANDLER(ViewMsg_WindowFrameChanged
, OnWindowFrameChanged
)
1047 IPC_MESSAGE_HANDLER(ViewMsg_ReleaseDisambiguationPopupDIB
,
1048 OnReleaseDisambiguationPopupDIB
)
1049 IPC_MESSAGE_HANDLER(ViewMsg_WindowSnapshotCompleted
,
1050 OnWindowSnapshotCompleted
)
1052 // Have the super handle all other messages.
1053 IPC_MESSAGE_UNHANDLED(handled
= RenderWidget::OnMessageReceived(message
))
1054 IPC_END_MESSAGE_MAP()
1057 // The message had a handler, but its deserialization failed.
1058 // Kill the renderer to avoid potential spoofing attacks.
1059 CHECK(false) << "Unable to deserialize message in RenderViewImpl.";
1065 void RenderViewImpl::OnNavigate(const ViewMsg_Navigate_Params
& params
) {
1066 MaybeHandleDebugURL(params
.url
);
1070 FOR_EACH_OBSERVER(RenderViewObserver
, observers_
, Navigate(params
.url
));
1072 bool is_reload
= IsReload(params
);
1074 // If this is a stale back/forward (due to a recent navigation the browser
1075 // didn't know about), ignore it.
1076 if (IsBackForwardToStaleEntry(params
, is_reload
))
1079 // Swap this renderer back in if necessary.
1080 if (is_swapped_out_
) {
1081 // We marked the view as hidden when swapping the view out, so be sure to
1082 // reset the visibility state before navigating to the new URL.
1083 webview()->setVisibilityState(visibilityState(), false);
1085 // If this is an attempt to reload while we are swapped out, we should not
1086 // reload swappedout://, but the previous page, which is stored in
1087 // params.state. Setting is_reload to false will treat this like a back
1088 // navigation to accomplish that.
1091 SetSwappedOut(false);
1094 history_list_offset_
= params
.current_history_list_offset
;
1095 history_list_length_
= params
.current_history_list_length
;
1096 if (history_list_length_
>= 0)
1097 history_page_ids_
.resize(history_list_length_
, -1);
1098 if (params
.pending_history_list_offset
>= 0 &&
1099 params
.pending_history_list_offset
< history_list_length_
)
1100 history_page_ids_
[params
.pending_history_list_offset
] = params
.page_id
;
1102 GetContentClient()->SetActiveURL(params
.url
);
1104 WebFrame
* main_frame
= webview()->mainFrame();
1105 if (is_reload
&& main_frame
->currentHistoryItem().isNull()) {
1106 // We cannot reload if we do not have any history state. This happens, for
1107 // example, when recovering from a crash. Our workaround here is a bit of
1108 // a hack since it means that reload after a crashed tab does not cause an
1109 // end-to-end cache validation.
1113 pending_navigation_params_
.reset(new ViewMsg_Navigate_Params(params
));
1115 // If we are reloading, then WebKit will use the history state of the current
1116 // page, so we should just ignore any given history state. Otherwise, if we
1117 // have history state, then we need to navigate to it, which corresponds to a
1118 // back/forward navigation event.
1120 bool reload_original_url
=
1121 (params
.navigation_type
==
1122 ViewMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL
);
1123 bool ignore_cache
= (params
.navigation_type
==
1124 ViewMsg_Navigate_Type::RELOAD_IGNORING_CACHE
);
1126 if (reload_original_url
)
1127 main_frame
->reloadWithOverrideURL(params
.url
, true);
1129 main_frame
->reload(ignore_cache
);
1130 } else if (!params
.state
.empty()) {
1131 // We must know the page ID of the page we are navigating back to.
1132 DCHECK_NE(params
.page_id
, -1);
1133 WebHistoryItem item
= webkit_glue::HistoryItemFromString(params
.state
);
1134 if (!item
.isNull()) {
1135 // Ensure we didn't save the swapped out URL in UpdateState, since the
1136 // browser should never be telling us to navigate to swappedout://.
1137 CHECK(item
.urlString() != WebString::fromUTF8(kSwappedOutURL
));
1138 main_frame
->loadHistoryItem(item
);
1140 } else if (!params
.base_url_for_data_url
.is_empty()) {
1141 // A loadData request with a specified base URL.
1142 std::string mime_type
, charset
, data
;
1143 if (net::DataURL::Parse(params
.url
, &mime_type
, &charset
, &data
)) {
1144 main_frame
->loadData(
1145 WebData(data
.c_str(), data
.length()),
1146 WebString::fromUTF8(mime_type
),
1147 WebString::fromUTF8(charset
),
1148 params
.base_url_for_data_url
,
1149 params
.history_url_for_data_url
,
1153 "Invalid URL passed: " << params
.url
.possibly_invalid_spec();
1156 // Navigate to the given URL.
1157 WebURLRequest
request(params
.url
);
1159 // A session history navigation should have been accompanied by state.
1160 CHECK_EQ(params
.page_id
, -1);
1162 if (main_frame
->isViewSourceModeEnabled())
1163 request
.setCachePolicy(WebURLRequest::ReturnCacheDataElseLoad
);
1165 if (params
.referrer
.url
.is_valid()) {
1166 WebString referrer
= WebSecurityPolicy::generateReferrerHeader(
1167 params
.referrer
.policy
,
1169 WebString::fromUTF8(params
.referrer
.url
.spec()));
1170 if (!referrer
.isEmpty())
1171 request
.setHTTPHeaderField(WebString::fromUTF8("Referer"), referrer
);
1174 if (!params
.extra_headers
.empty()) {
1175 for (net::HttpUtil::HeadersIterator
i(params
.extra_headers
.begin(),
1176 params
.extra_headers
.end(), "\n");
1178 request
.addHTTPHeaderField(WebString::fromUTF8(i
.name()),
1179 WebString::fromUTF8(i
.values()));
1183 if (params
.is_post
) {
1184 request
.setHTTPMethod(WebString::fromUTF8("POST"));
1187 WebHTTPBody http_body
;
1188 http_body
.initialize();
1189 http_body
.appendData(WebData(
1190 reinterpret_cast<const char*>(
1191 ¶ms
.browser_initiated_post_data
.front()),
1192 params
.browser_initiated_post_data
.size()));
1193 request
.setHTTPBody(http_body
);
1196 main_frame
->loadRequest(request
);
1199 // In case LoadRequest failed before DidCreateDataSource was called.
1200 pending_navigation_params_
.reset();
1203 bool RenderViewImpl::IsBackForwardToStaleEntry(
1204 const ViewMsg_Navigate_Params
& params
,
1206 // Make sure this isn't a back/forward to an entry we have already cropped
1207 // or replaced from our history, before the browser knew about it. If so,
1208 // a new navigation has committed in the mean time, and we can ignore this.
1209 bool is_back_forward
= !is_reload
&& !params
.state
.empty();
1211 // Note: if the history_list_length_ is 0 for a back/forward, we must be
1212 // restoring from a previous session. We'll update our state in OnNavigate.
1213 if (!is_back_forward
|| history_list_length_
<= 0)
1216 DCHECK_EQ(static_cast<int>(history_page_ids_
.size()), history_list_length_
);
1218 // Check for whether the forward history has been cropped due to a recent
1219 // navigation the browser didn't know about.
1220 if (params
.pending_history_list_offset
>= history_list_length_
)
1223 // Check for whether this entry has been replaced with a new one.
1224 int expected_page_id
=
1225 history_page_ids_
[params
.pending_history_list_offset
];
1226 if (expected_page_id
> 0 && params
.page_id
!= expected_page_id
) {
1227 if (params
.page_id
< expected_page_id
)
1230 // Otherwise we've removed an earlier entry and should have shifted all
1231 // entries left. For now, it's ok to lazily update the list.
1232 // TODO(creis): Notify all live renderers when we remove entries from
1233 // the front of the list, so that we don't hit this case.
1234 history_page_ids_
[params
.pending_history_list_offset
] = params
.page_id
;
1240 // Stop loading the current page
1241 void RenderViewImpl::OnStop() {
1243 WebFrame
* main_frame
= webview()->mainFrame();
1244 // Stop the alt error page fetcher. If we let it continue it may complete
1245 // and cause RenderViewHostManager to swap to this RenderView, even though
1246 // it may no longer be active.
1247 StopAltErrorPageFetcher(main_frame
->provisionalDataSource());
1248 StopAltErrorPageFetcher(main_frame
->dataSource());
1249 main_frame
->stopLoading();
1253 // Reload current focused frame.
1254 // E.g. called by right-clicking on the frame and picking "reload this frame".
1255 void RenderViewImpl::OnReloadFrame() {
1256 if (webview() && webview()->focusedFrame()) {
1257 // We always obey the cache (ignore_cache=false) here.
1258 // TODO(evanm): perhaps we could allow shift-clicking the menu item to do
1259 // a cache-ignoring reload of the frame.
1260 webview()->focusedFrame()->reload(false);
1264 void RenderViewImpl::OnCopyImageAt(int x
, int y
) {
1265 webview()->copyImageAt(WebPoint(x
, y
));
1268 void RenderViewImpl::OnExecuteEditCommand(const std::string
& name
,
1269 const std::string
& value
) {
1270 if (!webview() || !webview()->focusedFrame())
1273 webview()->focusedFrame()->executeCommand(
1274 WebString::fromUTF8(name
), WebString::fromUTF8(value
));
1277 void RenderViewImpl::OnUpdateTargetURLAck() {
1278 // Check if there is a targeturl waiting to be sent.
1279 if (target_url_status_
== TARGET_PENDING
) {
1280 Send(new ViewHostMsg_UpdateTargetURL(routing_id_
, page_id_
,
1281 pending_target_url_
));
1284 target_url_status_
= TARGET_NONE
;
1287 void RenderViewImpl::OnUndo() {
1291 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Undo"));
1294 void RenderViewImpl::OnRedo() {
1298 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Redo"));
1301 void RenderViewImpl::OnCut() {
1305 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Cut"));
1308 void RenderViewImpl::OnCopy() {
1312 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Copy"),
1313 context_menu_node_
);
1316 #if defined(OS_MACOSX)
1317 void RenderViewImpl::OnCopyToFindPboard() {
1321 // Since the find pasteboard supports only plain text, this can be simpler
1322 // than the |OnCopy()| case.
1323 WebFrame
* frame
= webview()->focusedFrame();
1324 if (frame
->hasSelection()) {
1325 string16 selection
= frame
->selectionAsText();
1326 RenderThread::Get()->Send(
1327 new ClipboardHostMsg_FindPboardWriteStringAsync(selection
));
1332 void RenderViewImpl::OnPaste() {
1336 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Paste"));
1339 void RenderViewImpl::OnPasteAndMatchStyle() {
1343 webview()->focusedFrame()->executeCommand(
1344 WebString::fromUTF8("PasteAndMatchStyle"));
1347 void RenderViewImpl::OnReplace(const string16
& text
) {
1351 WebFrame
* frame
= webview()->focusedFrame();
1352 if (!frame
->hasSelection())
1353 frame
->selectWordAroundCaret();
1354 frame
->replaceSelection(text
);
1357 void RenderViewImpl::OnDelete() {
1361 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Delete"));
1364 void RenderViewImpl::OnSelectAll() {
1368 webview()->focusedFrame()->executeCommand(
1369 WebString::fromUTF8("SelectAll"));
1372 void RenderViewImpl::OnUnselect() {
1376 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Unselect"));
1379 void RenderViewImpl::OnSetEditableSelectionOffsets(int start
, int end
) {
1380 webview()->setEditableSelectionOffsets(start
, end
);
1383 void RenderViewImpl::OnSetCompositionFromExistingText(
1385 const std::vector
<WebKit::WebCompositionUnderline
>& underlines
) {
1388 webview()->setCompositionFromExistingText(start
, end
, underlines
);
1391 void RenderViewImpl::OnExtendSelectionAndDelete(int before
, int after
) {
1394 webview()->extendSelectionAndDelete(before
, after
);
1397 void RenderViewImpl::OnSelectRange(const gfx::Point
& start
,
1398 const gfx::Point
& end
) {
1402 Send(new ViewHostMsg_SelectRange_ACK(routing_id_
));
1404 handling_select_range_
= true;
1405 webview()->focusedFrame()->selectRange(start
, end
);
1406 handling_select_range_
= false;
1409 void RenderViewImpl::OnSetHistoryLengthAndPrune(int history_length
,
1410 int32 minimum_page_id
) {
1411 DCHECK_GE(history_length
, 0);
1412 DCHECK(history_list_offset_
== history_list_length_
- 1);
1413 DCHECK_GE(minimum_page_id
, -1);
1415 // Generate the new list.
1416 std::vector
<int32
> new_history_page_ids(history_length
, -1);
1417 for (size_t i
= 0; i
< history_page_ids_
.size(); ++i
) {
1418 if (minimum_page_id
>= 0 && history_page_ids_
[i
] < minimum_page_id
)
1420 new_history_page_ids
.push_back(history_page_ids_
[i
]);
1422 new_history_page_ids
.swap(history_page_ids_
);
1425 history_list_length_
= history_page_ids_
.size();
1426 history_list_offset_
= history_list_length_
- 1;
1430 void RenderViewImpl::OnSetInitialFocus(bool reverse
) {
1433 webview()->setInitialFocus(reverse
);
1436 #if defined(OS_MACOSX)
1437 void RenderViewImpl::OnSetInLiveResize(bool in_live_resize
) {
1441 webview()->willStartLiveResize();
1443 webview()->willEndLiveResize();
1447 void RenderViewImpl::OnScrollFocusedEditableNodeIntoRect(
1448 const gfx::Rect
& rect
) {
1449 WebKit::WebNode node
= GetFocusedNode();
1450 if (!node
.isNull()) {
1451 if (IsEditableNode(node
)) {
1452 webview()->saveScrollAndScaleState();
1453 webview()->scrollFocusedNodeIntoRect(rect
);
1458 #if defined(OS_ANDROID)
1459 void RenderViewImpl::OnUndoScrollFocusedEditableNodeIntoRect() {
1460 const WebNode node
= GetFocusedNode();
1461 if (!node
.isNull() && IsEditableNode(node
))
1462 webview()->restoreScrollAndScaleState();
1466 ///////////////////////////////////////////////////////////////////////////////
1468 // Tell the embedding application that the URL of the active page has changed
1469 void RenderViewImpl::UpdateURL(WebFrame
* frame
) {
1470 WebDataSource
* ds
= frame
->dataSource();
1473 const WebURLRequest
& request
= ds
->request();
1474 const WebURLRequest
& original_request
= ds
->originalRequest();
1475 const WebURLResponse
& response
= ds
->response();
1477 DocumentState
* document_state
= DocumentState::FromDataSource(ds
);
1478 NavigationState
* navigation_state
= document_state
->navigation_state();
1480 ViewHostMsg_FrameNavigate_Params params
;
1481 params
.http_status_code
= response
.httpStatusCode();
1482 params
.is_post
= false;
1483 params
.post_id
= -1;
1484 params
.page_id
= page_id_
;
1485 params
.frame_id
= frame
->identifier();
1486 params
.socket_address
.set_host(response
.remoteIPAddress().utf8());
1487 params
.socket_address
.set_port(response
.remotePort());
1488 params
.was_fetched_via_proxy
= response
.wasFetchedViaProxy();
1489 params
.was_within_same_page
= navigation_state
->was_within_same_page();
1490 if (!document_state
->security_info().empty()) {
1491 // SSL state specified in the request takes precedence over the one in the
1493 // So far this is only intended for error pages that are not expected to be
1494 // over ssl, so we should not get any clash.
1495 DCHECK(response
.securityInfo().isEmpty());
1496 params
.security_info
= document_state
->security_info();
1498 params
.security_info
= response
.securityInfo();
1501 // Set the URL to be displayed in the browser UI to the user.
1502 params
.url
= GetLoadingUrl(frame
);
1504 if (frame
->document().baseURL() != params
.url
)
1505 params
.base_url
= frame
->document().baseURL();
1507 GetRedirectChain(ds
, ¶ms
.redirects
);
1508 params
.should_update_history
= !ds
->hasUnreachableURL() &&
1509 !response
.isMultipartPayload() && (response
.httpStatusCode() != 404);
1511 params
.searchable_form_url
= document_state
->searchable_form_url();
1512 params
.searchable_form_encoding
=
1513 document_state
->searchable_form_encoding();
1515 const PasswordForm
* password_form_data
=
1516 document_state
->password_form_data();
1517 if (password_form_data
)
1518 params
.password_form
= *password_form_data
;
1520 params
.gesture
= navigation_gesture_
;
1521 navigation_gesture_
= NavigationGestureUnknown
;
1523 // Make navigation state a part of the FrameNavigate message so that commited
1524 // entry had it at all times.
1525 const WebHistoryItem
& item
= frame
->currentHistoryItem();
1526 if (!item
.isNull()) {
1527 params
.content_state
= webkit_glue::HistoryItemToString(item
);
1529 params
.content_state
=
1530 webkit_glue::CreateHistoryStateForURL(GURL(request
.url()));
1533 if (!frame
->parent()) {
1534 // Top-level navigation.
1536 // Reset the zoom limits in case a plugin had changed them previously. This
1537 // will also call us back which will cause us to send a message to
1538 // update WebContentsImpl.
1539 webview()->zoomLimitsChanged(
1540 WebView::zoomFactorToZoomLevel(kMinimumZoomFactor
),
1541 WebView::zoomFactorToZoomLevel(kMaximumZoomFactor
));
1543 // Set zoom level, but don't do it for full-page plugin since they don't use
1544 // the same zoom settings.
1545 HostZoomLevels::iterator host_zoom
=
1546 host_zoom_levels_
.find(GURL(request
.url()));
1547 if (webview()->mainFrame()->document().isPluginDocument()) {
1548 // Reset the zoom levels for plugins.
1549 webview()->setZoomLevel(false, 0);
1551 if (host_zoom
!= host_zoom_levels_
.end())
1552 webview()->setZoomLevel(false, host_zoom
->second
);
1555 if (host_zoom
!= host_zoom_levels_
.end()) {
1556 // This zoom level was merely recorded transiently for this load. We can
1557 // erase it now. If at some point we reload this page, the browser will
1558 // send us a new, up-to-date zoom level.
1559 host_zoom_levels_
.erase(host_zoom
);
1562 // Update contents MIME type for main frame.
1563 params
.contents_mime_type
= ds
->response().mimeType().utf8();
1565 params
.transition
= navigation_state
->transition_type();
1566 if (!PageTransitionIsMainFrame(params
.transition
)) {
1567 // If the main frame does a load, it should not be reported as a subframe
1568 // navigation. This can occur in the following case:
1569 // 1. You're on a site with frames.
1570 // 2. You do a subframe navigation. This is stored with transition type
1572 // 3. You navigate to some non-frame site, say, google.com.
1573 // 4. You navigate back to the page from step 2. Since it was initially
1574 // MANUAL_SUBFRAME, it will be that same transition type here.
1575 // We don't want that, because any navigation that changes the toplevel
1576 // frame should be tracked as a toplevel navigation (this allows us to
1577 // update the URL bar, etc).
1578 params
.transition
= PAGE_TRANSITION_LINK
;
1581 // If we have a valid consumed client redirect source,
1582 // the page contained a client redirect (meta refresh, document.loc...),
1583 // so we set the referrer and transition to match.
1584 if (completed_client_redirect_src_
.url
.is_valid()) {
1585 DCHECK(completed_client_redirect_src_
.url
== params
.redirects
[0]);
1586 params
.referrer
= completed_client_redirect_src_
;
1587 params
.transition
= static_cast<PageTransition
>(
1588 params
.transition
| PAGE_TRANSITION_CLIENT_REDIRECT
);
1590 // Bug 654101: the referrer will be empty on https->http transitions. It
1591 // would be nice if we could get the real referrer from somewhere.
1592 params
.referrer
= Referrer(GURL(
1593 original_request
.httpHeaderField(WebString::fromUTF8("Referer"))),
1594 GetReferrerPolicyFromRequest(frame
, original_request
));
1597 string16 method
= request
.httpMethod();
1598 if (EqualsASCII(method
, "POST")) {
1599 params
.is_post
= true;
1600 params
.post_id
= ExtractPostId(item
);
1603 // Send the user agent override back.
1604 params
.is_overriding_user_agent
=
1605 document_state
->is_overriding_user_agent();
1607 // Track the URL of the original request.
1608 params
.original_request_url
= original_request
.url();
1610 // Save some histogram data so we can compute the average memory used per
1611 // page load of the glyphs.
1612 UMA_HISTOGRAM_COUNTS_10000("Memory.GlyphPagesPerLoad",
1613 webkit_glue::GetGlyphPageCount());
1615 // This message needs to be sent before any of allowScripts(),
1616 // allowImages(), allowPlugins() is called for the new page, so that when
1617 // these functions send a ViewHostMsg_ContentBlocked message, it arrives
1618 // after the ViewHostMsg_FrameNavigate message.
1619 Send(new ViewHostMsg_FrameNavigate(routing_id_
, params
));
1621 // Subframe navigation: the type depends on whether this navigation
1622 // generated a new session history entry. When they do generate a session
1623 // history entry, it means the user initiated the navigation and we should
1624 // mark it as such. This test checks if this is the first time UpdateURL
1625 // has been called since WillNavigateToURL was called to initiate the load.
1626 if (page_id_
> last_page_id_sent_to_browser_
)
1627 params
.transition
= PAGE_TRANSITION_MANUAL_SUBFRAME
;
1629 params
.transition
= PAGE_TRANSITION_AUTO_SUBFRAME
;
1631 Send(new ViewHostMsg_FrameNavigate(routing_id_
, params
));
1634 last_page_id_sent_to_browser_
=
1635 std::max(last_page_id_sent_to_browser_
, page_id_
);
1637 // If we end up reusing this WebRequest (for example, due to a #ref click),
1638 // we don't want the transition type to persist. Just clear it.
1639 navigation_state
->set_transition_type(PAGE_TRANSITION_LINK
);
1642 // Tell the embedding application that the title of the active page has changed
1643 void RenderViewImpl::UpdateTitle(WebFrame
* frame
,
1644 const string16
& title
,
1645 WebTextDirection title_direction
) {
1646 // Ignore all but top level navigations.
1647 if (frame
->parent())
1650 string16 shortened_title
= title
.substr(0, kMaxTitleChars
);
1651 Send(new ViewHostMsg_UpdateTitle(routing_id_
, page_id_
, shortened_title
,
1655 void RenderViewImpl::UpdateEncoding(WebFrame
* frame
,
1656 const std::string
& encoding_name
) {
1657 // Only update main frame's encoding_name.
1658 if (webview()->mainFrame() == frame
&&
1659 last_encoding_name_
!= encoding_name
) {
1660 // Save the encoding name for later comparing.
1661 last_encoding_name_
= encoding_name
;
1663 Send(new ViewHostMsg_UpdateEncoding(routing_id_
, last_encoding_name_
));
1667 // Sends the last committed session history state to the browser so it will be
1668 // saved before we navigate to a new page. This must be called *before* the
1669 // page ID has been updated so we know what it was.
1670 void RenderViewImpl::UpdateSessionHistory(WebFrame
* frame
) {
1671 // If we have a valid page ID at this point, then it corresponds to the page
1672 // we are navigating away from. Otherwise, this is the first navigation, so
1673 // there is no past session history to record.
1677 const WebHistoryItem
& item
=
1678 webview()->mainFrame()->previousHistoryItem();
1679 SendUpdateState(item
);
1682 void RenderViewImpl::SendUpdateState(const WebHistoryItem
& item
) {
1686 // Don't send state updates for kSwappedOutURL.
1687 if (item
.urlString() == WebString::fromUTF8(kSwappedOutURL
))
1690 Send(new ViewHostMsg_UpdateState(
1691 routing_id_
, page_id_
, webkit_glue::HistoryItemToString(item
)));
1694 void RenderViewImpl::OpenURL(WebFrame
* frame
,
1696 const Referrer
& referrer
,
1697 WebNavigationPolicy policy
) {
1698 ViewHostMsg_OpenURL_Params params
;
1700 params
.referrer
= referrer
;
1701 params
.disposition
= NavigationPolicyToDisposition(policy
);
1702 params
.frame_id
= frame
->identifier();
1703 WebDataSource
* ds
= frame
->provisionalDataSource();
1705 params
.is_cross_site_redirect
= ds
->isClientRedirect();
1707 params
.is_cross_site_redirect
= false;
1710 Send(new ViewHostMsg_OpenURL(routing_id_
, params
));
1713 // WebViewDelegate ------------------------------------------------------------
1715 void RenderViewImpl::LoadNavigationErrorPage(
1717 const WebURLRequest
& failed_request
,
1718 const WebURLError
& error
,
1719 const std::string
& html
,
1721 std::string alt_html
;
1722 const std::string
* error_html
;
1724 if (!html
.empty()) {
1727 GetContentClient()->renderer()->GetNavigationErrorStrings(
1728 failed_request
, error
, &alt_html
, NULL
);
1729 error_html
= &alt_html
;
1732 frame
->loadHTMLString(*error_html
,
1733 GURL(kUnreachableWebDataURL
),
1734 error
.unreachableURL
,
1738 bool RenderViewImpl::RunJavaScriptMessage(JavaScriptMessageType type
,
1739 const string16
& message
,
1740 const string16
& default_value
,
1741 const GURL
& frame_url
,
1743 bool success
= false;
1744 string16 result_temp
;
1746 result
= &result_temp
;
1748 SendAndRunNestedMessageLoop(new ViewHostMsg_RunJavaScriptMessage(
1749 routing_id_
, message
, default_value
, frame_url
, type
, &success
, result
));
1753 bool RenderViewImpl::SendAndRunNestedMessageLoop(IPC::SyncMessage
* message
) {
1754 // Before WebKit asks us to show an alert (etc.), it takes care of doing the
1755 // equivalent of WebView::willEnterModalLoop. In the case of showModalDialog
1756 // it is particularly important that we do not call willEnterModalLoop as
1757 // that would defer resource loads for the dialog itself.
1758 if (RenderThreadImpl::current()) // Will be NULL during unit tests.
1759 RenderThreadImpl::current()->DoNotNotifyWebKitOfModalLoop();
1761 message
->EnableMessagePumping(); // Runs a nested message loop.
1762 return Send(message
);
1765 void RenderViewImpl::GetWindowSnapshot(const WindowSnapshotCallback
& callback
) {
1766 int id
= next_snapshot_id_
++;
1767 pending_snapshots_
.insert(std::make_pair(id
, callback
));
1768 Send(new ViewHostMsg_GetWindowSnapshot(routing_id_
, id
));
1771 void RenderViewImpl::OnWindowSnapshotCompleted(const int snapshot_id
,
1772 const gfx::Size
& size
, const std::vector
<unsigned char>& png
) {
1773 PendingSnapshotMap::iterator it
= pending_snapshots_
.find(snapshot_id
);
1774 DCHECK(it
!= pending_snapshots_
.end());
1775 it
->second
.Run(size
, png
);
1776 pending_snapshots_
.erase(it
);
1779 // WebKit::WebViewClient ------------------------------------------------------
1781 WebView
* RenderViewImpl::createView(
1783 const WebURLRequest
& request
,
1784 const WebWindowFeatures
& features
,
1785 const WebString
& frame_name
,
1786 WebNavigationPolicy policy
) {
1787 // Check to make sure we aren't overloading on popups.
1788 if (shared_popup_counter_
->data
> kMaximumNumberOfUnacknowledgedPopups
)
1791 ViewHostMsg_CreateWindow_Params params
;
1792 params
.opener_id
= routing_id_
;
1793 params
.user_gesture
= creator
->isProcessingUserGesture();
1794 params
.window_container_type
= WindowFeaturesToContainerType(features
);
1795 params
.session_storage_namespace_id
= session_storage_namespace_id_
;
1796 params
.frame_name
= frame_name
;
1797 params
.opener_frame_id
= creator
->identifier();
1798 params
.opener_url
= creator
->document().url();
1799 params
.opener_security_origin
=
1800 creator
->document().securityOrigin().toString().utf8();
1801 params
.opener_suppressed
= creator
->willSuppressOpenerInNewFrame();
1802 params
.disposition
= NavigationPolicyToDisposition(policy
);
1803 if (!request
.isNull())
1804 params
.target_url
= request
.url();
1806 int32 routing_id
= MSG_ROUTING_NONE
;
1807 int32 surface_id
= 0;
1808 int64 cloned_session_storage_namespace_id
;
1810 RenderThread::Get()->Send(
1811 new ViewHostMsg_CreateWindow(params
,
1814 &cloned_session_storage_namespace_id
));
1815 if (routing_id
== MSG_ROUTING_NONE
)
1818 creator
->consumeUserGesture();
1820 RenderViewImpl
* view
= RenderViewImpl::Create(
1822 renderer_preferences_
,
1823 webkit_preferences_
,
1824 shared_popup_counter_
,
1827 cloned_session_storage_namespace_id
,
1833 accessibility_mode_
);
1834 view
->opened_by_user_gesture_
= params
.user_gesture
;
1836 // Record whether the creator frame is trying to suppress the opener field.
1837 view
->opener_suppressed_
= params
.opener_suppressed
;
1839 // Copy over the alternate error page URL so we can have alt error pages in
1840 // the new render view (we don't need the browser to send the URL back down).
1841 view
->alternate_error_page_url_
= alternate_error_page_url_
;
1843 return view
->webview();
1846 WebWidget
* RenderViewImpl::createPopupMenu(WebKit::WebPopupType popup_type
) {
1847 RenderWidget
* widget
=
1848 RenderWidget::Create(routing_id_
, popup_type
, screen_info_
);
1849 return widget
->webwidget();
1852 WebExternalPopupMenu
* RenderViewImpl::createExternalPopupMenu(
1853 const WebPopupMenuInfo
& popup_menu_info
,
1854 WebExternalPopupMenuClient
* popup_menu_client
) {
1855 // An IPC message is sent to the browser to build and display the actual
1856 // popup. The user could have time to click a different select by the time
1857 // the popup is shown. In that case external_popup_menu_ is non NULL.
1858 // By returning NULL in that case, we instruct WebKit to cancel that new
1859 // popup. So from the user perspective, only the first one will show, and
1860 // will have to close the first one before another one can be shown.
1861 if (external_popup_menu_
.get())
1863 external_popup_menu_
.reset(
1864 new ExternalPopupMenu(this, popup_menu_info
, popup_menu_client
));
1865 return external_popup_menu_
.get();
1868 RenderWidgetFullscreenPepper
* RenderViewImpl::CreatePepperFullscreenContainer(
1869 webkit::ppapi::PluginInstance
* plugin
) {
1871 if (webview() && webview()->mainFrame())
1872 active_url
= GURL(webview()->mainFrame()->document().url());
1873 RenderWidgetFullscreenPepper
* widget
= RenderWidgetFullscreenPepper::Create(
1874 routing_id_
, plugin
, active_url
, screen_info_
);
1875 widget
->show(WebKit::WebNavigationPolicyIgnore
);
1879 WebStorageNamespace
* RenderViewImpl::createSessionStorageNamespace(
1881 CHECK(session_storage_namespace_id_
!=
1882 dom_storage::kInvalidSessionStorageNamespaceId
);
1883 return new WebStorageNamespaceImpl(session_storage_namespace_id_
);
1886 WebKit::WebCompositorOutputSurface
* RenderViewImpl::createOutputSurface() {
1887 // Explicitly disable antialiasing for the compositor. As of the time of
1888 // this writing, the only platform that supported antialiasing for the
1889 // compositor was Mac OS X, because the on-screen OpenGL context creation
1890 // code paths on Windows and Linux didn't yet have multisampling support.
1891 // Mac OS X essentially always behaves as though it's rendering offscreen.
1892 // Multisampling has a heavy cost especially on devices with relatively low
1893 // fill rate like most notebooks, and the Mac implementation would need to
1894 // be optimized to resolve directly into the IOSurface shared between the
1895 // GPU and browser processes. For these reasons and to avoid platform
1896 // disparities we explicitly disable antialiasing.
1897 WebKit::WebGraphicsContext3D::Attributes attributes
;
1898 attributes
.antialias
= false;
1899 attributes
.shareResources
= true;
1900 attributes
.noAutomaticFlushes
= true;
1901 WebGraphicsContext3D
* context
= CreateGraphicsContext3D(attributes
);
1905 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
1906 if (command_line
.HasSwitch(switches::kEnableSoftwareCompositingGLAdapter
)) {
1907 // In the absence of a software-based delegating renderer, use this
1908 // stopgap adapter class to present the software renderer output using a
1910 return new CompositorOutputSurface(routing_id(), NULL
,
1911 new CompositorSoftwareOutputDeviceGLAdapter(context
));
1913 return new CompositorOutputSurface(routing_id(), context
, NULL
);
1916 void RenderViewImpl::didAddMessageToConsole(
1917 const WebConsoleMessage
& message
, const WebString
& source_name
,
1918 unsigned source_line
) {
1919 logging::LogSeverity log_severity
= logging::LOG_VERBOSE
;
1920 switch (message
.level
) {
1921 case WebConsoleMessage::LevelTip
:
1922 log_severity
= logging::LOG_VERBOSE
;
1924 case WebConsoleMessage::LevelLog
:
1925 log_severity
= logging::LOG_INFO
;
1927 case WebConsoleMessage::LevelWarning
:
1928 log_severity
= logging::LOG_WARNING
;
1930 case WebConsoleMessage::LevelError
:
1931 log_severity
= logging::LOG_ERROR
;
1937 Send(new ViewHostMsg_AddMessageToConsole(routing_id_
,
1938 static_cast<int32
>(log_severity
),
1940 static_cast<int32
>(source_line
),
1944 void RenderViewImpl::printPage(WebFrame
* frame
) {
1945 FOR_EACH_OBSERVER(RenderViewObserver
, observers_
,
1946 PrintPage(frame
, handling_input_event_
));
1949 WebKit::WebNotificationPresenter
* RenderViewImpl::notificationPresenter() {
1950 return notification_provider_
;
1953 bool RenderViewImpl::enumerateChosenDirectory(
1954 const WebString
& path
,
1955 WebFileChooserCompletion
* chooser_completion
) {
1956 int id
= enumeration_completion_id_
++;
1957 enumeration_completions_
[id
] = chooser_completion
;
1958 return Send(new ViewHostMsg_EnumerateDirectory(
1961 webkit_base::WebStringToFilePath(path
)));
1964 void RenderViewImpl::initializeHelperPluginWebFrame(
1965 WebKit::WebHelperPlugin
* plugin
) {
1966 plugin
->initializeFrame(this);
1969 void RenderViewImpl::didStartLoading() {
1971 DVLOG(1) << "didStartLoading called while loading";
1977 Send(new ViewHostMsg_DidStartLoading(routing_id_
));
1979 FOR_EACH_OBSERVER(RenderViewObserver
, observers_
, DidStartLoading());
1982 void RenderViewImpl::didStopLoading() {
1984 DVLOG(1) << "DidStopLoading called while not loading";
1988 is_loading_
= false;
1990 if (pending_frame_tree_update_
) {
1991 pending_frame_tree_update_
= false;
1992 SendUpdatedFrameTree(NULL
);
1995 // NOTE: For now we're doing the safest thing, and sending out notification
1996 // when done loading. This currently isn't an issue as the favicon is only
1997 // displayed when done loading. Ideally we would send notification when
1998 // finished parsing the head, but webkit doesn't support that yet.
1999 // The feed discovery code would also benefit from access to the head.
2000 Send(new ViewHostMsg_DidStopLoading(routing_id_
));
2002 if (load_progress_tracker_
!= NULL
)
2003 load_progress_tracker_
->DidStopLoading();
2005 FOR_EACH_OBSERVER(RenderViewObserver
, observers_
, DidStopLoading());
2008 void RenderViewImpl::didChangeLoadProgress(WebFrame
* frame
,
2009 double load_progress
) {
2010 if (load_progress_tracker_
!= NULL
)
2011 load_progress_tracker_
->DidChangeLoadProgress(frame
, load_progress
);
2014 bool RenderViewImpl::isSmartInsertDeleteEnabled() {
2015 #if defined(OS_MACOSX)
2022 bool RenderViewImpl::isSelectTrailingWhitespaceEnabled() {
2030 void RenderViewImpl::didChangeSelection(bool is_empty_selection
) {
2031 if (!handling_input_event_
&& !handling_select_range_
)
2033 handling_select_range_
= false;
2035 if (is_empty_selection
)
2036 selection_text_
.clear();
2038 SyncSelectionIfRequired();
2041 void RenderViewImpl::didExecuteCommand(const WebString
& command_name
) {
2042 const std::string
& name
= UTF16ToUTF8(command_name
);
2043 if (StartsWithASCII(name
, "Move", true) ||
2044 StartsWithASCII(name
, "Insert", true) ||
2045 StartsWithASCII(name
, "Delete", true))
2047 RenderThreadImpl::current()->RecordUserMetrics(name
);
2050 bool RenderViewImpl::handleCurrentKeyboardEvent() {
2051 if (edit_commands_
.empty())
2054 WebFrame
* frame
= webview()->focusedFrame();
2058 EditCommands::iterator it
= edit_commands_
.begin();
2059 EditCommands::iterator end
= edit_commands_
.end();
2061 bool did_execute_command
= false;
2062 for (; it
!= end
; ++it
) {
2063 // In gtk and cocoa, it's possible to bind multiple edit commands to one
2064 // key (but it's the exception). Once one edit command is not executed, it
2065 // seems safest to not execute the rest.
2066 if (!frame
->executeCommand(WebString::fromUTF8(it
->name
),
2067 WebString::fromUTF8(it
->value
)))
2069 did_execute_command
= true;
2072 return did_execute_command
;
2075 void RenderViewImpl::didHandleGestureEvent(const WebGestureEvent
& event
,
2076 bool event_swallowed
) {
2077 #if defined(OS_ANDROID)
2078 if (event
.type
== WebInputEvent::GestureTap
||
2079 event
.type
== WebInputEvent::GestureLongPress
) {
2080 UpdateTextInputState(SHOW_IME_IF_NEEDED
);
2083 FOR_EACH_OBSERVER(RenderViewObserver
, observers_
,
2084 DidHandleGestureEvent(event
));
2087 WebKit::WebColorChooser
* RenderViewImpl::createColorChooser(
2088 WebKit::WebColorChooserClient
* client
,
2089 const WebKit::WebColor
& initial_color
) {
2090 RendererWebColorChooserImpl
* color_chooser
=
2091 new RendererWebColorChooserImpl(this, client
);
2092 color_chooser
->Open(static_cast<SkColor
>(initial_color
));
2093 return color_chooser
;
2096 bool RenderViewImpl::runFileChooser(
2097 const WebKit::WebFileChooserParams
& params
,
2098 WebFileChooserCompletion
* chooser_completion
) {
2099 // Do not open the file dialog in a hidden RenderView.
2102 FileChooserParams ipc_params
;
2103 if (params
.directory
)
2104 ipc_params
.mode
= FileChooserParams::OpenFolder
;
2105 else if (params
.multiSelect
)
2106 ipc_params
.mode
= FileChooserParams::OpenMultiple
;
2107 else if (params
.saveAs
)
2108 ipc_params
.mode
= FileChooserParams::Save
;
2110 ipc_params
.mode
= FileChooserParams::Open
;
2111 ipc_params
.title
= params
.title
;
2112 ipc_params
.default_file_name
=
2113 webkit_base::WebStringToFilePath(params
.initialValue
);
2114 ipc_params
.accept_types
.reserve(params
.acceptTypes
.size());
2115 for (size_t i
= 0; i
< params
.acceptTypes
.size(); ++i
)
2116 ipc_params
.accept_types
.push_back(params
.acceptTypes
[i
]);
2117 #if defined(OS_ANDROID)
2118 ipc_params
.capture
= params
.capture
;
2121 return ScheduleFileChooser(ipc_params
, chooser_completion
);
2124 void RenderViewImpl::runModalAlertDialog(WebFrame
* frame
,
2125 const WebString
& message
) {
2126 RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_ALERT
,
2129 frame
->document().url(),
2133 bool RenderViewImpl::runModalConfirmDialog(WebFrame
* frame
,
2134 const WebString
& message
) {
2135 return RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_CONFIRM
,
2138 frame
->document().url(),
2142 bool RenderViewImpl::runModalPromptDialog(WebFrame
* frame
,
2143 const WebString
& message
,
2144 const WebString
& default_value
,
2145 WebString
* actual_value
) {
2147 bool ok
= RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_PROMPT
,
2150 frame
->document().url(),
2153 actual_value
->assign(result
);
2157 bool RenderViewImpl::runModalBeforeUnloadDialog(
2158 WebFrame
* frame
, const WebString
& message
) {
2159 // If we are swapping out, we have already run the beforeunload handler.
2160 // TODO(creis): Fix OnSwapOut to clear the frame without running beforeunload
2161 // at all, to avoid running it twice.
2162 if (is_swapped_out_
)
2165 bool is_reload
= false;
2166 WebDataSource
* ds
= frame
->provisionalDataSource();
2168 is_reload
= (ds
->navigationType() == WebKit::WebNavigationTypeReload
);
2170 bool success
= false;
2171 // This is an ignored return value, but is included so we can accept the same
2172 // response as RunJavaScriptMessage.
2173 string16 ignored_result
;
2174 SendAndRunNestedMessageLoop(new ViewHostMsg_RunBeforeUnloadConfirm(
2175 routing_id_
, frame
->document().url(), message
, is_reload
,
2176 &success
, &ignored_result
));
2180 void RenderViewImpl::showContextMenu(
2181 WebFrame
* frame
, const WebContextMenuData
& data
) {
2182 ContextMenuParams
params(data
);
2184 // Plugins, e.g. PDF, don't currently update the render view when their
2185 // selected text changes, but the context menu params do contain the updated
2186 // selection. If that's the case, update the render view's state just prior
2187 // to showing the context menu.
2188 // TODO(asvitkine): http://crbug.com/152432
2189 string16 selection_text
;
2190 if (!selection_text_
.empty() && !selection_range_
.is_empty()) {
2191 const int start
= selection_range_
.GetMin() - selection_text_offset_
;
2192 const size_t length
= selection_range_
.length();
2193 if (start
>= 0 && start
+ length
<= selection_text_
.length())
2194 selection_text
= selection_text_
.substr(start
, length
);
2196 if (params
.selection_text
!= selection_text
) {
2197 selection_text_
= params
.selection_text
;
2198 // TODO(asvitkine): Text offset and range is not available in this case.
2199 selection_text_offset_
= 0;
2200 selection_range_
= ui::Range(0, selection_text_
.length());
2201 Send(new ViewHostMsg_SelectionChanged(routing_id_
,
2203 selection_text_offset_
,
2207 // frame is NULL if invoked by BlockedPlugin.
2209 params
.frame_id
= frame
->identifier();
2211 // Serializing a GURL longer than kMaxURLChars will fail, so don't do
2212 // it. We replace it with an empty GURL so the appropriate items are disabled
2213 // in the context menu.
2214 // TODO(jcivelli): http://crbug.com/45160 This prevents us from saving large
2215 // data encoded images. We should have a way to save them.
2216 if (params
.src_url
.spec().size() > kMaxURLChars
)
2217 params
.src_url
= GURL();
2218 context_menu_node_
= data
.node
;
2220 #if defined(OS_ANDROID)
2221 gfx::Rect start_rect
;
2223 GetSelectionBounds(&start_rect
, &end_rect
);
2224 params
.selection_start
=
2225 gfx::Point(start_rect
.x(), start_rect
.bottom()) + GetScrollOffset();
2226 params
.selection_end
=
2227 gfx::Point(end_rect
.right(), end_rect
.bottom()) + GetScrollOffset();
2230 Send(new ViewHostMsg_ContextMenu(routing_id_
, params
));
2233 RenderViewObserver
, observers_
, DidRequestShowContextMenu(frame
, data
));
2236 void RenderViewImpl::setStatusText(const WebString
& text
) {
2239 void RenderViewImpl::UpdateTargetURL(const GURL
& url
,
2240 const GURL
& fallback_url
) {
2241 GURL latest_url
= url
.is_empty() ? fallback_url
: url
;
2242 if (latest_url
== target_url_
)
2245 // Tell the browser to display a destination link.
2246 if (target_url_status_
== TARGET_INFLIGHT
||
2247 target_url_status_
== TARGET_PENDING
) {
2248 // If we have a request in-flight, save the URL to be sent when we
2249 // receive an ACK to the in-flight request. We can happily overwrite
2250 // any existing pending sends.
2251 pending_target_url_
= latest_url
;
2252 target_url_status_
= TARGET_PENDING
;
2254 // URLs larger than |kMaxURLChars| cannot be sent through IPC -
2255 // see |ParamTraits<GURL>|.
2256 if (latest_url
.possibly_invalid_spec().size() > kMaxURLChars
)
2257 latest_url
= GURL();
2258 Send(new ViewHostMsg_UpdateTargetURL(routing_id_
, page_id_
, latest_url
));
2259 target_url_
= latest_url
;
2260 target_url_status_
= TARGET_INFLIGHT
;
2264 void RenderViewImpl::StartNavStateSyncTimerIfNecessary() {
2265 // No need to update state if no page has committed yet.
2270 if (send_content_state_immediately_
)
2272 else if (is_hidden())
2273 delay
= kDelaySecondsForContentStateSyncHidden
;
2275 delay
= kDelaySecondsForContentStateSync
;
2277 if (nav_state_sync_timer_
.IsRunning()) {
2278 // The timer is already running. If the delay of the timer maches the amount
2279 // we want to delay by, then return. Otherwise stop the timer so that it
2280 // gets started with the right delay.
2281 if (nav_state_sync_timer_
.GetCurrentDelay().InSeconds() == delay
)
2283 nav_state_sync_timer_
.Stop();
2286 nav_state_sync_timer_
.Start(FROM_HERE
, TimeDelta::FromSeconds(delay
), this,
2287 &RenderViewImpl::SyncNavigationState
);
2290 void RenderViewImpl::setMouseOverURL(const WebURL
& url
) {
2291 mouse_over_url_
= GURL(url
);
2292 UpdateTargetURL(mouse_over_url_
, focus_url_
);
2295 void RenderViewImpl::setKeyboardFocusURL(const WebURL
& url
) {
2296 focus_url_
= GURL(url
);
2297 UpdateTargetURL(focus_url_
, mouse_over_url_
);
2300 void RenderViewImpl::startDragging(WebFrame
* frame
,
2301 const WebDragData
& data
,
2302 WebDragOperationsMask mask
,
2303 const WebImage
& image
,
2304 const WebPoint
& webImageOffset
) {
2305 WebDropData
drop_data(data
);
2306 drop_data
.referrer_policy
= frame
->document().referrerPolicy();
2307 gfx::Vector2d
imageOffset(webImageOffset
.x
, webImageOffset
.y
);
2308 Send(new DragHostMsg_StartDragging(routing_id_
,
2311 image
.getSkBitmap(),
2313 possible_drag_event_info_
));
2316 bool RenderViewImpl::acceptsLoadDrops() {
2317 return renderer_preferences_
.can_accept_load_drops
;
2320 void RenderViewImpl::focusNext() {
2321 Send(new ViewHostMsg_TakeFocus(routing_id_
, false));
2324 void RenderViewImpl::focusPrevious() {
2325 Send(new ViewHostMsg_TakeFocus(routing_id_
, true));
2328 void RenderViewImpl::focusedNodeChanged(const WebNode
& node
) {
2329 Send(new ViewHostMsg_FocusedNodeChanged(routing_id_
, IsEditableNode(node
)));
2331 FOR_EACH_OBSERVER(RenderViewObserver
, observers_
, FocusedNodeChanged(node
));
2334 void RenderViewImpl::numberOfWheelEventHandlersChanged(unsigned num_handlers
) {
2335 Send(new ViewHostMsg_DidChangeNumWheelEvents(routing_id_
, num_handlers
));
2338 void RenderViewImpl::hasTouchEventHandlers(bool has_handlers
) {
2339 Send(new ViewHostMsg_HasTouchEventHandlers(routing_id_
, has_handlers
));
2342 void RenderViewImpl::didUpdateLayout() {
2343 // We don't always want to set up a timer, only if we've been put in that
2344 // mode by getting a |ViewMsg_EnablePreferredSizeChangedMode|
2346 if (!send_preferred_size_changes_
|| !webview())
2349 if (check_preferred_size_timer_
.IsRunning())
2351 check_preferred_size_timer_
.Start(FROM_HERE
,
2352 TimeDelta::FromMilliseconds(0), this,
2353 &RenderViewImpl::CheckPreferredSize
);
2356 void RenderViewImpl::navigateBackForwardSoon(int offset
) {
2357 Send(new ViewHostMsg_GoToEntryAtOffset(routing_id_
, offset
));
2360 int RenderViewImpl::historyBackListCount() {
2361 return history_list_offset_
< 0 ? 0 : history_list_offset_
;
2364 int RenderViewImpl::historyForwardListCount() {
2365 return history_list_length_
- historyBackListCount() - 1;
2368 void RenderViewImpl::postAccessibilityNotification(
2369 const WebAccessibilityObject
& obj
,
2370 WebAccessibilityNotification notification
) {
2371 if (renderer_accessibility_
) {
2372 renderer_accessibility_
->HandleWebAccessibilityNotification(
2377 void RenderViewImpl::didUpdateInspectorSetting(const WebString
& key
,
2378 const WebString
& value
) {
2379 Send(new ViewHostMsg_UpdateInspectorSetting(routing_id_
,
2384 // WebKit::WebWidgetClient ----------------------------------------------------
2386 void RenderViewImpl::didFocus() {
2387 // TODO(jcivelli): when https://bugs.webkit.org/show_bug.cgi?id=33389 is fixed
2388 // we won't have to test for user gesture anymore and we can
2389 // move that code back to render_widget.cc
2390 if (webview() && webview()->mainFrame() &&
2391 webview()->mainFrame()->isProcessingUserGesture()) {
2392 Send(new ViewHostMsg_Focus(routing_id_
));
2396 void RenderViewImpl::didBlur() {
2397 // TODO(jcivelli): see TODO above in didFocus().
2398 if (webview() && webview()->mainFrame() &&
2399 webview()->mainFrame()->isProcessingUserGesture()) {
2400 Send(new ViewHostMsg_Blur(routing_id_
));
2404 // We are supposed to get a single call to Show for a newly created RenderView
2405 // that was created via RenderViewImpl::CreateWebView. So, we wait until this
2406 // point to dispatch the ShowView message.
2408 // This method provides us with the information about how to display the newly
2409 // created RenderView (i.e., as a blocked popup or as a new tab).
2411 void RenderViewImpl::show(WebNavigationPolicy policy
) {
2413 #if defined(OS_ANDROID)
2414 // When supports_multiple_windows is disabled, popups are reusing
2415 // the same view. In some scenarios, this makes WebKit to call show() twice.
2416 if (!webkit_preferences_
.supports_multiple_windows
)
2419 NOTREACHED() << "received extraneous Show call";
2424 DCHECK(opener_id_
!= MSG_ROUTING_NONE
);
2426 if (GetContentClient()->renderer()->AllowPopup())
2427 opened_by_user_gesture_
= true;
2429 // Force new windows to a popup if they were not opened with a user gesture.
2430 if (!opened_by_user_gesture_
) {
2431 // We exempt background tabs for compat with older versions of Chrome.
2432 // TODO(darin): This seems bogus. These should have a user gesture, so
2433 // we probably don't need this check.
2434 if (policy
!= WebKit::WebNavigationPolicyNewBackgroundTab
)
2435 policy
= WebKit::WebNavigationPolicyNewPopup
;
2438 // NOTE: initial_pos_ may still have its default values at this point, but
2439 // that's okay. It'll be ignored if disposition is not NEW_POPUP, or the
2440 // browser process will impose a default position otherwise.
2441 Send(new ViewHostMsg_ShowView(opener_id_
, routing_id_
,
2442 NavigationPolicyToDisposition(policy
), initial_pos_
,
2443 opened_by_user_gesture_
));
2444 SetPendingWindowRect(initial_pos_
);
2447 void RenderViewImpl::runModal() {
2448 DCHECK(did_show_
) << "should already have shown the view";
2450 // We must keep WebKit's shared timer running in this case in order to allow
2451 // showModalDialog to function properly.
2453 // TODO(darin): WebKit should really be smarter about suppressing events and
2454 // timers so that we do not need to manage the shared timer in such a heavy
2457 if (RenderThreadImpl::current()) // Will be NULL during unit tests.
2458 RenderThreadImpl::current()->DoNotSuspendWebKitSharedTimer();
2460 SendAndRunNestedMessageLoop(new ViewHostMsg_RunModal(
2461 routing_id_
, opener_id_
));
2464 bool RenderViewImpl::enterFullScreen() {
2465 Send(new ViewHostMsg_ToggleFullscreen(routing_id_
, true));
2469 void RenderViewImpl::exitFullScreen() {
2470 Send(new ViewHostMsg_ToggleFullscreen(routing_id_
, false));
2473 bool RenderViewImpl::requestPointerLock() {
2474 return mouse_lock_dispatcher_
->LockMouse(webwidget_mouse_lock_target_
.get());
2477 void RenderViewImpl::requestPointerUnlock() {
2478 mouse_lock_dispatcher_
->UnlockMouse(webwidget_mouse_lock_target_
.get());
2481 bool RenderViewImpl::isPointerLocked() {
2482 return mouse_lock_dispatcher_
->IsMouseLockedTo(
2483 webwidget_mouse_lock_target_
.get());
2486 void RenderViewImpl::didActivateCompositor(int input_handler_identifier
) {
2487 CompositorThread
* compositor_thread
=
2488 RenderThreadImpl::current()->compositor_thread();
2489 if (compositor_thread
)
2490 compositor_thread
->AddInputHandler(
2491 routing_id_
, input_handler_identifier
, AsWeakPtr());
2493 RenderWidget::didActivateCompositor(input_handler_identifier
);
2495 ProcessAcceleratedPinchZoomFlags(*CommandLine::ForCurrentProcess());
2498 // WebKit::WebFrameClient -----------------------------------------------------
2500 WebPlugin
* RenderViewImpl::createPlugin(WebFrame
* frame
,
2501 const WebPluginParams
& params
) {
2502 WebPlugin
* plugin
= NULL
;
2503 if (GetContentClient()->renderer()->OverrideCreatePlugin(
2504 this, frame
, params
, &plugin
)) {
2508 if (UTF16ToASCII(params
.mimeType
) == kBrowserPluginMimeType
) {
2509 return browser_plugin_manager()->CreateBrowserPlugin(this, frame
, params
);
2512 webkit::WebPluginInfo info
;
2513 std::string mime_type
;
2514 bool found
= GetPluginInfo(params
.url
, frame
->top()->document().url(),
2515 params
.mimeType
.utf8(), &info
, &mime_type
);
2519 WebPluginParams params_to_use
= params
;
2520 params_to_use
.mimeType
= WebString::fromUTF8(mime_type
);
2521 return CreatePlugin(frame
, info
, params_to_use
);
2524 WebSharedWorker
* RenderViewImpl::createSharedWorker(
2525 WebFrame
* frame
, const WebURL
& url
, const WebString
& name
,
2526 unsigned long long document_id
) {
2528 int route_id
= MSG_ROUTING_NONE
;
2529 bool exists
= false;
2530 bool url_mismatch
= false;
2531 ViewHostMsg_CreateWorker_Params params
;
2534 params
.document_id
= document_id
;
2535 params
.render_view_route_id
= routing_id_
;
2536 params
.route_id
= MSG_ROUTING_NONE
;
2537 params
.script_resource_appcache_id
= 0;
2538 Send(new ViewHostMsg_LookupSharedWorker(
2539 params
, &exists
, &route_id
, &url_mismatch
));
2543 return new WebSharedWorkerProxy(RenderThreadImpl::current(),
2551 WebMediaPlayer
* RenderViewImpl::createMediaPlayer(
2552 WebFrame
* frame
, const WebKit::WebURL
& url
, WebMediaPlayerClient
* client
) {
2554 RenderViewObserver
, observers_
, WillCreateMediaPlayer(frame
, client
));
2556 const CommandLine
* cmd_line
= CommandLine::ForCurrentProcess();
2557 #if defined(ENABLE_WEBRTC)
2558 // TODO(wjia): when all patches related to WebMediaPlayerMS have been
2559 // landed, remove the switch. Refer to crbug.com/142988.
2560 if (!cmd_line
->HasSwitch(switches::kDisableWebMediaPlayerMS
) &&
2561 MediaStreamImpl::CheckMediaStream(url
)) {
2562 EnsureMediaStreamImpl();
2563 return new webkit_media::WebMediaPlayerMS(
2564 frame
, client
, AsWeakPtr(), media_stream_impl_
, new RenderMediaLog());
2568 #if defined(OS_ANDROID)
2569 WebGraphicsContext3D
* resource_context
=
2570 GetWebView()->sharedGraphicsContext3D();
2572 GpuChannelHost
* gpu_channel_host
=
2573 RenderThreadImpl::current()->EstablishGpuChannelSync(
2574 CAUSE_FOR_GPU_LAUNCH_VIDEODECODEACCELERATOR_INITIALIZE
);
2575 if (!gpu_channel_host
) {
2576 LOG(ERROR
) << "Failed to establish GPU channel for media player";
2580 if (cmd_line
->HasSwitch(switches::kMediaPlayerInRenderProcess
)) {
2581 if (!media_bridge_manager_
.get()) {
2582 media_bridge_manager_
.reset(
2583 new webkit_media::MediaPlayerBridgeManagerImpl(1));
2585 return new webkit_media::WebMediaPlayerInProcessAndroid(
2589 media_player_manager_
.get(),
2590 media_bridge_manager_
.get(),
2591 new StreamTextureFactoryImpl(
2592 resource_context
, gpu_channel_host
, routing_id_
),
2593 cmd_line
->HasSwitch(switches::kDisableMediaHistoryLogging
));
2595 if (!media_player_proxy_
) {
2596 media_player_proxy_
= new WebMediaPlayerProxyImplAndroid(
2597 this, media_player_manager_
.get());
2599 return new webkit_media::WebMediaPlayerImplAndroid(
2602 media_player_manager_
.get(),
2603 media_player_proxy_
,
2604 new StreamTextureFactoryImpl(
2605 resource_context
, gpu_channel_host
, routing_id_
));
2608 media::MessageLoopFactory
* message_loop_factory
=
2609 new media::MessageLoopFactory();
2610 media::FilterCollection
* collection
= new media::FilterCollection();
2611 RenderMediaLog
* render_media_log
= new RenderMediaLog();
2613 RenderAudioSourceProvider
* audio_source_provider
= NULL
;
2615 // |audio_source_provider| "provides" audio to WebKit and is a sink from the
2616 // perspective of the audio renderer.
2617 if (!cmd_line
->HasSwitch(switches::kDisableAudio
)) {
2618 audio_source_provider
= new RenderAudioSourceProvider(routing_id_
);
2621 WebGraphicsContext3DCommandBufferImpl
* context3d
= NULL
;
2622 if (!cmd_line
->HasSwitch(switches::kDisableAcceleratedVideoDecode
))
2623 context3d
= RenderThreadImpl::current()->GetGpuVDAContext3D();
2625 scoped_refptr
<base::MessageLoopProxy
> factories_loop
=
2626 RenderThreadImpl::current()->compositor_thread() ?
2627 RenderThreadImpl::current()->compositor_thread()->GetWebThread()
2628 ->message_loop()->message_loop_proxy() :
2629 base::MessageLoopProxy::current();
2630 GpuChannelHost
* gpu_channel_host
=
2631 RenderThreadImpl::current()->EstablishGpuChannelSync(
2632 CAUSE_FOR_GPU_LAUNCH_VIDEODECODEACCELERATOR_INITIALIZE
);
2633 collection
->GetVideoDecoders()->push_back(new media::GpuVideoDecoder(
2634 message_loop_factory
->GetMessageLoop(
2635 media::MessageLoopFactory::kPipeline
),
2637 new RendererGpuVideoDecoderFactories(
2638 gpu_channel_host
, factories_loop
, context3d
)));
2641 WebMediaPlayer
* media_player
=
2642 GetContentClient()->renderer()->OverrideCreateWebMediaPlayer(
2643 this, frame
, client
, AsWeakPtr(), collection
, audio_source_provider
,
2644 audio_source_provider
, message_loop_factory
, media_stream_impl_
,
2646 if (!media_player
) {
2647 media_player
= new webkit_media::WebMediaPlayerImpl(
2648 frame
, client
, AsWeakPtr(), collection
, audio_source_provider
,
2649 audio_source_provider
, message_loop_factory
, media_stream_impl_
,
2652 return media_player
;
2655 WebApplicationCacheHost
* RenderViewImpl::createApplicationCacheHost(
2656 WebFrame
* frame
, WebApplicationCacheHostClient
* client
) {
2657 if (!frame
|| !frame
->view())
2659 return new RendererWebApplicationCacheHostImpl(
2660 FromWebView(frame
->view()), client
,
2661 RenderThreadImpl::current()->appcache_dispatcher()->backend_proxy());
2664 WebCookieJar
* RenderViewImpl::cookieJar(WebFrame
* frame
) {
2665 return &cookie_jar_
;
2668 void RenderViewImpl::didCreateFrame(WebFrame
* parent
, WebFrame
* child
) {
2669 if (!updating_frame_tree_
)
2670 SendUpdatedFrameTree(NULL
);
2673 void RenderViewImpl::didDisownOpener(WebKit::WebFrame
* frame
) {
2674 // We should only hear this from the top-level frame, because subframes do not
2676 CHECK(!frame
->parent());
2678 // We only need to notify the browser if the active frame clears its opener.
2679 // We can ignore cases where a swapped out frame clears its opener after
2680 // hearing about it from the browser.
2681 if (is_swapped_out_
)
2684 // Notify WebContents and all its swapped out RenderViews.
2685 Send(new ViewHostMsg_DidDisownOpener(routing_id_
));
2688 void RenderViewImpl::frameDetached(WebFrame
* frame
) {
2690 pending_frame_tree_update_
= true;
2691 // Make sure observers are notified, even if we return right away.
2692 FOR_EACH_OBSERVER(RenderViewObserver
, observers_
, FrameDetached(frame
));
2695 if (!updating_frame_tree_
)
2696 SendUpdatedFrameTree(frame
);
2698 FOR_EACH_OBSERVER(RenderViewObserver
, observers_
, FrameDetached(frame
));
2701 void RenderViewImpl::willClose(WebFrame
* frame
) {
2702 FOR_EACH_OBSERVER(RenderViewObserver
, observers_
, FrameWillClose(frame
));
2705 void RenderViewImpl::loadURLExternally(
2706 WebFrame
* frame
, const WebURLRequest
& request
,
2707 WebNavigationPolicy policy
) {
2708 loadURLExternally(frame
, request
, policy
, WebString());
2711 void RenderViewImpl::Repaint(const gfx::Size
& size
) {
2715 void RenderViewImpl::SetEditCommandForNextKeyEvent(const std::string
& name
,
2716 const std::string
& value
) {
2717 EditCommands edit_commands
;
2718 edit_commands
.push_back(EditCommand(name
, value
));
2719 OnSetEditCommandsForNextKeyEvent(edit_commands
);
2722 void RenderViewImpl::ClearEditCommands() {
2723 edit_commands_
.clear();
2726 SSLStatus
RenderViewImpl::GetSSLStatusOfFrame(WebKit::WebFrame
* frame
) const {
2727 SSLStatus ssl_status
;
2729 DocumentState
* doc_state
= DocumentState::FromDataSource(frame
->dataSource());
2730 if (doc_state
&& !doc_state
->security_info().empty()) {
2731 DeserializeSecurityInfo(doc_state
->security_info(),
2732 &ssl_status
.cert_id
,
2733 &ssl_status
.cert_status
,
2734 &ssl_status
.security_bits
,
2735 &ssl_status
.connection_status
);
2741 void RenderViewImpl::loadURLExternally(
2742 WebFrame
* frame
, const WebURLRequest
& request
,
2743 WebNavigationPolicy policy
,
2744 const WebString
& suggested_name
) {
2746 GURL(request
.httpHeaderField(WebString::fromUTF8("Referer"))),
2747 GetReferrerPolicyFromRequest(frame
, request
));
2748 if (policy
== WebKit::WebNavigationPolicyDownload
) {
2749 Send(new ViewHostMsg_DownloadUrl(routing_id_
, request
.url(), referrer
,
2752 OpenURL(frame
, request
.url(), referrer
, policy
);
2756 WebNavigationPolicy
RenderViewImpl::decidePolicyForNavigation(
2757 WebFrame
* frame
, const WebURLRequest
& request
, WebNavigationType type
,
2758 const WebNode
&, WebNavigationPolicy default_policy
, bool is_redirect
) {
2759 if (request
.url() != GURL(kSwappedOutURL
) &&
2760 GetContentClient()->renderer()->HandleNavigation(frame
, request
, type
,
2763 return WebKit::WebNavigationPolicyIgnore
;
2767 GURL(request
.httpHeaderField(WebString::fromUTF8("Referer"))),
2768 GetReferrerPolicyFromRequest(frame
, request
));
2770 if (is_swapped_out_
) {
2771 if (request
.url() != GURL(kSwappedOutURL
)) {
2772 // Targeted links may try to navigate a swapped out frame. Allow the
2773 // browser process to navigate the tab instead. Note that it is also
2774 // possible for non-targeted navigations (from this view) to arrive
2775 // here just after we are swapped out. It's ok to send them to the
2776 // browser, as long as they're for the top level frame.
2777 // TODO(creis): Ensure this supports targeted form submissions when
2778 // fixing http://crbug.com/101395.
2779 if (frame
->parent() == NULL
) {
2780 OpenURL(frame
, request
.url(), referrer
, default_policy
);
2781 return WebKit::WebNavigationPolicyIgnore
; // Suppress the load here.
2784 // We should otherwise ignore in-process iframe navigations, if they
2785 // arrive just after we are swapped out.
2786 return WebKit::WebNavigationPolicyIgnore
;
2789 // Allow kSwappedOutURL to complete.
2790 return default_policy
;
2793 // Webkit is asking whether to navigate to a new URL.
2794 // This is fine normally, except if we're showing UI from one security
2795 // context and they're trying to navigate to a different context.
2796 const GURL
& url
= request
.url();
2798 // A content initiated navigation may have originated from a link-click,
2799 // script, drag-n-drop operation, etc.
2800 bool is_content_initiated
=
2801 DocumentState::FromDataSource(frame
->provisionalDataSource())->
2802 navigation_state()->is_content_initiated();
2805 // If --enable-strict-site-isolation or --site-per-process is enabled, send
2806 // all top-level navigations to the browser to let it swap processes when
2807 // crossing site boundaries. This is currently expected to break some script
2808 // calls and navigations, such as form submissions.
2809 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
2810 bool force_swap_due_to_flag
=
2811 command_line
.HasSwitch(switches::kEnableStrictSiteIsolation
) ||
2812 command_line
.HasSwitch(switches::kSitePerProcess
);
2813 if (force_swap_due_to_flag
&&
2814 !frame
->parent() && (is_content_initiated
|| is_redirect
)) {
2815 WebString origin_str
= frame
->document().securityOrigin().toString();
2816 GURL
frame_url(origin_str
.utf8().data());
2817 // TODO(cevans): revisit whether this site check is still necessary once
2818 // crbug.com/101395 is fixed.
2819 if (!net::RegistryControlledDomainService::SameDomainOrHost(frame_url
,
2821 frame_url
.scheme() != url
.scheme()) {
2822 OpenURL(frame
, url
, referrer
, default_policy
);
2823 return WebKit::WebNavigationPolicyIgnore
;
2827 // If the browser is interested, then give it a chance to look at the request.
2828 if (is_content_initiated
) {
2829 bool browser_handles_request
=
2830 renderer_preferences_
.browser_handles_non_local_top_level_requests
&&
2831 IsNonLocalTopLevelNavigation(url
, frame
, type
);
2832 if (!browser_handles_request
) {
2833 browser_handles_request
=
2834 renderer_preferences_
.browser_handles_all_top_level_requests
&&
2835 IsTopLevelNavigation(frame
);
2838 if (browser_handles_request
) {
2839 // Reset these counters as the RenderView could be reused for the next
2842 last_page_id_sent_to_browser_
= -1;
2843 OpenURL(frame
, url
, referrer
, default_policy
);
2844 return WebKit::WebNavigationPolicyIgnore
; // Suppress the load here.
2848 // Use the frame's original request's URL rather than the document's URL for
2849 // subsequent checks. For a popup, the document's URL may become the opener
2850 // window's URL if the opener has called document.write().
2851 // See http://crbug.com/93517.
2852 GURL
old_url(frame
->dataSource()->request().url());
2854 // Detect when we're crossing a permission-based boundary (e.g. into or out of
2855 // an extension or app origin, leaving a WebUI page, etc). We only care about
2856 // top-level navigations (not iframes). But we sometimes navigate to
2857 // about:blank to clear a tab, and we want to still allow that.
2859 // Note: this is known to break POST submissions when crossing process
2860 // boundaries until http://crbug.com/101395 is fixed. This is better for
2861 // security than loading a WebUI, extension or app page in the wrong process.
2862 // POST requests don't work because this mechanism does not preserve form
2863 // POST data. We will need to send the request's httpBody data up to the
2864 // browser process, and issue a special POST navigation in WebKit (via
2865 // FrameLoader::loadFrameRequest). See ResourceDispatcher and WebURLLoaderImpl
2866 // for examples of how to send the httpBody data.
2867 if (!frame
->parent() && is_content_initiated
&&
2868 !url
.SchemeIs(chrome::kAboutScheme
)) {
2869 bool send_referrer
= false;
2871 // All navigations to WebUI URLs or within WebUI-enabled RenderProcesses
2872 // must be handled by the browser process so that the correct bindings and
2873 // data sources can be registered.
2874 // Similarly, navigations to view-source URLs or within ViewSource mode
2875 // must be handled by the browser process (except for reloads - those are
2876 // safe to leave within the renderer).
2877 // Lastly, access to file:// URLs from non-file:// URL pages must be
2878 // handled by the browser so that ordinary renderer processes don't get
2879 // blessed with file permissions.
2880 int cumulative_bindings
= RenderProcess::current()->GetEnabledBindings();
2881 bool is_initial_navigation
= page_id_
== -1;
2883 GetContentClient()->HasWebUIScheme(url
) ||
2884 (cumulative_bindings
& BINDINGS_POLICY_WEB_UI
) ||
2885 url
.SchemeIs(chrome::kViewSourceScheme
) ||
2886 (frame
->isViewSourceModeEnabled() &&
2887 type
!= WebKit::WebNavigationTypeReload
);
2889 if (!should_fork
&& url
.SchemeIs(chrome::kFileScheme
)) {
2890 // Fork non-file to file opens. Check the opener URL if this is the
2891 // initial navigation in a newly opened window.
2892 GURL
source_url(old_url
);
2893 if (is_initial_navigation
&& source_url
.is_empty() && frame
->opener())
2894 source_url
= frame
->opener()->top()->document().url();
2895 DCHECK(!source_url
.is_empty());
2896 should_fork
= !source_url
.SchemeIs(chrome::kFileScheme
);
2900 // Give the embedder a chance.
2901 // For now, we skip this for POST submissions. This is because
2902 // http://crbug.com/101395 is more likely to cause compatibility issues
2903 // with hosted apps and extensions than WebUI pages. We will remove this
2904 // check when cross-process POST submissions are supported.
2905 if (request
.httpMethod() == "GET") {
2906 should_fork
= GetContentClient()->renderer()->ShouldFork(
2907 frame
, url
, is_initial_navigation
, &send_referrer
);
2913 frame
, url
, send_referrer
? referrer
: Referrer(), default_policy
);
2914 return WebKit::WebNavigationPolicyIgnore
; // Suppress the load here.
2918 // Detect when a page is "forking" a new tab that can be safely rendered in
2919 // its own process. This is done by sites like Gmail that try to open links
2920 // in new windows without script connections back to the original page. We
2921 // treat such cases as browser navigations (in which we will create a new
2922 // renderer for a cross-site navigation), rather than WebKit navigations.
2924 // We use the following heuristic to decide whether to fork a new page in its
2926 // The parent page must open a new tab to about:blank, set the new tab's
2927 // window.opener to null, and then redirect the tab to a cross-site URL using
2930 // TODO(creis): Deprecate this logic once we can rely on rel=noreferrer
2933 // Must start from a tab showing about:blank, which is later redirected.
2934 old_url
== GURL(chrome::kAboutBlankURL
) &&
2935 // Must be the first real navigation of the tab.
2936 historyBackListCount() < 1 &&
2937 historyForwardListCount() < 1 &&
2938 // The parent page must have set the child's window.opener to null before
2939 // redirecting to the desired URL.
2940 frame
->opener() == NULL
&&
2941 // Must be a top-level frame.
2942 frame
->parent() == NULL
&&
2943 // Must not have issued the request from this page.
2944 is_content_initiated
&&
2945 // Must be targeted at the current tab.
2946 default_policy
== WebKit::WebNavigationPolicyCurrentTab
&&
2947 // Must be a JavaScript navigation, which appears as "other".
2948 type
== WebKit::WebNavigationTypeOther
;
2951 // Open the URL via the browser, not via WebKit.
2952 OpenURL(frame
, url
, Referrer(), default_policy
);
2953 return WebKit::WebNavigationPolicyIgnore
;
2956 return default_policy
;
2959 bool RenderViewImpl::canHandleRequest(
2960 WebFrame
* frame
, const WebURLRequest
& request
) {
2961 // We allow WebKit to think that everything can be handled even though
2962 // browser-side we limit what we load.
2966 WebURLError
RenderViewImpl::cannotHandleRequestError(
2967 WebFrame
* frame
, const WebURLRequest
& request
) {
2968 NOTREACHED(); // Since we said we can handle all requests.
2969 return WebURLError();
2972 WebURLError
RenderViewImpl::cancelledError(
2973 WebFrame
* frame
, const WebURLRequest
& request
) {
2975 error
.domain
= WebString::fromUTF8(net::kErrorDomain
);
2976 error
.reason
= net::ERR_ABORTED
;
2977 error
.unreachableURL
= request
.url();
2981 void RenderViewImpl::unableToImplementPolicyWithError(
2982 WebFrame
*, const WebURLError
&) {
2983 NOTREACHED(); // Since we said we can handle all requests.
2986 void RenderViewImpl::willSendSubmitEvent(WebKit::WebFrame
* frame
,
2987 const WebKit::WebFormElement
& form
) {
2988 // Some login forms have onSubmit handlers that put a hash of the password
2989 // into a hidden field and then clear the password. (Issue 28910.)
2990 // This method gets called before any of those handlers run, so save away
2991 // a copy of the password in case it gets lost.
2992 DocumentState
* document_state
=
2993 DocumentState::FromDataSource(frame
->dataSource());
2994 document_state
->set_password_form_data(CreatePasswordForm(form
));
2997 void RenderViewImpl::willSubmitForm(WebFrame
* frame
,
2998 const WebFormElement
& form
) {
2999 DocumentState
* document_state
=
3000 DocumentState::FromDataSource(frame
->provisionalDataSource());
3001 NavigationState
* navigation_state
= document_state
->navigation_state();
3003 if (navigation_state
->transition_type() == PAGE_TRANSITION_LINK
)
3004 navigation_state
->set_transition_type(PAGE_TRANSITION_FORM_SUBMIT
);
3006 // Save these to be processed when the ensuing navigation is committed.
3007 WebSearchableFormData
web_searchable_form_data(form
);
3008 document_state
->set_searchable_form_url(web_searchable_form_data
.url());
3009 document_state
->set_searchable_form_encoding(
3010 web_searchable_form_data
.encoding().utf8());
3011 scoped_ptr
<PasswordForm
> password_form_data
=
3012 CreatePasswordForm(form
);
3014 // In order to save the password that the user actually typed and not one
3015 // that may have gotten transformed by the site prior to submit, recover it
3016 // from the form contents already stored by |willSendSubmitEvent| into the
3017 // dataSource's NavigationState (as opposed to the provisionalDataSource's,
3018 // which is what we're storing into now.)
3019 if (password_form_data
.get()) {
3020 DocumentState
* old_document_state
=
3021 DocumentState::FromDataSource(frame
->dataSource());
3022 if (old_document_state
) {
3023 PasswordForm
* old_form_data
= old_document_state
->password_form_data();
3024 if (old_form_data
&& old_form_data
->action
== password_form_data
->action
)
3025 password_form_data
->password_value
= old_form_data
->password_value
;
3029 document_state
->set_password_form_data(password_form_data
.Pass());
3032 RenderViewObserver
, observers_
, WillSubmitForm(frame
, form
));
3035 void RenderViewImpl::willPerformClientRedirect(
3036 WebFrame
* frame
, const WebURL
& from
, const WebURL
& to
, double interval
,
3038 // Replace any occurrences of swappedout:// with about:blank.
3039 const WebURL
& blank_url
= GURL(chrome::kAboutBlankURL
);
3042 RenderViewObserver
, observers_
,
3043 WillPerformClientRedirect(frame
,
3044 from
== GURL(kSwappedOutURL
) ? blank_url
: from
,
3045 to
, interval
, fire_time
));
3048 void RenderViewImpl::didCancelClientRedirect(WebFrame
* frame
) {
3050 RenderViewObserver
, observers_
, DidCancelClientRedirect(frame
));
3053 void RenderViewImpl::didCompleteClientRedirect(
3054 WebFrame
* frame
, const WebURL
& from
) {
3055 // Replace any occurrences of swappedout:// with about:blank.
3056 const WebURL
& blank_url
= GURL(chrome::kAboutBlankURL
);
3057 if (!frame
->parent()) {
3058 WebDataSource
* ds
= frame
->provisionalDataSource();
3059 // If there's no provisional data source, it's a reference fragment
3061 completed_client_redirect_src_
= Referrer(
3062 from
== GURL(kSwappedOutURL
) ? blank_url
: from
,
3063 ds
? GetReferrerPolicyFromRequest(frame
, ds
->request()) :
3064 frame
->document().referrerPolicy());
3067 RenderViewObserver
, observers_
, DidCompleteClientRedirect(
3068 frame
, from
== GURL(kSwappedOutURL
) ? blank_url
: from
));
3071 void RenderViewImpl::didCreateDataSource(WebFrame
* frame
, WebDataSource
* ds
) {
3072 bool content_initiated
= !pending_navigation_params_
.get();
3074 DocumentState
* document_state
= DocumentState::FromDataSource(ds
);
3075 if (!document_state
) {
3076 document_state
= new DocumentState
;
3077 ds
->setExtraData(document_state
);
3078 if (!content_initiated
)
3079 PopulateDocumentStateFromPending(document_state
);
3082 // Carry over the user agent override flag, if it exists.
3083 if (content_initiated
&& webview() && webview()->mainFrame() &&
3084 webview()->mainFrame()->dataSource()) {
3085 DocumentState
* old_document_state
=
3086 DocumentState::FromDataSource(webview()->mainFrame()->dataSource());
3087 if (old_document_state
) {
3088 document_state
->set_is_overriding_user_agent(
3089 old_document_state
->is_overriding_user_agent());
3093 // The rest of RenderView assumes that a WebDataSource will always have a
3094 // non-null NavigationState.
3095 if (content_initiated
) {
3096 document_state
->set_navigation_state(
3097 NavigationState::CreateContentInitiated());
3099 document_state
->set_navigation_state(CreateNavigationStateFromPending());
3100 pending_navigation_params_
.reset();
3103 // DocumentState::referred_by_prefetcher_ is true if we are
3104 // navigating from a page that used prefetching using a link on that
3105 // page. We are early enough in the request process here that we
3106 // can still see the DocumentState of the previous page and set
3107 // this value appropriately.
3108 // TODO(gavinp): catch the important case of navigation in a new
3109 // renderer process.
3111 if (WebFrame
* old_frame
= webview()->mainFrame()) {
3112 const WebURLRequest
& original_request
= ds
->originalRequest();
3113 const GURL
referrer(
3114 original_request
.httpHeaderField(WebString::fromUTF8("Referer")));
3115 if (!referrer
.is_empty() &&
3116 DocumentState::FromDataSource(
3117 old_frame
->dataSource())->was_prefetcher()) {
3118 for (; old_frame
; old_frame
= old_frame
->traverseNext(false)) {
3119 WebDataSource
* old_frame_ds
= old_frame
->dataSource();
3120 if (old_frame_ds
&& referrer
== GURL(old_frame_ds
->request().url())) {
3121 document_state
->set_was_referred_by_prefetcher(true);
3129 if (content_initiated
) {
3130 const WebURLRequest
& request
= ds
->request();
3131 switch (request
.cachePolicy()) {
3132 case WebURLRequest::UseProtocolCachePolicy
: // normal load.
3133 document_state
->set_load_type(DocumentState::LINK_LOAD_NORMAL
);
3135 case WebURLRequest::ReloadIgnoringCacheData
: // reload.
3136 document_state
->set_load_type(DocumentState::LINK_LOAD_RELOAD
);
3138 case WebURLRequest::ReturnCacheDataElseLoad
: // allow stale data.
3139 document_state
->set_load_type(
3140 DocumentState::LINK_LOAD_CACHE_STALE_OK
);
3142 case WebURLRequest::ReturnCacheDataDontLoad
: // Don't re-post.
3143 document_state
->set_load_type(DocumentState::LINK_LOAD_CACHE_ONLY
);
3149 RenderViewObserver
, observers_
, DidCreateDataSource(frame
, ds
));
3152 void RenderViewImpl::PopulateDocumentStateFromPending(
3153 DocumentState
* document_state
) {
3154 const ViewMsg_Navigate_Params
& params
= *pending_navigation_params_
.get();
3155 document_state
->set_request_time(params
.request_time
);
3157 if (!params
.url
.SchemeIs(chrome::kJavaScriptScheme
) &&
3158 params
.navigation_type
== ViewMsg_Navigate_Type::RESTORE
) {
3159 // We're doing a load of a page that was restored from the last session. By
3160 // default this prefers the cache over loading (LOAD_PREFERRING_CACHE) which
3161 // can result in stale data for pages that are set to expire. We explicitly
3162 // override that by setting the policy here so that as necessary we load
3163 // from the network.
3164 document_state
->set_cache_policy_override(
3165 WebURLRequest::UseProtocolCachePolicy
);
3168 if (IsReload(params
))
3169 document_state
->set_load_type(DocumentState::RELOAD
);
3170 else if (!params
.state
.empty())
3171 document_state
->set_load_type(DocumentState::HISTORY_LOAD
);
3173 document_state
->set_load_type(DocumentState::NORMAL_LOAD
);
3175 document_state
->set_referrer_policy(params
.referrer
.policy
);
3176 document_state
->set_is_overriding_user_agent(params
.is_overriding_user_agent
);
3177 document_state
->set_must_reset_scroll_and_scale_state(
3178 params
.navigation_type
==
3179 ViewMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL
);
3180 document_state
->set_can_load_local_resources(params
.can_load_local_resources
);
3183 NavigationState
* RenderViewImpl::CreateNavigationStateFromPending() {
3184 const ViewMsg_Navigate_Params
& params
= *pending_navigation_params_
.get();
3185 NavigationState
* navigation_state
= NULL
;
3187 // A navigation resulting from loading a javascript URL should not be treated
3188 // as a browser initiated event. Instead, we want it to look as if the page
3189 // initiated any load resulting from JS execution.
3190 if (!params
.url
.SchemeIs(chrome::kJavaScriptScheme
)) {
3191 navigation_state
= NavigationState::CreateBrowserInitiated(
3193 params
.pending_history_list_offset
,
3195 navigation_state
->set_transferred_request_child_id(
3196 params
.transferred_request_child_id
);
3197 navigation_state
->set_transferred_request_request_id(
3198 params
.transferred_request_request_id
);
3199 navigation_state
->set_allow_download(params
.allow_download
);
3201 navigation_state
= NavigationState::CreateContentInitiated();
3203 return navigation_state
;
3206 void RenderViewImpl::ProcessViewLayoutFlags(const CommandLine
& command_line
) {
3207 bool enable_viewport
=
3208 command_line
.HasSwitch(switches::kEnableViewport
);
3209 bool enable_fixed_layout
=
3210 command_line
.HasSwitch(switches::kEnableFixedLayout
);
3212 webview()->enableFixedLayoutMode(enable_fixed_layout
|| enable_viewport
);
3213 webview()->settings()->setFixedElementsLayoutRelativeToFrame(true);
3215 if (enable_viewport
) {
3216 webview()->settings()->setViewportEnabled(true);
3217 } else if (enable_fixed_layout
) {
3219 command_line
.GetSwitchValueASCII(switches::kEnableFixedLayout
);
3220 std::vector
<std::string
> tokens
;
3221 base::SplitString(str
, ',', &tokens
);
3222 if (tokens
.size() == 2) {
3224 if (base::StringToInt(tokens
[0], &width
) &&
3225 base::StringToInt(tokens
[1], &height
))
3226 webview()->setFixedLayoutSize(WebSize(width
, height
));
3230 ProcessAcceleratedPinchZoomFlags(command_line
);
3233 void RenderViewImpl::ProcessAcceleratedPinchZoomFlags(
3234 const CommandLine
& command_line
) {
3235 if (!webview()->isAcceleratedCompositingActive())
3238 bool enable_viewport
= command_line
.HasSwitch(switches::kEnableViewport
);
3239 bool enable_pinch
= command_line
.HasSwitch(switches::kEnablePinch
);
3241 if (enable_viewport
)
3245 webview()->setPageScaleFactorLimits(1, 4);
3247 webview()->setPageScaleFactorLimits(1, 1);
3250 void RenderViewImpl::didStartProvisionalLoad(WebFrame
* frame
) {
3251 WebDataSource
* ds
= frame
->provisionalDataSource();
3252 DocumentState
* document_state
= DocumentState::FromDataSource(ds
);
3254 // We should only navigate to swappedout:// when is_swapped_out_ is true.
3255 CHECK((ds
->request().url() != GURL(kSwappedOutURL
)) ||
3256 is_swapped_out_
) << "Heard swappedout:// when not swapped out.";
3258 // Update the request time if WebKit has better knowledge of it.
3259 if (document_state
->request_time().is_null()) {
3260 double event_time
= ds
->triggeringEventTime();
3261 if (event_time
!= 0.0)
3262 document_state
->set_request_time(Time::FromDoubleT(event_time
));
3265 // Start time is only set after request time.
3266 document_state
->set_start_load_time(Time::Now());
3268 bool is_top_most
= !frame
->parent();
3270 navigation_gesture_
= frame
->isProcessingUserGesture() ?
3271 NavigationGestureUser
: NavigationGestureAuto
;
3273 // Make sure redirect tracking state is clear for the new load.
3274 completed_client_redirect_src_
= Referrer();
3275 } else if (frame
->parent()->isLoading()) {
3276 // Take note of AUTO_SUBFRAME loads here, so that we can know how to
3277 // load an error page. See didFailProvisionalLoad.
3278 document_state
->navigation_state()->set_transition_type(
3279 PAGE_TRANSITION_AUTO_SUBFRAME
);
3283 RenderViewObserver
, observers_
, DidStartProvisionalLoad(frame
));
3285 Send(new ViewHostMsg_DidStartProvisionalLoadForFrame(
3286 routing_id_
, frame
->identifier(),
3287 frame
->parent() ? frame
->parent()->identifier() : -1,
3288 is_top_most
, ds
->request().url()));
3291 void RenderViewImpl::didReceiveServerRedirectForProvisionalLoad(
3293 if (frame
->parent())
3295 // Received a redirect on the main frame.
3296 WebDataSource
* data_source
= frame
->provisionalDataSource();
3298 // Should only be invoked when we have a data source.
3302 std::vector
<GURL
> redirects
;
3303 GetRedirectChain(data_source
, &redirects
);
3304 if (redirects
.size() >= 2) {
3305 Send(new ViewHostMsg_DidRedirectProvisionalLoad(routing_id_
, page_id_
,
3306 redirects
[redirects
.size() - 2], redirects
.back()));
3310 void RenderViewImpl::didFailProvisionalLoad(WebFrame
* frame
,
3311 const WebURLError
& error
) {
3312 // Notify the browser that we failed a provisional load with an error.
3314 // Note: It is important this notification occur before DidStopLoading so the
3315 // SSL manager can react to the provisional load failure before being
3316 // notified the load stopped.
3318 WebDataSource
* ds
= frame
->provisionalDataSource();
3321 const WebURLRequest
& failed_request
= ds
->request();
3324 RenderViewObserver
, observers_
, DidFailProvisionalLoad(frame
, error
));
3326 bool show_repost_interstitial
=
3327 (error
.reason
== net::ERR_CACHE_MISS
&&
3328 EqualsASCII(failed_request
.httpMethod(), "POST"));
3330 ViewHostMsg_DidFailProvisionalLoadWithError_Params params
;
3331 params
.frame_id
= frame
->identifier();
3332 params
.is_main_frame
= !frame
->parent();
3333 params
.error_code
= error
.reason
;
3334 GetContentClient()->renderer()->GetNavigationErrorStrings(
3338 ¶ms
.error_description
);
3339 params
.url
= error
.unreachableURL
;
3340 params
.showing_repost_interstitial
= show_repost_interstitial
;
3341 Send(new ViewHostMsg_DidFailProvisionalLoadWithError(
3342 routing_id_
, params
));
3344 // Don't display an error page if this is simply a cancelled load. Aside
3345 // from being dumb, WebCore doesn't expect it and it will cause a crash.
3346 if (error
.reason
== net::ERR_ABORTED
)
3349 // Make sure we never show errors in view source mode.
3350 frame
->enableViewSourceMode(false);
3352 DocumentState
* document_state
= DocumentState::FromDataSource(ds
);
3353 NavigationState
* navigation_state
= document_state
->navigation_state();
3355 // If this is a failed back/forward/reload navigation, then we need to do a
3356 // 'replace' load. This is necessary to avoid messing up session history.
3357 // Otherwise, we do a normal load, which simulates a 'go' navigation as far
3358 // as session history is concerned.
3360 // AUTO_SUBFRAME loads should always be treated as loads that do not advance
3364 navigation_state
->pending_page_id() != -1 ||
3365 navigation_state
->transition_type() ==
3366 PAGE_TRANSITION_AUTO_SUBFRAME
;
3368 // If we failed on a browser initiated request, then make sure that our error
3369 // page load is regarded as the same browser initiated request.
3370 if (!navigation_state
->is_content_initiated()) {
3371 pending_navigation_params_
.reset(new ViewMsg_Navigate_Params
);
3372 pending_navigation_params_
->page_id
=
3373 navigation_state
->pending_page_id();
3374 pending_navigation_params_
->pending_history_list_offset
=
3375 navigation_state
->pending_history_list_offset();
3376 pending_navigation_params_
->transition
=
3377 navigation_state
->transition_type();
3378 pending_navigation_params_
->request_time
=
3379 document_state
->request_time();
3382 // Provide the user with a more helpful error page?
3383 if (MaybeLoadAlternateErrorPage(frame
, error
, replace
))
3386 // Fallback to a local error page.
3387 LoadNavigationErrorPage(frame
, failed_request
, error
, std::string(), replace
);
3390 void RenderViewImpl::didReceiveDocumentData(
3391 WebFrame
* frame
, const char* data
, size_t data_len
,
3392 bool& prevent_default
) {
3393 DocumentState
* document_state
=
3394 DocumentState::FromDataSource(frame
->dataSource());
3395 document_state
->set_use_error_page(false);
3398 void RenderViewImpl::didCommitProvisionalLoad(WebFrame
* frame
,
3399 bool is_new_navigation
) {
3400 DocumentState
* document_state
=
3401 DocumentState::FromDataSource(frame
->dataSource());
3402 NavigationState
* navigation_state
= document_state
->navigation_state();
3404 if (document_state
->commit_load_time().is_null())
3405 document_state
->set_commit_load_time(Time::Now());
3407 if (document_state
->must_reset_scroll_and_scale_state()) {
3408 #if defined(OS_ANDROID) // crbug.com/153907
3409 webview()->resetScrollAndScaleState();
3411 document_state
->set_must_reset_scroll_and_scale_state(false);
3414 if (is_new_navigation
) {
3415 // When we perform a new navigation, we need to update the last committed
3416 // session history entry with state for the page we are leaving.
3417 UpdateSessionHistory(frame
);
3419 // We bump our Page ID to correspond with the new session history entry.
3420 page_id_
= next_page_id_
++;
3422 // Don't update history_page_ids_ (etc) for kSwappedOutURL, since
3423 // we don't want to forget the entry that was there, and since we will
3424 // never come back to kSwappedOutURL. Note that we have to call
3425 // UpdateSessionHistory and update page_id_ even in this case, so that
3426 // the current entry gets a state update and so that we don't send a
3427 // state update to the wrong entry when we swap back in.
3428 if (GetLoadingUrl(frame
) != GURL(kSwappedOutURL
)) {
3429 // Advance our offset in session history, applying the length limit.
3430 // There is now no forward history.
3431 history_list_offset_
++;
3432 if (history_list_offset_
>= kMaxSessionHistoryEntries
)
3433 history_list_offset_
= kMaxSessionHistoryEntries
- 1;
3434 history_list_length_
= history_list_offset_
+ 1;
3435 history_page_ids_
.resize(history_list_length_
, -1);
3436 history_page_ids_
[history_list_offset_
] = page_id_
;
3439 // Inspect the navigation_state on this frame to see if the navigation
3440 // corresponds to a session history navigation... Note: |frame| may or
3441 // may not be the toplevel frame, but for the case of capturing session
3442 // history, the first committed frame suffices. We keep track of whether
3443 // we've seen this commit before so that only capture session history once
3446 // Note that we need to check if the page ID changed. In the case of a
3447 // reload, the page ID doesn't change, and UpdateSessionHistory gets the
3448 // previous URL and the current page ID, which would be wrong.
3449 if (navigation_state
->pending_page_id() != -1 &&
3450 navigation_state
->pending_page_id() != page_id_
&&
3451 !navigation_state
->request_committed()) {
3452 // This is a successful session history navigation!
3453 UpdateSessionHistory(frame
);
3454 page_id_
= navigation_state
->pending_page_id();
3456 history_list_offset_
= navigation_state
->pending_history_list_offset();
3458 // If the history list is valid, our list of page IDs should be correct.
3459 DCHECK(history_list_length_
<= 0 ||
3460 history_list_offset_
< 0 ||
3461 history_list_offset_
>= history_list_length_
||
3462 history_page_ids_
[history_list_offset_
] == page_id_
);
3466 FOR_EACH_OBSERVER(RenderViewObserver
, observers_
,
3467 DidCommitProvisionalLoad(frame
, is_new_navigation
));
3469 // Remember that we've already processed this request, so we don't update
3470 // the session history again. We do this regardless of whether this is
3471 // a session history navigation, because if we attempted a session history
3472 // navigation without valid HistoryItem state, WebCore will think it is a
3474 navigation_state
->set_request_committed(true);
3478 // If this committed load was initiated by a client redirect, we're
3479 // at the last stop now, so clear it.
3480 completed_client_redirect_src_
= Referrer();
3482 // Check whether we have new encoding name.
3483 UpdateEncoding(frame
, frame
->view()->pageEncoding().utf8());
3485 if (!frame
->parent()) { // Only for top frames.
3486 RenderThreadImpl
* render_thread_impl
= RenderThreadImpl::current();
3487 if (render_thread_impl
) { // Can be NULL in tests.
3488 render_thread_impl
->histogram_customizer()->
3489 RenderViewNavigatedToHost(GURL(GetLoadingUrl(frame
)).host(),
3490 g_view_map
.Get().size());
3495 void RenderViewImpl::didClearWindowObject(WebFrame
* frame
) {
3496 FOR_EACH_OBSERVER(RenderViewObserver
, observers_
,
3497 DidClearWindowObject(frame
));
3499 if (enabled_bindings_
& BINDINGS_POLICY_DOM_AUTOMATION
) {
3500 if (!dom_automation_controller_
.get())
3501 dom_automation_controller_
.reset(new DomAutomationController());
3502 dom_automation_controller_
->set_message_sender(
3503 static_cast<RenderView
*>(this));
3504 dom_automation_controller_
->set_routing_id(routing_id());
3505 dom_automation_controller_
->BindToJavascript(frame
,
3506 "domAutomationController");
3509 InjectDoNotTrackBindings(frame
);
3512 void RenderViewImpl::didCreateDocumentElement(WebFrame
* frame
) {
3513 // Notify the browser about non-blank documents loading in the top frame.
3514 GURL url
= frame
->document().url();
3515 if (url
.is_valid() && url
.spec() != chrome::kAboutBlankURL
) {
3516 if (frame
== webview()->mainFrame())
3517 Send(new ViewHostMsg_DocumentAvailableInMainFrame(routing_id_
));
3520 FOR_EACH_OBSERVER(RenderViewObserver
, observers_
,
3521 DidCreateDocumentElement(frame
));
3524 void RenderViewImpl::didReceiveTitle(WebFrame
* frame
, const WebString
& title
,
3525 WebTextDirection direction
) {
3526 UpdateTitle(frame
, title
, direction
);
3528 // Also check whether we have new encoding name.
3529 UpdateEncoding(frame
, frame
->view()->pageEncoding().utf8());
3532 void RenderViewImpl::didChangeIcon(WebFrame
* frame
, WebIconURL::Type type
) {
3533 favicon_helper_
->DidChangeIcon(frame
, type
);
3536 void RenderViewImpl::didFinishDocumentLoad(WebFrame
* frame
) {
3537 WebDataSource
* ds
= frame
->dataSource();
3538 DocumentState
* document_state
= DocumentState::FromDataSource(ds
);
3539 document_state
->set_finish_document_load_time(Time::Now());
3541 Send(new ViewHostMsg_DocumentLoadedInFrame(routing_id_
, frame
->identifier()));
3543 FOR_EACH_OBSERVER(RenderViewObserver
, observers_
,
3544 DidFinishDocumentLoad(frame
));
3546 // Check whether we have new encoding name.
3547 UpdateEncoding(frame
, frame
->view()->pageEncoding().utf8());
3550 void RenderViewImpl::didHandleOnloadEvents(WebFrame
* frame
) {
3551 if (webview()->mainFrame() == frame
) {
3552 Send(new ViewHostMsg_DocumentOnLoadCompletedInMainFrame(routing_id_
,
3557 void RenderViewImpl::didFailLoad(WebFrame
* frame
, const WebURLError
& error
) {
3558 WebDataSource
* ds
= frame
->dataSource();
3562 FOR_EACH_OBSERVER(RenderViewObserver
, observers_
, DidFailLoad(frame
, error
));
3564 const WebURLRequest
& failed_request
= ds
->request();
3565 string16 error_description
;
3566 GetContentClient()->renderer()->GetNavigationErrorStrings(
3570 &error_description
);
3571 Send(new ViewHostMsg_DidFailLoadWithError(routing_id_
,
3572 frame
->identifier(),
3573 failed_request
.url(),
3576 error_description
));
3579 void RenderViewImpl::didFinishLoad(WebFrame
* frame
) {
3580 WebDataSource
* ds
= frame
->dataSource();
3581 DocumentState
* document_state
= DocumentState::FromDataSource(ds
);
3582 if (document_state
->finish_load_time().is_null())
3583 document_state
->set_finish_load_time(Time::Now());
3585 FOR_EACH_OBSERVER(RenderViewObserver
, observers_
, DidFinishLoad(frame
));
3587 Send(new ViewHostMsg_DidFinishLoad(routing_id_
,
3588 frame
->identifier(),
3589 ds
->request().url(),
3593 void RenderViewImpl::didNavigateWithinPage(
3594 WebFrame
* frame
, bool is_new_navigation
) {
3595 // If this was a reference fragment navigation that we initiated, then we
3596 // could end up having a non-null pending navigation params. We just need to
3597 // update the ExtraData on the datasource so that others who read the
3598 // ExtraData will get the new NavigationState. Similarly, if we did not
3599 // initiate this navigation, then we need to take care to reset any pre-
3600 // existing navigation state to a content-initiated navigation state.
3601 // DidCreateDataSource conveniently takes care of this for us.
3602 didCreateDataSource(frame
, frame
->dataSource());
3604 DocumentState
* document_state
=
3605 DocumentState::FromDataSource(frame
->dataSource());
3606 NavigationState
* new_state
= document_state
->navigation_state();
3607 new_state
->set_was_within_same_page(true);
3609 didCommitProvisionalLoad(frame
, is_new_navigation
);
3611 WebDataSource
* datasource
= frame
->view()->mainFrame()->dataSource();
3612 UpdateTitle(frame
, datasource
->pageTitle(), datasource
->pageTitleDirection());
3615 void RenderViewImpl::didUpdateCurrentHistoryItem(WebFrame
* frame
) {
3616 StartNavStateSyncTimerIfNecessary();
3619 void RenderViewImpl::assignIdentifierToRequest(
3620 WebFrame
* frame
, unsigned identifier
, const WebURLRequest
& request
) {
3624 void RenderViewImpl::willSendRequest(WebFrame
* frame
,
3625 unsigned identifier
,
3626 WebURLRequest
& request
,
3627 const WebURLResponse
& redirect_response
) {
3628 WebFrame
* top_frame
= frame
->top();
3631 WebDataSource
* provisional_data_source
= top_frame
->provisionalDataSource();
3632 WebDataSource
* top_data_source
= top_frame
->dataSource();
3633 WebDataSource
* data_source
=
3634 provisional_data_source
? provisional_data_source
: top_data_source
;
3636 PageTransition transition_type
= PAGE_TRANSITION_LINK
;
3637 DocumentState
* document_state
= DocumentState::FromDataSource(data_source
);
3638 DCHECK(document_state
);
3639 NavigationState
* navigation_state
= document_state
->navigation_state();
3640 transition_type
= navigation_state
->transition_type();
3642 GURL
request_url(request
.url());
3644 if (GetContentClient()->renderer()->WillSendRequest(
3648 request
.firstPartyForCookies(),
3650 request
.setURL(WebURL(new_url
));
3653 if (document_state
->is_cache_policy_override_set())
3654 request
.setCachePolicy(document_state
->cache_policy_override());
3656 WebKit::WebReferrerPolicy referrer_policy
;
3657 if (document_state
&& document_state
->is_referrer_policy_set()) {
3658 referrer_policy
= document_state
->referrer_policy();
3659 document_state
->clear_referrer_policy();
3661 referrer_policy
= frame
->document().referrerPolicy();
3664 // The request's extra data may indicate that we should set a custom user
3665 // agent. This needs to be done here, after WebKit is through with setting the
3666 // user agent on its own.
3667 WebString custom_user_agent
;
3668 if (request
.extraData()) {
3669 webkit_glue::WebURLRequestExtraDataImpl
* old_extra_data
=
3670 static_cast<webkit_glue::WebURLRequestExtraDataImpl
*>(
3671 request
.extraData());
3672 custom_user_agent
= old_extra_data
->custom_user_agent();
3674 if (!custom_user_agent
.isNull()) {
3675 if (custom_user_agent
.isEmpty())
3676 request
.clearHTTPHeaderField("User-Agent");
3678 request
.setHTTPHeaderField("User-Agent", custom_user_agent
);
3682 request
.setExtraData(
3683 new RequestExtraData(referrer_policy
,
3685 (frame
== top_frame
),
3686 frame
->identifier(),
3687 frame
->parent() == top_frame
,
3688 frame
->parent() ? frame
->parent()->identifier() : -1,
3689 navigation_state
->allow_download(),
3691 navigation_state
->transferred_request_child_id(),
3692 navigation_state
->transferred_request_request_id()));
3694 DocumentState
* top_document_state
=
3695 DocumentState::FromDataSource(top_data_source
);
3696 // TODO(gavinp): separate out prefetching and prerender field trials
3697 // if the rel=prerender rel type is sticking around.
3698 if (top_document_state
&&
3699 request
.targetType() == WebURLRequest::TargetIsPrefetch
)
3700 top_document_state
->set_was_prefetcher(true);
3702 request
.setRequestorID(routing_id_
);
3703 request
.setHasUserGesture(frame
->isProcessingUserGesture());
3705 if (!renderer_preferences_
.enable_referrers
)
3706 request
.clearHTTPHeaderField("Referer");
3709 void RenderViewImpl::didReceiveResponse(
3710 WebFrame
* frame
, unsigned identifier
, const WebURLResponse
& response
) {
3712 // Only do this for responses that correspond to a provisional data source
3713 // of the top-most frame. If we have a provisional data source, then we
3714 // can't have any sub-resources yet, so we know that this response must
3715 // correspond to a frame load.
3716 if (!frame
->provisionalDataSource() || frame
->parent())
3719 // If we are in view source mode, then just let the user see the source of
3720 // the server's error page.
3721 if (frame
->isViewSourceModeEnabled())
3724 DocumentState
* document_state
=
3725 DocumentState::FromDataSource(frame
->provisionalDataSource());
3726 int http_status_code
= response
.httpStatusCode();
3728 // Record page load flags.
3729 document_state
->set_was_fetched_via_spdy(response
.wasFetchedViaSPDY());
3730 document_state
->set_was_npn_negotiated(response
.wasNpnNegotiated());
3731 WebURLResponseExtraDataImpl
* extra_data
= GetExtraDataFromResponse(response
);
3733 document_state
->set_npn_negotiated_protocol(
3734 extra_data
->npn_negotiated_protocol());
3736 document_state
->set_was_alternate_protocol_available(
3737 response
.wasAlternateProtocolAvailable());
3738 document_state
->set_was_fetched_via_proxy(response
.wasFetchedViaProxy());
3739 document_state
->set_http_status_code(http_status_code
);
3740 // Whether or not the http status code actually corresponds to an error is
3741 // only checked when the page is done loading, if |use_error_page| is
3743 document_state
->set_use_error_page(true);
3746 void RenderViewImpl::didFinishResourceLoad(
3747 WebFrame
* frame
, unsigned identifier
) {
3748 DocumentState
* document_state
=
3749 DocumentState::FromDataSource(frame
->dataSource());
3750 if (!document_state
->use_error_page())
3753 // Do not show error page when DevTools is attached.
3754 if (devtools_agent_
->IsAttached())
3757 // Display error page, if appropriate.
3758 int http_status_code
= document_state
->http_status_code();
3759 if (http_status_code
== 404) {
3760 // On 404s, try a remote search page as a fallback.
3761 const GURL
& document_url
= frame
->document().url();
3763 const GURL
& error_page_url
=
3764 GetAlternateErrorPageURL(document_url
, HTTP_404
);
3765 if (error_page_url
.is_valid()) {
3766 WebURLError original_error
;
3767 original_error
.domain
= "http";
3768 original_error
.reason
= 404;
3769 original_error
.unreachableURL
= document_url
;
3771 document_state
->set_alt_error_page_fetcher(
3772 new AltErrorPageResourceFetcher(
3773 error_page_url
, frame
, original_error
,
3774 base::Bind(&RenderViewImpl::AltErrorPageFinished
,
3775 base::Unretained(this))));
3780 std::string error_domain
;
3781 if (GetContentClient()->renderer()->HasErrorPage(
3782 http_status_code
, &error_domain
)) {
3784 error
.unreachableURL
= frame
->document().url();
3785 error
.domain
= WebString::fromUTF8(error_domain
);
3786 error
.reason
= http_status_code
;
3788 LoadNavigationErrorPage(
3789 frame
, frame
->dataSource()->request(), error
, std::string(), true);
3793 void RenderViewImpl::didFailResourceLoad(
3794 WebFrame
* frame
, unsigned identifier
, const WebURLError
& error
) {
3798 void RenderViewImpl::didLoadResourceFromMemoryCache(
3799 WebFrame
* frame
, const WebURLRequest
& request
,
3800 const WebURLResponse
& response
) {
3801 // The recipients of this message have no use for data: URLs: they don't
3802 // affect the page's insecure content list and are not in the disk cache. To
3803 // prevent large (1M+) data: URLs from crashing in the IPC system, we simply
3804 // filter them out here.
3805 GURL
url(request
.url());
3806 if (url
.SchemeIs("data"))
3809 // Let the browser know we loaded a resource from the memory cache. This
3810 // message is needed to display the correct SSL indicators.
3811 Send(new ViewHostMsg_DidLoadResourceFromMemoryCache(
3814 response
.securityInfo(),
3815 request
.httpMethod().utf8(),
3816 response
.mimeType().utf8(),
3817 ResourceType::FromTargetType(request
.targetType())));
3820 void RenderViewImpl::didDisplayInsecureContent(WebFrame
* frame
) {
3821 Send(new ViewHostMsg_DidDisplayInsecureContent(routing_id_
));
3824 void RenderViewImpl::didRunInsecureContent(
3825 WebFrame
* frame
, const WebSecurityOrigin
& origin
, const WebURL
& target
) {
3826 Send(new ViewHostMsg_DidRunInsecureContent(
3828 origin
.toString().utf8(),
3832 void RenderViewImpl::didExhaustMemoryAvailableForScript(WebFrame
* frame
) {
3833 Send(new ViewHostMsg_JSOutOfMemory(routing_id_
));
3836 void RenderViewImpl::didCreateScriptContext(WebFrame
* frame
,
3837 v8::Handle
<v8::Context
> context
,
3838 int extension_group
,
3840 GetContentClient()->renderer()->DidCreateScriptContext(
3841 frame
, context
, extension_group
, world_id
);
3843 intents_host_
->DidCreateScriptContext(
3844 frame
, context
, extension_group
, world_id
);
3847 void RenderViewImpl::willReleaseScriptContext(WebFrame
* frame
,
3848 v8::Handle
<v8::Context
> context
,
3850 GetContentClient()->renderer()->WillReleaseScriptContext(
3851 frame
, context
, world_id
);
3854 void RenderViewImpl::CheckPreferredSize() {
3855 // We don't always want to send the change messages over IPC, only if we've
3856 // been put in that mode by getting a |ViewMsg_EnablePreferredSizeChangedMode|
3858 if (!send_preferred_size_changes_
|| !webview())
3861 gfx::Size
size(webview()->mainFrame()->contentsPreferredWidth(),
3862 webview()->mainFrame()->documentElementScrollHeight());
3864 // In the presence of zoom, these sizes are still reported as if unzoomed,
3865 // so we need to adjust.
3866 double zoom_factor
= WebView::zoomLevelToZoomFactor(webview()->zoomLevel());
3867 size
.set_width(static_cast<int>(size
.width() * zoom_factor
));
3868 size
.set_height(static_cast<int>(size
.height() * zoom_factor
));
3870 if (size
== preferred_size_
)
3873 preferred_size_
= size
;
3874 Send(new ViewHostMsg_DidContentsPreferredSizeChange(routing_id_
,
3878 WebGraphicsContext3D
* RenderViewImpl::CreateGraphicsContext3D(
3879 const WebGraphicsContext3D::Attributes
& attributes
) {
3883 // The WebGraphicsContext3DInProcessImpl code path is used for
3884 // layout tests (though not through this code) as well as for
3885 // debugging and bringing up new ports.
3886 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessWebGL
)) {
3887 return webkit::gpu::WebGraphicsContext3DInProcessImpl::CreateForWebView(
3891 if (webview()->mainFrame())
3892 url
= GURL(webview()->mainFrame()->document().url());
3894 url
= GURL("chrome://gpu/RenderViewImpl::CreateGraphicsContext3D");
3896 scoped_ptr
<WebGraphicsContext3DCommandBufferImpl
> context(
3897 new WebGraphicsContext3DCommandBufferImpl(
3900 RenderThreadImpl::current(),
3903 if (!context
->Initialize(
3905 false /* bind generates resources */,
3906 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE
))
3908 return context
.release();
3912 // The browser process needs to know the shape of the tree, as well as the names
3913 // and ids of all frames. This allows it to properly route JavaScript messages
3914 // across processes and frames. The serialization format is described in the
3915 // comments of the ViewMsg_FrameTreeUpdated message.
3916 // This function sends those updates to the browser and updates the RVH
3917 // corresponding to this object. It must be called on any events that modify
3918 // the tree structure or the names of any frames.
3919 void RenderViewImpl::SendUpdatedFrameTree(
3920 WebKit::WebFrame
* exclude_frame_subtree
) {
3921 // TODO(nasko): Frame tree updates are causing issues with postMessage, as
3922 // described in http://crbug.com/153701. Disable them until a proper fix is
3926 BrowserPluginManager
* RenderViewImpl::browser_plugin_manager() {
3927 if (!browser_plugin_manager_
)
3928 browser_plugin_manager_
= BrowserPluginManager::Create(this);
3929 return browser_plugin_manager_
;
3932 void RenderViewImpl::CreateFrameTree(WebKit::WebFrame
* frame
,
3933 DictionaryValue
* frame_tree
) {
3934 // TODO(nasko): Remove once http://crbug.com/153701 is fixed.
3936 NavigateToSwappedOutURL(frame
);
3939 if (frame_tree
->GetString(kFrameTreeNodeNameKey
, &name
) && !name
.empty())
3940 frame
->setName(name
);
3943 if (frame_tree
->GetInteger(kFrameTreeNodeIdKey
, &remote_id
))
3944 active_frame_id_map_
.insert(std::pair
<int, int>(frame
->identifier(),
3947 ListValue
* children
;
3948 if (!frame_tree
->GetList(kFrameTreeNodeSubtreeKey
, &children
))
3951 // Create an invisible iframe tree in the swapped out page.
3952 base::DictionaryValue
* child
;
3953 for (size_t i
= 0; i
< children
->GetSize(); ++i
) {
3954 if (!children
->GetDictionary(i
, &child
))
3956 WebElement element
= frame
->document().createElement("iframe");
3957 element
.setAttribute("width", "0");
3958 element
.setAttribute("height", "0");
3959 element
.setAttribute("frameBorder", "0");
3960 if (frame
->document().body().appendChild(element
)) {
3961 WebFrame
* subframe
= WebFrame::fromFrameOwnerElement(element
);
3963 CreateFrameTree(subframe
, child
);
3965 LOG(ERROR
) << "Failed to append created iframe element.";
3970 WebKit::WebFrame
* RenderViewImpl::GetFrameByRemoteID(int remote_frame_id
) {
3971 std::map
<int, int>::const_iterator it
= active_frame_id_map_
.begin();
3972 for (; it
!= active_frame_id_map_
.end(); ++it
) {
3973 if (it
->second
== remote_frame_id
)
3974 return FindFrameByID(webview()->mainFrame(), it
->first
);
3979 void RenderViewImpl::EnsureMediaStreamImpl() {
3980 if (!RenderThreadImpl::current()) // Will be NULL during unit tests.
3983 #if defined(ENABLE_WEBRTC)
3984 if (!media_stream_dispatcher_
)
3985 media_stream_dispatcher_
= new MediaStreamDispatcher(this);
3987 if (!media_stream_impl_
) {
3988 media_stream_impl_
= new MediaStreamImpl(
3990 media_stream_dispatcher_
,
3991 RenderThreadImpl::current()->video_capture_impl_manager(),
3992 RenderThreadImpl::current()->GetMediaStreamDependencyFactory());
3997 void RenderViewImpl::didChangeContentsSize(WebFrame
* frame
,
3998 const WebSize
& size
) {
3999 if (webview()->mainFrame() != frame
)
4001 WebView
* frameView
= frame
->view();
4005 bool has_horizontal_scrollbar
= frame
->hasHorizontalScrollbar();
4006 bool has_vertical_scrollbar
= frame
->hasVerticalScrollbar();
4008 if (has_horizontal_scrollbar
!= cached_has_main_frame_horizontal_scrollbar_
||
4009 has_vertical_scrollbar
!= cached_has_main_frame_vertical_scrollbar_
) {
4010 Send(new ViewHostMsg_DidChangeScrollbarsForMainFrame(
4011 routing_id_
, has_horizontal_scrollbar
, has_vertical_scrollbar
));
4013 cached_has_main_frame_horizontal_scrollbar_
= has_horizontal_scrollbar
;
4014 cached_has_main_frame_vertical_scrollbar_
= has_vertical_scrollbar
;
4017 #if defined(OS_ANDROID)
4018 ScheduleUpdateFrameInfo();
4022 void RenderViewImpl::UpdateScrollState(WebFrame
* frame
) {
4023 WebSize offset
= frame
->scrollOffset();
4024 WebSize minimum_offset
= frame
->minimumScrollOffset();
4025 WebSize maximum_offset
= frame
->maximumScrollOffset();
4027 bool is_pinned_to_left
= offset
.width
<= minimum_offset
.width
;
4028 bool is_pinned_to_right
= offset
.width
>= maximum_offset
.width
;
4030 if (is_pinned_to_left
!= cached_is_main_frame_pinned_to_left_
||
4031 is_pinned_to_right
!= cached_is_main_frame_pinned_to_right_
) {
4032 Send(new ViewHostMsg_DidChangeScrollOffsetPinningForMainFrame(
4033 routing_id_
, is_pinned_to_left
, is_pinned_to_right
));
4035 cached_is_main_frame_pinned_to_left_
= is_pinned_to_left
;
4036 cached_is_main_frame_pinned_to_right_
= is_pinned_to_right
;
4040 void RenderViewImpl::didChangeScrollOffset(WebFrame
* frame
) {
4041 StartNavStateSyncTimerIfNecessary();
4043 if (webview()->mainFrame() == frame
)
4044 UpdateScrollState(frame
);
4047 RenderViewObserver
, observers_
, DidChangeScrollOffset(frame
));
4049 #if defined(OS_ANDROID)
4050 if (webview()->mainFrame() == frame
)
4051 ScheduleUpdateFrameInfo();
4055 #if defined(OS_ANDROID)
4056 void RenderViewImpl::didFirstVisuallyNonEmptyLayout(WebFrame
* frame
) {
4057 if (frame
!= webview()->mainFrame())
4060 // Update body background color if necessary.
4061 SkColor bg_color
= webwidget_
->backgroundColor();
4063 // If not initialized, default to white. Note that 0 is different from black
4064 // as black still has alpha 0xFF.
4066 bg_color
= SK_ColorWHITE
;
4068 if (bg_color
!= body_background_color_
) {
4069 body_background_color_
= bg_color
;
4070 Send(new ViewHostMsg_DidChangeBodyBackgroundColor(routing_id_
, bg_color
));
4075 void RenderViewImpl::SendFindReply(int request_id
,
4078 const WebRect
& selection_rect
,
4079 bool final_status_update
) {
4080 #if defined(OS_ANDROID)
4081 if (synchronous_find_reply_message_
.get()) {
4082 if (final_status_update
) {
4083 ViewMsg_SynchronousFind::WriteReplyParams(
4084 synchronous_find_reply_message_
.get(),
4086 match_count
? synchronous_find_active_match_ordinal_
: 0);
4087 Send(synchronous_find_reply_message_
.release());
4093 Send(new ViewHostMsg_Find_Reply(routing_id_
,
4098 final_status_update
));
4101 void RenderViewImpl::reportFindInPageMatchCount(int request_id
,
4103 bool final_update
) {
4104 int active_match_ordinal
= -1; // -1 = don't update active match ordinal
4106 active_match_ordinal
= 0;
4108 // Send the search result over to the browser process.
4109 SendFindReply(request_id
,
4111 active_match_ordinal
,
4116 void RenderViewImpl::reportFindInPageSelection(int request_id
,
4117 int active_match_ordinal
,
4118 const WebRect
& selection_rect
) {
4119 #if defined(OS_ANDROID)
4120 // If this was a SynchronousFind request, we need to remember the ordinal
4121 // value here for replying when reportFindInPageMatchCount is called.
4122 if (synchronous_find_reply_message_
.get()) {
4123 synchronous_find_active_match_ordinal_
= active_match_ordinal
;
4128 SendFindReply(request_id
,
4130 active_match_ordinal
,
4135 void RenderViewImpl::openFileSystem(
4137 WebFileSystem::Type type
,
4140 WebFileSystemCallbacks
* callbacks
) {
4143 WebSecurityOrigin origin
= frame
->document().securityOrigin();
4144 if (origin
.isUnique()) {
4145 // Unique origins cannot store persistent state.
4146 callbacks
->didFail(WebKit::WebFileErrorAbort
);
4150 ChildThread::current()->file_system_dispatcher()->OpenFileSystem(
4151 GURL(origin
.toString()), static_cast<fileapi::FileSystemType
>(type
),
4152 size
, create
, new WebFileSystemCallbackDispatcher(callbacks
));
4155 void RenderViewImpl::deleteFileSystem(
4157 WebFileSystem::Type type
,
4158 WebFileSystemCallbacks
* callbacks
) {
4161 WebSecurityOrigin origin
= frame
->document().securityOrigin();
4162 if (origin
.isUnique()) {
4163 // Unique origins cannot store persistent state.
4164 callbacks
->didSucceed();
4168 ChildThread::current()->file_system_dispatcher()->DeleteFileSystem(
4169 GURL(origin
.toString()),
4170 static_cast<fileapi::FileSystemType
>(type
),
4171 new WebFileSystemCallbackDispatcher(callbacks
));
4174 void RenderViewImpl::queryStorageUsageAndQuota(
4176 WebStorageQuotaType type
,
4177 WebStorageQuotaCallbacks
* callbacks
) {
4179 WebSecurityOrigin origin
= frame
->document().securityOrigin();
4180 if (origin
.isUnique()) {
4181 // Unique origins cannot store persistent state.
4182 callbacks
->didFail(WebKit::WebStorageQuotaErrorAbort
);
4185 ChildThread::current()->quota_dispatcher()->QueryStorageUsageAndQuota(
4186 GURL(origin
.toString()),
4187 static_cast<quota::StorageType
>(type
),
4188 QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(callbacks
));
4191 void RenderViewImpl::requestStorageQuota(
4193 WebStorageQuotaType type
,
4194 unsigned long long requested_size
,
4195 WebStorageQuotaCallbacks
* callbacks
) {
4197 WebSecurityOrigin origin
= frame
->document().securityOrigin();
4198 if (origin
.isUnique()) {
4199 // Unique origins cannot store persistent state.
4200 callbacks
->didFail(WebKit::WebStorageQuotaErrorAbort
);
4203 ChildThread::current()->quota_dispatcher()->RequestStorageQuota(
4204 routing_id(), GURL(origin
.toString()),
4205 static_cast<quota::StorageType
>(type
), requested_size
,
4206 QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(callbacks
));
4209 void RenderViewImpl::registerIntentService(
4210 WebFrame
* frame
, const WebIntentServiceInfo
& service
) {
4211 webkit_glue::WebIntentServiceData
data(service
);
4212 if (data
.title
.empty())
4213 data
.title
= webview()->mainFrame()->document().title();
4214 bool user_gesture
= frame
->isProcessingUserGesture();
4215 Send(new IntentsHostMsg_RegisterIntentService(routing_id_
,
4220 void RenderViewImpl::dispatchIntent(
4221 WebFrame
* frame
, const WebIntentRequest
& intentRequest
) {
4222 webkit_glue::WebIntentData
intent_data(intentRequest
.intent());
4224 // See WebMessagePortChannelImpl::postMessage() and ::OnMessagedQueued()
4225 WebKit::WebMessagePortChannelArray
* channels
=
4226 intentRequest
.intent().messagePortChannelsRelease();
4228 for (size_t i
= 0; i
< channels
->size(); ++i
) {
4229 WebMessagePortChannelImpl
* webchannel
=
4230 static_cast<WebMessagePortChannelImpl
*>((*channels
)[i
]);
4231 intent_data
.message_port_ids
.push_back(webchannel
->message_port_id());
4232 DCHECK(intent_data
.message_port_ids
[i
] != MSG_ROUTING_NONE
);
4237 int id
= intents_host_
->RegisterWebIntent(intentRequest
);
4238 Send(new IntentsHostMsg_WebIntentDispatch(
4239 routing_id_
, intent_data
, id
));
4242 bool RenderViewImpl::willCheckAndDispatchMessageEvent(
4243 WebKit::WebFrame
* sourceFrame
,
4244 WebKit::WebFrame
* targetFrame
,
4245 WebKit::WebSecurityOrigin target_origin
,
4246 WebKit::WebDOMMessageEvent event
) {
4247 if (!is_swapped_out_
)
4250 ViewMsg_PostMessage_Params params
;
4251 params
.data
= event
.data().toString();
4252 params
.source_origin
= event
.origin();
4253 if (!target_origin
.isNull())
4254 params
.target_origin
= target_origin
.toString();
4256 // Include the routing ID for the source frame, which the browser process
4257 // will translate into the routing ID for the equivalent frame in the target
4259 params
.source_routing_id
= MSG_ROUTING_NONE
;
4260 RenderViewImpl
* source_view
= FromWebView(sourceFrame
->view());
4262 params
.source_routing_id
= source_view
->routing_id();
4263 params
.source_frame_id
= sourceFrame
->identifier();
4265 // Include the process, route, and frame IDs of the target frame. This allows
4266 // the browser to detect races between this message being sent and the target
4267 // frame no longer being valid.
4268 params
.target_process_id
= target_process_id_
;
4269 params
.target_routing_id
= target_routing_id_
;
4271 std::map
<int,int>::iterator it
= active_frame_id_map_
.find(
4272 targetFrame
->identifier());
4273 if (it
!= active_frame_id_map_
.end()) {
4274 params
.target_frame_id
= it
->second
;
4276 params
.target_frame_id
= 0;
4279 Send(new ViewHostMsg_RouteMessageEvent(routing_id_
, params
));
4283 void RenderViewImpl::willOpenSocketStream(
4284 WebSocketStreamHandle
* handle
) {
4285 SocketStreamHandleData::AddToHandle(handle
, routing_id_
);
4288 void RenderViewImpl::willStartUsingPeerConnectionHandler(
4289 WebKit::WebFrame
* frame
, WebKit::WebRTCPeerConnectionHandler
* handler
) {
4290 #if defined(ENABLE_WEBRTC)
4291 static_cast<RTCPeerConnectionHandler
*>(handler
)->associateWithFrame(frame
);
4295 WebKit::WebString
RenderViewImpl::userAgentOverride(
4296 WebKit::WebFrame
* frame
,
4297 const WebKit::WebURL
& url
) {
4298 if (!webview() || !webview()->mainFrame() ||
4299 renderer_preferences_
.user_agent_override
.empty()) {
4300 return WebKit::WebString();
4303 // If we're in the middle of committing a load, the data source we need
4304 // will still be provisional.
4305 WebFrame
* main_frame
= webview()->mainFrame();
4306 WebDataSource
* data_source
= NULL
;
4307 if (main_frame
->provisionalDataSource())
4308 data_source
= main_frame
->provisionalDataSource();
4310 data_source
= main_frame
->dataSource();
4312 DocumentState
* document_state
=
4313 data_source
? DocumentState::FromDataSource(data_source
) : NULL
;
4314 if (document_state
&& document_state
->is_overriding_user_agent())
4315 return WebString::fromUTF8(renderer_preferences_
.user_agent_override
);
4317 return WebKit::WebString();
4320 bool RenderViewImpl::allowWebGL(WebFrame
* frame
, bool default_value
) {
4324 bool blocked
= true;
4325 Send(new ViewHostMsg_Are3DAPIsBlocked(
4327 GURL(frame
->top()->document().securityOrigin().toString()),
4328 THREE_D_API_TYPE_WEBGL
,
4333 void RenderViewImpl::didLoseWebGLContext(
4334 WebKit::WebFrame
* frame
,
4335 int arb_robustness_status_code
) {
4336 Send(new ViewHostMsg_DidLose3DContext(
4337 GURL(frame
->top()->document().securityOrigin().toString()),
4338 THREE_D_API_TYPE_WEBGL
,
4339 arb_robustness_status_code
));
4342 // WebKit::WebPageSerializerClient implementation ------------------------------
4344 void RenderViewImpl::didSerializeDataForFrame(
4345 const WebURL
& frame_url
,
4346 const WebCString
& data
,
4347 WebPageSerializerClient::PageSerializationStatus status
) {
4348 Send(new ViewHostMsg_SendSerializedHtmlData(
4352 static_cast<int32
>(status
)));
4355 // RenderView implementation ---------------------------------------------------
4357 bool RenderViewImpl::Send(IPC::Message
* message
) {
4358 return RenderWidget::Send(message
);
4361 int RenderViewImpl::GetRoutingID() const {
4365 int RenderViewImpl::GetPageId() const {
4369 gfx::Size
RenderViewImpl::GetSize() const {
4373 WebPreferences
& RenderViewImpl::GetWebkitPreferences() {
4374 return webkit_preferences_
;
4377 void RenderViewImpl::SetWebkitPreferences(const WebPreferences
& preferences
) {
4378 OnUpdateWebPreferences(preferences
);
4381 WebKit::WebView
* RenderViewImpl::GetWebView() {
4385 WebKit::WebNode
RenderViewImpl::GetFocusedNode() const {
4388 WebFrame
* focused_frame
= webview()->focusedFrame();
4389 if (focused_frame
) {
4390 WebDocument doc
= focused_frame
->document();
4392 return doc
.focusedNode();
4398 WebKit::WebNode
RenderViewImpl::GetContextMenuNode() const {
4399 return context_menu_node_
;
4402 bool RenderViewImpl::IsEditableNode(const WebNode
& node
) const {
4406 if (node
.isContentEditable())
4409 if (node
.isElementNode()) {
4410 const WebElement
& element
= node
.toConst
<WebElement
>();
4411 if (element
.isTextFormControlElement())
4414 // Also return true if it has an ARIA role of 'textbox'.
4415 for (unsigned i
= 0; i
< element
.attributeCount(); ++i
) {
4416 if (LowerCaseEqualsASCII(element
.attributeLocalName(i
), "role")) {
4417 if (LowerCaseEqualsASCII(element
.attributeValue(i
), "textbox"))
4427 WebKit::WebPlugin
* RenderViewImpl::CreatePlugin(
4428 WebKit::WebFrame
* frame
,
4429 const webkit::WebPluginInfo
& info
,
4430 const WebKit::WebPluginParams
& params
) {
4431 WebKit::WebPlugin
* pepper_webplugin
=
4432 pepper_helper_
->CreatePepperWebPlugin(info
, params
);
4434 if (pepper_webplugin
)
4435 return pepper_webplugin
;
4437 #if defined(USE_AURA) && !defined(OS_WIN)
4440 return new webkit::npapi::WebPluginImpl(
4441 frame
, params
, info
.path
, AsWeakPtr());
4445 void RenderViewImpl::EvaluateScript(const string16
& frame_xpath
,
4446 const string16
& jscript
,
4448 bool notify_result
) {
4449 v8::Handle
<v8::Value
> result
;
4450 WebFrame
* web_frame
= GetChildFrame(frame_xpath
);
4452 result
= web_frame
->executeScriptAndReturnValue(WebScriptSource(jscript
));
4453 if (notify_result
) {
4455 if (!result
.IsEmpty() && web_frame
) {
4456 v8::HandleScope handle_scope
;
4457 v8::Local
<v8::Context
> context
= web_frame
->mainWorldScriptContext();
4458 v8::Context::Scope
context_scope(context
);
4459 V8ValueConverterImpl converter
;
4460 converter
.SetDateAllowed(true);
4461 converter
.SetRegExpAllowed(true);
4462 base::Value
* result_value
= converter
.FromV8Value(result
, context
);
4463 list
.Set(0, result_value
? result_value
:
4464 base::Value::CreateNullValue());
4466 list
.Set(0, Value::CreateNullValue());
4468 Send(new ViewHostMsg_ScriptEvalResponse(routing_id_
, id
, list
));
4472 bool RenderViewImpl::ShouldDisplayScrollbars(int width
, int height
) const {
4473 return (!send_preferred_size_changes_
||
4474 (disable_scrollbars_size_limit_
.width() <= width
||
4475 disable_scrollbars_size_limit_
.height() <= height
));
4478 int RenderViewImpl::GetEnabledBindings() const {
4479 return enabled_bindings_
;
4482 bool RenderViewImpl::GetContentStateImmediately() const {
4483 return send_content_state_immediately_
;
4486 float RenderViewImpl::GetFilteredTimePerFrame() const {
4487 return filtered_time_per_frame();
4490 int RenderViewImpl::ShowContextMenu(ContextMenuClient
* client
,
4491 const ContextMenuParams
& params
) {
4492 DCHECK(client
); // A null client means "internal" when we issue callbacks.
4493 ContextMenuParams
our_params(params
);
4494 our_params
.custom_context
.request_id
= pending_context_menus_
.Add(client
);
4495 Send(new ViewHostMsg_ContextMenu(routing_id_
, our_params
));
4496 return our_params
.custom_context
.request_id
;
4499 void RenderViewImpl::CancelContextMenu(int request_id
) {
4500 DCHECK(pending_context_menus_
.Lookup(request_id
));
4501 pending_context_menus_
.Remove(request_id
);
4504 WebKit::WebPageVisibilityState
RenderViewImpl::GetVisibilityState() const {
4505 return visibilityState();
4508 void RenderViewImpl::RunModalAlertDialog(WebKit::WebFrame
* frame
,
4509 const WebKit::WebString
& message
) {
4510 return runModalAlertDialog(frame
, message
);
4513 void RenderViewImpl::LoadURLExternally(
4514 WebKit::WebFrame
* frame
,
4515 const WebKit::WebURLRequest
& request
,
4516 WebKit::WebNavigationPolicy policy
) {
4517 loadURLExternally(frame
, request
, policy
);
4520 // webkit_glue::WebPluginPageDelegate ------------------------------------------
4522 webkit::npapi::WebPluginDelegate
* RenderViewImpl::CreatePluginDelegate(
4523 const FilePath
& file_path
,
4524 const std::string
& mime_type
) {
4525 if (!PluginChannelHost::IsListening()) {
4526 LOG(ERROR
) << "PluginChannelHost isn't listening";
4530 bool in_process_plugin
= RenderProcess::current()->UseInProcessPlugins();
4531 if (in_process_plugin
) {
4532 #if defined(OS_WIN) && !defined(USE_AURA)
4533 return webkit::npapi::WebPluginDelegateImpl::Create(file_path
, mime_type
);
4535 // In-proc plugins aren't supported on non-Windows.
4541 return new WebPluginDelegateProxy(mime_type
, AsWeakPtr());
4544 WebKit::WebPlugin
* RenderViewImpl::CreatePluginReplacement(
4545 const FilePath
& file_path
) {
4546 return GetContentClient()->renderer()->CreatePluginReplacement(
4550 void RenderViewImpl::CreatedPluginWindow(gfx::PluginWindowHandle window
) {
4551 #if defined(USE_X11)
4552 Send(new ViewHostMsg_CreatePluginContainer(routing_id(), window
));
4556 void RenderViewImpl::WillDestroyPluginWindow(gfx::PluginWindowHandle window
) {
4557 #if defined(USE_X11)
4558 Send(new ViewHostMsg_DestroyPluginContainer(routing_id(), window
));
4560 CleanupWindowInPluginMoves(window
);
4563 void RenderViewImpl::DidMovePlugin(
4564 const webkit::npapi::WebPluginGeometry
& move
) {
4565 SchedulePluginMove(move
);
4568 void RenderViewImpl::DidStartLoadingForPlugin() {
4569 // TODO(darin): Make is_loading_ be a counter!
4573 void RenderViewImpl::DidStopLoadingForPlugin() {
4574 // TODO(darin): Make is_loading_ be a counter!
4578 WebCookieJar
* RenderViewImpl::GetCookieJar() {
4579 return &cookie_jar_
;
4582 void RenderViewImpl::DidPlay(WebKit::WebMediaPlayer
* player
) {
4583 Send(new ViewHostMsg_MediaNotification(routing_id_
,
4584 reinterpret_cast<int64
>(player
),
4590 void RenderViewImpl::DidPause(WebKit::WebMediaPlayer
* player
) {
4591 Send(new ViewHostMsg_MediaNotification(routing_id_
,
4592 reinterpret_cast<int64
>(player
),
4598 void RenderViewImpl::PlayerGone(WebKit::WebMediaPlayer
* player
) {
4602 void RenderViewImpl::SyncNavigationState() {
4606 const WebHistoryItem
& item
= webview()->mainFrame()->currentHistoryItem();
4607 SendUpdateState(item
);
4610 void RenderViewImpl::SyncSelectionIfRequired() {
4611 WebFrame
* frame
= webview()->focusedFrame();
4618 if (pepper_helper_
->IsPluginFocused()) {
4619 pepper_helper_
->GetSurroundingText(&text
, &range
);
4620 offset
= 0; // Pepper API does not support offset reporting.
4621 // TODO(kinaba): cut as needed.
4623 size_t location
, length
;
4624 if (!webview()->caretOrSelectionRange(&location
, &length
))
4627 range
= ui::Range(location
, location
+ length
);
4629 if (webview()->textInputType() != WebKit::WebTextInputTypeNone
) {
4630 // If current focused element is editable, we will send 100 more chars
4631 // before and after selection. It is for input method surrounding text
4633 if (location
> kExtraCharsBeforeAndAfterSelection
)
4634 offset
= location
- kExtraCharsBeforeAndAfterSelection
;
4637 length
= location
+ length
- offset
+ kExtraCharsBeforeAndAfterSelection
;
4638 WebRange webrange
= WebRange::fromDocumentRange(frame
, offset
, length
);
4639 if (!webrange
.isNull())
4640 text
= WebRange::fromDocumentRange(frame
, offset
, length
).toPlainText();
4643 text
= frame
->selectionAsText();
4644 // http://crbug.com/101435
4645 // In some case, frame->selectionAsText() returned text's length is not
4646 // equal to the length returned from webview()->caretOrSelectionRange().
4647 // So we have to set the range according to text.length().
4648 range
.set_end(range
.start() + text
.length());
4652 // Sometimes we get repeated didChangeSelection calls from webkit when
4653 // the selection hasn't actually changed. We don't want to report these
4654 // because it will cause us to continually claim the X clipboard.
4655 if (selection_text_offset_
!= offset
||
4656 selection_range_
!= range
||
4657 selection_text_
!= text
) {
4658 selection_text_
= text
;
4659 selection_text_offset_
= offset
;
4660 selection_range_
= range
;
4661 Send(new ViewHostMsg_SelectionChanged(routing_id_
, text
, offset
, range
));
4665 GURL
RenderViewImpl::GetAlternateErrorPageURL(const GURL
& failed_url
,
4666 ErrorPageType error_type
) {
4667 if (failed_url
.SchemeIsSecure()) {
4668 // If the URL that failed was secure, then the embedding web page was not
4669 // expecting a network attacker to be able to manipulate its contents. As
4670 // we fetch alternate error pages over HTTP, we would be allowing a network
4671 // attacker to manipulate the contents of the response if we tried to use
4672 // the link doctor here.
4676 // Grab the base URL from the browser process.
4677 if (!alternate_error_page_url_
.is_valid())
4680 // Strip query params from the failed URL.
4681 GURL::Replacements remove_params
;
4682 remove_params
.ClearUsername();
4683 remove_params
.ClearPassword();
4684 remove_params
.ClearQuery();
4685 remove_params
.ClearRef();
4686 const GURL url_to_send
= failed_url
.ReplaceComponents(remove_params
);
4687 std::string spec_to_send
= url_to_send
.spec();
4688 // Notify link doctor of the url truncation by sending of "?" at the end.
4689 if (failed_url
.has_query())
4690 spec_to_send
.append("?");
4692 // Construct the query params to send to link doctor.
4693 std::string
params(alternate_error_page_url_
.query());
4694 params
.append("&url=");
4695 params
.append(net::EscapeQueryParamValue(spec_to_send
, true));
4696 params
.append("&sourceid=chrome");
4697 params
.append("&error=");
4698 switch (error_type
) {
4700 params
.append("dnserror");
4704 params
.append("http404");
4707 case CONNECTION_ERROR
:
4708 params
.append("connectionfailure");
4712 NOTREACHED() << "unknown ErrorPageType";
4715 // OK, build the final url to return.
4716 GURL::Replacements link_doctor_params
;
4717 link_doctor_params
.SetQueryStr(params
);
4718 GURL url
= alternate_error_page_url_
.ReplaceComponents(link_doctor_params
);
4722 GURL
RenderViewImpl::GetLoadingUrl(WebKit::WebFrame
* frame
) const {
4723 WebDataSource
* ds
= frame
->dataSource();
4724 if (ds
->hasUnreachableURL())
4725 return ds
->unreachableURL();
4727 const WebURLRequest
& request
= ds
->request();
4728 return request
.url();
4731 WebKit::WebPlugin
* RenderViewImpl::GetWebPluginFromPluginDocument() {
4732 return webview()->mainFrame()->document().to
<WebPluginDocument
>().plugin();
4735 void RenderViewImpl::OnFind(int request_id
,
4736 const string16
& search_text
,
4737 const WebFindOptions
& options
) {
4738 #if defined(OS_ANDROID)
4739 // Make sure any asynchronous messages do not disrupt an ongoing synchronous
4740 // find request as it might lead to deadlocks. Also, these should be safe to
4741 // ignore since they would belong to a previous find request.
4742 if (synchronous_find_reply_message_
.get())
4745 Find(request_id
, search_text
, options
);
4748 void RenderViewImpl::Find(int request_id
,
4749 const string16
& search_text
,
4750 const WebFindOptions
& options
) {
4751 WebFrame
* main_frame
= webview()->mainFrame();
4753 // Check if the plugin still exists in the document.
4754 if (main_frame
->document().isPluginDocument() &&
4755 GetWebPluginFromPluginDocument()) {
4756 if (options
.findNext
) {
4757 // Just navigate back/forward.
4758 GetWebPluginFromPluginDocument()->selectFindResult(options
.forward
);
4760 if (!GetWebPluginFromPluginDocument()->startFind(
4761 search_text
, options
.matchCase
, request_id
)) {
4762 // Send "no results".
4763 SendFindReply(request_id
, 0, 0, gfx::Rect(), true);
4769 WebFrame
* frame_after_main
= main_frame
->traverseNext(true);
4770 WebFrame
* focused_frame
= webview()->focusedFrame();
4771 WebFrame
* search_frame
= focused_frame
; // start searching focused frame.
4773 bool multi_frame
= (frame_after_main
!= main_frame
);
4775 // If we have multiple frames, we don't want to wrap the search within the
4776 // frame, so we check here if we only have main_frame in the chain.
4777 bool wrap_within_frame
= !multi_frame
;
4779 WebRect selection_rect
;
4780 bool result
= false;
4782 // If something is selected when we start searching it means we cannot just
4783 // increment the current match ordinal; we need to re-generate it.
4784 WebRange current_selection
= focused_frame
->selectionRange();
4787 result
= search_frame
->find(
4788 request_id
, search_text
, options
, wrap_within_frame
, &selection_rect
);
4791 // don't leave text selected as you move to the next frame.
4792 search_frame
->executeCommand(WebString::fromUTF8("Unselect"));
4794 // Find the next frame, but skip the invisible ones.
4796 // What is the next frame to search? (we might be going backwards). Note
4797 // that we specify wrap=true so that search_frame never becomes NULL.
4798 search_frame
= options
.forward
?
4799 search_frame
->traverseNext(true) :
4800 search_frame
->traversePrevious(true);
4801 } while (!search_frame
->hasVisibleContent() &&
4802 search_frame
!= focused_frame
);
4804 // Make sure selection doesn't affect the search operation in new frame.
4805 search_frame
->executeCommand(WebString::fromUTF8("Unselect"));
4807 // If we have multiple frames and we have wrapped back around to the
4808 // focused frame, we need to search it once more allowing wrap within
4809 // the frame, otherwise it will report 'no match' if the focused frame has
4810 // reported matches, but no frames after the focused_frame contain a
4811 // match for the search word(s).
4812 if (multi_frame
&& search_frame
== focused_frame
) {
4813 result
= search_frame
->find(
4814 request_id
, search_text
, options
, true, // Force wrapping.
4819 webview()->setFocusedFrame(search_frame
);
4820 } while (!result
&& search_frame
!= focused_frame
);
4822 if (options
.findNext
&& current_selection
.isNull()) {
4823 // Force the main_frame to report the actual count.
4824 main_frame
->increaseMatchCount(0, request_id
);
4826 // If nothing is found, set result to "0 of 0", otherwise, set it to
4827 // "-1 of 1" to indicate that we found at least one item, but we don't know
4828 // yet what is active.
4829 int ordinal
= result
? -1 : 0; // -1 here means, we might know more later.
4830 int match_count
= result
? 1 : 0; // 1 here means possibly more coming.
4832 // If we find no matches then this will be our last status update.
4833 // Otherwise the scoping effort will send more results.
4834 bool final_status_update
= !result
;
4836 SendFindReply(request_id
, match_count
, ordinal
, selection_rect
,
4837 final_status_update
);
4839 // Scoping effort begins, starting with the mainframe.
4840 search_frame
= main_frame
;
4842 main_frame
->resetMatchCount();
4845 // Cancel all old scoping requests before starting a new one.
4846 search_frame
->cancelPendingScopingEffort();
4848 // We don't start another scoping effort unless at least one match has
4851 // Start new scoping request. If the scoping function determines that it
4852 // needs to scope, it will defer until later.
4853 search_frame
->scopeStringMatches(request_id
,
4856 true); // reset the tickmarks
4859 // Iterate to the next frame. The frame will not necessarily scope, for
4860 // example if it is not visible.
4861 search_frame
= search_frame
->traverseNext(true);
4862 } while (search_frame
!= main_frame
);
4866 void RenderViewImpl::OnStopFinding(StopFindAction action
) {
4867 #if defined(OS_ANDROID)
4868 // Make sure any asynchronous messages do not disrupt an ongoing synchronous
4869 // find request as it might lead to deadlocks. Also, these should be safe to
4870 // ignore since they would belong to a previous find request.
4871 if (synchronous_find_reply_message_
.get())
4875 StopFinding(action
);
4878 void RenderViewImpl::StopFinding(StopFindAction action
) {
4879 WebView
* view
= webview();
4883 WebDocument doc
= view
->mainFrame()->document();
4884 if (doc
.isPluginDocument() && GetWebPluginFromPluginDocument()) {
4885 GetWebPluginFromPluginDocument()->stopFind();
4889 bool clear_selection
= action
== STOP_FIND_ACTION_CLEAR_SELECTION
;
4890 if (clear_selection
)
4891 view
->focusedFrame()->executeCommand(WebString::fromUTF8("Unselect"));
4893 WebFrame
* frame
= view
->mainFrame();
4895 frame
->stopFinding(clear_selection
);
4896 frame
= frame
->traverseNext(false);
4899 if (action
== STOP_FIND_ACTION_ACTIVATE_SELECTION
) {
4900 WebFrame
* focused_frame
= view
->focusedFrame();
4901 if (focused_frame
) {
4902 WebDocument doc
= focused_frame
->document();
4903 if (!doc
.isNull()) {
4904 WebNode node
= doc
.focusedNode();
4906 node
.simulateClick();
4912 #if defined(OS_ANDROID)
4913 void RenderViewImpl::OnSynchronousFind(int request_id
,
4914 const string16
& search_string
,
4915 const WebFindOptions
& options
,
4916 IPC::Message
* reply_msg
) {
4917 // It is impossible for simultaneous blocking finds to occur.
4918 CHECK(!synchronous_find_reply_message_
.get());
4919 synchronous_find_reply_message_
.reset(reply_msg
);
4921 // Find next should be asynchronous in order to minimize blocking
4922 // the UI thread as much as possible.
4923 DCHECK(!options
.findNext
);
4924 StopFinding(STOP_FIND_ACTION_KEEP_SELECTION
);
4925 synchronous_find_active_match_ordinal_
= -1;
4927 Find(request_id
, search_string
, options
);
4930 void RenderViewImpl::OnActivateNearestFindResult(int request_id
,
4935 WebFrame
* main_frame
= webview()->mainFrame();
4936 WebRect selection_rect
;
4937 int ordinal
= main_frame
->selectNearestFindMatch(WebFloatPoint(x
, y
),
4939 if (ordinal
== -1) {
4940 // Something went wrong, so send a no-op reply (force the main_frame to
4941 // report the current match count) in case the host is waiting for a
4942 // response due to rate-limiting).
4943 main_frame
->increaseMatchCount(0, request_id
);
4947 SendFindReply(request_id
,
4948 -1 /* number_of_matches */,
4951 true /* final_update */);
4954 void RenderViewImpl::OnFindMatchRects(int current_version
) {
4958 WebFrame
* main_frame
= webview()->mainFrame();
4959 std::vector
<gfx::RectF
> match_rects
;
4961 int rects_version
= main_frame
->findMatchMarkersVersion();
4962 if (current_version
!= rects_version
) {
4963 WebVector
<WebFloatRect
> web_match_rects
;
4964 main_frame
->findMatchRects(web_match_rects
);
4965 match_rects
.reserve(web_match_rects
.size());
4966 for (size_t i
= 0; i
< web_match_rects
.size(); ++i
)
4967 match_rects
.push_back(gfx::RectF(web_match_rects
[i
]));
4970 gfx::RectF active_rect
= main_frame
->activeFindMatchRect();
4971 Send(new ViewHostMsg_FindMatchRects_Reply(routing_id_
,
4978 void RenderViewImpl::OnZoom(PageZoom zoom
) {
4979 if (!webview()) // Not sure if this can happen, but no harm in being safe.
4982 webview()->hidePopups();
4984 double old_zoom_level
= webview()->zoomLevel();
4986 if (zoom
== PAGE_ZOOM_RESET
) {
4988 } else if (static_cast<int>(old_zoom_level
) == old_zoom_level
) {
4989 // Previous zoom level is a whole number, so just increment/decrement.
4990 zoom_level
= old_zoom_level
+ zoom
;
4992 // Either the user hit the zoom factor limit and thus the zoom level is now
4993 // not a whole number, or a plugin changed it to a custom value. We want
4994 // to go to the next whole number so that the user can always get back to
4995 // 100% with the keyboard/menu.
4996 if ((old_zoom_level
> 1 && zoom
> 0) ||
4997 (old_zoom_level
< 1 && zoom
< 0)) {
4998 zoom_level
= static_cast<int>(old_zoom_level
+ zoom
);
5000 // We're going towards 100%, so first go to the next whole number.
5001 zoom_level
= static_cast<int>(old_zoom_level
);
5004 webview()->setZoomLevel(false, zoom_level
);
5008 void RenderViewImpl::OnZoomFactor(PageZoom zoom
, int zoom_center_x
,
5009 int zoom_center_y
) {
5010 ZoomFactorHelper(zoom
, zoom_center_x
, zoom_center_y
,
5011 kScalingIncrementForGesture
);
5014 void RenderViewImpl::ZoomFactorHelper(PageZoom zoom
,
5017 float scaling_increment
) {
5018 if (!webview()) // Not sure if this can happen, but no harm in being safe.
5021 double old_page_scale_factor
= webview()->pageScaleFactor();
5022 double page_scale_factor
;
5023 if (zoom
== PAGE_ZOOM_RESET
) {
5024 page_scale_factor
= 1.0;
5026 page_scale_factor
= old_page_scale_factor
+
5027 (zoom
> 0 ? scaling_increment
: -scaling_increment
);
5029 if (page_scale_factor
> 0) {
5030 webview()->setPageScaleFactor(page_scale_factor
,
5031 WebPoint(zoom_center_x
, zoom_center_y
));
5035 void RenderViewImpl::OnSetZoomLevel(double zoom_level
) {
5036 webview()->hidePopups();
5037 webview()->setZoomLevel(false, zoom_level
);
5041 void RenderViewImpl::OnSetZoomLevelForLoadingURL(const GURL
& url
,
5042 double zoom_level
) {
5043 host_zoom_levels_
[url
] = zoom_level
;
5046 void RenderViewImpl::OnSetPageEncoding(const std::string
& encoding_name
) {
5047 webview()->setPageEncoding(WebString::fromUTF8(encoding_name
));
5050 void RenderViewImpl::OnResetPageEncodingToDefault() {
5051 WebString no_encoding
;
5052 webview()->setPageEncoding(no_encoding
);
5055 WebFrame
* RenderViewImpl::GetChildFrame(const string16
& xpath
) const {
5057 return webview()->mainFrame();
5059 // xpath string can represent a frame deep down the tree (across multiple
5061 // Example, /html/body/table/tbody/tr/td/iframe\n/frameset/frame[0]
5062 // should break into 2 xpaths
5063 // /html/body/table/tbody/tr/td/iframe & /frameset/frame[0]
5064 std::vector
<string16
> xpaths
;
5065 base::SplitString(xpath
, '\n', &xpaths
);
5067 WebFrame
* frame
= webview()->mainFrame();
5068 for (std::vector
<string16
>::const_iterator i
= xpaths
.begin();
5069 frame
&& i
!= xpaths
.end(); ++i
) {
5070 frame
= frame
->findChildByExpression(*i
);
5076 void RenderViewImpl::OnScriptEvalRequest(const string16
& frame_xpath
,
5077 const string16
& jscript
,
5079 bool notify_result
) {
5080 TRACE_EVENT_INSTANT0("test_tracing", "OnScriptEvalRequest");
5081 EvaluateScript(frame_xpath
, jscript
, id
, notify_result
);
5084 void RenderViewImpl::OnPostMessageEvent(
5085 const ViewMsg_PostMessage_Params
& params
) {
5086 // Find the target frame of this message. The source tags the message with
5087 // |target_frame_id|, so use it to locate the frame.
5088 // TODO(nasko): Lookup based on the frame id, once http://crbug.com/153701
5089 // is fixed and we can rely on having frame tree updates again.
5090 WebFrame
* frame
= webview()->mainFrame();
5092 // Find the source frame if it exists.
5093 WebFrame
* source_frame
= NULL
;
5094 if (params
.source_routing_id
!= MSG_ROUTING_NONE
) {
5095 RenderViewImpl
* source_view
= FromRoutingID(params
.source_routing_id
);
5096 // TODO(nasko): Lookup based on the frame id, once http://crbug.com/153701
5097 // is fixed and we can rely on having frame tree updates again.
5099 source_frame
= source_view
->webview()->mainFrame();
5102 // Create an event with the message. The final parameter to initMessageEvent
5103 // is the last event ID, which is not used with postMessage.
5104 WebDOMEvent event
= frame
->document().createEvent("MessageEvent");
5105 WebDOMMessageEvent msg_event
= event
.to
<WebDOMMessageEvent
>();
5106 msg_event
.initMessageEvent("message",
5107 // |canBubble| and |cancellable| are always false
5109 WebSerializedScriptValue::fromString(params
.data
),
5110 params
.source_origin
, source_frame
, "");
5112 // We must pass in the target_origin to do the security check on this side,
5113 // since it may have changed since the original postMessage call was made.
5114 WebSecurityOrigin target_origin
;
5115 if (!params
.target_origin
.empty()) {
5117 WebSecurityOrigin::createFromString(WebString(params
.target_origin
));
5119 frame
->dispatchMessageEventWithOriginCheck(target_origin
, msg_event
);
5122 void RenderViewImpl::OnCSSInsertRequest(const string16
& frame_xpath
,
5123 const std::string
& css
) {
5124 WebFrame
* frame
= GetChildFrame(frame_xpath
);
5128 frame
->document().insertUserStyleSheet(
5129 WebString::fromUTF8(css
),
5130 WebDocument::UserStyleAuthorLevel
);
5133 void RenderViewImpl::OnAllowBindings(int enabled_bindings_flags
) {
5134 if ((enabled_bindings_flags
& BINDINGS_POLICY_WEB_UI
) &&
5135 !(enabled_bindings_
& BINDINGS_POLICY_WEB_UI
)) {
5136 RenderThread::Get()->RegisterExtension(content::WebUIExtension::Get());
5137 new WebUIExtensionData(this);
5140 enabled_bindings_
|= enabled_bindings_flags
;
5142 // Keep track of the total bindings accumulated in this process.
5143 RenderProcess::current()->AddBindings(enabled_bindings_flags
);
5146 void RenderViewImpl::OnDragTargetDragEnter(const WebDropData
& drop_data
,
5147 const gfx::Point
& client_point
,
5148 const gfx::Point
& screen_point
,
5149 WebDragOperationsMask ops
,
5150 int key_modifiers
) {
5151 WebDragOperation operation
= webview()->dragTargetDragEnter(
5152 drop_data
.ToDragData(),
5158 Send(new DragHostMsg_UpdateDragCursor(routing_id_
, operation
));
5161 void RenderViewImpl::OnDragTargetDragOver(const gfx::Point
& client_point
,
5162 const gfx::Point
& screen_point
,
5163 WebDragOperationsMask ops
,
5164 int key_modifiers
) {
5165 WebDragOperation operation
= webview()->dragTargetDragOver(
5171 Send(new DragHostMsg_UpdateDragCursor(routing_id_
, operation
));
5174 void RenderViewImpl::OnDragTargetDragLeave() {
5175 webview()->dragTargetDragLeave();
5178 void RenderViewImpl::OnDragTargetDrop(const gfx::Point
& client_point
,
5179 const gfx::Point
& screen_point
,
5180 int key_modifiers
) {
5181 webview()->dragTargetDrop(client_point
, screen_point
, key_modifiers
);
5183 Send(new DragHostMsg_TargetDrop_ACK(routing_id_
));
5186 void RenderViewImpl::OnDragSourceEndedOrMoved(const gfx::Point
& client_point
,
5187 const gfx::Point
& screen_point
,
5189 WebDragOperation op
) {
5191 webview()->dragSourceEndedAt(client_point
, screen_point
, op
);
5193 webview()->dragSourceMovedTo(client_point
, screen_point
, op
);
5197 void RenderViewImpl::OnDragSourceSystemDragEnded() {
5198 webview()->dragSourceSystemDragEnded();
5201 void RenderViewImpl::OnUpdateWebPreferences(const WebPreferences
& prefs
) {
5202 webkit_preferences_
= prefs
;
5203 webkit_preferences_
.Apply(webview());
5206 void RenderViewImpl::OnUpdateTimezone() {
5208 NotifyTimezoneChange(webview()->mainFrame());
5211 void RenderViewImpl::OnSetAltErrorPageURL(const GURL
& url
) {
5212 alternate_error_page_url_
= url
;
5215 void RenderViewImpl::OnCustomContextMenuAction(
5216 const CustomContextMenuContext
& custom_context
,
5218 if (custom_context
.request_id
) {
5219 // External context menu request, look in our map.
5220 ContextMenuClient
* client
=
5221 pending_context_menus_
.Lookup(custom_context
.request_id
);
5223 client
->OnMenuAction(custom_context
.request_id
, action
);
5225 // Internal request, forward to WebKit.
5226 webview()->performCustomContextMenuAction(action
);
5230 void RenderViewImpl::OnEnumerateDirectoryResponse(
5232 const std::vector
<FilePath
>& paths
) {
5233 if (!enumeration_completions_
[id
])
5236 WebVector
<WebString
> ws_file_names(paths
.size());
5237 for (size_t i
= 0; i
< paths
.size(); ++i
)
5238 ws_file_names
[i
] = webkit_base::FilePathToWebString(paths
[i
]);
5240 enumeration_completions_
[id
]->didChooseFile(ws_file_names
);
5241 enumeration_completions_
.erase(id
);
5244 void RenderViewImpl::OnFileChooserResponse(
5245 const std::vector
<ui::SelectedFileInfo
>& files
) {
5246 // This could happen if we navigated to a different page before the user
5247 // closed the chooser.
5248 if (file_chooser_completions_
.empty())
5251 // Convert Chrome's SelectedFileInfo list to WebKit's.
5252 WebVector
<WebFileChooserCompletion::SelectedFileInfo
> selected_files(
5254 for (size_t i
= 0; i
< files
.size(); ++i
) {
5255 WebFileChooserCompletion::SelectedFileInfo selected_file
;
5256 selected_file
.path
= webkit_base::FilePathToWebString(files
[i
].local_path
);
5257 selected_file
.displayName
= webkit_base::FilePathStringToWebString(
5258 files
[i
].display_name
);
5259 selected_files
[i
] = selected_file
;
5262 if (file_chooser_completions_
.front()->completion
)
5263 file_chooser_completions_
.front()->completion
->didChooseFile(
5265 file_chooser_completions_
.pop_front();
5267 // If there are more pending file chooser requests, schedule one now.
5268 if (!file_chooser_completions_
.empty()) {
5269 Send(new ViewHostMsg_RunFileChooser(routing_id_
,
5270 file_chooser_completions_
.front()->params
));
5274 void RenderViewImpl::OnEnableAutoResize(const gfx::Size
& min_size
,
5275 const gfx::Size
& max_size
) {
5276 DCHECK(disable_scrollbars_size_limit_
.IsEmpty());
5279 webview()->enableAutoResizeMode(min_size
, max_size
);
5282 void RenderViewImpl::OnDisableAutoResize(const gfx::Size
& new_size
) {
5283 DCHECK(disable_scrollbars_size_limit_
.IsEmpty());
5286 webview()->disableAutoResizeMode();
5288 Resize(new_size
, resizer_rect_
, is_fullscreen_
, NO_RESIZE_ACK
);
5291 void RenderViewImpl::OnEnablePreferredSizeChangedMode() {
5292 if (send_preferred_size_changes_
)
5294 send_preferred_size_changes_
= true;
5296 // Start off with an initial preferred size notification (in case
5297 // |didUpdateLayout| was already called).
5301 void RenderViewImpl::OnDisableScrollbarsForSmallWindows(
5302 const gfx::Size
& disable_scrollbar_size_limit
) {
5303 disable_scrollbars_size_limit_
= disable_scrollbar_size_limit
;
5306 void RenderViewImpl::OnSetRendererPrefs(
5307 const RendererPreferences
& renderer_prefs
) {
5308 double old_zoom_level
= renderer_preferences_
.default_zoom_level
;
5309 renderer_preferences_
= renderer_prefs
;
5310 UpdateFontRenderingFromRendererPrefs();
5311 #if defined(TOOLKIT_GTK)
5312 WebColorName name
= WebKit::WebColorWebkitFocusRingColor
;
5313 WebKit::setNamedColors(&name
, &renderer_prefs
.focus_ring_color
, 1);
5314 WebKit::setCaretBlinkInterval(renderer_prefs
.caret_blink_interval
);
5315 ui::NativeTheme::instance()->SetScrollbarColors(
5316 renderer_prefs
.thumb_inactive_color
,
5317 renderer_prefs
.thumb_active_color
,
5318 renderer_prefs
.track_color
);
5321 #if defined(USE_DEFAULT_RENDER_THEME) || defined(TOOLKIT_GTK)
5323 #if defined(TOOLKIT_GTK)
5324 webview()->setScrollbarColors(
5325 renderer_prefs
.thumb_inactive_color
,
5326 renderer_prefs
.thumb_active_color
,
5327 renderer_prefs
.track_color
);
5329 webview()->setSelectionColors(
5330 renderer_prefs
.active_selection_bg_color
,
5331 renderer_prefs
.active_selection_fg_color
,
5332 renderer_prefs
.inactive_selection_bg_color
,
5333 renderer_prefs
.inactive_selection_fg_color
);
5334 webview()->themeChanged();
5338 // If the zoom level for this page matches the old zoom default, and this
5339 // is not a plugin, update the zoom level to match the new default.
5340 if (webview() && !webview()->mainFrame()->document().isPluginDocument() &&
5341 ZoomValuesEqual(webview()->zoomLevel(), old_zoom_level
)) {
5342 webview()->setZoomLevel(false, renderer_preferences_
.default_zoom_level
);
5347 void RenderViewImpl::OnMediaPlayerActionAt(const gfx::Point
& location
,
5348 const WebMediaPlayerAction
& action
) {
5350 webview()->performMediaPlayerAction(action
, location
);
5353 void RenderViewImpl::OnOrientationChangeEvent(int orientation
) {
5354 webview()->mainFrame()->sendOrientationChangeEvent(orientation
);
5357 void RenderViewImpl::OnPluginActionAt(const gfx::Point
& location
,
5358 const WebPluginAction
& action
) {
5360 webview()->performPluginAction(action
, location
);
5363 void RenderViewImpl::OnGetAllSavableResourceLinksForCurrentPage(
5364 const GURL
& page_url
) {
5365 // Prepare list to storage all savable resource links.
5366 std::vector
<GURL
> resources_list
;
5367 std::vector
<GURL
> referrer_urls_list
;
5368 std::vector
<WebKit::WebReferrerPolicy
> referrer_policies_list
;
5369 std::vector
<GURL
> frames_list
;
5370 webkit_glue::SavableResourcesResult
result(&resources_list
,
5371 &referrer_urls_list
,
5372 &referrer_policies_list
,
5375 // webkit/ doesn't know about Referrer.
5376 if (!webkit_glue::GetAllSavableResourceLinksForCurrentPage(
5380 const_cast<const char**>(GetSavableSchemes()))) {
5381 // If something is wrong when collecting all savable resource links,
5382 // send empty list to embedder(browser) to tell it failed.
5383 referrer_urls_list
.clear();
5384 referrer_policies_list
.clear();
5385 resources_list
.clear();
5386 frames_list
.clear();
5389 std::vector
<Referrer
> referrers_list
;
5390 CHECK_EQ(referrer_urls_list
.size(), referrer_policies_list
.size());
5391 for (unsigned i
= 0; i
< referrer_urls_list
.size(); ++i
) {
5392 referrers_list
.push_back(
5393 Referrer(referrer_urls_list
[i
], referrer_policies_list
[i
]));
5396 // Send result of all savable resource links to embedder.
5397 Send(new ViewHostMsg_SendCurrentPageAllSavableResourceLinks(routing_id(),
5403 void RenderViewImpl::OnGetSerializedHtmlDataForCurrentPageWithLocalLinks(
5404 const std::vector
<GURL
>& links
,
5405 const std::vector
<FilePath
>& local_paths
,
5406 const FilePath
& local_directory_name
) {
5408 // Convert std::vector of GURLs to WebVector<WebURL>
5409 WebVector
<WebURL
> weburl_links(links
);
5411 // Convert std::vector of std::strings to WebVector<WebString>
5412 WebVector
<WebString
> webstring_paths(local_paths
.size());
5413 for (size_t i
= 0; i
< local_paths
.size(); i
++)
5414 webstring_paths
[i
] = webkit_base::FilePathToWebString(local_paths
[i
]);
5416 WebPageSerializer::serialize(webview()->mainFrame(), true, this, weburl_links
,
5418 webkit_base::FilePathToWebString(
5419 local_directory_name
));
5422 void RenderViewImpl::OnShouldClose() {
5423 base::TimeTicks before_unload_start_time
= base::TimeTicks::Now();
5424 bool should_close
= webview()->dispatchBeforeUnloadEvent();
5425 base::TimeTicks before_unload_end_time
= base::TimeTicks::Now();
5426 Send(new ViewHostMsg_ShouldClose_ACK(routing_id_
, should_close
,
5427 before_unload_start_time
,
5428 before_unload_end_time
));
5431 void RenderViewImpl::OnSwapOut(const ViewMsg_SwapOut_Params
& params
) {
5432 // Ensure that no other in-progress navigation continues.
5435 // Only run unload if we're not swapped out yet, but send the ack either way.
5436 if (!is_swapped_out_
) {
5437 // Swap this RenderView out so the tab can navigate to a page rendered by a
5438 // different process. This involves running the unload handler and clearing
5439 // the page. Once WasSwappedOut is called, we also allow this process to
5440 // exit if there are no other active RenderViews in it.
5442 // Send an UpdateState message before we get swapped out.
5443 SyncNavigationState();
5445 // Synchronously run the unload handler before sending the ACK.
5446 webview()->dispatchUnloadEvent();
5448 // Swap out and stop sending any IPC messages that are not ACKs.
5449 SetSwappedOut(true);
5451 // Replace the page with a blank dummy URL. The unload handler will not be
5452 // run a second time, thanks to a check in FrameLoader::stopLoading.
5453 // TODO(creis): Need to add a better way to do this that avoids running the
5454 // beforeunload handler. For now, we just run it a second time silently.
5455 NavigateToSwappedOutURL(webview()->mainFrame());
5457 // Let WebKit know that this view is hidden so it can drop resources and
5458 // stop compositing.
5459 webview()->setVisibilityState(WebKit::WebPageVisibilityStateHidden
, false);
5462 // Just echo back the params in the ACK.
5463 Send(new ViewHostMsg_SwapOut_ACK(routing_id_
, params
));
5466 void RenderViewImpl::NavigateToSwappedOutURL(WebKit::WebFrame
* frame
) {
5467 // We use loadRequest instead of loadHTMLString because the former commits
5468 // synchronously. Otherwise a new navigation can interrupt the navigation
5469 // to kSwappedOutURL. If that happens to be to the page we had been
5470 // showing, then WebKit will never send a commit and we'll be left spinning.
5471 CHECK(is_swapped_out_
);
5472 GURL
swappedOutURL(kSwappedOutURL
);
5473 WebURLRequest
request(swappedOutURL
);
5474 frame
->loadRequest(request
);
5477 void RenderViewImpl::OnClosePage() {
5478 FOR_EACH_OBSERVER(RenderViewObserver
, observers_
, ClosePage());
5479 // TODO(creis): We'd rather use webview()->Close() here, but that currently
5480 // sets the WebView's delegate_ to NULL, preventing any JavaScript dialogs
5481 // in the onunload handler from appearing. For now, we're bypassing that and
5482 // calling the FrameLoader's CloseURL method directly. This should be
5483 // revisited to avoid having two ways to close a page. Having a single way
5484 // to close that can run onunload is also useful for fixing
5485 // http://b/issue?id=753080.
5486 webview()->dispatchUnloadEvent();
5488 Send(new ViewHostMsg_ClosePage_ACK(routing_id_
));
5491 void RenderViewImpl::OnThemeChanged() {
5492 #if defined(USE_AURA)
5493 // Aura doesn't care if we switch themes.
5494 #elif defined(OS_WIN)
5495 ui::NativeThemeWin::instance()->CloseHandles();
5497 webview()->themeChanged();
5498 #else // defined(OS_WIN)
5499 // TODO(port): we don't support theming on non-Windows platforms yet
5504 void RenderViewImpl::OnDisassociateFromPopupCount() {
5505 if (decrement_shared_popup_at_destruction_
)
5506 shared_popup_counter_
->data
--;
5507 shared_popup_counter_
= new SharedRenderViewCounter(0);
5508 decrement_shared_popup_at_destruction_
= false;
5511 bool RenderViewImpl::MaybeLoadAlternateErrorPage(WebFrame
* frame
,
5512 const WebURLError
& error
,
5514 // We only show alternate error pages in the main frame. They are
5515 // intended to assist the user when navigating, so there is not much
5516 // value in showing them for failed subframes. Ideally, we would be
5517 // able to use the TYPED transition type for this, but that flag is
5518 // not preserved across page reloads.
5519 if (frame
->parent())
5522 // Use the alternate error page service if this is a DNS failure or
5523 // connection failure.
5524 int ec
= error
.reason
;
5525 if (ec
!= net::ERR_NAME_NOT_RESOLVED
&&
5526 ec
!= net::ERR_CONNECTION_FAILED
&&
5527 ec
!= net::ERR_CONNECTION_REFUSED
&&
5528 ec
!= net::ERR_ADDRESS_UNREACHABLE
&&
5529 ec
!= net::ERR_CONNECTION_TIMED_OUT
) {
5533 const GURL
& error_page_url
= GetAlternateErrorPageURL(error
.unreachableURL
,
5534 ec
== net::ERR_NAME_NOT_RESOLVED
? DNS_ERROR
: CONNECTION_ERROR
);
5535 if (!error_page_url
.is_valid())
5538 // Load an empty page first so there is an immediate response to the error,
5539 // and then kick off a request for the alternate error page.
5540 frame
->loadHTMLString(std::string(),
5541 GURL(kUnreachableWebDataURL
),
5542 error
.unreachableURL
,
5545 // Now, create a fetcher for the error page and associate it with the data
5546 // source we just created via the LoadHTMLString call. That way if another
5547 // navigation occurs, the fetcher will get destroyed.
5548 DocumentState
* document_state
=
5549 DocumentState::FromDataSource(frame
->provisionalDataSource());
5550 document_state
->set_alt_error_page_fetcher(
5551 new AltErrorPageResourceFetcher(
5552 error_page_url
, frame
, error
,
5553 base::Bind(&RenderViewImpl::AltErrorPageFinished
,
5554 base::Unretained(this))));
5558 void RenderViewImpl::AltErrorPageFinished(WebFrame
* frame
,
5559 const WebURLError
& original_error
,
5560 const std::string
& html
) {
5561 // Here, we replace the blank page we loaded previously.
5562 // If we failed to download the alternate error page, LoadNavigationErrorPage
5563 // will simply display a default error page.
5564 LoadNavigationErrorPage(frame
, WebURLRequest(), original_error
, html
, true);
5567 void RenderViewImpl::OnMoveOrResizeStarted() {
5569 webview()->hidePopups();
5572 void RenderViewImpl::OnResize(const gfx::Size
& new_size
,
5573 const gfx::Rect
& resizer_rect
,
5574 bool is_fullscreen
) {
5576 webview()->hidePopups();
5577 if (send_preferred_size_changes_
) {
5578 webview()->mainFrame()->setCanHaveScrollbars(
5579 ShouldDisplayScrollbars(new_size
.width(), new_size
.height()));
5581 UpdateScrollState(webview()->mainFrame());
5584 RenderWidget::OnResize(new_size
, resizer_rect
, is_fullscreen
);
5587 void RenderViewImpl::WillInitiatePaint() {
5588 // Notify the pepper plugins that we're about to paint.
5589 pepper_helper_
->ViewWillInitiatePaint();
5592 void RenderViewImpl::DidInitiatePaint() {
5593 // Notify the pepper plugins that we've painted, and are waiting to flush.
5594 pepper_helper_
->ViewInitiatedPaint();
5597 void RenderViewImpl::DidFlushPaint() {
5598 // Notify any pepper plugins that we painted. This will call into the plugin,
5599 // and we it may ask to close itself as a result. This will, in turn, modify
5600 // our set, possibly invalidating the iterator. So we iterate on a copy that
5601 // won't change out from under us.
5602 pepper_helper_
->ViewFlushedPaint();
5604 // If the RenderWidget is closing down then early-exit, otherwise we'll crash.
5605 // See crbug.com/112921.
5609 WebFrame
* main_frame
= webview()->mainFrame();
5611 // If we have a provisional frame we are between the start and commit stages
5612 // of loading and we don't want to save stats.
5613 if (!main_frame
->provisionalDataSource()) {
5614 WebDataSource
* ds
= main_frame
->dataSource();
5615 DocumentState
* document_state
= DocumentState::FromDataSource(ds
);
5617 // TODO(jar): The following code should all be inside a method, probably in
5619 Time now
= Time::Now();
5620 if (document_state
->first_paint_time().is_null()) {
5621 document_state
->set_first_paint_time(now
);
5623 if (document_state
->first_paint_after_load_time().is_null() &&
5624 !document_state
->finish_load_time().is_null()) {
5625 document_state
->set_first_paint_after_load_time(now
);
5630 void RenderViewImpl::OnViewContextSwapBuffersPosted() {
5631 RenderWidget::OnSwapBuffersPosted();
5634 void RenderViewImpl::OnViewContextSwapBuffersComplete() {
5635 RenderWidget::OnSwapBuffersComplete();
5638 void RenderViewImpl::OnViewContextSwapBuffersAborted() {
5639 RenderWidget::OnSwapBuffersAborted();
5642 webkit::ppapi::PluginInstance
* RenderViewImpl::GetBitmapForOptimizedPluginPaint(
5643 const gfx::Rect
& paint_bounds
,
5645 gfx::Rect
* location
,
5647 float* scale_factor
) {
5648 return pepper_helper_
->GetBitmapForOptimizedPluginPaint(
5649 paint_bounds
, dib
, location
, clip
, scale_factor
);
5652 gfx::Vector2d
RenderViewImpl::GetScrollOffset() {
5653 WebSize scroll_offset
= webview()->mainFrame()->scrollOffset();
5654 return gfx::Vector2d(scroll_offset
.width
, scroll_offset
.height
);
5657 void RenderViewImpl::OnClearFocusedNode() {
5659 webview()->clearFocusedNode();
5662 void RenderViewImpl::OnSetBackground(const SkBitmap
& background
) {
5664 webview()->setIsTransparent(!background
.empty());
5666 SetBackground(background
);
5669 void RenderViewImpl::OnSetAccessibilityMode(AccessibilityMode new_mode
) {
5670 if (accessibility_mode_
== new_mode
)
5672 accessibility_mode_
= new_mode
;
5673 if (renderer_accessibility_
) {
5674 delete renderer_accessibility_
;
5675 renderer_accessibility_
= NULL
;
5677 if (accessibility_mode_
== AccessibilityModeComplete
)
5678 renderer_accessibility_
= new RendererAccessibilityComplete(this);
5679 else if (accessibility_mode_
== AccessibilityModeEditableTextOnly
)
5680 renderer_accessibility_
= new RendererAccessibilityFocusOnly(this);
5683 void RenderViewImpl::OnSetActive(bool active
) {
5685 webview()->setIsActive(active
);
5687 #if defined(OS_MACOSX)
5688 std::set
<WebPluginDelegateProxy
*>::iterator plugin_it
;
5689 for (plugin_it
= plugin_delegates_
.begin();
5690 plugin_it
!= plugin_delegates_
.end(); ++plugin_it
) {
5691 (*plugin_it
)->SetWindowFocus(active
);
5696 void RenderViewImpl::OnSetNavigationStartTime(
5697 const base::TimeTicks
& browser_navigation_start
) {
5701 // Only the initial navigation can be a cross-renderer navigation. If we've
5702 // already navigated away from that page, we can ignore this message.
5706 // browser_navigation_start is likely before this process existed, so we can't
5707 // use InterProcessTimeTicksConverter. Instead, the best we can do is just
5708 // ensure we don't report a bogus value in the future.
5709 base::TimeTicks navigation_start
= std::min(base::TimeTicks::Now(),
5710 browser_navigation_start
);
5711 webview()->mainFrame()->provisionalDataSource()->setNavigationStartTime(
5712 (navigation_start
- base::TimeTicks()).InSecondsF());
5715 #if defined(OS_MACOSX)
5716 void RenderViewImpl::OnSetWindowVisibility(bool visible
) {
5717 // Inform plugins that their container has changed visibility.
5718 std::set
<WebPluginDelegateProxy
*>::iterator plugin_it
;
5719 for (plugin_it
= plugin_delegates_
.begin();
5720 plugin_it
!= plugin_delegates_
.end(); ++plugin_it
) {
5721 (*plugin_it
)->SetContainerVisibility(visible
);
5725 void RenderViewImpl::OnWindowFrameChanged(const gfx::Rect
& window_frame
,
5726 const gfx::Rect
& view_frame
) {
5727 // Inform plugins that their window's frame has changed.
5728 std::set
<WebPluginDelegateProxy
*>::iterator plugin_it
;
5729 for (plugin_it
= plugin_delegates_
.begin();
5730 plugin_it
!= plugin_delegates_
.end(); ++plugin_it
) {
5731 (*plugin_it
)->WindowFrameChanged(window_frame
, view_frame
);
5735 void RenderViewImpl::OnPluginImeCompositionCompleted(const string16
& text
,
5737 // WebPluginDelegateProxy is responsible for figuring out if this event
5738 // applies to it or not, so inform all the delegates.
5739 std::set
<WebPluginDelegateProxy
*>::iterator plugin_it
;
5740 for (plugin_it
= plugin_delegates_
.begin();
5741 plugin_it
!= plugin_delegates_
.end(); ++plugin_it
) {
5742 (*plugin_it
)->ImeCompositionCompleted(text
, plugin_id
);
5747 void RenderViewImpl::OnSetEditCommandsForNextKeyEvent(
5748 const EditCommands
& edit_commands
) {
5749 edit_commands_
= edit_commands
;
5752 void RenderViewImpl::Close() {
5753 // We need to grab a pointer to the doomed WebView before we destroy it.
5754 WebView
* doomed
= webview();
5755 RenderWidget::Close();
5756 g_view_map
.Get().erase(doomed
);
5757 g_routing_id_view_map
.Get().erase(routing_id_
);
5760 void RenderViewImpl::DidHandleKeyEvent() {
5761 ClearEditCommands();
5764 bool RenderViewImpl::WillHandleMouseEvent(const WebKit::WebMouseEvent
& event
) {
5765 possible_drag_event_info_
.event_source
=
5766 ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE
;
5767 possible_drag_event_info_
.event_location
=
5768 gfx::Point(event
.globalX
, event
.globalY
);
5769 pepper_helper_
->WillHandleMouseEvent();
5771 // If the mouse is locked, only the current owner of the mouse lock can
5772 // process mouse events.
5773 return mouse_lock_dispatcher_
->WillHandleMouseEvent(event
);
5776 bool RenderViewImpl::WillHandleGestureEvent(
5777 const WebKit::WebGestureEvent
& event
) {
5778 possible_drag_event_info_
.event_source
=
5779 ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH
;
5780 possible_drag_event_info_
.event_location
=
5781 gfx::Point(event
.globalX
, event
.globalY
);
5785 void RenderViewImpl::DidHandleMouseEvent(const WebMouseEvent
& event
) {
5786 FOR_EACH_OBSERVER(RenderViewObserver
, observers_
, DidHandleMouseEvent(event
));
5789 void RenderViewImpl::DidHandleTouchEvent(const WebTouchEvent
& event
) {
5790 FOR_EACH_OBSERVER(RenderViewObserver
, observers_
, DidHandleTouchEvent(event
));
5793 bool RenderViewImpl::HasTouchEventHandlersAt(const gfx::Point
& point
) const {
5796 return webview()->hasTouchEventHandlersAt(point
);
5799 void RenderViewImpl::OnWasHidden() {
5800 RenderWidget::OnWasHidden();
5802 #if defined(OS_ANDROID)
5803 // Inform WebMediaPlayerManagerAndroid to release all media player resources.
5804 // unless some audio is playing.
5805 // If something is in progress the resource will not be freed, it will
5806 // only be freed once the tab is destroyed or if the user navigates away
5807 // via WebMediaPlayerAndroid::Destroy
5808 media_player_manager_
->ReleaseMediaResources();
5812 webview()->settings()->setMinimumTimerInterval(
5813 webkit_glue::kBackgroundTabTimerInterval
);
5814 webview()->setVisibilityState(visibilityState(), false);
5817 // Inform PPAPI plugins that their page is no longer visible.
5818 pepper_helper_
->PageVisibilityChanged(false);
5820 #if defined(OS_MACOSX)
5821 // Inform NPAPI plugins that their container is no longer visible.
5822 std::set
<WebPluginDelegateProxy
*>::iterator plugin_it
;
5823 for (plugin_it
= plugin_delegates_
.begin();
5824 plugin_it
!= plugin_delegates_
.end(); ++plugin_it
) {
5825 (*plugin_it
)->SetContainerVisibility(false);
5830 void RenderViewImpl::OnWasShown(bool needs_repainting
) {
5831 RenderWidget::OnWasShown(needs_repainting
);
5834 webview()->settings()->setMinimumTimerInterval(
5835 webkit_glue::kForegroundTabTimerInterval
);
5836 webview()->setVisibilityState(visibilityState(), false);
5839 // Inform PPAPI plugins that their page is visible.
5840 pepper_helper_
->PageVisibilityChanged(true);
5842 #if defined(OS_MACOSX)
5843 // Inform NPAPI plugins that their container is now visible.
5844 std::set
<WebPluginDelegateProxy
*>::iterator plugin_it
;
5845 for (plugin_it
= plugin_delegates_
.begin();
5846 plugin_it
!= plugin_delegates_
.end(); ++plugin_it
) {
5847 (*plugin_it
)->SetContainerVisibility(true);
5852 bool RenderViewImpl::SupportsAsynchronousSwapBuffers() {
5853 // Contexts using the command buffer support asynchronous swapbuffers.
5854 // See RenderViewImpl::createOutputSurface().
5855 if (WebWidgetHandlesCompositorScheduling() ||
5856 CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessWebGL
))
5862 bool RenderViewImpl::ForceCompositingModeEnabled() {
5863 return webkit_preferences_
.force_compositing_mode
;
5866 void RenderViewImpl::OnSetFocus(bool enable
) {
5867 RenderWidget::OnSetFocus(enable
);
5869 if (webview() && webview()->isActive()) {
5870 // Notify all NPAPI plugins.
5871 std::set
<WebPluginDelegateProxy
*>::iterator plugin_it
;
5872 for (plugin_it
= plugin_delegates_
.begin();
5873 plugin_it
!= plugin_delegates_
.end(); ++plugin_it
) {
5874 #if defined(OS_MACOSX)
5875 // RenderWidget's call to setFocus can cause the underlying webview's
5876 // activation state to change just like a call to setIsActive.
5878 (*plugin_it
)->SetWindowFocus(true);
5880 (*plugin_it
)->SetContentAreaFocus(enable
);
5883 // Notify all Pepper plugins.
5884 pepper_helper_
->OnSetFocus(enable
);
5885 // Notify all BrowserPlugins of the RenderView's focus state.
5886 if (browser_plugin_manager_
)
5887 browser_plugin_manager()->SetEmbedderFocus(this, enable
);
5890 void RenderViewImpl::PpapiPluginFocusChanged() {
5891 UpdateTextInputState(DO_NOT_SHOW_IME
);
5892 UpdateSelectionBounds();
5895 void RenderViewImpl::PpapiPluginTextInputTypeChanged() {
5896 UpdateTextInputState(DO_NOT_SHOW_IME
);
5897 if (renderer_accessibility_
)
5898 renderer_accessibility_
->FocusedNodeChanged(WebNode());
5901 void RenderViewImpl::PpapiPluginCaretPositionChanged() {
5902 UpdateSelectionBounds();
5905 bool RenderViewImpl::GetPpapiPluginCaretBounds(gfx::Rect
* rect
) {
5906 if (!pepper_helper_
->IsPluginFocused())
5908 *rect
= pepper_helper_
->GetCaretBounds();
5912 void RenderViewImpl::SimulateImeSetComposition(
5913 const string16
& text
,
5914 const std::vector
<WebKit::WebCompositionUnderline
>& underlines
,
5915 int selection_start
,
5916 int selection_end
) {
5917 OnImeSetComposition(text
, underlines
, selection_start
, selection_end
);
5920 void RenderViewImpl::SimulateImeConfirmComposition(
5921 const string16
& text
,
5922 const ui::Range
& replacement_range
) {
5923 OnImeConfirmComposition(text
, replacement_range
);
5926 void RenderViewImpl::PpapiPluginCancelComposition() {
5927 Send(new ViewHostMsg_ImeCancelComposition(routing_id()));
5928 const ui::Range
range(ui::Range::InvalidRange());
5929 const std::vector
<gfx::Rect
> empty_bounds
;
5930 UpdateCompositionInfo(range
, empty_bounds
);
5933 void RenderViewImpl::PpapiPluginSelectionChanged() {
5934 SyncSelectionIfRequired();
5937 void RenderViewImpl::PpapiPluginCreated(RendererPpapiHost
* host
) {
5938 FOR_EACH_OBSERVER(RenderViewObserver
, observers_
,
5939 DidCreatePepperPlugin(host
));
5942 void RenderViewImpl::OnImeSetComposition(
5943 const string16
& text
,
5944 const std::vector
<WebKit::WebCompositionUnderline
>& underlines
,
5945 int selection_start
,
5946 int selection_end
) {
5947 if (pepper_helper_
->IsPluginFocused()) {
5948 // When a PPAPI plugin has focus, we bypass WebKit.
5949 pepper_helper_
->OnImeSetComposition(text
,
5955 // When a plug-in has focus, we create platform-specific IME data used by
5956 // our IME emulator and send it directly to the focused plug-in, i.e. we
5957 // bypass WebKit. (WebPluginDelegate dispatches this IME data only when its
5958 // instance ID is the same one as the specified ID.)
5959 if (focused_plugin_id_
>= 0) {
5960 std::vector
<int> clauses
;
5961 std::vector
<int> target
;
5962 for (size_t i
= 0; i
< underlines
.size(); ++i
) {
5963 clauses
.push_back(underlines
[i
].startOffset
);
5964 clauses
.push_back(underlines
[i
].endOffset
);
5965 if (underlines
[i
].thick
) {
5967 target
.push_back(underlines
[i
].startOffset
);
5968 target
.push_back(underlines
[i
].endOffset
);
5971 std::set
<WebPluginDelegateProxy
*>::iterator it
;
5972 for (it
= plugin_delegates_
.begin();
5973 it
!= plugin_delegates_
.end(); ++it
) {
5974 (*it
)->ImeCompositionUpdated(text
, clauses
, target
, selection_end
,
5975 focused_plugin_id_
);
5980 RenderWidget::OnImeSetComposition(text
,
5987 void RenderViewImpl::OnImeConfirmComposition(
5988 const string16
& text
, const ui::Range
& replacement_range
) {
5989 if (pepper_helper_
->IsPluginFocused()) {
5990 // When a PPAPI plugin has focus, we bypass WebKit.
5991 pepper_helper_
->OnImeConfirmComposition(text
);
5994 // Same as OnImeSetComposition(), we send the text from IMEs directly to
5995 // plug-ins. When we send IME text directly to plug-ins, we should not send
5996 // it to WebKit to prevent WebKit from controlling IMEs.
5997 // TODO(thakis): Honor |replacement_range| for plugins?
5998 if (focused_plugin_id_
>= 0) {
5999 std::set
<WebPluginDelegateProxy
*>::iterator it
;
6000 for (it
= plugin_delegates_
.begin();
6001 it
!= plugin_delegates_
.end(); ++it
) {
6002 (*it
)->ImeCompositionCompleted(text
, focused_plugin_id_
);
6007 if (replacement_range
.IsValid() && webview()) {
6008 // Select the text in |replacement_range|, it will then be replaced by
6009 // text added by the call to RenderWidget::OnImeConfirmComposition().
6010 if (WebFrame
* frame
= webview()->focusedFrame()) {
6011 WebRange webrange
= WebRange::fromDocumentRange(
6012 frame
, replacement_range
.start(), replacement_range
.length());
6013 if (!webrange
.isNull())
6014 frame
->selectRange(webrange
);
6017 RenderWidget::OnImeConfirmComposition(text
, replacement_range
);
6021 void RenderViewImpl::SetDeviceScaleFactor(float device_scale_factor
) {
6022 RenderWidget::SetDeviceScaleFactor(device_scale_factor
);
6024 webview()->setDeviceScaleFactor(device_scale_factor
);
6027 ui::TextInputType
RenderViewImpl::GetTextInputType() {
6028 return pepper_helper_
->IsPluginFocused() ?
6029 pepper_helper_
->GetTextInputType() : RenderWidget::GetTextInputType();
6032 void RenderViewImpl::GetSelectionBounds(gfx::Rect
* start
, gfx::Rect
* end
) {
6033 if (pepper_helper_
->IsPluginFocused()) {
6034 // TODO(kinaba) http://crbug.com/101101
6035 // Current Pepper IME API does not handle selection bounds. So we simply
6036 // use the caret position as an empty range for now. It will be updated
6037 // after Pepper API equips features related to surrounding text retrieval.
6038 gfx::Rect caret
= pepper_helper_
->GetCaretBounds();
6043 RenderWidget::GetSelectionBounds(start
, end
);
6046 void RenderViewImpl::GetCompositionCharacterBounds(
6047 std::vector
<gfx::Rect
>* bounds
) {
6053 size_t start_offset
= 0;
6054 size_t character_count
= 0;
6055 if (!webview()->compositionRange(&start_offset
, &character_count
))
6057 if (character_count
== 0)
6060 WebKit::WebFrame
* frame
= webview()->focusedFrame();
6064 bounds
->reserve(character_count
);
6065 WebKit::WebRect webrect
;
6066 for (size_t i
= 0; i
< character_count
; ++i
) {
6067 if (!frame
->firstRectForCharacterRange(start_offset
+ i
, 1, webrect
)) {
6068 DLOG(ERROR
) << "Could not retrieve character rectangle at " << i
;
6072 bounds
->push_back(webrect
);
6076 bool RenderViewImpl::CanComposeInline() {
6077 return pepper_helper_
->IsPluginFocused() ?
6078 pepper_helper_
->CanComposeInline() : true;
6082 void RenderViewImpl::PluginFocusChanged(bool focused
, int plugin_id
) {
6084 focused_plugin_id_
= plugin_id
;
6086 focused_plugin_id_
= -1;
6090 #if defined(OS_MACOSX)
6091 void RenderViewImpl::PluginFocusChanged(bool focused
, int plugin_id
) {
6092 Send(new ViewHostMsg_PluginFocusChanged(routing_id(), focused
, plugin_id
));
6095 void RenderViewImpl::StartPluginIme() {
6096 IPC::Message
* msg
= new ViewHostMsg_StartPluginIme(routing_id());
6097 // This message can be sent during event-handling, and needs to be delivered
6098 // within that context.
6099 msg
->set_unblock(true);
6103 gfx::PluginWindowHandle
RenderViewImpl::AllocateFakePluginWindowHandle(
6104 bool opaque
, bool root
) {
6105 gfx::PluginWindowHandle window
= gfx::kNullPluginWindow
;
6106 Send(new ViewHostMsg_AllocateFakePluginWindowHandle(
6107 routing_id(), opaque
, root
, &window
));
6109 fake_plugin_window_handles_
.insert(window
);
6114 void RenderViewImpl::DestroyFakePluginWindowHandle(
6115 gfx::PluginWindowHandle window
) {
6116 if (window
&& fake_plugin_window_handles_
.find(window
) !=
6117 fake_plugin_window_handles_
.end()) {
6118 Send(new ViewHostMsg_DestroyFakePluginWindowHandle(routing_id(), window
));
6119 fake_plugin_window_handles_
.erase(window
);
6123 void RenderViewImpl::AcceleratedSurfaceSetIOSurface(
6124 gfx::PluginWindowHandle window
,
6127 uint64 io_surface_identifier
) {
6128 Send(new ViewHostMsg_AcceleratedSurfaceSetIOSurface(
6129 routing_id(), window
, width
, height
, io_surface_identifier
));
6132 void RenderViewImpl::AcceleratedSurfaceSetTransportDIB(
6133 gfx::PluginWindowHandle window
,
6136 TransportDIB::Handle transport_dib
) {
6137 Send(new ViewHostMsg_AcceleratedSurfaceSetTransportDIB(
6138 routing_id(), window
, width
, height
, transport_dib
));
6141 TransportDIB::Handle
RenderViewImpl::AcceleratedSurfaceAllocTransportDIB(
6143 TransportDIB::Handle dib_handle
;
6144 // Assume this is a synchronous RPC.
6145 if (Send(new ViewHostMsg_AllocTransportDIB(size
, true, &dib_handle
)))
6147 // Return an invalid handle if Send() fails.
6148 return TransportDIB::DefaultHandleValue();
6151 void RenderViewImpl::AcceleratedSurfaceFreeTransportDIB(
6152 TransportDIB::Id dib_id
) {
6153 Send(new ViewHostMsg_FreeTransportDIB(dib_id
));
6156 void RenderViewImpl::AcceleratedSurfaceBuffersSwapped(
6157 gfx::PluginWindowHandle window
, uint64 surface_handle
) {
6158 Send(new ViewHostMsg_AcceleratedSurfaceBuffersSwapped(
6159 routing_id(), window
, surface_handle
));
6161 #endif // defined(OS_MACOSX)
6163 bool RenderViewImpl::ScheduleFileChooser(
6164 const FileChooserParams
& params
,
6165 WebFileChooserCompletion
* completion
) {
6166 static const size_t kMaximumPendingFileChooseRequests
= 4;
6167 if (file_chooser_completions_
.size() > kMaximumPendingFileChooseRequests
) {
6168 // This sanity check prevents too many file choose requests from getting
6169 // queued which could DoS the user. Getting these is most likely a
6170 // programming error (there are many ways to DoS the user so it's not
6171 // considered a "real" security check), either in JS requesting many file
6172 // choosers to pop up, or in a plugin.
6174 // TODO(brettw) we might possibly want to require a user gesture to open
6175 // a file picker, which will address this issue in a better way.
6179 file_chooser_completions_
.push_back(linked_ptr
<PendingFileChooser
>(
6180 new PendingFileChooser(params
, completion
)));
6181 if (file_chooser_completions_
.size() == 1) {
6182 // Actually show the browse dialog when this is the first request.
6183 Send(new ViewHostMsg_RunFileChooser(routing_id_
, params
));
6188 WebKit::WebGeolocationClient
* RenderViewImpl::geolocationClient() {
6189 if (!geolocation_dispatcher_
)
6190 geolocation_dispatcher_
= new GeolocationDispatcher(this);
6191 return geolocation_dispatcher_
;
6194 WebKit::WebSpeechInputController
* RenderViewImpl::speechInputController(
6195 WebKit::WebSpeechInputListener
* listener
) {
6196 #if defined(ENABLE_INPUT_SPEECH)
6197 if (!input_tag_speech_dispatcher_
)
6198 input_tag_speech_dispatcher_
=
6199 new InputTagSpeechDispatcher(this, listener
);
6201 return input_tag_speech_dispatcher_
;
6204 WebKit::WebSpeechRecognizer
* RenderViewImpl::speechRecognizer() {
6205 #if defined(ENABLE_INPUT_SPEECH)
6206 if (!speech_recognition_dispatcher_
)
6207 speech_recognition_dispatcher_
= new SpeechRecognitionDispatcher(this);
6209 return speech_recognition_dispatcher_
;
6212 WebKit::WebDeviceOrientationClient
* RenderViewImpl::deviceOrientationClient() {
6213 if (!device_orientation_dispatcher_
)
6214 device_orientation_dispatcher_
= new DeviceOrientationDispatcher(this);
6215 return device_orientation_dispatcher_
;
6218 void RenderViewImpl::zoomLimitsChanged(double minimum_level
,
6219 double maximum_level
) {
6220 // For now, don't remember plugin zoom values. We don't want to mix them with
6221 // normal web content (i.e. a fixed layout plugin would usually want them
6223 bool remember
= !webview()->mainFrame()->document().isPluginDocument();
6225 int minimum_percent
= static_cast<int>(
6226 WebView::zoomLevelToZoomFactor(minimum_level
) * 100);
6227 int maximum_percent
= static_cast<int>(
6228 WebView::zoomLevelToZoomFactor(maximum_level
) * 100);
6230 Send(new ViewHostMsg_UpdateZoomLimits(
6231 routing_id_
, minimum_percent
, maximum_percent
, remember
));
6234 void RenderViewImpl::zoomLevelChanged() {
6235 bool remember
= !webview()->mainFrame()->document().isPluginDocument();
6236 float zoom_level
= webview()->zoomLevel();
6238 FOR_EACH_OBSERVER(RenderViewObserver
, observers_
, ZoomLevelChanged());
6240 // Tell the browser which url got zoomed so it can update the menu and the
6241 // saved values if necessary
6242 Send(new ViewHostMsg_DidZoomURL(
6243 routing_id_
, zoom_level
, remember
,
6244 GURL(webview()->mainFrame()->document().url())));
6247 void RenderViewImpl::registerProtocolHandler(const WebString
& scheme
,
6248 const WebString
& base_url
,
6249 const WebString
& url
,
6250 const WebString
& title
) {
6251 bool user_gesture
= (webview()->focusedFrame() &&
6252 webview()->focusedFrame()->isProcessingUserGesture());
6253 GURL
base(base_url
);
6254 GURL absolute_url
= base
.Resolve(UTF16ToUTF8(url
));
6255 if (base
.GetOrigin() != absolute_url
.GetOrigin()) {
6258 Send(new ViewHostMsg_RegisterProtocolHandler(routing_id_
,
6259 UTF16ToUTF8(scheme
),
6265 WebKit::WebPageVisibilityState
RenderViewImpl::visibilityState() const {
6266 WebKit::WebPageVisibilityState current_state
= is_hidden() ?
6267 WebKit::WebPageVisibilityStateHidden
:
6268 WebKit::WebPageVisibilityStateVisible
;
6269 WebKit::WebPageVisibilityState override_state
= current_state
;
6270 if (GetContentClient()->renderer()->
6271 ShouldOverridePageVisibilityState(this,
6273 return override_state
;
6274 return current_state
;
6277 WebKit::WebUserMediaClient
* RenderViewImpl::userMediaClient() {
6278 EnsureMediaStreamImpl();
6279 return media_stream_impl_
;
6282 void RenderViewImpl::draggableRegionsChanged() {
6286 DraggableRegionsChanged(webview()->mainFrame()));
6289 #if defined(OS_ANDROID)
6290 WebContentDetectionResult
RenderViewImpl::detectContentAround(
6291 const WebHitTestResult
& touch_hit
) {
6292 DCHECK(!touch_hit
.isNull());
6293 DCHECK(!touch_hit
.node().isNull());
6294 DCHECK(touch_hit
.node().isTextNode());
6296 // Process the position with all the registered content detectors until
6297 // a match is found. Priority is provided by their relative order.
6298 for (ContentDetectorList::const_iterator it
= content_detectors_
.begin();
6299 it
!= content_detectors_
.end(); ++it
) {
6300 ContentDetector::Result content
= (*it
)->FindTappedContent(touch_hit
);
6301 if (content
.valid
) {
6302 return WebContentDetectionResult(content
.content_boundaries
,
6303 UTF8ToUTF16(content
.text
), content
.intent_url
);
6306 return WebContentDetectionResult();
6309 void RenderViewImpl::scheduleContentIntent(const WebURL
& intent
) {
6310 // Introduce a short delay so that the user can notice the content.
6311 MessageLoop::current()->PostDelayedTask(
6313 base::Bind(&RenderViewImpl::LaunchAndroidContentIntent
, AsWeakPtr(),
6314 intent
, expected_content_intent_id_
),
6315 base::TimeDelta::FromMilliseconds(kContentIntentDelayMilliseconds
));
6318 void RenderViewImpl::cancelScheduledContentIntents() {
6319 ++expected_content_intent_id_
;
6322 void RenderViewImpl::LaunchAndroidContentIntent(const GURL
& intent
,
6323 size_t request_id
) {
6324 if (request_id
!= expected_content_intent_id_
)
6327 // Remove the content highlighting if any.
6328 scheduleComposite();
6330 if (!intent
.is_empty())
6331 Send(new ViewHostMsg_StartContentIntent(routing_id_
, intent
));
6334 bool RenderViewImpl::openDateTimeChooser(
6335 const WebKit::WebDateTimeChooserParams
& params
,
6336 WebKit::WebDateTimeChooserCompletion
* completion
) {
6337 date_time_picker_client_
.reset(
6338 new RendererDateTimePicker(this, params
, completion
));
6339 return date_time_picker_client_
->Open();
6342 #endif // defined(OS_ANDROID)
6344 void RenderViewImpl::OnAsyncFileOpened(
6345 base::PlatformFileError error_code
,
6346 IPC::PlatformFileForTransit file_for_transit
,
6348 pepper_helper_
->OnAsyncFileOpened(
6350 IPC::PlatformFileForTransitToPlatformFile(file_for_transit
),
6354 void RenderViewImpl::OnPpapiBrokerChannelCreated(
6356 const IPC::ChannelHandle
& handle
) {
6357 pepper_helper_
->OnPpapiBrokerChannelCreated(request_id
,
6361 void RenderViewImpl::OnPpapiBrokerPermissionResult(
6364 pepper_helper_
->OnPpapiBrokerPermissionResult(request_id
, result
);
6367 #if defined(OS_MACOSX)
6368 void RenderViewImpl::OnSelectPopupMenuItem(int selected_index
) {
6369 if (external_popup_menu_
== NULL
) {
6370 // Crash reports from the field indicate that we can be notified with a
6371 // NULL external popup menu (we probably get notified twice).
6372 // If you hit this please file a bug against jcivelli and include the page
6373 // and steps to repro.
6377 external_popup_menu_
->DidSelectItem(selected_index
);
6378 external_popup_menu_
.reset();
6382 #if defined(OS_ANDROID)
6383 void RenderViewImpl::OnSelectPopupMenuItems(
6385 const std::vector
<int>& selected_indices
) {
6386 // It is possible to receive more than one of these calls if the user presses
6387 // a select faster than it takes for the show-select-popup IPC message to make
6388 // it to the browser UI thread. Ignore the extra-messages.
6389 // TODO(jcivelli): http:/b/5793321 Implement a better fix, as detailed in bug.
6390 if (!external_popup_menu_
.get())
6393 external_popup_menu_
->DidSelectItems(canceled
, selected_indices
);
6394 external_popup_menu_
.reset();
6398 void RenderViewImpl::OnContextMenuClosed(
6399 const CustomContextMenuContext
& custom_context
) {
6400 if (custom_context
.request_id
) {
6401 // External request, should be in our map.
6402 ContextMenuClient
* client
=
6403 pending_context_menus_
.Lookup(custom_context
.request_id
);
6405 client
->OnMenuClosed(custom_context
.request_id
);
6406 pending_context_menus_
.Remove(custom_context
.request_id
);
6409 // Internal request, forward to WebKit.
6410 context_menu_node_
.reset();
6414 void RenderViewImpl::OnEnableViewSourceMode() {
6417 WebFrame
* main_frame
= webview()->mainFrame();
6420 main_frame
->enableViewSourceMode(true);
6423 bool RenderViewImpl::WebWidgetHandlesCompositorScheduling() const {
6424 return !!RenderThreadImpl::current()->compositor_thread();
6427 void RenderViewImpl::OnJavaBridgeInit() {
6428 DCHECK(!java_bridge_dispatcher_
);
6429 #if defined(ENABLE_JAVA_BRIDGE)
6430 java_bridge_dispatcher_
= new JavaBridgeDispatcher(this);
6434 void RenderViewImpl::OnDisownOpener() {
6438 WebFrame
* main_frame
= webview()->mainFrame();
6439 if (main_frame
&& main_frame
->opener())
6440 main_frame
->setOpener(NULL
);
6443 void RenderViewImpl::OnUpdatedFrameTree(
6446 const std::string
& frame_tree
) {
6447 // TODO(nasko): Remove once http://crbug.com/153701 is fixed.
6449 // We should only act on this message if we are swapped out. It's possible
6450 // for this to happen due to races.
6451 if (!is_swapped_out_
)
6454 base::DictionaryValue
* frames
= NULL
;
6455 scoped_ptr
<base::Value
> tree(base::JSONReader::Read(frame_tree
));
6456 if (tree
.get() && tree
->IsType(base::Value::TYPE_DICTIONARY
))
6457 tree
->GetAsDictionary(&frames
);
6459 updating_frame_tree_
= true;
6460 active_frame_id_map_
.clear();
6462 target_process_id_
= process_id
;
6463 target_routing_id_
= route_id
;
6464 CreateFrameTree(webview()->mainFrame(), frames
);
6466 updating_frame_tree_
= false;
6469 #if defined(OS_ANDROID)
6470 bool RenderViewImpl::didTapMultipleTargets(
6471 const WebKit::WebGestureEvent
& event
,
6472 const WebVector
<WebRect
>& target_rects
) {
6473 gfx::Rect
finger_rect(
6474 event
.x
- event
.data
.tap
.width
/ 2, event
.y
- event
.data
.tap
.height
/ 2,
6475 event
.data
.tap
.width
, event
.data
.tap
.height
);
6476 gfx::Rect zoom_rect
;
6477 float scale
= DisambiguationPopupHelper::ComputeZoomAreaAndScaleFactor(
6478 finger_rect
, target_rects
, GetSize(), &zoom_rect
);
6482 gfx::Size canvas_size
= zoom_rect
.size();
6483 canvas_size
= ToCeiledSize(gfx::ScaleSize(canvas_size
, scale
));
6484 TransportDIB
* transport_dib
= NULL
;
6486 scoped_ptr
<skia::PlatformCanvas
> canvas(
6487 RenderProcess::current()->GetDrawingCanvas(&transport_dib
,
6488 gfx::Rect(canvas_size
)));
6492 canvas
->scale(scale
, scale
);
6494 canvas
->translate(-zoom_rect
.x(), -zoom_rect
.y());
6495 webwidget_
->paint(webkit_glue::ToWebCanvas(canvas
.get()), zoom_rect
,
6496 WebWidget::ForceSoftwareRenderingAndIgnoreGPUResidentContent
);
6498 Send(new ViewHostMsg_ShowDisambiguationPopup(routing_id_
,
6501 transport_dib
->id()));
6507 void RenderViewImpl::OnReleaseDisambiguationPopupDIB(
6508 TransportDIB::Handle dib_handle
) {
6509 TransportDIB
* dib
= TransportDIB::CreateWithHandle(dib_handle
);
6510 RenderProcess::current()->ReleaseTransportDIB(dib
);
6513 } // namespace content