blob: 5299bdd7977d12b64c527706ea04a5bef32396bd [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// 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.
4
5#include "content/renderer/render_view_impl.h"
6
7#include <algorithm>
8#include <cmath>
9
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010#include "base/auto_reset.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000011#include "base/bind.h"
12#include "base/bind_helpers.h"
13#include "base/command_line.h"
14#include "base/compiler_specific.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010015#include "base/debug/alias.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000016#include "base/debug/trace_event.h"
Ben Murdocheb525c52013-07-10 11:40:50 +010017#include "base/files/file_path.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000018#include "base/json/json_writer.h"
19#include "base/lazy_instance.h"
20#include "base/memory/scoped_ptr.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010021#include "base/message_loop/message_loop_proxy.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000022#include "base/metrics/histogram.h"
23#include "base/path_service.h"
Ben Murdochbbcdd452013-07-25 10:06:34 +010024#include "base/process/kill.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010025#include "base/strings/string_number_conversions.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010026#include "base/strings/string_piece.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000027#include "base/strings/string_split.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010028#include "base/strings/string_util.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010029#include "base/strings/sys_string_conversions.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010030#include "base/strings/utf_string_conversions.h"
Ben Murdocheb525c52013-07-10 11:40:50 +010031#include "base/time/time.h"
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010032#include "content/child/appcache_dispatcher.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010033#include "content/child/child_thread.h"
34#include "content/child/fileapi/file_system_dispatcher.h"
35#include "content/child/fileapi/webfilesystem_callback_adapters.h"
Ben Murdochca12bfa2013-07-23 11:17:05 +010036#include "content/child/npapi/webplugin_delegate_impl.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010037#include "content/child/quota_dispatcher.h"
38#include "content/child/request_extra_data.h"
39#include "content/child/webmessageportchannel_impl.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000040#include "content/common/clipboard_messages.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000041#include "content/common/database_messages.h"
Ben Murdochbb1529c2013-08-08 10:24:53 +010042#include "content/common/dom_storage/dom_storage_types.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000043#include "content/common/drag_messages.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000044#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010045#include "content/common/input_messages.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000046#include "content/common/java_bridge_messages.h"
47#include "content/common/pepper_messages.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000048#include "content/common/socket_stream_handle_data.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000049#include "content/common/ssl_status_serialization.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000050#include "content/common/view_messages.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000051#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"
Ben Murdocheb525c52013-07-10 11:40:50 +010056#include "content/public/common/drop_data.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010057#include "content/public/common/favicon_url.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000058#include "content/public/common/file_chooser_params.h"
Ben Murdoch58e6fbe2013-07-26 10:20:38 +010059#include "content/public/common/page_zoom.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000060#include "content/public/common/ssl_status.h"
61#include "content/public/common/three_d_api_types.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000062#include "content/public/common/url_constants.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010063#include "content/public/common/url_utils.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000064#include "content/public/renderer/content_renderer_client.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000065#include "content/public/renderer/context_menu_client.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000066#include "content/public/renderer/document_state.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010067#include "content/public/renderer/history_item_serialization.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000068#include "content/public/renderer/navigation_state.h"
69#include "content/public/renderer/password_form_conversion_utils.h"
70#include "content/public/renderer/render_view_observer.h"
71#include "content/public/renderer/render_view_visitor.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000072#include "content/renderer/accessibility/renderer_accessibility.h"
73#include "content/renderer/accessibility/renderer_accessibility_complete.h"
74#include "content/renderer/accessibility/renderer_accessibility_focus_only.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000075#include "content/renderer/browser_plugin/browser_plugin.h"
76#include "content/renderer/browser_plugin/browser_plugin_manager.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000077#include "content/renderer/browser_plugin/browser_plugin_manager_impl.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010078#include "content/renderer/context_menu_params_builder.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000079#include "content/renderer/device_orientation_dispatcher.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000080#include "content/renderer/devtools/devtools_agent.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000081#include "content/renderer/disambiguation_popup_helper.h"
82#include "content/renderer/dom_automation_controller.h"
83#include "content/renderer/dom_storage/webstoragenamespace_impl.h"
Ben Murdocheb525c52013-07-10 11:40:50 +010084#include "content/renderer/drop_data_builder.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000085#include "content/renderer/external_popup_menu.h"
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +010086#include "content/renderer/fetchers/alt_error_page_resource_fetcher.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000087#include "content/renderer/geolocation_dispatcher.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000088#include "content/renderer/gpu/input_handler_manager.h"
89#include "content/renderer/gpu/render_widget_compositor.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000090#include "content/renderer/idle_user_detector.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010091#include "content/renderer/image_loading_helper.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010092#include "content/renderer/ime_event_guard.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000093#include "content/renderer/input_tag_speech_dispatcher.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010094#include "content/renderer/internal_document_state_data.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000095#include "content/renderer/java/java_bridge_dispatcher.h"
96#include "content/renderer/load_progress_tracker.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000097#include "content/renderer/media/audio_device_factory.h"
98#include "content/renderer/media/audio_renderer_mixer_manager.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000099#include "content/renderer/media/media_stream_dependency_factory.h"
100#include "content/renderer/media/media_stream_dispatcher.h"
101#include "content/renderer/media/media_stream_impl.h"
Ben Murdoch58e6fbe2013-07-26 10:20:38 +0100102#include "content/renderer/media/midi_dispatcher.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000103#include "content/renderer/media/render_media_log.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000104#include "content/renderer/media/rtc_peer_connection_handler.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100105#include "content/renderer/media/video_capture_impl_manager.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100106#include "content/renderer/media/webmediaplayer_impl.h"
107#include "content/renderer/media/webmediaplayer_ms.h"
108#include "content/renderer/media/webmediaplayer_params.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000109#include "content/renderer/mhtml_generator.h"
110#include "content/renderer/notification_provider.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100111#include "content/renderer/render_frame_impl.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000112#include "content/renderer/render_process.h"
113#include "content/renderer/render_thread_impl.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000114#include "content/renderer/render_view_impl_params.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000115#include "content/renderer/render_view_mouse_lock_dispatcher.h"
116#include "content/renderer/render_widget_fullscreen_pepper.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000117#include "content/renderer/renderer_date_time_picker.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000118#include "content/renderer/renderer_webapplicationcachehost_impl.h"
119#include "content/renderer/renderer_webcolorchooser_impl.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100120#include "content/renderer/savable_resources.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000121#include "content/renderer/speech_recognition_dispatcher.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100122#include "content/renderer/stats_collection_controller.h"
123#include "content/renderer/stats_collection_observer.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000124#include "content/renderer/text_input_client_observer.h"
125#include "content/renderer/v8_value_converter_impl.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000126#include "content/renderer/web_ui_extension.h"
127#include "content/renderer/web_ui_extension_data.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000128#include "content/renderer/websharedworker_proxy.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100129#include "media/audio/audio_output_device.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000130#include "media/base/audio_renderer_mixer_input.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000131#include "media/base/filter_collection.h"
132#include "media/base/media_switches.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000133#include "media/filters/audio_renderer_impl.h"
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100134#include "media/filters/gpu_video_decoder_factories.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000135#include "net/base/data_url.h"
136#include "net/base/escape.h"
137#include "net/base/net_errors.h"
138#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
139#include "net/http/http_util.h"
Ben Murdochca12bfa2013-07-23 11:17:05 +0100140#include "third_party/WebKit/public/platform/WebCString.h"
141#include "third_party/WebKit/public/platform/WebDragData.h"
142#include "third_party/WebKit/public/platform/WebFileSystemType.h"
143#include "third_party/WebKit/public/platform/WebHTTPBody.h"
144#include "third_party/WebKit/public/platform/WebImage.h"
145#include "third_party/WebKit/public/platform/WebMessagePortChannel.h"
146#include "third_party/WebKit/public/platform/WebPoint.h"
147#include "third_party/WebKit/public/platform/WebRect.h"
148#include "third_party/WebKit/public/platform/WebSize.h"
149#include "third_party/WebKit/public/platform/WebSocketStreamHandle.h"
150#include "third_party/WebKit/public/platform/WebString.h"
151#include "third_party/WebKit/public/platform/WebURL.h"
152#include "third_party/WebKit/public/platform/WebURLError.h"
153#include "third_party/WebKit/public/platform/WebURLRequest.h"
154#include "third_party/WebKit/public/platform/WebURLResponse.h"
155#include "third_party/WebKit/public/platform/WebVector.h"
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100156#include "third_party/WebKit/public/web/WebAccessibilityObject.h"
157#include "third_party/WebKit/public/web/WebColorName.h"
158#include "third_party/WebKit/public/web/WebDOMEvent.h"
159#include "third_party/WebKit/public/web/WebDOMMessageEvent.h"
160#include "third_party/WebKit/public/web/WebDataSource.h"
161#include "third_party/WebKit/public/web/WebDateTimeChooserCompletion.h"
162#include "third_party/WebKit/public/web/WebDateTimeChooserParams.h"
163#include "third_party/WebKit/public/web/WebDevToolsAgent.h"
164#include "third_party/WebKit/public/web/WebDocument.h"
165#include "third_party/WebKit/public/web/WebElement.h"
166#include "third_party/WebKit/public/web/WebFileChooserParams.h"
167#include "third_party/WebKit/public/web/WebFileSystemCallbacks.h"
168#include "third_party/WebKit/public/web/WebFindOptions.h"
169#include "third_party/WebKit/public/web/WebFormControlElement.h"
170#include "third_party/WebKit/public/web/WebFormElement.h"
171#include "third_party/WebKit/public/web/WebFrame.h"
Ben Murdochbbcdd452013-07-25 10:06:34 +0100172#include "third_party/WebKit/public/web/WebGlyphCache.h"
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100173#include "third_party/WebKit/public/web/WebHelperPlugin.h"
174#include "third_party/WebKit/public/web/WebHistoryItem.h"
175#include "third_party/WebKit/public/web/WebInputElement.h"
176#include "third_party/WebKit/public/web/WebInputEvent.h"
177#include "third_party/WebKit/public/web/WebMediaPlayerAction.h"
178#include "third_party/WebKit/public/web/WebNavigationPolicy.h"
179#include "third_party/WebKit/public/web/WebNodeList.h"
180#include "third_party/WebKit/public/web/WebPageSerializer.h"
181#include "third_party/WebKit/public/web/WebPlugin.h"
182#include "third_party/WebKit/public/web/WebPluginAction.h"
183#include "third_party/WebKit/public/web/WebPluginContainer.h"
184#include "third_party/WebKit/public/web/WebPluginDocument.h"
185#include "third_party/WebKit/public/web/WebPluginParams.h"
186#include "third_party/WebKit/public/web/WebRange.h"
187#include "third_party/WebKit/public/web/WebScriptSource.h"
188#include "third_party/WebKit/public/web/WebSearchableFormData.h"
189#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
190#include "third_party/WebKit/public/web/WebSecurityPolicy.h"
191#include "third_party/WebKit/public/web/WebSerializedScriptValue.h"
192#include "third_party/WebKit/public/web/WebSettings.h"
193#include "third_party/WebKit/public/web/WebStorageQuotaCallbacks.h"
194#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
195#include "third_party/WebKit/public/web/WebUserMediaClient.h"
196#include "third_party/WebKit/public/web/WebView.h"
197#include "third_party/WebKit/public/web/WebWindowFeatures.h"
198#include "third_party/WebKit/public/web/default/WebRenderTheme.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100199#include "ui/base/ui_base_switches_util.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000200#include "ui/gfx/native_widget_types.h"
201#include "ui/gfx/point.h"
202#include "ui/gfx/rect.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000203#include "ui/gfx/rect_conversions.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000204#include "ui/gfx/size_conversions.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000205#include "ui/shell_dialogs/selected_file_info.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000206#include "v8/include/v8.h"
Ben Murdochca12bfa2013-07-23 11:17:05 +0100207#include "webkit/child/weburlresponse_extradata_impl.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100208#include "webkit/renderer/appcache/web_application_cache_host_impl.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100209#include "webkit/renderer/webpreferences_renderer.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000210
211#if defined(OS_ANDROID)
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100212#include <cpu-features.h>
213
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000214#include "content/common/android/device_telephony_info.h"
215#include "content/common/gpu/client/context_provider_command_buffer.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000216#include "content/renderer/android/address_detector.h"
217#include "content/renderer/android/content_detector.h"
218#include "content/renderer/android/email_detector.h"
219#include "content/renderer/android/phone_number_detector.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100220#include "content/renderer/media/android/renderer_media_player_manager.h"
Ben Murdocheb525c52013-07-10 11:40:50 +0100221#include "content/renderer/media/android/stream_texture_factory_android.h"
222#include "content/renderer/media/android/webmediaplayer_android.h"
Ben Murdocheb525c52013-07-10 11:40:50 +0100223#include "content/renderer/media/android/webmediaplayer_proxy_android.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100224#include "skia/ext/platform_canvas.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100225#include "third_party/WebKit/public/platform/WebFloatPoint.h"
226#include "third_party/WebKit/public/platform/WebFloatRect.h"
Ben Murdochca12bfa2013-07-23 11:17:05 +0100227#include "third_party/WebKit/public/web/WebHitTestResult.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000228#include "ui/gfx/rect_f.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100229
230#if defined(GOOGLE_TV)
231#include "content/renderer/media/rtc_video_decoder_bridge_tv.h"
232#include "content/renderer/media/rtc_video_decoder_factory_tv.h"
233#endif
234
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000235#elif defined(OS_WIN)
236// TODO(port): these files are currently Windows only because they concern:
237// * theming
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000238#include "ui/native_theme/native_theme_win.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000239#elif defined(USE_X11)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000240#include "ui/native_theme/native_theme.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000241#elif defined(OS_MACOSX)
242#include "skia/ext/skia_utils_mac.h"
243#endif
244
Ben Murdoch32409262013-08-07 11:04:47 +0100245#if defined(ENABLE_PLUGINS)
Ben Murdochbb1529c2013-08-08 10:24:53 +0100246#include "content/renderer/npapi/webplugin_delegate_proxy.h"
247#include "content/renderer/npapi/webplugin_impl.h"
Ben Murdoch32409262013-08-07 11:04:47 +0100248#include "content/renderer/pepper/pepper_browser_connection.h"
249#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
250#include "content/renderer/pepper/pepper_plugin_registry.h"
251#include "content/renderer/pepper/pepper_webplugin_impl.h"
252#include "content/renderer/pepper/plugin_module.h"
253#endif
254
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000255using WebKit::WebAccessibilityNotification;
256using WebKit::WebAccessibilityObject;
257using WebKit::WebApplicationCacheHost;
258using WebKit::WebApplicationCacheHostClient;
259using WebKit::WebCString;
260using WebKit::WebColor;
261using WebKit::WebColorName;
262using WebKit::WebConsoleMessage;
263using WebKit::WebContextMenuData;
264using WebKit::WebCookieJar;
265using WebKit::WebData;
266using WebKit::WebDataSource;
267using WebKit::WebDocument;
268using WebKit::WebDOMEvent;
269using WebKit::WebDOMMessageEvent;
270using WebKit::WebDragData;
271using WebKit::WebDragOperation;
272using WebKit::WebDragOperationsMask;
273using WebKit::WebEditingAction;
274using WebKit::WebElement;
275using WebKit::WebExternalPopupMenu;
276using WebKit::WebExternalPopupMenuClient;
277using WebKit::WebFileChooserCompletion;
278using WebKit::WebFileSystem;
279using WebKit::WebFileSystemCallbacks;
280using WebKit::WebFindOptions;
281using WebKit::WebFormControlElement;
282using WebKit::WebFormElement;
283using WebKit::WebFrame;
284using WebKit::WebGestureEvent;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000285using WebKit::WebHistoryItem;
286using WebKit::WebHTTPBody;
287using WebKit::WebIconURL;
288using WebKit::WebImage;
289using WebKit::WebInputElement;
290using WebKit::WebInputEvent;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000291using WebKit::WebMediaPlayer;
292using WebKit::WebMediaPlayerAction;
293using WebKit::WebMediaPlayerClient;
294using WebKit::WebMouseEvent;
295using WebKit::WebNavigationPolicy;
296using WebKit::WebNavigationType;
297using WebKit::WebNode;
298using WebKit::WebPageSerializer;
299using WebKit::WebPageSerializerClient;
300using WebKit::WebPeerConnection00Handler;
301using WebKit::WebPeerConnection00HandlerClient;
302using WebKit::WebPeerConnectionHandler;
303using WebKit::WebPeerConnectionHandlerClient;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000304using WebKit::WebPluginAction;
305using WebKit::WebPluginContainer;
306using WebKit::WebPluginDocument;
307using WebKit::WebPluginParams;
308using WebKit::WebPoint;
309using WebKit::WebPopupMenuInfo;
310using WebKit::WebRange;
311using WebKit::WebRect;
312using WebKit::WebReferrerPolicy;
313using WebKit::WebScriptSource;
314using WebKit::WebSearchableFormData;
315using WebKit::WebSecurityOrigin;
316using WebKit::WebSecurityPolicy;
317using WebKit::WebSerializedScriptValue;
318using WebKit::WebSettings;
319using WebKit::WebSharedWorker;
320using WebKit::WebSize;
321using WebKit::WebSocketStreamHandle;
322using WebKit::WebStorageNamespace;
323using WebKit::WebStorageQuotaCallbacks;
324using WebKit::WebStorageQuotaError;
325using WebKit::WebStorageQuotaType;
326using WebKit::WebString;
327using WebKit::WebTextAffinity;
328using WebKit::WebTextDirection;
329using WebKit::WebTouchEvent;
330using WebKit::WebURL;
331using WebKit::WebURLError;
332using WebKit::WebURLRequest;
333using WebKit::WebURLResponse;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000334using WebKit::WebUserGestureIndicator;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000335using WebKit::WebVector;
336using WebKit::WebView;
337using WebKit::WebWidget;
338using WebKit::WebWindowFeatures;
339using appcache::WebApplicationCacheHostImpl;
340using base::Time;
341using base::TimeDelta;
342
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000343using webkit_glue::WebURLResponseExtraDataImpl;
344
345#if defined(OS_ANDROID)
346using WebKit::WebContentDetectionResult;
347using WebKit::WebFloatPoint;
348using WebKit::WebFloatRect;
349using WebKit::WebHitTestResult;
350#endif
351
352namespace content {
353
354//-----------------------------------------------------------------------------
355
356typedef std::map<WebKit::WebView*, RenderViewImpl*> ViewMap;
357static base::LazyInstance<ViewMap> g_view_map = LAZY_INSTANCE_INITIALIZER;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000358typedef std::map<int32, RenderViewImpl*> RoutingIDViewMap;
359static base::LazyInstance<RoutingIDViewMap> g_routing_id_view_map =
360 LAZY_INSTANCE_INITIALIZER;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000361
362// Time, in seconds, we delay before sending content state changes (such as form
363// state and scroll position) to the browser. We delay sending changes to avoid
364// spamming the browser.
365// To avoid having tab/session restore require sending a message to get the
366// current content state during tab closing we use a shorter timeout for the
367// foreground renderer. This means there is a small window of time from which
368// content state is modified and not sent to session restore, but this is
369// better than having to wake up all renderers during shutdown.
370static const int kDelaySecondsForContentStateSyncHidden = 5;
371static const int kDelaySecondsForContentStateSync = 1;
372
373static const size_t kExtraCharsBeforeAndAfterSelection = 100;
374
375// The maximum number of popups that can be spawned from one page.
376static const int kMaximumNumberOfUnacknowledgedPopups = 25;
377
378static const float kScalingIncrement = 0.1f;
379
380static const float kScalingIncrementForGesture = 0.01f;
381
382#if defined(OS_ANDROID)
383// Delay between tapping in content and launching the associated android intent.
384// Used to allow users see what has been recognized as content.
385static const size_t kContentIntentDelayMilliseconds = 700;
386#endif
387
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000388static RenderViewImpl* (*g_create_render_view_impl)(RenderViewImplParams*) =
389 NULL;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000390
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000391static void GetRedirectChain(WebDataSource* ds, std::vector<GURL>* result) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000392 // Replace any occurrences of swappedout:// with about:blank.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100393 const WebURL& blank_url = GURL(kAboutBlankURL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000394 WebVector<WebURL> urls;
395 ds->redirectChain(urls);
396 result->reserve(urls.size());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000397 for (size_t i = 0; i < urls.size(); ++i) {
398 if (urls[i] != GURL(kSwappedOutURL))
399 result->push_back(urls[i]);
400 else
401 result->push_back(blank_url);
402 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000403}
404
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100405// If |data_source| is non-null and has an InternalDocumentStateData associated
406// with it, the AltErrorPageResourceFetcher is reset.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000407static void StopAltErrorPageFetcher(WebDataSource* data_source) {
408 if (data_source) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100409 InternalDocumentStateData* internal_data =
410 InternalDocumentStateData::FromDataSource(data_source);
411 if (internal_data)
412 internal_data->set_alt_error_page_fetcher(NULL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000413 }
414}
415
416static bool IsReload(const ViewMsg_Navigate_Params& params) {
417 return
418 params.navigation_type == ViewMsg_Navigate_Type::RELOAD ||
419 params.navigation_type == ViewMsg_Navigate_Type::RELOAD_IGNORING_CACHE ||
420 params.navigation_type ==
421 ViewMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL;
422}
423
Ben Murdochbbcdd452013-07-25 10:06:34 +0100424// static
425WebReferrerPolicy RenderViewImpl::GetReferrerPolicyFromRequest(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000426 WebFrame* frame,
427 const WebURLRequest& request) {
428 return request.extraData() ?
429 static_cast<RequestExtraData*>(request.extraData())->referrer_policy() :
430 frame->document().referrerPolicy();
431}
432
Ben Murdochbbcdd452013-07-25 10:06:34 +0100433// static
434Referrer RenderViewImpl::GetReferrerFromRequest(
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100435 WebFrame* frame,
436 const WebURLRequest& request) {
437 return Referrer(GURL(request.httpHeaderField(WebString::fromUTF8("Referer"))),
438 GetReferrerPolicyFromRequest(frame, request));
439}
440
Ben Murdochbbcdd452013-07-25 10:06:34 +0100441// static
442WebURLResponseExtraDataImpl* RenderViewImpl::GetExtraDataFromResponse(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000443 const WebURLResponse& response) {
444 return static_cast<WebURLResponseExtraDataImpl*>(
445 response.extraData());
446}
447
448NOINLINE static void CrashIntentionally() {
449 // NOTE(shess): Crash directly rather than using NOTREACHED() so
450 // that the signature is easier to triage in crash reports.
451 volatile int* zero = NULL;
452 *zero = 0;
453}
454
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100455#if defined(ADDRESS_SANITIZER)
456NOINLINE static void MaybeTriggerAsanError(const GURL& url) {
457 // NOTE(rogerm): We intentionally perform an invalid heap access here in
458 // order to trigger an Address Sanitizer (ASAN) error report.
459 static const char kCrashDomain[] = "crash";
460 static const char kHeapOverflow[] = "/heap-overflow";
461 static const char kHeapUnderflow[] = "/heap-underflow";
462 static const char kUseAfterFree[] = "/use-after-free";
463 static const int kArraySize = 5;
464
465 if (!url.DomainIs(kCrashDomain, sizeof(kCrashDomain) - 1))
466 return;
467
468 if (!url.has_path())
469 return;
470
471 scoped_ptr<int[]> array(new int[kArraySize]);
472 std::string crash_type(url.path());
473 int dummy = 0;
474 if (crash_type == kHeapOverflow) {
475 dummy = array[kArraySize];
476 } else if (crash_type == kHeapUnderflow ) {
477 dummy = array[-1];
478 } else if (crash_type == kUseAfterFree) {
479 int* dangling = array.get();
480 array.reset();
481 dummy = dangling[kArraySize / 2];
482 }
483
484 // Make sure the assignments to the dummy value aren't optimized away.
485 base::debug::Alias(&dummy);
486}
487#endif // ADDRESS_SANITIZER
488
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000489static void MaybeHandleDebugURL(const GURL& url) {
490 if (!url.SchemeIs(chrome::kChromeUIScheme))
491 return;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000492 if (url == GURL(kChromeUICrashURL)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000493 CrashIntentionally();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000494 } else if (url == GURL(kChromeUIKillURL)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000495 base::KillProcess(base::GetCurrentProcessHandle(), 1, false);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000496 } else if (url == GURL(kChromeUIHangURL)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000497 for (;;) {
498 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
499 }
500 } else if (url == GURL(kChromeUIShorthangURL)) {
501 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(20));
502 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100503
504#if defined(ADDRESS_SANITIZER)
505 MaybeTriggerAsanError(url);
506#endif // ADDRESS_SANITIZER
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000507}
508
509// Returns false unless this is a top-level navigation.
510static bool IsTopLevelNavigation(WebFrame* frame) {
511 return frame->parent() == NULL;
512}
513
514// Returns false unless this is a top-level navigation that crosses origins.
515static bool IsNonLocalTopLevelNavigation(const GURL& url,
516 WebFrame* frame,
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100517 WebNavigationType type,
518 bool is_form_post) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000519 if (!IsTopLevelNavigation(frame))
520 return false;
521
522 // Navigations initiated within Webkit are not sent out to the external host
523 // in the following cases.
524 // 1. The url scheme is not http/https
525 // 2. The origin of the url and the opener is the same in which case the
526 // opener relationship is maintained.
527 // 3. Reloads/form submits/back forward navigations
528 if (!url.SchemeIs(chrome::kHttpScheme) && !url.SchemeIs(chrome::kHttpsScheme))
529 return false;
530
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000531 if (type != WebKit::WebNavigationTypeReload &&
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100532 type != WebKit::WebNavigationTypeBackForward && !is_form_post) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000533 // The opener relationship between the new window and the parent allows the
534 // new window to script the parent and vice versa. This is not allowed if
535 // the origins of the two domains are different. This can be treated as a
536 // top level navigation and routed back to the host.
537 WebKit::WebFrame* opener = frame->opener();
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100538 if (!opener)
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000539 return true;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000540
541 if (url.GetOrigin() != GURL(opener->document().url()).GetOrigin())
542 return true;
543 }
544 return false;
545}
546
547static void NotifyTimezoneChange(WebKit::WebFrame* frame) {
548 v8::HandleScope handle_scope;
549 v8::Context::Scope context_scope(frame->mainWorldScriptContext());
550 v8::Date::DateTimeConfigurationChangeNotification();
551 WebKit::WebFrame* child = frame->firstChild();
552 for (; child; child = child->nextSibling())
553 NotifyTimezoneChange(child);
554}
555
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000556static WindowOpenDisposition NavigationPolicyToDisposition(
557 WebNavigationPolicy policy) {
558 switch (policy) {
559 case WebKit::WebNavigationPolicyIgnore:
560 return IGNORE_ACTION;
561 case WebKit::WebNavigationPolicyDownload:
562 return SAVE_TO_DISK;
563 case WebKit::WebNavigationPolicyCurrentTab:
564 return CURRENT_TAB;
565 case WebKit::WebNavigationPolicyNewBackgroundTab:
566 return NEW_BACKGROUND_TAB;
567 case WebKit::WebNavigationPolicyNewForegroundTab:
568 return NEW_FOREGROUND_TAB;
569 case WebKit::WebNavigationPolicyNewWindow:
570 return NEW_WINDOW;
571 case WebKit::WebNavigationPolicyNewPopup:
572 return NEW_POPUP;
573 default:
574 NOTREACHED() << "Unexpected WebNavigationPolicy";
575 return IGNORE_ACTION;
576 }
577}
578
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100579// Returns true if the device scale is high enough that losing subpixel
580// antialiasing won't have a noticeable effect on text quality.
581static bool DeviceScaleEnsuresTextQuality(float device_scale_factor) {
582#if defined(OS_ANDROID)
583 // On Android, we never have subpixel antialiasing.
584 return true;
585#else
586 return device_scale_factor > 1.5f;
587#endif
588
589}
590
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000591static bool ShouldUseFixedPositionCompositing(float device_scale_factor) {
592 // Compositing for fixed-position elements is dependent on
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100593 // device_scale_factor if no flag is set. http://crbug.com/172738
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000594 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
595
596 if (command_line.HasSwitch(switches::kDisableCompositingForFixedPosition))
597 return false;
598
599 if (command_line.HasSwitch(switches::kEnableCompositingForFixedPosition))
600 return true;
601
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100602 return DeviceScaleEnsuresTextQuality(device_scale_factor);
603}
604
Ben Murdocheb525c52013-07-10 11:40:50 +0100605static bool ShouldUseAcceleratedCompositingForOverflowScroll(
606 float device_scale_factor) {
607 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
608
609 if (command_line.HasSwitch(switches::kEnableAcceleratedOverflowScroll))
610 return true;
611
612 return DeviceScaleEnsuresTextQuality(device_scale_factor);
613}
614
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100615static bool ShouldUseTransitionCompositing(float device_scale_factor) {
616 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
617
618 if (command_line.HasSwitch(switches::kDisableCompositingForTransition))
619 return false;
620
621 if (command_line.HasSwitch(switches::kEnableCompositingForTransition))
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000622 return true;
623
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100624 // TODO(ajuma): Re-enable this by default for high-DPI once the problem
625 // of excessive layer promotion caused by overlap has been addressed.
626 // http://crbug.com/178119.
627 return false;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100628}
629
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100630static bool ShouldUseAcceleratedFixedRootBackground(float device_scale_factor) {
631 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
632
633 if (command_line.HasSwitch(switches::kDisableAcceleratedFixedRootBackground))
634 return false;
635
636 if (command_line.HasSwitch(switches::kEnableAcceleratedFixedRootBackground))
637 return true;
638
639 return DeviceScaleEnsuresTextQuality(device_scale_factor);
640}
641
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100642static FaviconURL::IconType ToFaviconType(WebKit::WebIconURL::Type type) {
643 switch (type) {
644 case WebKit::WebIconURL::TypeFavicon:
645 return FaviconURL::FAVICON;
646 case WebKit::WebIconURL::TypeTouch:
647 return FaviconURL::TOUCH_ICON;
648 case WebKit::WebIconURL::TypeTouchPrecomposed:
649 return FaviconURL::TOUCH_PRECOMPOSED_ICON;
650 case WebKit::WebIconURL::TypeInvalid:
651 return FaviconURL::INVALID_ICON;
652 }
653 return FaviconURL::INVALID_ICON;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000654}
655
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000656///////////////////////////////////////////////////////////////////////////////
657
658struct RenderViewImpl::PendingFileChooser {
659 PendingFileChooser(const FileChooserParams& p, WebFileChooserCompletion* c)
660 : params(p),
661 completion(c) {
662 }
663 FileChooserParams params;
664 WebFileChooserCompletion* completion; // MAY BE NULL to skip callback.
665};
666
667namespace {
668
669class WebWidgetLockTarget : public MouseLockDispatcher::LockTarget {
670 public:
671 explicit WebWidgetLockTarget(WebKit::WebWidget* webwidget)
672 : webwidget_(webwidget) {}
673
674 virtual void OnLockMouseACK(bool succeeded) OVERRIDE {
675 if (succeeded)
676 webwidget_->didAcquirePointerLock();
677 else
678 webwidget_->didNotAcquirePointerLock();
679 }
680
681 virtual void OnMouseLockLost() OVERRIDE {
682 webwidget_->didLosePointerLock();
683 }
684
685 virtual bool HandleMouseLockedInputEvent(
686 const WebKit::WebMouseEvent &event) OVERRIDE {
687 // The WebWidget handles mouse lock in WebKit's handleInputEvent().
688 return false;
689 }
690
691 private:
692 WebKit::WebWidget* webwidget_;
693};
694
695int64 ExtractPostId(const WebHistoryItem& item) {
696 if (item.isNull())
697 return -1;
698
699 if (item.httpBody().isNull())
700 return -1;
701
702 return item.httpBody().identifier();
703}
704
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100705bool TouchEnabled() {
706// Based on the definition of chrome::kEnableTouchIcon.
707#if defined(OS_ANDROID)
708 return true;
709#else
710 return false;
711#endif
712}
713
Ben Murdocheb525c52013-07-10 11:40:50 +0100714WebDragData DropDataToWebDragData(const DropData& drop_data) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100715 std::vector<WebDragData::Item> item_list;
716
717 // These fields are currently unused when dragging into WebKit.
718 DCHECK(drop_data.download_metadata.empty());
719 DCHECK(drop_data.file_contents.empty());
720 DCHECK(drop_data.file_description_filename.empty());
721
722 if (!drop_data.text.is_null()) {
723 WebDragData::Item item;
724 item.storageType = WebDragData::Item::StorageTypeString;
725 item.stringType = WebString::fromUTF8(ui::Clipboard::kMimeTypeText);
726 item.stringData = drop_data.text.string();
727 item_list.push_back(item);
728 }
729
730 // TODO(dcheng): Do we need to distinguish between null and empty URLs? Is it
731 // meaningful to write an empty URL to the clipboard?
732 if (!drop_data.url.is_empty()) {
733 WebDragData::Item item;
734 item.storageType = WebDragData::Item::StorageTypeString;
735 item.stringType = WebString::fromUTF8(ui::Clipboard::kMimeTypeURIList);
736 item.stringData = WebString::fromUTF8(drop_data.url.spec());
737 item.title = drop_data.url_title;
738 item_list.push_back(item);
739 }
740
741 if (!drop_data.html.is_null()) {
742 WebDragData::Item item;
743 item.storageType = WebDragData::Item::StorageTypeString;
744 item.stringType = WebString::fromUTF8(ui::Clipboard::kMimeTypeHTML);
745 item.stringData = drop_data.html.string();
746 item.baseURL = drop_data.html_base_url;
747 item_list.push_back(item);
748 }
749
Ben Murdocheb525c52013-07-10 11:40:50 +0100750 for (std::vector<DropData::FileInfo>::const_iterator it =
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100751 drop_data.filenames.begin();
752 it != drop_data.filenames.end();
753 ++it) {
754 WebDragData::Item item;
755 item.storageType = WebDragData::Item::StorageTypeFilename;
756 item.filenameData = it->path;
757 item.displayNameData = it->display_name;
758 item_list.push_back(item);
759 }
760
761 for (std::map<base::string16, base::string16>::const_iterator it =
762 drop_data.custom_data.begin();
763 it != drop_data.custom_data.end();
764 ++it) {
765 WebDragData::Item item;
766 item.storageType = WebDragData::Item::StorageTypeString;
767 item.stringType = it->first;
768 item.stringData = it->second;
769 item_list.push_back(item);
770 }
771
772 WebDragData result;
773 result.initialize();
774 result.setItems(item_list);
775 result.setFilesystemId(drop_data.filesystem_id);
776 return result;
777}
778
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000779} // namespace
780
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000781RenderViewImpl::RenderViewImpl(RenderViewImplParams* params)
782 : RenderWidget(WebKit::WebPopupTypeNone,
783 params->screen_info,
784 params->swapped_out),
785 webkit_preferences_(params->webkit_prefs),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000786 send_content_state_immediately_(false),
787 enabled_bindings_(0),
788 send_preferred_size_changes_(false),
789 is_loading_(false),
790 navigation_gesture_(NavigationGestureUnknown),
791 opened_by_user_gesture_(true),
792 opener_suppressed_(false),
793 page_id_(-1),
794 last_page_id_sent_to_browser_(-1),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000795 next_page_id_(params->next_page_id),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000796 history_list_offset_(-1),
797 history_list_length_(0),
798 target_url_status_(TARGET_NONE),
799 selection_text_offset_(0),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000800 selection_range_(ui::Range::InvalidRange()),
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100801#if defined(OS_ANDROID)
802 top_controls_constraints_(cc::BOTH),
803#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000804 cached_is_main_frame_pinned_to_left_(false),
805 cached_is_main_frame_pinned_to_right_(false),
806 cached_has_main_frame_horizontal_scrollbar_(false),
807 cached_has_main_frame_vertical_scrollbar_(false),
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100808 cookie_jar_(this),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000809 notification_provider_(NULL),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000810 geolocation_dispatcher_(NULL),
811 input_tag_speech_dispatcher_(NULL),
812 speech_recognition_dispatcher_(NULL),
813 device_orientation_dispatcher_(NULL),
814 media_stream_dispatcher_(NULL),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000815 browser_plugin_manager_(NULL),
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100816 media_stream_client_(NULL),
817 web_user_media_client_(NULL),
Ben Murdoch558790d2013-07-30 15:19:42 +0100818 midi_dispatcher_(NULL),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000819 devtools_agent_(NULL),
820 accessibility_mode_(AccessibilityModeOff),
821 renderer_accessibility_(NULL),
822 java_bridge_dispatcher_(NULL),
823 mouse_lock_dispatcher_(NULL),
824#if defined(OS_ANDROID)
825 body_background_color_(SK_ColorWHITE),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000826 expected_content_intent_id_(0),
827 media_player_proxy_(NULL),
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100828#endif
829#if defined(OS_WIN)
830 focused_plugin_id_(-1),
831#endif
Ben Murdoch32409262013-08-07 11:04:47 +0100832#if defined(ENABLE_PLUGINS)
833 focused_pepper_plugin_(NULL),
834 pepper_last_mouse_event_target_(NULL),
835#endif
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000836 enumeration_completion_id_(0),
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100837#if defined(OS_ANDROID)
838 load_progress_tracker_(new LoadProgressTracker(this)),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000839#endif
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000840 session_storage_namespace_id_(params->session_storage_namespace_id),
841 decrement_shared_popup_at_destruction_(false),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000842 handling_select_range_(false),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000843 next_snapshot_id_(0),
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100844 allow_partial_swap_(params->allow_partial_swap),
Ben Murdochbb1529c2013-08-08 10:24:53 +0100845 context_menu_source_type_(ui::MENU_SOURCE_MOUSE) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000846}
847
848void RenderViewImpl::Initialize(RenderViewImplParams* params) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100849 RenderFrameImpl* main_frame = RenderFrameImpl::Create(
850 this, params->main_frame_routing_id);
851 main_render_frame_.reset(main_frame);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000852 routing_id_ = params->routing_id;
853 surface_id_ = params->surface_id;
854 if (params->opener_id != MSG_ROUTING_NONE && params->is_renderer_created)
855 opener_id_ = params->opener_id;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000856
857 // Ensure we start with a valid next_page_id_ from the browser.
858 DCHECK_GE(next_page_id_, 0);
859
860#if defined(ENABLE_NOTIFICATIONS)
861 notification_provider_ = new NotificationProvider(this);
862#else
863 notification_provider_ = NULL;
864#endif
865
866 webwidget_ = WebView::create(this);
867 webwidget_mouse_lock_target_.reset(new WebWidgetLockTarget(webwidget_));
868
869 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
870
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100871 if (command_line.HasSwitch(switches::kStatsCollectionController))
872 stats_collection_observer_.reset(new StatsCollectionObserver(this));
873
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000874#if defined(OS_ANDROID)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000875 content::DeviceTelephonyInfo device_info;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000876
877 const std::string region_code =
878 command_line.HasSwitch(switches::kNetworkCountryIso)
879 ? command_line.GetSwitchValueASCII(switches::kNetworkCountryIso)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000880 : device_info.GetNetworkCountryIso();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000881 content_detectors_.push_back(linked_ptr<ContentDetector>(
882 new AddressDetector()));
883 content_detectors_.push_back(linked_ptr<ContentDetector>(
884 new PhoneNumberDetector(region_code)));
885 content_detectors_.push_back(linked_ptr<ContentDetector>(
886 new EmailDetector()));
887#endif
888
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000889 if (params->counter) {
890 shared_popup_counter_ = params->counter;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000891 // Only count this if it isn't swapped out upon creation.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000892 if (!params->swapped_out)
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000893 shared_popup_counter_->data++;
894 decrement_shared_popup_at_destruction_ = true;
895 } else {
896 shared_popup_counter_ = new SharedRenderViewCounter(0);
897 decrement_shared_popup_at_destruction_ = false;
898 }
899
900 RenderThread::Get()->AddRoute(routing_id_, this);
901 // Take a reference on behalf of the RenderThread. This will be balanced
902 // when we receive ViewMsg_ClosePage.
903 AddRef();
904
905 // If this is a popup, we must wait for the CreatingNew_ACK message before
906 // completing initialization. Otherwise, we can finish it now.
907 if (opener_id_ == MSG_ROUTING_NONE) {
908 did_show_ = true;
909 CompleteInit();
910 }
911
912 g_view_map.Get().insert(std::make_pair(webview(), this));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000913 g_routing_id_view_map.Get().insert(std::make_pair(routing_id_, this));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000914 webview()->setDeviceScaleFactor(device_scale_factor_);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000915 webview()->settings()->setAcceleratedCompositingForFixedPositionEnabled(
916 ShouldUseFixedPositionCompositing(device_scale_factor_));
Ben Murdocheb525c52013-07-10 11:40:50 +0100917 webview()->settings()->setAcceleratedCompositingForOverflowScrollEnabled(
918 ShouldUseAcceleratedCompositingForOverflowScroll(device_scale_factor_));
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100919 webview()->settings()->setAcceleratedCompositingForTransitionEnabled(
920 ShouldUseTransitionCompositing(device_scale_factor_));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100921 webview()->settings()->setAcceleratedCompositingForFixedRootBackgroundEnabled(
922 ShouldUseAcceleratedFixedRootBackground(device_scale_factor_));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000923
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100924 webkit_glue::ApplyWebPreferences(webkit_preferences_, webview());
Ben Murdocheb525c52013-07-10 11:40:50 +0100925 webview()->initializeMainFrame(main_render_frame_.get());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000926
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100927 if (switches::IsTouchDragDropEnabled())
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000928 webview()->settings()->setTouchDragDropEnabled(true);
929
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100930 if (switches::IsTouchEditingEnabled())
931 webview()->settings()->setTouchEditingEnabled(true);
932
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000933 if (!params->frame_name.empty())
934 webview()->mainFrame()->setName(params->frame_name);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000935
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000936 OnSetRendererPrefs(params->renderer_prefs);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000937
938#if defined(ENABLE_WEBRTC)
939 if (!media_stream_dispatcher_)
940 media_stream_dispatcher_ = new MediaStreamDispatcher(this);
941#endif
942
943 new MHTMLGenerator(this);
944#if defined(OS_MACOSX)
945 new TextInputClientObserver(this);
946#endif // defined(OS_MACOSX)
947
948#if defined(OS_ANDROID)
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100949 media_player_manager_.reset(new RendererMediaPlayerManager());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000950#endif
951
952 // The next group of objects all implement RenderViewObserver, so are deleted
953 // along with the RenderView automatically.
954 devtools_agent_ = new DevToolsAgent(this);
Ben Murdocha3f7b4e2013-07-24 10:36:34 +0100955 if (RenderWidgetCompositor* rwc = compositor()) {
956 webview()->devToolsAgent()->setLayerTreeId(rwc->GetLayerTreeId());
957 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000958 mouse_lock_dispatcher_ = new RenderViewMouseLockDispatcher(this);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100959 new ImageLoadingHelper(this);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000960
961 // Create renderer_accessibility_ if needed.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000962 OnSetAccessibilityMode(params->accessibility_mode);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000963
964 new IdleUserDetector(this);
965
966 if (command_line.HasSwitch(switches::kDomAutomationController))
967 enabled_bindings_ |= BINDINGS_POLICY_DOM_AUTOMATION;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100968 if (command_line.HasSwitch(switches::kStatsCollectionController))
969 enabled_bindings_ |= BINDINGS_POLICY_STATS_COLLECTION;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000970
971 ProcessViewLayoutFlags(command_line);
972
Ben Murdoch558790d2013-07-30 15:19:42 +0100973#if defined(ENABLE_PLUGINS)
Ben Murdoch32409262013-08-07 11:04:47 +0100974 new PepperBrowserConnection(this);
Ben Murdoch558790d2013-07-30 15:19:42 +0100975#endif
976
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000977 GetContentClient()->renderer()->RenderViewCreated(this);
978
979 // If we have an opener_id but we weren't created by a renderer, then
980 // it's the browser asking us to set our opener to another RenderView.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000981 if (params->opener_id != MSG_ROUTING_NONE && !params->is_renderer_created) {
982 RenderViewImpl* opener_view = FromRoutingID(params->opener_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000983 if (opener_view)
984 webview()->mainFrame()->setOpener(opener_view->webview()->mainFrame());
985 }
986
987 // If we are initially swapped out, navigate to kSwappedOutURL.
988 // This ensures we are in a unique origin that others cannot script.
989 if (is_swapped_out_)
990 NavigateToSwappedOutURL(webview()->mainFrame());
991}
992
993RenderViewImpl::~RenderViewImpl() {
994 history_page_ids_.clear();
995
996 if (decrement_shared_popup_at_destruction_)
997 shared_popup_counter_->data--;
998
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100999 base::debug::TraceLog::GetInstance()->RemoveProcessLabel(routing_id_);
1000
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001001 // If file chooser is still waiting for answer, dispatch empty answer.
1002 while (!file_chooser_completions_.empty()) {
1003 if (file_chooser_completions_.front()->completion) {
1004 file_chooser_completions_.front()->completion->didChooseFile(
1005 WebVector<WebString>());
1006 }
1007 file_chooser_completions_.pop_front();
1008 }
1009
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001010#if defined(OS_ANDROID)
1011 // The date/time picker client is both a scoped_ptr member of this class and
1012 // a RenderViewObserver. Reset it to prevent double deletion.
1013 date_time_picker_client_.reset();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001014#endif
1015
1016#ifndef NDEBUG
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001017 // Make sure we are no longer referenced by the ViewMap or RoutingIDViewMap.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001018 ViewMap* views = g_view_map.Pointer();
1019 for (ViewMap::iterator it = views->begin(); it != views->end(); ++it)
1020 DCHECK_NE(this, it->second) << "Failed to call Close?";
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001021 RoutingIDViewMap* routing_id_views = g_routing_id_view_map.Pointer();
1022 for (RoutingIDViewMap::iterator it = routing_id_views->begin();
1023 it != routing_id_views->end(); ++it)
1024 DCHECK_NE(this, it->second) << "Failed to call Close?";
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001025#endif
1026
1027 FOR_EACH_OBSERVER(RenderViewObserver, observers_, RenderViewGone());
1028 FOR_EACH_OBSERVER(RenderViewObserver, observers_, OnDestruct());
1029}
1030
1031/*static*/
1032RenderViewImpl* RenderViewImpl::FromWebView(WebView* webview) {
1033 ViewMap* views = g_view_map.Pointer();
1034 ViewMap::iterator it = views->find(webview);
1035 return it == views->end() ? NULL : it->second;
1036}
1037
1038/*static*/
1039RenderView* RenderView::FromWebView(WebKit::WebView* webview) {
1040 return RenderViewImpl::FromWebView(webview);
1041}
1042
1043/*static*/
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001044RenderViewImpl* RenderViewImpl::FromRoutingID(int32 routing_id) {
1045 RoutingIDViewMap* views = g_routing_id_view_map.Pointer();
1046 RoutingIDViewMap::iterator it = views->find(routing_id);
1047 return it == views->end() ? NULL : it->second;
1048}
1049
1050/*static*/
1051RenderView* RenderView::FromRoutingID(int routing_id) {
1052 return RenderViewImpl::FromRoutingID(routing_id);
1053}
1054
1055/*static*/
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001056void RenderView::ForEach(RenderViewVisitor* visitor) {
1057 ViewMap* views = g_view_map.Pointer();
1058 for (ViewMap::iterator it = views->begin(); it != views->end(); ++it) {
1059 if (!visitor->Visit(it->second))
1060 return;
1061 }
1062}
1063
1064/*static*/
1065RenderViewImpl* RenderViewImpl::Create(
1066 int32 opener_id,
1067 const RendererPreferences& renderer_prefs,
1068 const WebPreferences& webkit_prefs,
1069 SharedRenderViewCounter* counter,
1070 int32 routing_id,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001071 int32 main_frame_routing_id,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001072 int32 surface_id,
1073 int64 session_storage_namespace_id,
1074 const string16& frame_name,
1075 bool is_renderer_created,
1076 bool swapped_out,
1077 int32 next_page_id,
1078 const WebKit::WebScreenInfo& screen_info,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001079 AccessibilityMode accessibility_mode,
1080 bool allow_partial_swap) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001081 DCHECK(routing_id != MSG_ROUTING_NONE);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001082 RenderViewImplParams params(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001083 opener_id,
1084 renderer_prefs,
1085 webkit_prefs,
1086 counter,
1087 routing_id,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01001088 main_frame_routing_id,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001089 surface_id,
1090 session_storage_namespace_id,
1091 frame_name,
1092 is_renderer_created,
1093 swapped_out,
1094 next_page_id,
1095 screen_info,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001096 accessibility_mode,
1097 allow_partial_swap);
1098 RenderViewImpl* render_view = NULL;
1099 if (g_create_render_view_impl)
1100 render_view = g_create_render_view_impl(&params);
1101 else
1102 render_view = new RenderViewImpl(&params);
1103 render_view->Initialize(&params);
1104 return render_view;
1105}
1106
1107// static
1108void RenderViewImpl::InstallCreateHook(
1109 RenderViewImpl* (*create_render_view_impl)(RenderViewImplParams*)) {
1110 CHECK(!g_create_render_view_impl);
1111 g_create_render_view_impl = create_render_view_impl;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001112}
1113
1114void RenderViewImpl::AddObserver(RenderViewObserver* observer) {
1115 observers_.AddObserver(observer);
1116}
1117
1118void RenderViewImpl::RemoveObserver(RenderViewObserver* observer) {
1119 observer->RenderViewGone();
1120 observers_.RemoveObserver(observer);
1121}
1122
1123WebKit::WebView* RenderViewImpl::webview() const {
1124 return static_cast<WebKit::WebView*>(webwidget());
1125}
1126
Ben Murdoch32409262013-08-07 11:04:47 +01001127#if defined(ENABLE_PLUGINS)
1128void RenderViewImpl::PepperInstanceCreated(PepperPluginInstanceImpl* instance) {
1129 active_pepper_instances_.insert(instance);
1130}
1131
1132void RenderViewImpl::PepperInstanceDeleted(PepperPluginInstanceImpl* instance) {
1133 active_pepper_instances_.erase(instance);
1134
1135 if (pepper_last_mouse_event_target_ == instance)
1136 pepper_last_mouse_event_target_ = NULL;
1137 if (focused_pepper_plugin_ == instance)
1138 PepperFocusChanged(instance, false);
1139}
1140
1141void RenderViewImpl::PepperDidChangeCursor(
1142 PepperPluginInstanceImpl* instance,
1143 const WebKit::WebCursorInfo& cursor) {
1144 // Update the cursor appearance immediately if the requesting plugin is the
1145 // one which receives the last mouse event. Otherwise, the new cursor won't be
1146 // picked up until the plugin gets the next input event. That is bad if, e.g.,
1147 // the plugin would like to set an invisible cursor when there isn't any user
1148 // input for a while.
1149 if (instance == pepper_last_mouse_event_target_)
1150 didChangeCursor(cursor);
1151}
1152
1153void RenderViewImpl::PepperDidReceiveMouseEvent(
1154 PepperPluginInstanceImpl* instance) {
1155 pepper_last_mouse_event_target_ = instance;
1156}
1157
1158void RenderViewImpl::PepperFocusChanged(PepperPluginInstanceImpl* instance,
1159 bool focused) {
1160 if (focused)
1161 focused_pepper_plugin_ = instance;
1162 else if (focused_pepper_plugin_ == instance)
1163 focused_pepper_plugin_ = NULL;
1164
1165 UpdateTextInputType();
1166 UpdateSelectionBounds();
1167}
1168
1169void RenderViewImpl::PepperTextInputTypeChanged(
1170 PepperPluginInstanceImpl* instance) {
1171 if (instance != focused_pepper_plugin_)
1172 return;
1173
1174 UpdateTextInputType();
1175 if (renderer_accessibility_)
1176 renderer_accessibility_->FocusedNodeChanged(WebNode());
1177}
1178
1179void RenderViewImpl::PepperCaretPositionChanged(
1180 PepperPluginInstanceImpl* instance) {
1181 if (instance != focused_pepper_plugin_)
1182 return;
1183 UpdateSelectionBounds();
1184}
1185
1186void RenderViewImpl::PepperCancelComposition(
1187 PepperPluginInstanceImpl* instance) {
1188 if (instance != focused_pepper_plugin_)
1189 return;
1190 Send(new ViewHostMsg_ImeCancelComposition(routing_id()));;
1191#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
1192 UpdateCompositionInfo(true);
1193#endif
1194}
1195
1196void RenderViewImpl::PepperSelectionChanged(
1197 PepperPluginInstanceImpl* instance) {
1198 if (instance != focused_pepper_plugin_)
1199 return;
1200 SyncSelectionIfRequired();
1201}
1202
1203RenderWidgetFullscreenPepper* RenderViewImpl::CreatePepperFullscreenContainer(
1204 PepperPluginInstanceImpl* plugin) {
1205 GURL active_url;
1206 if (webview() && webview()->mainFrame())
1207 active_url = GURL(webview()->mainFrame()->document().url());
1208 RenderWidgetFullscreenPepper* widget = RenderWidgetFullscreenPepper::Create(
1209 routing_id_, plugin, active_url, screen_info_);
1210 widget->show(WebKit::WebNavigationPolicyIgnore);
1211 return widget;
1212}
1213
1214void RenderViewImpl::PepperPluginCreated(RendererPpapiHost* host) {
1215 FOR_EACH_OBSERVER(RenderViewObserver, observers_,
1216 DidCreatePepperPlugin(host));
1217}
1218
1219bool RenderViewImpl::GetPepperCaretBounds(gfx::Rect* rect) {
1220 if (!focused_pepper_plugin_)
1221 return false;
1222 *rect = focused_pepper_plugin_->GetCaretBounds();
1223 return true;
1224}
1225
1226bool RenderViewImpl::IsPepperAcceptingCompositionEvents() const {
1227 if (!focused_pepper_plugin_)
1228 return false;
1229 return focused_pepper_plugin_->IsPluginAcceptingCompositionEvents();
1230}
1231
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001232void RenderViewImpl::PluginCrashed(const base::FilePath& plugin_path,
1233 base::ProcessId plugin_pid) {
1234 Send(new ViewHostMsg_CrashedPlugin(routing_id_, plugin_path, plugin_pid));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001235}
1236
1237void RenderViewImpl::RegisterPluginDelegate(WebPluginDelegateProxy* delegate) {
1238 plugin_delegates_.insert(delegate);
1239 // If the renderer is visible, set initial visibility and focus state.
1240 if (!is_hidden()) {
1241#if defined(OS_MACOSX)
1242 delegate->SetContainerVisibility(true);
1243 if (webview() && webview()->isActive())
1244 delegate->SetWindowFocus(true);
1245#endif
1246 }
1247 // Plugins start assuming the content has focus (so that they work in
1248 // environments where RenderView isn't hosting them), so we always have to
1249 // set the initial state. See webplugin_delegate_impl.h for details.
1250 delegate->SetContentAreaFocus(has_focus());
1251}
1252
1253void RenderViewImpl::UnregisterPluginDelegate(
1254 WebPluginDelegateProxy* delegate) {
1255 plugin_delegates_.erase(delegate);
1256}
1257
1258bool RenderViewImpl::GetPluginInfo(const GURL& url,
1259 const GURL& page_url,
1260 const std::string& mime_type,
Ben Murdochca12bfa2013-07-23 11:17:05 +01001261 WebPluginInfo* plugin_info,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001262 std::string* actual_mime_type) {
1263 bool found = false;
1264 Send(new ViewHostMsg_GetPluginInfo(
1265 routing_id_, url, page_url, mime_type, &found, plugin_info,
1266 actual_mime_type));
1267 return found;
1268}
1269
Ben Murdochbb1529c2013-08-08 10:24:53 +01001270void RenderViewImpl::SimulateImeSetComposition(
1271 const string16& text,
1272 const std::vector<WebKit::WebCompositionUnderline>& underlines,
1273 int selection_start,
1274 int selection_end) {
1275 OnImeSetComposition(text, underlines, selection_start, selection_end);
1276}
1277
1278void RenderViewImpl::SimulateImeConfirmComposition(
1279 const string16& text,
1280 const ui::Range& replacement_range) {
1281 OnImeConfirmComposition(text, replacement_range, false);
1282}
1283
1284#if defined(OS_WIN)
1285void RenderViewImpl::PluginFocusChanged(bool focused, int plugin_id) {
1286 if (focused)
1287 focused_plugin_id_ = plugin_id;
1288 else
1289 focused_plugin_id_ = -1;
1290}
1291#endif
1292
1293#if defined(OS_MACOSX)
1294void RenderViewImpl::PluginFocusChanged(bool focused, int plugin_id) {
1295 Send(new ViewHostMsg_PluginFocusChanged(routing_id(), focused, plugin_id));
1296}
1297
1298void RenderViewImpl::StartPluginIme() {
1299 IPC::Message* msg = new ViewHostMsg_StartPluginIme(routing_id());
1300 // This message can be sent during event-handling, and needs to be delivered
1301 // within that context.
1302 msg->set_unblock(true);
1303 Send(msg);
1304}
1305#endif // defined(OS_MACOSX)
1306
1307#endif // ENABLE_PLUGINS
1308
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001309void RenderViewImpl::TransferActiveWheelFlingAnimation(
1310 const WebKit::WebActiveWheelFlingParameters& params) {
1311 if (webview())
1312 webview()->transferActiveWheelFlingAnimation(params);
1313}
1314
1315bool RenderViewImpl::HasIMETextFocus() {
1316 return GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE;
1317}
1318
1319bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
1320 WebFrame* main_frame = webview() ? webview()->mainFrame() : NULL;
1321 if (main_frame)
1322 GetContentClient()->SetActiveURL(main_frame->document().url());
1323
1324 ObserverListBase<RenderViewObserver>::Iterator it(observers_);
1325 RenderViewObserver* observer;
1326 while ((observer = it.GetNext()) != NULL)
1327 if (observer->OnMessageReceived(message))
1328 return true;
1329
1330 bool handled = true;
1331 bool msg_is_ok = true;
1332 IPC_BEGIN_MESSAGE_MAP_EX(RenderViewImpl, message, msg_is_ok)
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001333 IPC_MESSAGE_HANDLER(InputMsg_Copy, OnCopy)
1334 IPC_MESSAGE_HANDLER(InputMsg_Cut, OnCut)
1335 IPC_MESSAGE_HANDLER(InputMsg_Delete, OnDelete)
1336 IPC_MESSAGE_HANDLER(InputMsg_ExecuteEditCommand, OnExecuteEditCommand)
1337 IPC_MESSAGE_HANDLER(InputMsg_MoveCaret, OnMoveCaret)
1338 IPC_MESSAGE_HANDLER(InputMsg_Paste, OnPaste)
1339 IPC_MESSAGE_HANDLER(InputMsg_PasteAndMatchStyle, OnPasteAndMatchStyle)
1340 IPC_MESSAGE_HANDLER(InputMsg_Redo, OnRedo)
1341 IPC_MESSAGE_HANDLER(InputMsg_Replace, OnReplace)
1342 IPC_MESSAGE_HANDLER(InputMsg_ReplaceMisspelling, OnReplaceMisspelling)
1343 IPC_MESSAGE_HANDLER(InputMsg_ScrollFocusedEditableNodeIntoRect,
1344 OnScrollFocusedEditableNodeIntoRect)
1345 IPC_MESSAGE_HANDLER(InputMsg_SelectAll, OnSelectAll)
1346 IPC_MESSAGE_HANDLER(InputMsg_SelectRange, OnSelectRange)
1347 IPC_MESSAGE_HANDLER(InputMsg_SetEditCommandsForNextKeyEvent,
1348 OnSetEditCommandsForNextKeyEvent)
1349 IPC_MESSAGE_HANDLER(InputMsg_Undo, OnUndo)
1350 IPC_MESSAGE_HANDLER(InputMsg_Unselect, OnUnselect)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001351 IPC_MESSAGE_HANDLER(ViewMsg_Navigate, OnNavigate)
1352 IPC_MESSAGE_HANDLER(ViewMsg_Stop, OnStop)
1353 IPC_MESSAGE_HANDLER(ViewMsg_ReloadFrame, OnReloadFrame)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001354 IPC_MESSAGE_HANDLER(ViewMsg_SetName, OnSetName)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001355 IPC_MESSAGE_HANDLER(ViewMsg_SetEditableSelectionOffsets,
1356 OnSetEditableSelectionOffsets)
1357 IPC_MESSAGE_HANDLER(ViewMsg_SetCompositionFromExistingText,
1358 OnSetCompositionFromExistingText)
1359 IPC_MESSAGE_HANDLER(ViewMsg_ExtendSelectionAndDelete,
1360 OnExtendSelectionAndDelete)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001361 IPC_MESSAGE_HANDLER(ViewMsg_CopyImageAt, OnCopyImageAt)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001362 IPC_MESSAGE_HANDLER(ViewMsg_Find, OnFind)
1363 IPC_MESSAGE_HANDLER(ViewMsg_StopFinding, OnStopFinding)
1364 IPC_MESSAGE_HANDLER(ViewMsg_Zoom, OnZoom)
1365 IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevel, OnSetZoomLevel)
1366 IPC_MESSAGE_HANDLER(ViewMsg_ZoomFactor, OnZoomFactor)
1367 IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevelForLoadingURL,
1368 OnSetZoomLevelForLoadingURL)
1369 IPC_MESSAGE_HANDLER(ViewMsg_SetPageEncoding, OnSetPageEncoding)
1370 IPC_MESSAGE_HANDLER(ViewMsg_ResetPageEncodingToDefault,
1371 OnResetPageEncodingToDefault)
1372 IPC_MESSAGE_HANDLER(ViewMsg_ScriptEvalRequest, OnScriptEvalRequest)
1373 IPC_MESSAGE_HANDLER(ViewMsg_PostMessageEvent, OnPostMessageEvent)
1374 IPC_MESSAGE_HANDLER(ViewMsg_CSSInsertRequest, OnCSSInsertRequest)
1375 IPC_MESSAGE_HANDLER(DragMsg_TargetDragEnter, OnDragTargetDragEnter)
1376 IPC_MESSAGE_HANDLER(DragMsg_TargetDragOver, OnDragTargetDragOver)
1377 IPC_MESSAGE_HANDLER(DragMsg_TargetDragLeave, OnDragTargetDragLeave)
1378 IPC_MESSAGE_HANDLER(DragMsg_TargetDrop, OnDragTargetDrop)
1379 IPC_MESSAGE_HANDLER(DragMsg_SourceEndedOrMoved, OnDragSourceEndedOrMoved)
1380 IPC_MESSAGE_HANDLER(DragMsg_SourceSystemDragEnded,
1381 OnDragSourceSystemDragEnded)
1382 IPC_MESSAGE_HANDLER(ViewMsg_AllowBindings, OnAllowBindings)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001383 IPC_MESSAGE_HANDLER(ViewMsg_SetInitialFocus, OnSetInitialFocus)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001384 IPC_MESSAGE_HANDLER(ViewMsg_UpdateTargetURL_ACK, OnUpdateTargetURLAck)
1385 IPC_MESSAGE_HANDLER(ViewMsg_UpdateWebPreferences, OnUpdateWebPreferences)
1386 IPC_MESSAGE_HANDLER(ViewMsg_TimezoneChange, OnUpdateTimezone)
1387 IPC_MESSAGE_HANDLER(ViewMsg_SetAltErrorPageURL, OnSetAltErrorPageURL)
1388 IPC_MESSAGE_HANDLER(ViewMsg_EnumerateDirectoryResponse,
1389 OnEnumerateDirectoryResponse)
1390 IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse)
1391 IPC_MESSAGE_HANDLER(ViewMsg_ShouldClose, OnShouldClose)
1392 IPC_MESSAGE_HANDLER(ViewMsg_SwapOut, OnSwapOut)
1393 IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage)
1394 IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged)
1395 IPC_MESSAGE_HANDLER(ViewMsg_DisassociateFromPopupCount,
1396 OnDisassociateFromPopupCount)
1397 IPC_MESSAGE_HANDLER(ViewMsg_MoveOrResizeStarted, OnMoveOrResizeStarted)
1398 IPC_MESSAGE_HANDLER(ViewMsg_ClearFocusedNode, OnClearFocusedNode)
1399 IPC_MESSAGE_HANDLER(ViewMsg_SetBackground, OnSetBackground)
1400 IPC_MESSAGE_HANDLER(ViewMsg_EnablePreferredSizeChangedMode,
1401 OnEnablePreferredSizeChangedMode)
1402 IPC_MESSAGE_HANDLER(ViewMsg_EnableAutoResize, OnEnableAutoResize)
1403 IPC_MESSAGE_HANDLER(ViewMsg_DisableAutoResize, OnDisableAutoResize)
1404 IPC_MESSAGE_HANDLER(ViewMsg_DisableScrollbarsForSmallWindows,
1405 OnDisableScrollbarsForSmallWindows)
1406 IPC_MESSAGE_HANDLER(ViewMsg_SetRendererPrefs, OnSetRendererPrefs)
1407 IPC_MESSAGE_HANDLER(ViewMsg_MediaPlayerActionAt, OnMediaPlayerActionAt)
1408 IPC_MESSAGE_HANDLER(ViewMsg_OrientationChangeEvent,
1409 OnOrientationChangeEvent)
1410 IPC_MESSAGE_HANDLER(ViewMsg_PluginActionAt, OnPluginActionAt)
1411 IPC_MESSAGE_HANDLER(ViewMsg_SetActive, OnSetActive)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001412 IPC_MESSAGE_HANDLER(ViewMsg_CustomContextMenuAction,
1413 OnCustomContextMenuAction)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001414 IPC_MESSAGE_HANDLER(ViewMsg_GetAllSavableResourceLinksForCurrentPage,
1415 OnGetAllSavableResourceLinksForCurrentPage)
1416 IPC_MESSAGE_HANDLER(
1417 ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks,
1418 OnGetSerializedHtmlDataForCurrentPageWithLocalLinks)
1419 IPC_MESSAGE_HANDLER(ViewMsg_ContextMenuClosed, OnContextMenuClosed)
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001420 IPC_MESSAGE_HANDLER(ViewMsg_ShowContextMenu, OnShowContextMenu)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001421 // TODO(viettrungluu): Move to a separate message filter.
1422 IPC_MESSAGE_HANDLER(ViewMsg_SetHistoryLengthAndPrune,
1423 OnSetHistoryLengthAndPrune)
1424 IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode, OnEnableViewSourceMode)
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01001425#if defined(OS_ANDROID)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001426 IPC_MESSAGE_HANDLER(JavaBridgeMsg_Init, OnJavaBridgeInit)
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001427#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001428 IPC_MESSAGE_HANDLER(ViewMsg_SetAccessibilityMode, OnSetAccessibilityMode)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001429 IPC_MESSAGE_HANDLER(ViewMsg_DisownOpener, OnDisownOpener)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001430#if defined(OS_ANDROID)
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001431 IPC_MESSAGE_HANDLER(InputMsg_ActivateNearestFindResult,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001432 OnActivateNearestFindResult)
1433 IPC_MESSAGE_HANDLER(ViewMsg_FindMatchRects, OnFindMatchRects)
1434 IPC_MESSAGE_HANDLER(ViewMsg_SelectPopupMenuItems, OnSelectPopupMenuItems)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001435 IPC_MESSAGE_HANDLER(ViewMsg_UndoScrollFocusedEditableNodeIntoView,
1436 OnUndoScrollFocusedEditableNodeIntoRect)
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001437 IPC_MESSAGE_HANDLER(ViewMsg_UpdateTopControlsState,
1438 OnUpdateTopControlsState)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001439#elif defined(OS_MACOSX)
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001440 IPC_MESSAGE_HANDLER(InputMsg_CopyToFindPboard, OnCopyToFindPboard)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001441 IPC_MESSAGE_HANDLER(ViewMsg_PluginImeCompositionCompleted,
1442 OnPluginImeCompositionCompleted)
1443 IPC_MESSAGE_HANDLER(ViewMsg_SelectPopupMenuItem, OnSelectPopupMenuItem)
1444 IPC_MESSAGE_HANDLER(ViewMsg_SetInLiveResize, OnSetInLiveResize)
1445 IPC_MESSAGE_HANDLER(ViewMsg_SetWindowVisibility, OnSetWindowVisibility)
1446 IPC_MESSAGE_HANDLER(ViewMsg_WindowFrameChanged, OnWindowFrameChanged)
1447#endif
1448 IPC_MESSAGE_HANDLER(ViewMsg_ReleaseDisambiguationPopupDIB,
1449 OnReleaseDisambiguationPopupDIB)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001450 IPC_MESSAGE_HANDLER(ViewMsg_WindowSnapshotCompleted,
1451 OnWindowSnapshotCompleted)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001452
1453 // Have the super handle all other messages.
1454 IPC_MESSAGE_UNHANDLED(handled = RenderWidget::OnMessageReceived(message))
1455 IPC_END_MESSAGE_MAP()
1456
1457 if (!msg_is_ok) {
1458 // The message had a handler, but its deserialization failed.
1459 // Kill the renderer to avoid potential spoofing attacks.
1460 CHECK(false) << "Unable to deserialize message in RenderViewImpl.";
1461 }
1462
1463 return handled;
1464}
1465
1466void RenderViewImpl::OnNavigate(const ViewMsg_Navigate_Params& params) {
1467 MaybeHandleDebugURL(params.url);
1468 if (!webview())
1469 return;
1470
1471 FOR_EACH_OBSERVER(RenderViewObserver, observers_, Navigate(params.url));
1472
1473 bool is_reload = IsReload(params);
1474
1475 // If this is a stale back/forward (due to a recent navigation the browser
1476 // didn't know about), ignore it.
1477 if (IsBackForwardToStaleEntry(params, is_reload))
1478 return;
1479
1480 // Swap this renderer back in if necessary.
1481 if (is_swapped_out_) {
1482 // We marked the view as hidden when swapping the view out, so be sure to
1483 // reset the visibility state before navigating to the new URL.
1484 webview()->setVisibilityState(visibilityState(), false);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001485
1486 // If this is an attempt to reload while we are swapped out, we should not
1487 // reload swappedout://, but the previous page, which is stored in
1488 // params.state. Setting is_reload to false will treat this like a back
1489 // navigation to accomplish that.
1490 is_reload = false;
1491
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01001492 // We refresh timezone when a view is swapped in since timezone
1493 // can get out of sync when the system timezone is updated while
1494 // the view is swapped out.
1495 NotifyTimezoneChange(webview()->mainFrame());
1496
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001497 SetSwappedOut(false);
1498 }
1499
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001500 if (params.should_clear_history_list) {
1501 CHECK_EQ(params.pending_history_list_offset, -1);
1502 CHECK_EQ(params.current_history_list_offset, -1);
1503 CHECK_EQ(params.current_history_list_length, 0);
1504 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001505 history_list_offset_ = params.current_history_list_offset;
1506 history_list_length_ = params.current_history_list_length;
1507 if (history_list_length_ >= 0)
1508 history_page_ids_.resize(history_list_length_, -1);
1509 if (params.pending_history_list_offset >= 0 &&
1510 params.pending_history_list_offset < history_list_length_)
1511 history_page_ids_[params.pending_history_list_offset] = params.page_id;
1512
1513 GetContentClient()->SetActiveURL(params.url);
1514
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001515 WebFrame* frame = webview()->mainFrame();
1516 if (!params.frame_to_navigate.empty()) {
1517 frame = webview()->findFrameByName(
1518 WebString::fromUTF8(params.frame_to_navigate));
1519 CHECK(frame) << "Invalid frame name passed: " << params.frame_to_navigate;
1520 }
1521
1522 if (is_reload && frame->currentHistoryItem().isNull()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001523 // We cannot reload if we do not have any history state. This happens, for
1524 // example, when recovering from a crash. Our workaround here is a bit of
1525 // a hack since it means that reload after a crashed tab does not cause an
1526 // end-to-end cache validation.
1527 is_reload = false;
1528 }
1529
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001530 pending_navigation_params_.reset(new ViewMsg_Navigate_Params(params));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001531
1532 // If we are reloading, then WebKit will use the history state of the current
1533 // page, so we should just ignore any given history state. Otherwise, if we
1534 // have history state, then we need to navigate to it, which corresponds to a
1535 // back/forward navigation event.
1536 if (is_reload) {
1537 bool reload_original_url =
1538 (params.navigation_type ==
1539 ViewMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL);
1540 bool ignore_cache = (params.navigation_type ==
1541 ViewMsg_Navigate_Type::RELOAD_IGNORING_CACHE);
1542
1543 if (reload_original_url)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001544 frame->reloadWithOverrideURL(params.url, true);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001545 else
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001546 frame->reload(ignore_cache);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001547 } else if (params.page_state.IsValid()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001548 // We must know the page ID of the page we are navigating back to.
1549 DCHECK_NE(params.page_id, -1);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001550 WebHistoryItem item = PageStateToHistoryItem(params.page_state);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001551 if (!item.isNull()) {
1552 // Ensure we didn't save the swapped out URL in UpdateState, since the
1553 // browser should never be telling us to navigate to swappedout://.
1554 CHECK(item.urlString() != WebString::fromUTF8(kSwappedOutURL));
1555 frame->loadHistoryItem(item);
1556 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001557 } else if (!params.base_url_for_data_url.is_empty()) {
1558 // A loadData request with a specified base URL.
1559 std::string mime_type, charset, data;
1560 if (net::DataURL::Parse(params.url, &mime_type, &charset, &data)) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001561 frame->loadData(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001562 WebData(data.c_str(), data.length()),
1563 WebString::fromUTF8(mime_type),
1564 WebString::fromUTF8(charset),
1565 params.base_url_for_data_url,
1566 params.history_url_for_data_url,
1567 false);
1568 } else {
1569 CHECK(false) <<
1570 "Invalid URL passed: " << params.url.possibly_invalid_spec();
1571 }
1572 } else {
1573 // Navigate to the given URL.
1574 WebURLRequest request(params.url);
1575
1576 // A session history navigation should have been accompanied by state.
1577 CHECK_EQ(params.page_id, -1);
1578
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001579 if (frame->isViewSourceModeEnabled())
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001580 request.setCachePolicy(WebURLRequest::ReturnCacheDataElseLoad);
1581
1582 if (params.referrer.url.is_valid()) {
1583 WebString referrer = WebSecurityPolicy::generateReferrerHeader(
1584 params.referrer.policy,
1585 params.url,
1586 WebString::fromUTF8(params.referrer.url.spec()));
1587 if (!referrer.isEmpty())
1588 request.setHTTPHeaderField(WebString::fromUTF8("Referer"), referrer);
1589 }
1590
1591 if (!params.extra_headers.empty()) {
1592 for (net::HttpUtil::HeadersIterator i(params.extra_headers.begin(),
1593 params.extra_headers.end(), "\n");
1594 i.GetNext(); ) {
1595 request.addHTTPHeaderField(WebString::fromUTF8(i.name()),
1596 WebString::fromUTF8(i.values()));
1597 }
1598 }
1599
1600 if (params.is_post) {
1601 request.setHTTPMethod(WebString::fromUTF8("POST"));
1602
1603 // Set post data.
1604 WebHTTPBody http_body;
1605 http_body.initialize();
1606 http_body.appendData(WebData(
1607 reinterpret_cast<const char*>(
1608 &params.browser_initiated_post_data.front()),
1609 params.browser_initiated_post_data.size()));
1610 request.setHTTPBody(http_body);
1611 }
1612
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001613 frame->loadRequest(request);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001614
1615 // If this is a cross-process navigation, the browser process will send
1616 // along the proper navigation start value.
1617 if (!params.browser_navigation_start.is_null() &&
1618 frame->provisionalDataSource()) {
1619 // browser_navigation_start is likely before this process existed, so we
1620 // can't use InterProcessTimeTicksConverter. Instead, the best we can do
1621 // is just ensure we don't report a bogus value in the future.
1622 base::TimeTicks navigation_start = std::min(
1623 base::TimeTicks::Now(), params.browser_navigation_start);
1624 double navigation_start_seconds =
1625 (navigation_start - base::TimeTicks()).InSecondsF();
1626 frame->provisionalDataSource()->setNavigationStartTime(
1627 navigation_start_seconds);
1628 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001629 }
1630
1631 // In case LoadRequest failed before DidCreateDataSource was called.
1632 pending_navigation_params_.reset();
1633}
1634
1635bool RenderViewImpl::IsBackForwardToStaleEntry(
1636 const ViewMsg_Navigate_Params& params,
1637 bool is_reload) {
1638 // Make sure this isn't a back/forward to an entry we have already cropped
1639 // or replaced from our history, before the browser knew about it. If so,
1640 // a new navigation has committed in the mean time, and we can ignore this.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001641 bool is_back_forward = !is_reload && params.page_state.IsValid();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001642
1643 // Note: if the history_list_length_ is 0 for a back/forward, we must be
1644 // restoring from a previous session. We'll update our state in OnNavigate.
1645 if (!is_back_forward || history_list_length_ <= 0)
1646 return false;
1647
1648 DCHECK_EQ(static_cast<int>(history_page_ids_.size()), history_list_length_);
1649
1650 // Check for whether the forward history has been cropped due to a recent
1651 // navigation the browser didn't know about.
1652 if (params.pending_history_list_offset >= history_list_length_)
1653 return true;
1654
1655 // Check for whether this entry has been replaced with a new one.
1656 int expected_page_id =
1657 history_page_ids_[params.pending_history_list_offset];
1658 if (expected_page_id > 0 && params.page_id != expected_page_id) {
1659 if (params.page_id < expected_page_id)
1660 return true;
1661
1662 // Otherwise we've removed an earlier entry and should have shifted all
1663 // entries left. For now, it's ok to lazily update the list.
1664 // TODO(creis): Notify all live renderers when we remove entries from
1665 // the front of the list, so that we don't hit this case.
1666 history_page_ids_[params.pending_history_list_offset] = params.page_id;
1667 }
1668
1669 return false;
1670}
1671
1672// Stop loading the current page
1673void RenderViewImpl::OnStop() {
1674 if (webview()) {
1675 WebFrame* main_frame = webview()->mainFrame();
1676 // Stop the alt error page fetcher. If we let it continue it may complete
1677 // and cause RenderViewHostManager to swap to this RenderView, even though
1678 // it may no longer be active.
1679 StopAltErrorPageFetcher(main_frame->provisionalDataSource());
1680 StopAltErrorPageFetcher(main_frame->dataSource());
1681 main_frame->stopLoading();
1682 }
1683}
1684
1685// Reload current focused frame.
1686// E.g. called by right-clicking on the frame and picking "reload this frame".
1687void RenderViewImpl::OnReloadFrame() {
1688 if (webview() && webview()->focusedFrame()) {
1689 // We always obey the cache (ignore_cache=false) here.
1690 // TODO(evanm): perhaps we could allow shift-clicking the menu item to do
1691 // a cache-ignoring reload of the frame.
1692 webview()->focusedFrame()->reload(false);
1693 }
1694}
1695
1696void RenderViewImpl::OnCopyImageAt(int x, int y) {
1697 webview()->copyImageAt(WebPoint(x, y));
1698}
1699
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001700void RenderViewImpl::OnUpdateTargetURLAck() {
1701 // Check if there is a targeturl waiting to be sent.
1702 if (target_url_status_ == TARGET_PENDING) {
1703 Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_,
1704 pending_target_url_));
1705 }
1706
1707 target_url_status_ = TARGET_NONE;
1708}
1709
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001710void RenderViewImpl::OnCopy() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001711 if (!webview())
1712 return;
1713
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001714 base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
1715 WebNode current_node = context_menu_node_.isNull() ?
1716 GetFocusedNode() : context_menu_node_;
1717 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Copy"),
1718 current_node);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001719}
1720
1721void RenderViewImpl::OnCut() {
1722 if (!webview())
1723 return;
1724
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001725 base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001726 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Cut"),
1727 GetFocusedNode());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001728}
1729
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001730void RenderViewImpl::OnDelete() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001731 if (!webview())
1732 return;
1733
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001734 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Delete"),
1735 GetFocusedNode());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001736}
1737
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001738void RenderViewImpl::OnExecuteEditCommand(const std::string& name,
1739 const std::string& value) {
1740 if (!webview() || !webview()->focusedFrame())
1741 return;
1742
1743 webview()->focusedFrame()->executeCommand(
1744 WebString::fromUTF8(name), WebString::fromUTF8(value));
1745}
1746
1747void RenderViewImpl::OnMoveCaret(const gfx::Point& point) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001748 if (!webview())
1749 return;
1750
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001751 Send(new ViewHostMsg_MoveCaret_ACK(routing_id_));
1752
1753 webview()->focusedFrame()->moveCaretSelectionTowardsWindowPoint(point);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001754}
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001755
1756void RenderViewImpl::OnPaste() {
1757 if (!webview())
1758 return;
1759
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001760 base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001761 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Paste"),
1762 GetFocusedNode());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001763}
1764
1765void RenderViewImpl::OnPasteAndMatchStyle() {
1766 if (!webview())
1767 return;
1768
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001769 base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001770 webview()->focusedFrame()->executeCommand(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001771 WebString::fromUTF8("PasteAndMatchStyle"), GetFocusedNode());
1772}
1773
1774void RenderViewImpl::OnRedo() {
1775 if (!webview())
1776 return;
1777
1778 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Redo"),
1779 GetFocusedNode());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001780}
1781
1782void RenderViewImpl::OnReplace(const string16& text) {
1783 if (!webview())
1784 return;
1785
1786 WebFrame* frame = webview()->focusedFrame();
1787 if (!frame->hasSelection())
1788 frame->selectWordAroundCaret();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001789
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001790 frame->replaceSelection(text);
1791}
1792
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001793void RenderViewImpl::OnReplaceMisspelling(const string16& text) {
1794 if (!webview())
1795 return;
1796
1797 WebFrame* frame = webview()->focusedFrame();
1798 if (!frame->hasSelection())
1799 return;
1800
1801 frame->replaceMisspelledRange(text);
1802}
1803
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001804void RenderViewImpl::OnScrollFocusedEditableNodeIntoRect(
1805 const gfx::Rect& rect) {
1806 WebKit::WebNode node = GetFocusedNode();
1807 if (!node.isNull()) {
1808 if (IsEditableNode(node)) {
1809 webview()->saveScrollAndScaleState();
1810 webview()->scrollFocusedNodeIntoRect(rect);
1811 }
1812 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001813}
1814
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001815void RenderViewImpl::OnSelectAll() {
1816 if (!webview())
1817 return;
1818
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001819 base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001820 webview()->focusedFrame()->executeCommand(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001821 WebString::fromUTF8("SelectAll"), GetFocusedNode());
1822}
1823
1824void RenderViewImpl::OnSelectRange(const gfx::Point& start,
1825 const gfx::Point& end) {
1826 if (!webview())
1827 return;
1828
1829 Send(new ViewHostMsg_SelectRange_ACK(routing_id_));
1830
1831 base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
1832 webview()->focusedFrame()->selectRange(start, end);
1833}
1834
1835void RenderViewImpl::OnSetEditCommandsForNextKeyEvent(
1836 const EditCommands& edit_commands) {
1837 edit_commands_ = edit_commands;
1838}
1839
1840void RenderViewImpl::OnUndo() {
1841 if (!webview())
1842 return;
1843
1844 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Undo"),
1845 GetFocusedNode());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001846}
1847
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001848void RenderViewImpl::OnUnselect() {
1849 if (!webview())
1850 return;
1851
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001852 base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001853 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Unselect"),
1854 GetFocusedNode());
1855}
1856
1857#if defined(OS_MACOSX)
1858void RenderViewImpl::OnCopyToFindPboard() {
1859 if (!webview())
1860 return;
1861
1862 // Since the find pasteboard supports only plain text, this can be simpler
1863 // than the |OnCopy()| case.
1864 WebFrame* frame = webview()->focusedFrame();
1865 if (frame->hasSelection()) {
1866 string16 selection = frame->selectionAsText();
1867 RenderThread::Get()->Send(
1868 new ClipboardHostMsg_FindPboardWriteStringAsync(selection));
1869 }
1870}
1871#endif
1872
1873void RenderViewImpl::OnSetName(const std::string& name) {
1874 if (!webview())
1875 return;
1876
1877 webview()->mainFrame()->setName(WebString::fromUTF8(name));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001878}
1879
1880void RenderViewImpl::OnSetEditableSelectionOffsets(int start, int end) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001881 base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
Ben Murdoch2385ea32013-08-06 11:01:04 +01001882 if (!ShouldHandleImeEvent())
1883 return;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001884 ImeEventGuard guard(this);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001885 webview()->setEditableSelectionOffsets(start, end);
1886}
1887
1888void RenderViewImpl::OnSetCompositionFromExistingText(
1889 int start, int end,
1890 const std::vector<WebKit::WebCompositionUnderline>& underlines) {
Ben Murdoch2385ea32013-08-06 11:01:04 +01001891 if (!ShouldHandleImeEvent())
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001892 return;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001893 ImeEventGuard guard(this);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001894 webview()->setCompositionFromExistingText(start, end, underlines);
1895}
1896
1897void RenderViewImpl::OnExtendSelectionAndDelete(int before, int after) {
Ben Murdoch2385ea32013-08-06 11:01:04 +01001898 if (!ShouldHandleImeEvent())
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001899 return;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001900 ImeEventGuard guard(this);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001901 webview()->extendSelectionAndDelete(before, after);
1902}
1903
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001904void RenderViewImpl::OnSetHistoryLengthAndPrune(int history_length,
1905 int32 minimum_page_id) {
1906 DCHECK_GE(history_length, 0);
1907 DCHECK(history_list_offset_ == history_list_length_ - 1);
1908 DCHECK_GE(minimum_page_id, -1);
1909
1910 // Generate the new list.
1911 std::vector<int32> new_history_page_ids(history_length, -1);
1912 for (size_t i = 0; i < history_page_ids_.size(); ++i) {
1913 if (minimum_page_id >= 0 && history_page_ids_[i] < minimum_page_id)
1914 continue;
1915 new_history_page_ids.push_back(history_page_ids_[i]);
1916 }
1917 new_history_page_ids.swap(history_page_ids_);
1918
1919 // Update indexes.
1920 history_list_length_ = history_page_ids_.size();
1921 history_list_offset_ = history_list_length_ - 1;
1922}
1923
1924
1925void RenderViewImpl::OnSetInitialFocus(bool reverse) {
1926 if (!webview())
1927 return;
1928 webview()->setInitialFocus(reverse);
1929}
1930
1931#if defined(OS_MACOSX)
1932void RenderViewImpl::OnSetInLiveResize(bool in_live_resize) {
1933 if (!webview())
1934 return;
1935 if (in_live_resize)
1936 webview()->willStartLiveResize();
1937 else
1938 webview()->willEndLiveResize();
1939}
1940#endif
1941
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001942#if defined(OS_ANDROID)
1943void RenderViewImpl::OnUndoScrollFocusedEditableNodeIntoRect() {
1944 const WebNode node = GetFocusedNode();
1945 if (!node.isNull() && IsEditableNode(node))
1946 webview()->restoreScrollAndScaleState();
1947}
1948#endif
1949
1950///////////////////////////////////////////////////////////////////////////////
1951
1952// Tell the embedding application that the URL of the active page has changed
1953void RenderViewImpl::UpdateURL(WebFrame* frame) {
1954 WebDataSource* ds = frame->dataSource();
1955 DCHECK(ds);
1956
1957 const WebURLRequest& request = ds->request();
1958 const WebURLRequest& original_request = ds->originalRequest();
1959 const WebURLResponse& response = ds->response();
1960
1961 DocumentState* document_state = DocumentState::FromDataSource(ds);
1962 NavigationState* navigation_state = document_state->navigation_state();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001963 InternalDocumentStateData* internal_data =
1964 InternalDocumentStateData::FromDocumentState(document_state);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001965
1966 ViewHostMsg_FrameNavigate_Params params;
1967 params.http_status_code = response.httpStatusCode();
1968 params.is_post = false;
1969 params.post_id = -1;
1970 params.page_id = page_id_;
1971 params.frame_id = frame->identifier();
1972 params.socket_address.set_host(response.remoteIPAddress().utf8());
1973 params.socket_address.set_port(response.remotePort());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001974 WebURLResponseExtraDataImpl* extra_data = GetExtraDataFromResponse(response);
1975 if (extra_data) {
1976 params.was_fetched_via_proxy = extra_data->was_fetched_via_proxy();
1977 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001978 params.was_within_same_page = navigation_state->was_within_same_page();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001979 params.security_info = response.securityInfo();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001980
1981 // Set the URL to be displayed in the browser UI to the user.
1982 params.url = GetLoadingUrl(frame);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001983 DCHECK(!is_swapped_out_ || params.url == GURL(kSwappedOutURL));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001984
1985 if (frame->document().baseURL() != params.url)
1986 params.base_url = frame->document().baseURL();
1987
1988 GetRedirectChain(ds, &params.redirects);
1989 params.should_update_history = !ds->hasUnreachableURL() &&
1990 !response.isMultipartPayload() && (response.httpStatusCode() != 404);
1991
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001992 params.searchable_form_url = internal_data->searchable_form_url();
1993 params.searchable_form_encoding = internal_data->searchable_form_encoding();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001994
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001995 const PasswordForm* password_form_data = document_state->password_form_data();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001996 if (password_form_data)
1997 params.password_form = *password_form_data;
1998
1999 params.gesture = navigation_gesture_;
2000 navigation_gesture_ = NavigationGestureUnknown;
2001
2002 // Make navigation state a part of the FrameNavigate message so that commited
2003 // entry had it at all times.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002004 WebHistoryItem item = frame->currentHistoryItem();
2005 if (item.isNull()) {
2006 item.initialize();
2007 item.setURLString(request.url().spec().utf16());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002008 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002009 params.page_state = HistoryItemToPageState(item);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002010
2011 if (!frame->parent()) {
2012 // Top-level navigation.
2013
2014 // Reset the zoom limits in case a plugin had changed them previously. This
2015 // will also call us back which will cause us to send a message to
2016 // update WebContentsImpl.
Ben Murdoch58e6fbe2013-07-26 10:20:38 +01002017 webview()->zoomLimitsChanged(ZoomFactorToZoomLevel(kMinimumZoomFactor),
2018 ZoomFactorToZoomLevel(kMaximumZoomFactor));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002019
2020 // Set zoom level, but don't do it for full-page plugin since they don't use
2021 // the same zoom settings.
2022 HostZoomLevels::iterator host_zoom =
2023 host_zoom_levels_.find(GURL(request.url()));
2024 if (webview()->mainFrame()->document().isPluginDocument()) {
2025 // Reset the zoom levels for plugins.
2026 webview()->setZoomLevel(false, 0);
2027 } else {
2028 if (host_zoom != host_zoom_levels_.end())
2029 webview()->setZoomLevel(false, host_zoom->second);
2030 }
2031
2032 if (host_zoom != host_zoom_levels_.end()) {
2033 // This zoom level was merely recorded transiently for this load. We can
2034 // erase it now. If at some point we reload this page, the browser will
2035 // send us a new, up-to-date zoom level.
2036 host_zoom_levels_.erase(host_zoom);
2037 }
2038
2039 // Update contents MIME type for main frame.
2040 params.contents_mime_type = ds->response().mimeType().utf8();
2041
2042 params.transition = navigation_state->transition_type();
2043 if (!PageTransitionIsMainFrame(params.transition)) {
2044 // If the main frame does a load, it should not be reported as a subframe
2045 // navigation. This can occur in the following case:
2046 // 1. You're on a site with frames.
2047 // 2. You do a subframe navigation. This is stored with transition type
2048 // MANUAL_SUBFRAME.
2049 // 3. You navigate to some non-frame site, say, google.com.
2050 // 4. You navigate back to the page from step 2. Since it was initially
2051 // MANUAL_SUBFRAME, it will be that same transition type here.
2052 // We don't want that, because any navigation that changes the toplevel
2053 // frame should be tracked as a toplevel navigation (this allows us to
2054 // update the URL bar, etc).
2055 params.transition = PAGE_TRANSITION_LINK;
2056 }
2057
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +01002058 // If the page contained a client redirect (meta refresh, document.loc...),
2059 // set the referrer and transition appropriately.
2060 if (ds->isClientRedirect()) {
2061 params.referrer = Referrer(params.redirects[0],
2062 GetReferrerPolicyFromRequest(frame, ds->request()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002063 params.transition = static_cast<PageTransition>(
2064 params.transition | PAGE_TRANSITION_CLIENT_REDIRECT);
2065 } else {
2066 // Bug 654101: the referrer will be empty on https->http transitions. It
2067 // would be nice if we could get the real referrer from somewhere.
Ben Murdocha3f7b4e2013-07-24 10:36:34 +01002068 params.referrer = GetReferrerFromRequest(frame, original_request);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002069 }
2070
2071 string16 method = request.httpMethod();
2072 if (EqualsASCII(method, "POST")) {
2073 params.is_post = true;
2074 params.post_id = ExtractPostId(item);
2075 }
2076
2077 // Send the user agent override back.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002078 params.is_overriding_user_agent = internal_data->is_overriding_user_agent();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002079
2080 // Track the URL of the original request.
2081 params.original_request_url = original_request.url();
2082
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002083 params.history_list_was_cleared =
2084 navigation_state->history_list_was_cleared();
2085
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002086 // Save some histogram data so we can compute the average memory used per
2087 // page load of the glyphs.
2088 UMA_HISTOGRAM_COUNTS_10000("Memory.GlyphPagesPerLoad",
Ben Murdochbbcdd452013-07-25 10:06:34 +01002089 WebKit::WebGlyphCache::pageCount());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002090
2091 // This message needs to be sent before any of allowScripts(),
2092 // allowImages(), allowPlugins() is called for the new page, so that when
2093 // these functions send a ViewHostMsg_ContentBlocked message, it arrives
2094 // after the ViewHostMsg_FrameNavigate message.
2095 Send(new ViewHostMsg_FrameNavigate(routing_id_, params));
2096 } else {
2097 // Subframe navigation: the type depends on whether this navigation
2098 // generated a new session history entry. When they do generate a session
2099 // history entry, it means the user initiated the navigation and we should
2100 // mark it as such. This test checks if this is the first time UpdateURL
2101 // has been called since WillNavigateToURL was called to initiate the load.
2102 if (page_id_ > last_page_id_sent_to_browser_)
2103 params.transition = PAGE_TRANSITION_MANUAL_SUBFRAME;
2104 else
2105 params.transition = PAGE_TRANSITION_AUTO_SUBFRAME;
2106
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002107 DCHECK(!navigation_state->history_list_was_cleared());
2108 params.history_list_was_cleared = false;
2109
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002110 Send(new ViewHostMsg_FrameNavigate(routing_id_, params));
2111 }
2112
2113 last_page_id_sent_to_browser_ =
2114 std::max(last_page_id_sent_to_browser_, page_id_);
2115
2116 // If we end up reusing this WebRequest (for example, due to a #ref click),
2117 // we don't want the transition type to persist. Just clear it.
2118 navigation_state->set_transition_type(PAGE_TRANSITION_LINK);
2119}
2120
2121// Tell the embedding application that the title of the active page has changed
2122void RenderViewImpl::UpdateTitle(WebFrame* frame,
2123 const string16& title,
2124 WebTextDirection title_direction) {
2125 // Ignore all but top level navigations.
2126 if (frame->parent())
2127 return;
2128
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002129 base::debug::TraceLog::GetInstance()->UpdateProcessLabel(
2130 routing_id_, UTF16ToUTF8(title));
2131
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002132 string16 shortened_title = title.substr(0, kMaxTitleChars);
2133 Send(new ViewHostMsg_UpdateTitle(routing_id_, page_id_, shortened_title,
2134 title_direction));
2135}
2136
2137void RenderViewImpl::UpdateEncoding(WebFrame* frame,
2138 const std::string& encoding_name) {
2139 // Only update main frame's encoding_name.
2140 if (webview()->mainFrame() == frame &&
2141 last_encoding_name_ != encoding_name) {
2142 // Save the encoding name for later comparing.
2143 last_encoding_name_ = encoding_name;
2144
2145 Send(new ViewHostMsg_UpdateEncoding(routing_id_, last_encoding_name_));
2146 }
2147}
2148
2149// Sends the last committed session history state to the browser so it will be
2150// saved before we navigate to a new page. This must be called *before* the
2151// page ID has been updated so we know what it was.
2152void RenderViewImpl::UpdateSessionHistory(WebFrame* frame) {
2153 // If we have a valid page ID at this point, then it corresponds to the page
2154 // we are navigating away from. Otherwise, this is the first navigation, so
2155 // there is no past session history to record.
2156 if (page_id_ == -1)
2157 return;
2158
2159 const WebHistoryItem& item =
2160 webview()->mainFrame()->previousHistoryItem();
2161 SendUpdateState(item);
2162}
2163
2164void RenderViewImpl::SendUpdateState(const WebHistoryItem& item) {
2165 if (item.isNull())
2166 return;
2167
2168 // Don't send state updates for kSwappedOutURL.
2169 if (item.urlString() == WebString::fromUTF8(kSwappedOutURL))
2170 return;
2171
2172 Send(new ViewHostMsg_UpdateState(
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002173 routing_id_, page_id_, HistoryItemToPageState(item)));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002174}
2175
2176void RenderViewImpl::OpenURL(WebFrame* frame,
2177 const GURL& url,
2178 const Referrer& referrer,
2179 WebNavigationPolicy policy) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002180 ViewHostMsg_OpenURL_Params params;
2181 params.url = url;
2182 params.referrer = referrer;
2183 params.disposition = NavigationPolicyToDisposition(policy);
2184 params.frame_id = frame->identifier();
2185 WebDataSource* ds = frame->provisionalDataSource();
2186 if (ds) {
Ben Murdochca12bfa2013-07-23 11:17:05 +01002187 params.should_replace_current_entry = ds->replacesCurrentHistoryItem();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002188 } else {
Ben Murdochca12bfa2013-07-23 11:17:05 +01002189 params.should_replace_current_entry = false;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002190 }
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002191 params.user_gesture = WebUserGestureIndicator::isProcessingUserGesture();
Ben Murdochbbcdd452013-07-25 10:06:34 +01002192 if (GetContentClient()->renderer()->AllowPopup())
2193 params.user_gesture = true;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002194
2195 if (policy == WebKit::WebNavigationPolicyNewBackgroundTab ||
2196 policy == WebKit::WebNavigationPolicyNewForegroundTab ||
2197 policy == WebKit::WebNavigationPolicyNewWindow ||
2198 policy == WebKit::WebNavigationPolicyNewPopup) {
2199 WebUserGestureIndicator::consumeUserGesture();
2200 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002201
2202 Send(new ViewHostMsg_OpenURL(routing_id_, params));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002203}
2204
2205// WebViewDelegate ------------------------------------------------------------
2206
2207void RenderViewImpl::LoadNavigationErrorPage(
2208 WebFrame* frame,
2209 const WebURLRequest& failed_request,
2210 const WebURLError& error,
2211 const std::string& html,
2212 bool replace) {
2213 std::string alt_html;
2214 const std::string* error_html;
2215
2216 if (!html.empty()) {
2217 error_html = &html;
2218 } else {
2219 GetContentClient()->renderer()->GetNavigationErrorStrings(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002220 frame, failed_request, error, &alt_html, NULL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002221 error_html = &alt_html;
2222 }
2223
2224 frame->loadHTMLString(*error_html,
2225 GURL(kUnreachableWebDataURL),
2226 error.unreachableURL,
2227 replace);
2228}
2229
2230bool RenderViewImpl::RunJavaScriptMessage(JavaScriptMessageType type,
2231 const string16& message,
2232 const string16& default_value,
2233 const GURL& frame_url,
2234 string16* result) {
2235 bool success = false;
2236 string16 result_temp;
2237 if (!result)
2238 result = &result_temp;
2239
2240 SendAndRunNestedMessageLoop(new ViewHostMsg_RunJavaScriptMessage(
2241 routing_id_, message, default_value, frame_url, type, &success, result));
2242 return success;
2243}
2244
2245bool RenderViewImpl::SendAndRunNestedMessageLoop(IPC::SyncMessage* message) {
2246 // Before WebKit asks us to show an alert (etc.), it takes care of doing the
2247 // equivalent of WebView::willEnterModalLoop. In the case of showModalDialog
2248 // it is particularly important that we do not call willEnterModalLoop as
2249 // that would defer resource loads for the dialog itself.
2250 if (RenderThreadImpl::current()) // Will be NULL during unit tests.
2251 RenderThreadImpl::current()->DoNotNotifyWebKitOfModalLoop();
2252
2253 message->EnableMessagePumping(); // Runs a nested message loop.
2254 return Send(message);
2255}
2256
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002257void RenderViewImpl::GetWindowSnapshot(const WindowSnapshotCallback& callback) {
2258 int id = next_snapshot_id_++;
2259 pending_snapshots_.insert(std::make_pair(id, callback));
2260 Send(new ViewHostMsg_GetWindowSnapshot(routing_id_, id));
2261}
2262
2263void RenderViewImpl::OnWindowSnapshotCompleted(const int snapshot_id,
2264 const gfx::Size& size, const std::vector<unsigned char>& png) {
2265 PendingSnapshotMap::iterator it = pending_snapshots_.find(snapshot_id);
2266 DCHECK(it != pending_snapshots_.end());
2267 it->second.Run(size, png);
2268 pending_snapshots_.erase(it);
2269}
2270
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002271// WebKit::WebViewClient ------------------------------------------------------
2272
2273WebView* RenderViewImpl::createView(
2274 WebFrame* creator,
2275 const WebURLRequest& request,
2276 const WebWindowFeatures& features,
2277 const WebString& frame_name,
2278 WebNavigationPolicy policy) {
2279 // Check to make sure we aren't overloading on popups.
2280 if (shared_popup_counter_->data > kMaximumNumberOfUnacknowledgedPopups)
2281 return NULL;
2282
2283 ViewHostMsg_CreateWindow_Params params;
2284 params.opener_id = routing_id_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002285 params.user_gesture = WebUserGestureIndicator::isProcessingUserGesture();
Ben Murdochbbcdd452013-07-25 10:06:34 +01002286 if (GetContentClient()->renderer()->AllowPopup())
2287 params.user_gesture = true;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002288 params.window_container_type = WindowFeaturesToContainerType(features);
2289 params.session_storage_namespace_id = session_storage_namespace_id_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002290 if (frame_name != "_blank")
2291 params.frame_name = frame_name;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002292 params.opener_frame_id = creator->identifier();
2293 params.opener_url = creator->document().url();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002294 GURL security_url(creator->document().securityOrigin().toString().utf8());
2295 if (!security_url.is_valid())
2296 security_url = GURL();
2297 params.opener_security_origin = security_url;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002298 params.opener_suppressed = creator->willSuppressOpenerInNewFrame();
2299 params.disposition = NavigationPolicyToDisposition(policy);
Ben Murdocha3f7b4e2013-07-24 10:36:34 +01002300 if (!request.isNull()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002301 params.target_url = request.url();
Ben Murdocha3f7b4e2013-07-24 10:36:34 +01002302 params.referrer = GetReferrerFromRequest(creator, request);
2303 }
2304 params.features = features;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002305
2306 int32 routing_id = MSG_ROUTING_NONE;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002307 int32 main_frame_routing_id = MSG_ROUTING_NONE;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002308 int32 surface_id = 0;
2309 int64 cloned_session_storage_namespace_id;
2310
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002311 RenderThread::Get()->Send(
2312 new ViewHostMsg_CreateWindow(params,
2313 &routing_id,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002314 &main_frame_routing_id,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002315 &surface_id,
2316 &cloned_session_storage_namespace_id));
2317 if (routing_id == MSG_ROUTING_NONE)
2318 return NULL;
2319
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002320 WebUserGestureIndicator::consumeUserGesture();
2321
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002322 WebPreferences transferred_preferences = webkit_preferences_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002323
2324 // Unless accelerated compositing has been explicitly disabled from the
2325 // command line (e.g. via the blacklist or about:flags) re-enable it for
2326 // new views that get spawned by this view. This gets around the issue that
2327 // background extension pages disable accelerated compositing via web prefs
2328 // but can themselves spawn a visible render view which should be allowed
2329 // use gpu acceleration.
2330 if (!webkit_preferences_.accelerated_compositing_enabled) {
2331 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
2332 if (!command_line.HasSwitch(switches::kDisableAcceleratedCompositing))
2333 transferred_preferences.accelerated_compositing_enabled = true;
2334 }
2335
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002336 RenderViewImpl* view = RenderViewImpl::Create(
2337 routing_id_,
2338 renderer_preferences_,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002339 transferred_preferences,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002340 shared_popup_counter_.get(),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002341 routing_id,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002342 main_frame_routing_id,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002343 surface_id,
2344 cloned_session_storage_namespace_id,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002345 string16(), // WebCore will take care of setting the correct name.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002346 true,
2347 false,
2348 1,
2349 screen_info_,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002350 accessibility_mode_,
2351 allow_partial_swap_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002352 view->opened_by_user_gesture_ = params.user_gesture;
2353
2354 // Record whether the creator frame is trying to suppress the opener field.
2355 view->opener_suppressed_ = params.opener_suppressed;
2356
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002357 // Copy over the alternate error page URL so we can have alt error pages in
2358 // the new render view (we don't need the browser to send the URL back down).
2359 view->alternate_error_page_url_ = alternate_error_page_url_;
2360
2361 return view->webview();
2362}
2363
2364WebWidget* RenderViewImpl::createPopupMenu(WebKit::WebPopupType popup_type) {
2365 RenderWidget* widget =
2366 RenderWidget::Create(routing_id_, popup_type, screen_info_);
2367 return widget->webwidget();
2368}
2369
2370WebExternalPopupMenu* RenderViewImpl::createExternalPopupMenu(
2371 const WebPopupMenuInfo& popup_menu_info,
2372 WebExternalPopupMenuClient* popup_menu_client) {
2373 // An IPC message is sent to the browser to build and display the actual
2374 // popup. The user could have time to click a different select by the time
2375 // the popup is shown. In that case external_popup_menu_ is non NULL.
2376 // By returning NULL in that case, we instruct WebKit to cancel that new
2377 // popup. So from the user perspective, only the first one will show, and
2378 // will have to close the first one before another one can be shown.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002379 if (external_popup_menu_)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002380 return NULL;
2381 external_popup_menu_.reset(
2382 new ExternalPopupMenu(this, popup_menu_info, popup_menu_client));
2383 return external_popup_menu_.get();
2384}
2385
Ben Murdocheb525c52013-07-10 11:40:50 +01002386WebStorageNamespace* RenderViewImpl::createSessionStorageNamespace() {
Ben Murdochbb1529c2013-08-08 10:24:53 +01002387 CHECK(session_storage_namespace_id_ != kInvalidSessionStorageNamespaceId);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002388 return new WebStorageNamespaceImpl(session_storage_namespace_id_);
2389}
2390
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002391void RenderViewImpl::didAddMessageToConsole(
2392 const WebConsoleMessage& message, const WebString& source_name,
2393 unsigned source_line) {
2394 logging::LogSeverity log_severity = logging::LOG_VERBOSE;
2395 switch (message.level) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002396 case WebConsoleMessage::LevelDebug:
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002397 log_severity = logging::LOG_VERBOSE;
2398 break;
2399 case WebConsoleMessage::LevelLog:
2400 log_severity = logging::LOG_INFO;
2401 break;
2402 case WebConsoleMessage::LevelWarning:
2403 log_severity = logging::LOG_WARNING;
2404 break;
2405 case WebConsoleMessage::LevelError:
2406 log_severity = logging::LOG_ERROR;
2407 break;
2408 default:
2409 NOTREACHED();
2410 }
2411
Ben Murdochbb1529c2013-08-08 10:24:53 +01002412 Send(new ViewHostMsg_AddMessageToConsole(routing_id_,
2413 static_cast<int32>(log_severity),
2414 message.text,
2415 static_cast<int32>(source_line),
2416 source_name));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002417}
2418
2419void RenderViewImpl::printPage(WebFrame* frame) {
2420 FOR_EACH_OBSERVER(RenderViewObserver, observers_,
2421 PrintPage(frame, handling_input_event_));
2422}
2423
2424WebKit::WebNotificationPresenter* RenderViewImpl::notificationPresenter() {
2425 return notification_provider_;
2426}
2427
2428bool RenderViewImpl::enumerateChosenDirectory(
2429 const WebString& path,
2430 WebFileChooserCompletion* chooser_completion) {
2431 int id = enumeration_completion_id_++;
2432 enumeration_completions_[id] = chooser_completion;
2433 return Send(new ViewHostMsg_EnumerateDirectory(
2434 routing_id_,
2435 id,
Ben Murdocheb525c52013-07-10 11:40:50 +01002436 base::FilePath::FromUTF16Unsafe(path)));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002437}
2438
2439void RenderViewImpl::initializeHelperPluginWebFrame(
2440 WebKit::WebHelperPlugin* plugin) {
Ben Murdocheb525c52013-07-10 11:40:50 +01002441 plugin->initializeFrame(main_render_frame_.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002442}
2443
2444void RenderViewImpl::didStartLoading() {
2445 if (is_loading_) {
2446 DVLOG(1) << "didStartLoading called while loading";
2447 return;
2448 }
2449
2450 is_loading_ = true;
2451
2452 Send(new ViewHostMsg_DidStartLoading(routing_id_));
2453
2454 FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidStartLoading());
2455}
2456
2457void RenderViewImpl::didStopLoading() {
2458 if (!is_loading_) {
2459 DVLOG(1) << "DidStopLoading called while not loading";
2460 return;
2461 }
2462
2463 is_loading_ = false;
2464
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002465 // NOTE: For now we're doing the safest thing, and sending out notification
2466 // when done loading. This currently isn't an issue as the favicon is only
2467 // displayed when done loading. Ideally we would send notification when
2468 // finished parsing the head, but webkit doesn't support that yet.
2469 // The feed discovery code would also benefit from access to the head.
2470 Send(new ViewHostMsg_DidStopLoading(routing_id_));
2471
2472 if (load_progress_tracker_ != NULL)
2473 load_progress_tracker_->DidStopLoading();
2474
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002475 DidStopLoadingIcons();
2476
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002477 FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidStopLoading());
2478}
2479
2480void RenderViewImpl::didChangeLoadProgress(WebFrame* frame,
2481 double load_progress) {
2482 if (load_progress_tracker_ != NULL)
2483 load_progress_tracker_->DidChangeLoadProgress(frame, load_progress);
2484}
2485
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002486void RenderViewImpl::didCancelCompositionOnSelectionChange() {
2487 Send(new ViewHostMsg_ImeCancelComposition(routing_id()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002488}
2489
2490void RenderViewImpl::didChangeSelection(bool is_empty_selection) {
2491 if (!handling_input_event_ && !handling_select_range_)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002492 return;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002493
2494 if (is_empty_selection)
2495 selection_text_.clear();
2496
2497 SyncSelectionIfRequired();
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01002498 UpdateTextInputType();
2499#if defined(OS_ANDROID)
Ben Murdoch2385ea32013-08-06 11:01:04 +01002500 UpdateTextInputState(false, true);
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01002501#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002502}
2503
2504void RenderViewImpl::didExecuteCommand(const WebString& command_name) {
2505 const std::string& name = UTF16ToUTF8(command_name);
2506 if (StartsWithASCII(name, "Move", true) ||
2507 StartsWithASCII(name, "Insert", true) ||
2508 StartsWithASCII(name, "Delete", true))
2509 return;
2510 RenderThreadImpl::current()->RecordUserMetrics(name);
2511}
2512
2513bool RenderViewImpl::handleCurrentKeyboardEvent() {
2514 if (edit_commands_.empty())
2515 return false;
2516
2517 WebFrame* frame = webview()->focusedFrame();
2518 if (!frame)
2519 return false;
2520
2521 EditCommands::iterator it = edit_commands_.begin();
2522 EditCommands::iterator end = edit_commands_.end();
2523
2524 bool did_execute_command = false;
2525 for (; it != end; ++it) {
2526 // In gtk and cocoa, it's possible to bind multiple edit commands to one
2527 // key (but it's the exception). Once one edit command is not executed, it
2528 // seems safest to not execute the rest.
2529 if (!frame->executeCommand(WebString::fromUTF8(it->name),
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002530 WebString::fromUTF8(it->value),
2531 GetFocusedNode()))
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002532 break;
2533 did_execute_command = true;
2534 }
2535
2536 return did_execute_command;
2537}
2538
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002539WebKit::WebColorChooser* RenderViewImpl::createColorChooser(
2540 WebKit::WebColorChooserClient* client,
2541 const WebKit::WebColor& initial_color) {
2542 RendererWebColorChooserImpl* color_chooser =
2543 new RendererWebColorChooserImpl(this, client);
2544 color_chooser->Open(static_cast<SkColor>(initial_color));
2545 return color_chooser;
2546}
2547
2548bool RenderViewImpl::runFileChooser(
2549 const WebKit::WebFileChooserParams& params,
2550 WebFileChooserCompletion* chooser_completion) {
2551 // Do not open the file dialog in a hidden RenderView.
2552 if (is_hidden())
2553 return false;
2554 FileChooserParams ipc_params;
2555 if (params.directory)
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +01002556 ipc_params.mode = FileChooserParams::UploadFolder;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002557 else if (params.multiSelect)
2558 ipc_params.mode = FileChooserParams::OpenMultiple;
2559 else if (params.saveAs)
2560 ipc_params.mode = FileChooserParams::Save;
2561 else
2562 ipc_params.mode = FileChooserParams::Open;
2563 ipc_params.title = params.title;
2564 ipc_params.default_file_name =
Ben Murdocheb525c52013-07-10 11:40:50 +01002565 base::FilePath::FromUTF16Unsafe(params.initialValue);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002566 ipc_params.accept_types.reserve(params.acceptTypes.size());
2567 for (size_t i = 0; i < params.acceptTypes.size(); ++i)
2568 ipc_params.accept_types.push_back(params.acceptTypes[i]);
2569#if defined(OS_ANDROID)
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002570 ipc_params.capture = params.useMediaCapture;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002571#endif
2572
2573 return ScheduleFileChooser(ipc_params, chooser_completion);
2574}
2575
2576void RenderViewImpl::runModalAlertDialog(WebFrame* frame,
2577 const WebString& message) {
2578 RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_ALERT,
2579 message,
2580 string16(),
2581 frame->document().url(),
2582 NULL);
2583}
2584
2585bool RenderViewImpl::runModalConfirmDialog(WebFrame* frame,
2586 const WebString& message) {
2587 return RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_CONFIRM,
2588 message,
2589 string16(),
2590 frame->document().url(),
2591 NULL);
2592}
2593
2594bool RenderViewImpl::runModalPromptDialog(WebFrame* frame,
2595 const WebString& message,
2596 const WebString& default_value,
2597 WebString* actual_value) {
2598 string16 result;
2599 bool ok = RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_PROMPT,
2600 message,
2601 default_value,
2602 frame->document().url(),
2603 &result);
2604 if (ok)
2605 actual_value->assign(result);
2606 return ok;
2607}
2608
2609bool RenderViewImpl::runModalBeforeUnloadDialog(
2610 WebFrame* frame, const WebString& message) {
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01002611 bool is_reload = false;
2612 WebDataSource* ds = frame->provisionalDataSource();
2613 if (ds)
2614 is_reload = (ds->navigationType() == WebKit::WebNavigationTypeReload);
2615 return runModalBeforeUnloadDialog(frame, is_reload, message);
2616}
2617
2618bool RenderViewImpl::runModalBeforeUnloadDialog(
2619 WebFrame* frame, bool is_reload, const WebString& message) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002620 // If we are swapping out, we have already run the beforeunload handler.
2621 // TODO(creis): Fix OnSwapOut to clear the frame without running beforeunload
2622 // at all, to avoid running it twice.
2623 if (is_swapped_out_)
2624 return true;
2625
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002626 bool success = false;
2627 // This is an ignored return value, but is included so we can accept the same
2628 // response as RunJavaScriptMessage.
2629 string16 ignored_result;
2630 SendAndRunNestedMessageLoop(new ViewHostMsg_RunBeforeUnloadConfirm(
2631 routing_id_, frame->document().url(), message, is_reload,
2632 &success, &ignored_result));
2633 return success;
2634}
2635
2636void RenderViewImpl::showContextMenu(
2637 WebFrame* frame, const WebContextMenuData& data) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002638 ContextMenuParams params = ContextMenuParamsBuilder::Build(data);
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01002639 params.source_type = context_menu_source_type_;
Ben Murdocheb525c52013-07-10 11:40:50 +01002640 if (context_menu_source_type_ == ui::MENU_SOURCE_TOUCH_EDIT_MENU) {
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01002641 params.x = touch_editing_context_menu_location_.x();
2642 params.y = touch_editing_context_menu_location_.y();
2643 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002644
2645 // Plugins, e.g. PDF, don't currently update the render view when their
2646 // selected text changes, but the context menu params do contain the updated
2647 // selection. If that's the case, update the render view's state just prior
2648 // to showing the context menu.
2649 // TODO(asvitkine): http://crbug.com/152432
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002650 if (ShouldUpdateSelectionTextFromContextMenuParams(selection_text_,
2651 selection_text_offset_,
2652 selection_range_,
2653 params)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002654 selection_text_ = params.selection_text;
2655 // TODO(asvitkine): Text offset and range is not available in this case.
2656 selection_text_offset_ = 0;
2657 selection_range_ = ui::Range(0, selection_text_.length());
2658 Send(new ViewHostMsg_SelectionChanged(routing_id_,
2659 selection_text_,
2660 selection_text_offset_,
2661 selection_range_));
2662 }
2663
2664 // frame is NULL if invoked by BlockedPlugin.
2665 if (frame)
2666 params.frame_id = frame->identifier();
2667
2668 // Serializing a GURL longer than kMaxURLChars will fail, so don't do
2669 // it. We replace it with an empty GURL so the appropriate items are disabled
2670 // in the context menu.
2671 // TODO(jcivelli): http://crbug.com/45160 This prevents us from saving large
2672 // data encoded images. We should have a way to save them.
2673 if (params.src_url.spec().size() > kMaxURLChars)
2674 params.src_url = GURL();
2675 context_menu_node_ = data.node;
2676
2677#if defined(OS_ANDROID)
2678 gfx::Rect start_rect;
2679 gfx::Rect end_rect;
2680 GetSelectionBounds(&start_rect, &end_rect);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002681 params.selection_start = gfx::Point(start_rect.x(), start_rect.bottom());
2682 params.selection_end = gfx::Point(end_rect.right(), end_rect.bottom());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002683#endif
2684
2685 Send(new ViewHostMsg_ContextMenu(routing_id_, params));
2686
2687 FOR_EACH_OBSERVER(
2688 RenderViewObserver, observers_, DidRequestShowContextMenu(frame, data));
2689}
2690
2691void RenderViewImpl::setStatusText(const WebString& text) {
2692}
2693
2694void RenderViewImpl::UpdateTargetURL(const GURL& url,
2695 const GURL& fallback_url) {
2696 GURL latest_url = url.is_empty() ? fallback_url : url;
2697 if (latest_url == target_url_)
2698 return;
2699
2700 // Tell the browser to display a destination link.
2701 if (target_url_status_ == TARGET_INFLIGHT ||
2702 target_url_status_ == TARGET_PENDING) {
2703 // If we have a request in-flight, save the URL to be sent when we
2704 // receive an ACK to the in-flight request. We can happily overwrite
2705 // any existing pending sends.
2706 pending_target_url_ = latest_url;
2707 target_url_status_ = TARGET_PENDING;
2708 } else {
2709 // URLs larger than |kMaxURLChars| cannot be sent through IPC -
2710 // see |ParamTraits<GURL>|.
2711 if (latest_url.possibly_invalid_spec().size() > kMaxURLChars)
2712 latest_url = GURL();
2713 Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_, latest_url));
2714 target_url_ = latest_url;
2715 target_url_status_ = TARGET_INFLIGHT;
2716 }
2717}
2718
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002719gfx::RectF RenderViewImpl::ClientRectToPhysicalWindowRect(
2720 const gfx::RectF& rect) const {
2721 gfx::RectF window_rect = rect;
2722 window_rect.Scale(device_scale_factor_ * webview()->pageScaleFactor());
2723 return window_rect;
2724}
2725
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002726void RenderViewImpl::StartNavStateSyncTimerIfNecessary() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002727 // No need to update state if no page has committed yet.
2728 if (page_id_ == -1)
2729 return;
2730
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002731 int delay;
2732 if (send_content_state_immediately_)
2733 delay = 0;
2734 else if (is_hidden())
2735 delay = kDelaySecondsForContentStateSyncHidden;
2736 else
2737 delay = kDelaySecondsForContentStateSync;
2738
2739 if (nav_state_sync_timer_.IsRunning()) {
2740 // The timer is already running. If the delay of the timer maches the amount
2741 // we want to delay by, then return. Otherwise stop the timer so that it
2742 // gets started with the right delay.
2743 if (nav_state_sync_timer_.GetCurrentDelay().InSeconds() == delay)
2744 return;
2745 nav_state_sync_timer_.Stop();
2746 }
2747
2748 nav_state_sync_timer_.Start(FROM_HERE, TimeDelta::FromSeconds(delay), this,
2749 &RenderViewImpl::SyncNavigationState);
2750}
2751
2752void RenderViewImpl::setMouseOverURL(const WebURL& url) {
2753 mouse_over_url_ = GURL(url);
2754 UpdateTargetURL(mouse_over_url_, focus_url_);
2755}
2756
2757void RenderViewImpl::setKeyboardFocusURL(const WebURL& url) {
2758 focus_url_ = GURL(url);
2759 UpdateTargetURL(focus_url_, mouse_over_url_);
2760}
2761
2762void RenderViewImpl::startDragging(WebFrame* frame,
2763 const WebDragData& data,
2764 WebDragOperationsMask mask,
2765 const WebImage& image,
2766 const WebPoint& webImageOffset) {
Ben Murdocheb525c52013-07-10 11:40:50 +01002767 DropData drop_data(DropDataBuilder::Build(data));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002768 drop_data.referrer_policy = frame->document().referrerPolicy();
2769 gfx::Vector2d imageOffset(webImageOffset.x, webImageOffset.y);
2770 Send(new DragHostMsg_StartDragging(routing_id_,
2771 drop_data,
2772 mask,
2773 image.getSkBitmap(),
2774 imageOffset,
2775 possible_drag_event_info_));
2776}
2777
2778bool RenderViewImpl::acceptsLoadDrops() {
2779 return renderer_preferences_.can_accept_load_drops;
2780}
2781
2782void RenderViewImpl::focusNext() {
2783 Send(new ViewHostMsg_TakeFocus(routing_id_, false));
2784}
2785
2786void RenderViewImpl::focusPrevious() {
2787 Send(new ViewHostMsg_TakeFocus(routing_id_, true));
2788}
2789
2790void RenderViewImpl::focusedNodeChanged(const WebNode& node) {
2791 Send(new ViewHostMsg_FocusedNodeChanged(routing_id_, IsEditableNode(node)));
2792
2793 FOR_EACH_OBSERVER(RenderViewObserver, observers_, FocusedNodeChanged(node));
2794}
2795
2796void RenderViewImpl::numberOfWheelEventHandlersChanged(unsigned num_handlers) {
2797 Send(new ViewHostMsg_DidChangeNumWheelEvents(routing_id_, num_handlers));
2798}
2799
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002800void RenderViewImpl::didUpdateLayout() {
2801 // We don't always want to set up a timer, only if we've been put in that
2802 // mode by getting a |ViewMsg_EnablePreferredSizeChangedMode|
2803 // message.
2804 if (!send_preferred_size_changes_ || !webview())
2805 return;
2806
2807 if (check_preferred_size_timer_.IsRunning())
2808 return;
2809 check_preferred_size_timer_.Start(FROM_HERE,
2810 TimeDelta::FromMilliseconds(0), this,
2811 &RenderViewImpl::CheckPreferredSize);
2812}
2813
2814void RenderViewImpl::navigateBackForwardSoon(int offset) {
2815 Send(new ViewHostMsg_GoToEntryAtOffset(routing_id_, offset));
2816}
2817
2818int RenderViewImpl::historyBackListCount() {
2819 return history_list_offset_ < 0 ? 0 : history_list_offset_;
2820}
2821
2822int RenderViewImpl::historyForwardListCount() {
2823 return history_list_length_ - historyBackListCount() - 1;
2824}
2825
2826void RenderViewImpl::postAccessibilityNotification(
2827 const WebAccessibilityObject& obj,
2828 WebAccessibilityNotification notification) {
2829 if (renderer_accessibility_) {
2830 renderer_accessibility_->HandleWebAccessibilityNotification(
2831 obj, notification);
2832 }
2833}
2834
2835void RenderViewImpl::didUpdateInspectorSetting(const WebString& key,
2836 const WebString& value) {
2837 Send(new ViewHostMsg_UpdateInspectorSetting(routing_id_,
2838 key.utf8(),
2839 value.utf8()));
2840}
2841
2842// WebKit::WebWidgetClient ----------------------------------------------------
2843
2844void RenderViewImpl::didFocus() {
2845 // TODO(jcivelli): when https://bugs.webkit.org/show_bug.cgi?id=33389 is fixed
2846 // we won't have to test for user gesture anymore and we can
2847 // move that code back to render_widget.cc
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002848 if (WebUserGestureIndicator::isProcessingUserGesture() &&
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002849 !RenderThreadImpl::current()->layout_test_mode()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002850 Send(new ViewHostMsg_Focus(routing_id_));
2851 }
2852}
2853
2854void RenderViewImpl::didBlur() {
2855 // TODO(jcivelli): see TODO above in didFocus().
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002856 if (WebUserGestureIndicator::isProcessingUserGesture() &&
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002857 !RenderThreadImpl::current()->layout_test_mode()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002858 Send(new ViewHostMsg_Blur(routing_id_));
2859 }
2860}
2861
2862// We are supposed to get a single call to Show for a newly created RenderView
2863// that was created via RenderViewImpl::CreateWebView. So, we wait until this
2864// point to dispatch the ShowView message.
2865//
2866// This method provides us with the information about how to display the newly
2867// created RenderView (i.e., as a blocked popup or as a new tab).
2868//
2869void RenderViewImpl::show(WebNavigationPolicy policy) {
2870 if (did_show_) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002871 // When supports_multiple_windows is disabled, popups are reusing
2872 // the same view. In some scenarios, this makes WebKit to call show() twice.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002873 if (webkit_preferences_.supports_multiple_windows)
2874 NOTREACHED() << "received extraneous Show call";
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002875 return;
2876 }
2877 did_show_ = true;
2878
2879 DCHECK(opener_id_ != MSG_ROUTING_NONE);
2880
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002881 // Force new windows to a popup if they were not opened with a user gesture.
2882 if (!opened_by_user_gesture_) {
2883 // We exempt background tabs for compat with older versions of Chrome.
2884 // TODO(darin): This seems bogus. These should have a user gesture, so
2885 // we probably don't need this check.
2886 if (policy != WebKit::WebNavigationPolicyNewBackgroundTab)
2887 policy = WebKit::WebNavigationPolicyNewPopup;
2888 }
2889
2890 // NOTE: initial_pos_ may still have its default values at this point, but
2891 // that's okay. It'll be ignored if disposition is not NEW_POPUP, or the
2892 // browser process will impose a default position otherwise.
2893 Send(new ViewHostMsg_ShowView(opener_id_, routing_id_,
2894 NavigationPolicyToDisposition(policy), initial_pos_,
2895 opened_by_user_gesture_));
2896 SetPendingWindowRect(initial_pos_);
2897}
2898
2899void RenderViewImpl::runModal() {
2900 DCHECK(did_show_) << "should already have shown the view";
2901
2902 // We must keep WebKit's shared timer running in this case in order to allow
2903 // showModalDialog to function properly.
2904 //
2905 // TODO(darin): WebKit should really be smarter about suppressing events and
2906 // timers so that we do not need to manage the shared timer in such a heavy
2907 // handed manner.
2908 //
2909 if (RenderThreadImpl::current()) // Will be NULL during unit tests.
2910 RenderThreadImpl::current()->DoNotSuspendWebKitSharedTimer();
2911
2912 SendAndRunNestedMessageLoop(new ViewHostMsg_RunModal(
2913 routing_id_, opener_id_));
2914}
2915
2916bool RenderViewImpl::enterFullScreen() {
2917 Send(new ViewHostMsg_ToggleFullscreen(routing_id_, true));
2918 return true;
2919}
2920
2921void RenderViewImpl::exitFullScreen() {
2922 Send(new ViewHostMsg_ToggleFullscreen(routing_id_, false));
2923}
2924
2925bool RenderViewImpl::requestPointerLock() {
2926 return mouse_lock_dispatcher_->LockMouse(webwidget_mouse_lock_target_.get());
2927}
2928
2929void RenderViewImpl::requestPointerUnlock() {
2930 mouse_lock_dispatcher_->UnlockMouse(webwidget_mouse_lock_target_.get());
2931}
2932
2933bool RenderViewImpl::isPointerLocked() {
2934 return mouse_lock_dispatcher_->IsMouseLockedTo(
2935 webwidget_mouse_lock_target_.get());
2936}
2937
2938void RenderViewImpl::didActivateCompositor(int input_handler_identifier) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002939#if !defined(OS_MACOSX) // many events are unhandled - http://crbug.com/138003
2940 InputHandlerManager* input_handler_manager =
2941 RenderThreadImpl::current()->input_handler_manager();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01002942 if (input_handler_manager) {
2943 input_handler_manager->AddInputHandler(
2944 routing_id_,
2945 compositor_->GetInputHandler(),
2946 AsWeakPtr());
2947 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002948#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002949
2950 RenderWidget::didActivateCompositor(input_handler_identifier);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002951}
2952
2953void RenderViewImpl::didHandleGestureEvent(
2954 const WebGestureEvent& event,
2955 bool event_cancelled) {
2956 RenderWidget::didHandleGestureEvent(event, event_cancelled);
2957 FOR_EACH_OBSERVER(RenderViewObserver, observers_,
2958 DidHandleGestureEvent(event));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002959}
2960
Ben Murdocha3f7b4e2013-07-24 10:36:34 +01002961void RenderViewImpl::initializeLayerTreeView() {
2962 RenderWidget::initializeLayerTreeView();
2963 RenderWidgetCompositor* rwc = compositor();
2964 if (!rwc || !webview() || !webview()->devToolsAgent())
2965 return;
2966 webview()->devToolsAgent()->setLayerTreeId(rwc->GetLayerTreeId());
2967}
2968
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002969// WebKit::WebFrameClient -----------------------------------------------------
2970
Ben Murdochca12bfa2013-07-23 11:17:05 +01002971WebKit::WebPlugin* RenderViewImpl::createPlugin(WebFrame* frame,
2972 const WebPluginParams& params) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01002973 NOTREACHED();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00002974 return NULL;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002975}
2976
2977WebSharedWorker* RenderViewImpl::createSharedWorker(
2978 WebFrame* frame, const WebURL& url, const WebString& name,
2979 unsigned long long document_id) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01002980 NOTREACHED();
2981 return NULL;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002982}
2983
2984WebMediaPlayer* RenderViewImpl::createMediaPlayer(
2985 WebFrame* frame, const WebKit::WebURL& url, WebMediaPlayerClient* client) {
2986 FOR_EACH_OBSERVER(
2987 RenderViewObserver, observers_, WillCreateMediaPlayer(frame, client));
2988
2989 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002990#if defined(ENABLE_WEBRTC)
2991 EnsureMediaStreamClient();
2992#if !defined(GOOGLE_TV)
2993 if (media_stream_client_->IsMediaStream(url)) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01002994#if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL)
2995 bool found_neon =
2996 (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0;
2997 UMA_HISTOGRAM_BOOLEAN("Platform.WebRtcNEONFound", found_neon);
2998#endif // defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL)
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01002999 return new WebMediaPlayerMS(
3000 frame, client, AsWeakPtr(), media_stream_client_, new RenderMediaLog());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003001 }
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01003002#endif // !defined(GOOGLE_TV)
3003#endif // defined(ENABLE_WEBRTC)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003004
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003005#if defined(OS_ANDROID)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003006 GpuChannelHost* gpu_channel_host =
3007 RenderThreadImpl::current()->EstablishGpuChannelSync(
3008 CAUSE_FOR_GPU_LAUNCH_VIDEODECODEACCELERATOR_INITIALIZE);
3009 if (!gpu_channel_host) {
3010 LOG(ERROR) << "Failed to establish GPU channel for media player";
3011 return NULL;
3012 }
3013
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003014 scoped_refptr<cc::ContextProvider> context_provider =
3015 RenderThreadImpl::current()->OffscreenContextProviderForMainThread();
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01003016 if (!context_provider.get()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003017 LOG(ERROR) << "Failed to get context3d for media player";
3018 return NULL;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003019 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003020
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003021 if (!media_player_proxy_) {
Ben Murdocheb525c52013-07-10 11:40:50 +01003022 media_player_proxy_ = new WebMediaPlayerProxyAndroid(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003023 this, media_player_manager_.get());
3024 }
Ben Murdocheb525c52013-07-10 11:40:50 +01003025 scoped_ptr<WebMediaPlayerAndroid> web_media_player_android(
3026 new WebMediaPlayerAndroid(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003027 frame,
3028 client,
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01003029 AsWeakPtr(),
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003030 media_player_manager_.get(),
3031 media_player_proxy_,
Ben Murdocheb525c52013-07-10 11:40:50 +01003032 new StreamTextureFactory(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003033 context_provider->Context3d(), gpu_channel_host, routing_id_),
3034 new RenderMediaLog()));
3035#if defined(ENABLE_WEBRTC) && defined(GOOGLE_TV)
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01003036 if (media_stream_client_->IsMediaStream(url)) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003037 RTCVideoDecoderFactoryTv* factory = RenderThreadImpl::current()
3038 ->GetMediaStreamDependencyFactory()->decoder_factory_tv();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01003039 // |media_stream_client| and |factory| outlives |web_media_player_android|.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003040 if (!factory->AcquireDemuxer() ||
3041 !web_media_player_android->InjectMediaStream(
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01003042 media_stream_client_,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003043 factory,
3044 base::Bind(
3045 base::IgnoreResult(&RTCVideoDecoderFactoryTv::ReleaseDemuxer),
3046 base::Unretained(factory)))) {
3047 LOG(ERROR) << "Failed to inject media stream.";
3048 return NULL;
3049 }
3050 }
3051#endif // defined(ENABLE_WEBRTC) && defined(GOOGLE_TV)
3052 return web_media_player_android.release();
3053#endif // defined(OS_ANDROID)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003054
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003055 scoped_refptr<media::AudioRendererSink> sink;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003056 if (!cmd_line->HasSwitch(switches::kDisableAudio)) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003057 sink = RenderThreadImpl::current()->GetAudioRendererMixerManager()->
3058 CreateInput(routing_id_);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003059 DVLOG(1) << "Using AudioRendererMixerManager-provided sink: " << sink.get();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003060 }
3061
Ben Murdocha3f7b4e2013-07-24 10:36:34 +01003062 scoped_refptr<media::GpuVideoDecoderFactories> gpu_factories =
Ben Murdochbbcdd452013-07-25 10:06:34 +01003063 RenderThreadImpl::current()->GetGpuFactories(
3064 RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003065
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01003066 WebMediaPlayerParams params(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003067 RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy(),
Ben Murdocheb525c52013-07-10 11:40:50 +01003068 base::Bind(&ContentRendererClient::DeferMediaLoad,
3069 base::Unretained(GetContentClient()->renderer()),
3070 static_cast<RenderView*>(this)),
3071 sink,
3072 gpu_factories,
3073 new RenderMediaLog());
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01003074 return new WebMediaPlayerImpl(frame, client, AsWeakPtr(), params);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003075}
3076
3077WebApplicationCacheHost* RenderViewImpl::createApplicationCacheHost(
3078 WebFrame* frame, WebApplicationCacheHostClient* client) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01003079 NOTREACHED();
3080 return NULL;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003081}
3082
3083WebCookieJar* RenderViewImpl::cookieJar(WebFrame* frame) {
3084 return &cookie_jar_;
3085}
3086
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003087void RenderViewImpl::didAccessInitialDocument(WebFrame* frame) {
3088 // Notify the browser process that it is no longer safe to show the pending
3089 // URL of the main frame, since a URL spoof is now possible.
3090 if (!frame->parent() && page_id_ == -1)
3091 Send(new ViewHostMsg_DidAccessInitialDocument(routing_id_));
3092}
3093
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003094void RenderViewImpl::didCreateFrame(WebFrame* parent, WebFrame* child) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01003095 NOTREACHED();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003096}
3097
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003098void RenderViewImpl::didDisownOpener(WebKit::WebFrame* frame) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003099 // We only need to notify the browser if the active, top-level frame clears
3100 // its opener. We can ignore cases where a swapped out frame clears its
3101 // opener after hearing about it from the browser, and the browser does not
3102 // (yet) care about subframe openers.
3103 if (is_swapped_out_ || frame->parent())
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003104 return;
3105
3106 // Notify WebContents and all its swapped out RenderViews.
3107 Send(new ViewHostMsg_DidDisownOpener(routing_id_));
3108}
3109
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003110void RenderViewImpl::frameDetached(WebFrame* frame) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003111 FOR_EACH_OBSERVER(RenderViewObserver, observers_, FrameDetached(frame));
3112}
3113
3114void RenderViewImpl::willClose(WebFrame* frame) {
3115 FOR_EACH_OBSERVER(RenderViewObserver, observers_, FrameWillClose(frame));
3116}
3117
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003118void RenderViewImpl::didChangeName(WebFrame* frame,
3119 const WebString& name) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01003120 NOTREACHED();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003121}
3122
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003123void RenderViewImpl::loadURLExternally(
3124 WebFrame* frame, const WebURLRequest& request,
3125 WebNavigationPolicy policy) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01003126 NOTREACHED();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003127}
3128
3129void RenderViewImpl::Repaint(const gfx::Size& size) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003130 OnRepaint(size);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003131}
3132
3133void RenderViewImpl::SetEditCommandForNextKeyEvent(const std::string& name,
3134 const std::string& value) {
3135 EditCommands edit_commands;
3136 edit_commands.push_back(EditCommand(name, value));
3137 OnSetEditCommandsForNextKeyEvent(edit_commands);
3138}
3139
3140void RenderViewImpl::ClearEditCommands() {
3141 edit_commands_.clear();
3142}
3143
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003144SSLStatus RenderViewImpl::GetSSLStatusOfFrame(WebKit::WebFrame* frame) const {
Ben Murdocha3f7b4e2013-07-24 10:36:34 +01003145 std::string security_info;
3146 if (frame && frame->dataSource())
3147 security_info = frame->dataSource()->response().securityInfo();
3148
3149 SSLStatus ssl_status;
3150 DeserializeSecurityInfo(security_info,
3151 &ssl_status.cert_id,
3152 &ssl_status.cert_status,
3153 &ssl_status.security_bits,
3154 &ssl_status.connection_status);
3155 return ssl_status;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003156}
3157
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003158void RenderViewImpl::loadURLExternally(
3159 WebFrame* frame, const WebURLRequest& request,
3160 WebNavigationPolicy policy,
3161 const WebString& suggested_name) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01003162 NOTREACHED();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003163}
3164
3165WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003166 WebFrame* frame, WebDataSource::ExtraData* extraData,
3167 const WebURLRequest& request, WebNavigationType type,
3168 WebNavigationPolicy default_policy, bool is_redirect) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003169 if (request.url() != GURL(kSwappedOutURL) &&
3170 GetContentClient()->renderer()->HandleNavigation(frame, request, type,
3171 default_policy,
3172 is_redirect)) {
3173 return WebKit::WebNavigationPolicyIgnore;
3174 }
3175
Ben Murdocha3f7b4e2013-07-24 10:36:34 +01003176 Referrer referrer(GetReferrerFromRequest(frame, request));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003177
3178 if (is_swapped_out_) {
3179 if (request.url() != GURL(kSwappedOutURL)) {
3180 // Targeted links may try to navigate a swapped out frame. Allow the
3181 // browser process to navigate the tab instead. Note that it is also
3182 // possible for non-targeted navigations (from this view) to arrive
3183 // here just after we are swapped out. It's ok to send them to the
3184 // browser, as long as they're for the top level frame.
3185 // TODO(creis): Ensure this supports targeted form submissions when
3186 // fixing http://crbug.com/101395.
3187 if (frame->parent() == NULL) {
3188 OpenURL(frame, request.url(), referrer, default_policy);
3189 return WebKit::WebNavigationPolicyIgnore; // Suppress the load here.
3190 }
3191
3192 // We should otherwise ignore in-process iframe navigations, if they
3193 // arrive just after we are swapped out.
3194 return WebKit::WebNavigationPolicyIgnore;
3195 }
3196
3197 // Allow kSwappedOutURL to complete.
3198 return default_policy;
3199 }
3200
3201 // Webkit is asking whether to navigate to a new URL.
3202 // This is fine normally, except if we're showing UI from one security
3203 // context and they're trying to navigate to a different context.
3204 const GURL& url = request.url();
3205
3206 // A content initiated navigation may have originated from a link-click,
3207 // script, drag-n-drop operation, etc.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003208 bool is_content_initiated = static_cast<DocumentState*>(extraData)->
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003209 navigation_state()->is_content_initiated();
3210
3211 // Experimental:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003212 // If --enable-strict-site-isolation or --site-per-process is enabled, send
3213 // all top-level navigations to the browser to let it swap processes when
3214 // crossing site boundaries. This is currently expected to break some script
3215 // calls and navigations, such as form submissions.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003216 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003217 bool force_swap_due_to_flag =
3218 command_line.HasSwitch(switches::kEnableStrictSiteIsolation) ||
3219 command_line.HasSwitch(switches::kSitePerProcess);
3220 if (force_swap_due_to_flag &&
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003221 !frame->parent() && (is_content_initiated || is_redirect)) {
3222 WebString origin_str = frame->document().securityOrigin().toString();
3223 GURL frame_url(origin_str.utf8().data());
3224 // TODO(cevans): revisit whether this site check is still necessary once
3225 // crbug.com/101395 is fixed.
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01003226 bool same_domain_or_host =
3227 net::registry_controlled_domains::SameDomainOrHost(
3228 frame_url,
3229 url,
3230 net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
3231 if (!same_domain_or_host || frame_url.scheme() != url.scheme()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003232 OpenURL(frame, url, referrer, default_policy);
3233 return WebKit::WebNavigationPolicyIgnore;
3234 }
3235 }
3236
3237 // If the browser is interested, then give it a chance to look at the request.
3238 if (is_content_initiated) {
Ben Murdocha3f7b4e2013-07-24 10:36:34 +01003239 bool is_form_post = ((type == WebKit::WebNavigationTypeFormSubmitted) ||
3240 (type == WebKit::WebNavigationTypeFormResubmitted)) &&
3241 EqualsASCII(request.httpMethod(), "POST");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003242 bool browser_handles_request =
3243 renderer_preferences_.browser_handles_non_local_top_level_requests &&
Ben Murdocha3f7b4e2013-07-24 10:36:34 +01003244 IsNonLocalTopLevelNavigation(url, frame, type, is_form_post);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003245 if (!browser_handles_request) {
3246 browser_handles_request =
3247 renderer_preferences_.browser_handles_all_top_level_requests &&
3248 IsTopLevelNavigation(frame);
3249 }
3250
3251 if (browser_handles_request) {
3252 // Reset these counters as the RenderView could be reused for the next
3253 // navigation.
3254 page_id_ = -1;
3255 last_page_id_sent_to_browser_ = -1;
3256 OpenURL(frame, url, referrer, default_policy);
3257 return WebKit::WebNavigationPolicyIgnore; // Suppress the load here.
3258 }
3259 }
3260
3261 // Use the frame's original request's URL rather than the document's URL for
3262 // subsequent checks. For a popup, the document's URL may become the opener
3263 // window's URL if the opener has called document.write().
3264 // See http://crbug.com/93517.
3265 GURL old_url(frame->dataSource()->request().url());
3266
3267 // Detect when we're crossing a permission-based boundary (e.g. into or out of
3268 // an extension or app origin, leaving a WebUI page, etc). We only care about
3269 // top-level navigations (not iframes). But we sometimes navigate to
3270 // about:blank to clear a tab, and we want to still allow that.
3271 //
3272 // Note: this is known to break POST submissions when crossing process
3273 // boundaries until http://crbug.com/101395 is fixed. This is better for
3274 // security than loading a WebUI, extension or app page in the wrong process.
3275 // POST requests don't work because this mechanism does not preserve form
3276 // POST data. We will need to send the request's httpBody data up to the
3277 // browser process, and issue a special POST navigation in WebKit (via
3278 // FrameLoader::loadFrameRequest). See ResourceDispatcher and WebURLLoaderImpl
3279 // for examples of how to send the httpBody data.
3280 if (!frame->parent() && is_content_initiated &&
3281 !url.SchemeIs(chrome::kAboutScheme)) {
3282 bool send_referrer = false;
3283
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003284 // All navigations to or from WebUI URLs or within WebUI-enabled
3285 // RenderProcesses must be handled by the browser process so that the
3286 // correct bindings and data sources can be registered.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003287 // Similarly, navigations to view-source URLs or within ViewSource mode
3288 // must be handled by the browser process (except for reloads - those are
3289 // safe to leave within the renderer).
3290 // Lastly, access to file:// URLs from non-file:// URL pages must be
3291 // handled by the browser so that ordinary renderer processes don't get
3292 // blessed with file permissions.
3293 int cumulative_bindings = RenderProcess::current()->GetEnabledBindings();
3294 bool is_initial_navigation = page_id_ == -1;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003295 bool should_fork = HasWebUIScheme(url) || HasWebUIScheme(old_url) ||
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003296 (cumulative_bindings & BINDINGS_POLICY_WEB_UI) ||
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003297 url.SchemeIs(kViewSourceScheme) ||
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003298 (frame->isViewSourceModeEnabled() &&
3299 type != WebKit::WebNavigationTypeReload);
3300
3301 if (!should_fork && url.SchemeIs(chrome::kFileScheme)) {
3302 // Fork non-file to file opens. Check the opener URL if this is the
3303 // initial navigation in a newly opened window.
3304 GURL source_url(old_url);
3305 if (is_initial_navigation && source_url.is_empty() && frame->opener())
3306 source_url = frame->opener()->top()->document().url();
3307 DCHECK(!source_url.is_empty());
3308 should_fork = !source_url.SchemeIs(chrome::kFileScheme);
3309 }
3310
3311 if (!should_fork) {
3312 // Give the embedder a chance.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003313 should_fork = GetContentClient()->renderer()->ShouldFork(
3314 frame, url, request.httpMethod().utf8(), is_initial_navigation,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003315 is_redirect, &send_referrer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003316 }
3317
3318 if (should_fork) {
3319 OpenURL(
3320 frame, url, send_referrer ? referrer : Referrer(), default_policy);
3321 return WebKit::WebNavigationPolicyIgnore; // Suppress the load here.
3322 }
3323 }
3324
3325 // Detect when a page is "forking" a new tab that can be safely rendered in
3326 // its own process. This is done by sites like Gmail that try to open links
3327 // in new windows without script connections back to the original page. We
3328 // treat such cases as browser navigations (in which we will create a new
3329 // renderer for a cross-site navigation), rather than WebKit navigations.
3330 //
3331 // We use the following heuristic to decide whether to fork a new page in its
3332 // own process:
3333 // The parent page must open a new tab to about:blank, set the new tab's
3334 // window.opener to null, and then redirect the tab to a cross-site URL using
3335 // JavaScript.
3336 //
3337 // TODO(creis): Deprecate this logic once we can rely on rel=noreferrer
3338 // (see below).
3339 bool is_fork =
3340 // Must start from a tab showing about:blank, which is later redirected.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003341 old_url == GURL(kAboutBlankURL) &&
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003342 // Must be the first real navigation of the tab.
3343 historyBackListCount() < 1 &&
3344 historyForwardListCount() < 1 &&
3345 // The parent page must have set the child's window.opener to null before
3346 // redirecting to the desired URL.
3347 frame->opener() == NULL &&
3348 // Must be a top-level frame.
3349 frame->parent() == NULL &&
3350 // Must not have issued the request from this page.
3351 is_content_initiated &&
3352 // Must be targeted at the current tab.
3353 default_policy == WebKit::WebNavigationPolicyCurrentTab &&
3354 // Must be a JavaScript navigation, which appears as "other".
3355 type == WebKit::WebNavigationTypeOther;
3356
3357 if (is_fork) {
3358 // Open the URL via the browser, not via WebKit.
3359 OpenURL(frame, url, Referrer(), default_policy);
3360 return WebKit::WebNavigationPolicyIgnore;
3361 }
3362
3363 return default_policy;
3364}
3365
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003366WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation(
3367 WebFrame* frame, const WebURLRequest& request, WebNavigationType type,
3368 WebNavigationPolicy default_policy, bool is_redirect) {
3369 return decidePolicyForNavigation(frame,
3370 frame->provisionalDataSource()->extraData(),
3371 request, type, default_policy, is_redirect);
3372}
3373
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003374void RenderViewImpl::willSendSubmitEvent(WebKit::WebFrame* frame,
3375 const WebKit::WebFormElement& form) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01003376 NOTREACHED();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003377}
3378
3379void RenderViewImpl::willSubmitForm(WebFrame* frame,
3380 const WebFormElement& form) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003381 FOR_EACH_OBSERVER(
3382 RenderViewObserver, observers_, WillSubmitForm(frame, form));
3383}
3384
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003385void RenderViewImpl::didCreateDataSource(WebFrame* frame, WebDataSource* ds) {
3386 bool content_initiated = !pending_navigation_params_.get();
3387
3388 DocumentState* document_state = DocumentState::FromDataSource(ds);
3389 if (!document_state) {
3390 document_state = new DocumentState;
3391 ds->setExtraData(document_state);
3392 if (!content_initiated)
3393 PopulateDocumentStateFromPending(document_state);
3394 }
3395
3396 // Carry over the user agent override flag, if it exists.
3397 if (content_initiated && webview() && webview()->mainFrame() &&
3398 webview()->mainFrame()->dataSource()) {
3399 DocumentState* old_document_state =
3400 DocumentState::FromDataSource(webview()->mainFrame()->dataSource());
3401 if (old_document_state) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003402 InternalDocumentStateData* internal_data =
3403 InternalDocumentStateData::FromDocumentState(document_state);
3404 InternalDocumentStateData* old_internal_data =
3405 InternalDocumentStateData::FromDocumentState(old_document_state);
3406 internal_data->set_is_overriding_user_agent(
3407 old_internal_data->is_overriding_user_agent());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003408 }
3409 }
3410
3411 // The rest of RenderView assumes that a WebDataSource will always have a
3412 // non-null NavigationState.
3413 if (content_initiated) {
3414 document_state->set_navigation_state(
3415 NavigationState::CreateContentInitiated());
3416 } else {
3417 document_state->set_navigation_state(CreateNavigationStateFromPending());
3418 pending_navigation_params_.reset();
3419 }
3420
3421 // DocumentState::referred_by_prefetcher_ is true if we are
3422 // navigating from a page that used prefetching using a link on that
3423 // page. We are early enough in the request process here that we
3424 // can still see the DocumentState of the previous page and set
3425 // this value appropriately.
3426 // TODO(gavinp): catch the important case of navigation in a new
3427 // renderer process.
3428 if (webview()) {
3429 if (WebFrame* old_frame = webview()->mainFrame()) {
3430 const WebURLRequest& original_request = ds->originalRequest();
3431 const GURL referrer(
3432 original_request.httpHeaderField(WebString::fromUTF8("Referer")));
3433 if (!referrer.is_empty() &&
3434 DocumentState::FromDataSource(
3435 old_frame->dataSource())->was_prefetcher()) {
3436 for (; old_frame; old_frame = old_frame->traverseNext(false)) {
3437 WebDataSource* old_frame_ds = old_frame->dataSource();
3438 if (old_frame_ds && referrer == GURL(old_frame_ds->request().url())) {
3439 document_state->set_was_referred_by_prefetcher(true);
3440 break;
3441 }
3442 }
3443 }
3444 }
3445 }
3446
3447 if (content_initiated) {
3448 const WebURLRequest& request = ds->request();
3449 switch (request.cachePolicy()) {
3450 case WebURLRequest::UseProtocolCachePolicy: // normal load.
3451 document_state->set_load_type(DocumentState::LINK_LOAD_NORMAL);
3452 break;
3453 case WebURLRequest::ReloadIgnoringCacheData: // reload.
3454 document_state->set_load_type(DocumentState::LINK_LOAD_RELOAD);
3455 break;
3456 case WebURLRequest::ReturnCacheDataElseLoad: // allow stale data.
3457 document_state->set_load_type(
3458 DocumentState::LINK_LOAD_CACHE_STALE_OK);
3459 break;
3460 case WebURLRequest::ReturnCacheDataDontLoad: // Don't re-post.
3461 document_state->set_load_type(DocumentState::LINK_LOAD_CACHE_ONLY);
3462 break;
3463 }
3464 }
3465
3466 FOR_EACH_OBSERVER(
3467 RenderViewObserver, observers_, DidCreateDataSource(frame, ds));
3468}
3469
3470void RenderViewImpl::PopulateDocumentStateFromPending(
3471 DocumentState* document_state) {
3472 const ViewMsg_Navigate_Params& params = *pending_navigation_params_.get();
3473 document_state->set_request_time(params.request_time);
3474
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003475 InternalDocumentStateData* internal_data =
3476 InternalDocumentStateData::FromDocumentState(document_state);
3477
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003478 if (!params.url.SchemeIs(chrome::kJavaScriptScheme) &&
3479 params.navigation_type == ViewMsg_Navigate_Type::RESTORE) {
3480 // We're doing a load of a page that was restored from the last session. By
3481 // default this prefers the cache over loading (LOAD_PREFERRING_CACHE) which
3482 // can result in stale data for pages that are set to expire. We explicitly
3483 // override that by setting the policy here so that as necessary we load
3484 // from the network.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003485 internal_data->set_cache_policy_override(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003486 WebURLRequest::UseProtocolCachePolicy);
3487 }
3488
3489 if (IsReload(params))
3490 document_state->set_load_type(DocumentState::RELOAD);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01003491 else if (params.page_state.IsValid())
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003492 document_state->set_load_type(DocumentState::HISTORY_LOAD);
3493 else
3494 document_state->set_load_type(DocumentState::NORMAL_LOAD);
3495
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003496 internal_data->set_referrer_policy(params.referrer.policy);
3497 internal_data->set_is_overriding_user_agent(params.is_overriding_user_agent);
3498 internal_data->set_must_reset_scroll_and_scale_state(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003499 params.navigation_type ==
3500 ViewMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL);
3501 document_state->set_can_load_local_resources(params.can_load_local_resources);
3502}
3503
3504NavigationState* RenderViewImpl::CreateNavigationStateFromPending() {
3505 const ViewMsg_Navigate_Params& params = *pending_navigation_params_.get();
3506 NavigationState* navigation_state = NULL;
3507
3508 // A navigation resulting from loading a javascript URL should not be treated
3509 // as a browser initiated event. Instead, we want it to look as if the page
3510 // initiated any load resulting from JS execution.
3511 if (!params.url.SchemeIs(chrome::kJavaScriptScheme)) {
3512 navigation_state = NavigationState::CreateBrowserInitiated(
3513 params.page_id,
3514 params.pending_history_list_offset,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003515 params.should_clear_history_list,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003516 params.transition);
3517 navigation_state->set_transferred_request_child_id(
3518 params.transferred_request_child_id);
3519 navigation_state->set_transferred_request_request_id(
3520 params.transferred_request_request_id);
3521 navigation_state->set_allow_download(params.allow_download);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003522 navigation_state->set_extra_headers(params.extra_headers);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003523 } else {
3524 navigation_state = NavigationState::CreateContentInitiated();
3525 }
3526 return navigation_state;
3527}
3528
3529void RenderViewImpl::ProcessViewLayoutFlags(const CommandLine& command_line) {
3530 bool enable_viewport =
3531 command_line.HasSwitch(switches::kEnableViewport);
3532 bool enable_fixed_layout =
3533 command_line.HasSwitch(switches::kEnableFixedLayout);
3534
3535 webview()->enableFixedLayoutMode(enable_fixed_layout || enable_viewport);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003536
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003537 // If viewport tag is enabled, then the WebKit side will take care
3538 // of setting the fixed layout size and page scale limits.
3539 if (enable_viewport)
3540 return;
3541
3542 if (enable_fixed_layout) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003543 std::string str =
3544 command_line.GetSwitchValueASCII(switches::kEnableFixedLayout);
3545 std::vector<std::string> tokens;
3546 base::SplitString(str, ',', &tokens);
3547 if (tokens.size() == 2) {
3548 int width, height;
3549 if (base::StringToInt(tokens[0], &width) &&
3550 base::StringToInt(tokens[1], &height))
3551 webview()->setFixedLayoutSize(WebSize(width, height));
3552 }
3553 }
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003554 float maxPageScaleFactor =
3555 command_line.HasSwitch(switches::kEnablePinch) ? 4.f : 1.f ;
3556 webview()->setPageScaleFactorLimits(1, maxPageScaleFactor);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003557}
3558
3559void RenderViewImpl::didStartProvisionalLoad(WebFrame* frame) {
3560 WebDataSource* ds = frame->provisionalDataSource();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003561
3562 // In fast/loader/stop-provisional-loads.html, we abort the load before this
3563 // callback is invoked.
3564 if (!ds)
3565 return;
3566
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003567 DocumentState* document_state = DocumentState::FromDataSource(ds);
3568
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003569 // We should only navigate to swappedout:// when is_swapped_out_ is true.
3570 CHECK((ds->request().url() != GURL(kSwappedOutURL)) ||
3571 is_swapped_out_) << "Heard swappedout:// when not swapped out.";
3572
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003573 // Update the request time if WebKit has better knowledge of it.
3574 if (document_state->request_time().is_null()) {
3575 double event_time = ds->triggeringEventTime();
3576 if (event_time != 0.0)
3577 document_state->set_request_time(Time::FromDoubleT(event_time));
3578 }
3579
3580 // Start time is only set after request time.
3581 document_state->set_start_load_time(Time::Now());
3582
3583 bool is_top_most = !frame->parent();
3584 if (is_top_most) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003585 navigation_gesture_ = WebUserGestureIndicator::isProcessingUserGesture() ?
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003586 NavigationGestureUser : NavigationGestureAuto;
3587
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003588 // If the navigation is not triggered by a user gesture, e.g. by some ajax
3589 // callback, then inherit the submitted password form from the previous
3590 // state. This fixes the no password save issue for ajax login, tracked in
3591 // [http://crbug/43219]. Note that there are still some sites that this
3592 // fails for because they use some element other than a submit button to
3593 // trigger submission.
3594 if (navigation_gesture_ == NavigationGestureAuto) {
3595 DocumentState* old_document_state = DocumentState::FromDataSource(
3596 frame->dataSource());
3597 const content::PasswordForm* old_password_form =
3598 old_document_state->password_form_data();
3599 if (old_password_form) {
3600 document_state->set_password_form_data(
3601 make_scoped_ptr(new content::PasswordForm(*old_password_form)));
3602 }
3603 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003604 } else if (frame->parent()->isLoading()) {
3605 // Take note of AUTO_SUBFRAME loads here, so that we can know how to
3606 // load an error page. See didFailProvisionalLoad.
3607 document_state->navigation_state()->set_transition_type(
3608 PAGE_TRANSITION_AUTO_SUBFRAME);
3609 }
3610
3611 FOR_EACH_OBSERVER(
3612 RenderViewObserver, observers_, DidStartProvisionalLoad(frame));
3613
3614 Send(new ViewHostMsg_DidStartProvisionalLoadForFrame(
3615 routing_id_, frame->identifier(),
3616 frame->parent() ? frame->parent()->identifier() : -1,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003617 is_top_most, ds->request().url()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003618}
3619
3620void RenderViewImpl::didReceiveServerRedirectForProvisionalLoad(
3621 WebFrame* frame) {
3622 if (frame->parent())
3623 return;
3624 // Received a redirect on the main frame.
3625 WebDataSource* data_source = frame->provisionalDataSource();
3626 if (!data_source) {
3627 // Should only be invoked when we have a data source.
3628 NOTREACHED();
3629 return;
3630 }
3631 std::vector<GURL> redirects;
3632 GetRedirectChain(data_source, &redirects);
3633 if (redirects.size() >= 2) {
3634 Send(new ViewHostMsg_DidRedirectProvisionalLoad(routing_id_, page_id_,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003635 redirects[redirects.size() - 2], redirects.back()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003636 }
3637}
3638
3639void RenderViewImpl::didFailProvisionalLoad(WebFrame* frame,
3640 const WebURLError& error) {
3641 // Notify the browser that we failed a provisional load with an error.
3642 //
3643 // Note: It is important this notification occur before DidStopLoading so the
3644 // SSL manager can react to the provisional load failure before being
3645 // notified the load stopped.
3646 //
3647 WebDataSource* ds = frame->provisionalDataSource();
3648 DCHECK(ds);
3649
3650 const WebURLRequest& failed_request = ds->request();
3651
3652 FOR_EACH_OBSERVER(
3653 RenderViewObserver, observers_, DidFailProvisionalLoad(frame, error));
3654
3655 bool show_repost_interstitial =
3656 (error.reason == net::ERR_CACHE_MISS &&
3657 EqualsASCII(failed_request.httpMethod(), "POST"));
3658
3659 ViewHostMsg_DidFailProvisionalLoadWithError_Params params;
3660 params.frame_id = frame->identifier();
3661 params.is_main_frame = !frame->parent();
3662 params.error_code = error.reason;
3663 GetContentClient()->renderer()->GetNavigationErrorStrings(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003664 frame,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003665 failed_request,
3666 error,
3667 NULL,
3668 &params.error_description);
3669 params.url = error.unreachableURL;
3670 params.showing_repost_interstitial = show_repost_interstitial;
3671 Send(new ViewHostMsg_DidFailProvisionalLoadWithError(
3672 routing_id_, params));
3673
3674 // Don't display an error page if this is simply a cancelled load. Aside
3675 // from being dumb, WebCore doesn't expect it and it will cause a crash.
3676 if (error.reason == net::ERR_ABORTED)
3677 return;
3678
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003679 if (RenderThreadImpl::current()->layout_test_mode())
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00003680 return;
3681
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003682 // Make sure we never show errors in view source mode.
3683 frame->enableViewSourceMode(false);
3684
3685 DocumentState* document_state = DocumentState::FromDataSource(ds);
3686 NavigationState* navigation_state = document_state->navigation_state();
3687
3688 // If this is a failed back/forward/reload navigation, then we need to do a
3689 // 'replace' load. This is necessary to avoid messing up session history.
3690 // Otherwise, we do a normal load, which simulates a 'go' navigation as far
3691 // as session history is concerned.
3692 //
3693 // AUTO_SUBFRAME loads should always be treated as loads that do not advance
3694 // the page id.
3695 //
3696 bool replace =
3697 navigation_state->pending_page_id() != -1 ||
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01003698 PageTransitionCoreTypeIs(navigation_state->transition_type(),
3699 PAGE_TRANSITION_AUTO_SUBFRAME);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003700
3701 // If we failed on a browser initiated request, then make sure that our error
3702 // page load is regarded as the same browser initiated request.
3703 if (!navigation_state->is_content_initiated()) {
3704 pending_navigation_params_.reset(new ViewMsg_Navigate_Params);
3705 pending_navigation_params_->page_id =
3706 navigation_state->pending_page_id();
3707 pending_navigation_params_->pending_history_list_offset =
3708 navigation_state->pending_history_list_offset();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003709 pending_navigation_params_->should_clear_history_list =
3710 navigation_state->history_list_was_cleared();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003711 pending_navigation_params_->transition =
3712 navigation_state->transition_type();
3713 pending_navigation_params_->request_time =
3714 document_state->request_time();
3715 }
3716
3717 // Provide the user with a more helpful error page?
3718 if (MaybeLoadAlternateErrorPage(frame, error, replace))
3719 return;
3720
3721 // Fallback to a local error page.
3722 LoadNavigationErrorPage(frame, failed_request, error, std::string(), replace);
3723}
3724
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003725void RenderViewImpl::didCommitProvisionalLoad(WebFrame* frame,
3726 bool is_new_navigation) {
3727 DocumentState* document_state =
3728 DocumentState::FromDataSource(frame->dataSource());
3729 NavigationState* navigation_state = document_state->navigation_state();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003730 InternalDocumentStateData* internal_data =
3731 InternalDocumentStateData::FromDocumentState(document_state);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003732
3733 if (document_state->commit_load_time().is_null())
3734 document_state->set_commit_load_time(Time::Now());
3735
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003736 if (internal_data->must_reset_scroll_and_scale_state()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003737 webview()->resetScrollAndScaleState();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003738 internal_data->set_must_reset_scroll_and_scale_state(false);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003739 }
Ben Murdochca12bfa2013-07-23 11:17:05 +01003740 internal_data->set_use_error_page(false);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003741
3742 if (is_new_navigation) {
3743 // When we perform a new navigation, we need to update the last committed
3744 // session history entry with state for the page we are leaving.
3745 UpdateSessionHistory(frame);
3746
3747 // We bump our Page ID to correspond with the new session history entry.
3748 page_id_ = next_page_id_++;
3749
3750 // Don't update history_page_ids_ (etc) for kSwappedOutURL, since
3751 // we don't want to forget the entry that was there, and since we will
3752 // never come back to kSwappedOutURL. Note that we have to call
3753 // UpdateSessionHistory and update page_id_ even in this case, so that
3754 // the current entry gets a state update and so that we don't send a
3755 // state update to the wrong entry when we swap back in.
3756 if (GetLoadingUrl(frame) != GURL(kSwappedOutURL)) {
3757 // Advance our offset in session history, applying the length limit.
3758 // There is now no forward history.
3759 history_list_offset_++;
3760 if (history_list_offset_ >= kMaxSessionHistoryEntries)
3761 history_list_offset_ = kMaxSessionHistoryEntries - 1;
3762 history_list_length_ = history_list_offset_ + 1;
3763 history_page_ids_.resize(history_list_length_, -1);
3764 history_page_ids_[history_list_offset_] = page_id_;
3765 }
3766 } else {
3767 // Inspect the navigation_state on this frame to see if the navigation
3768 // corresponds to a session history navigation... Note: |frame| may or
3769 // may not be the toplevel frame, but for the case of capturing session
3770 // history, the first committed frame suffices. We keep track of whether
3771 // we've seen this commit before so that only capture session history once
3772 // per navigation.
3773 //
3774 // Note that we need to check if the page ID changed. In the case of a
3775 // reload, the page ID doesn't change, and UpdateSessionHistory gets the
3776 // previous URL and the current page ID, which would be wrong.
3777 if (navigation_state->pending_page_id() != -1 &&
3778 navigation_state->pending_page_id() != page_id_ &&
3779 !navigation_state->request_committed()) {
3780 // This is a successful session history navigation!
3781 UpdateSessionHistory(frame);
3782 page_id_ = navigation_state->pending_page_id();
3783
3784 history_list_offset_ = navigation_state->pending_history_list_offset();
3785
3786 // If the history list is valid, our list of page IDs should be correct.
3787 DCHECK(history_list_length_ <= 0 ||
3788 history_list_offset_ < 0 ||
3789 history_list_offset_ >= history_list_length_ ||
3790 history_page_ids_[history_list_offset_] == page_id_);
3791 }
3792 }
3793
3794 FOR_EACH_OBSERVER(RenderViewObserver, observers_,
3795 DidCommitProvisionalLoad(frame, is_new_navigation));
3796
3797 // Remember that we've already processed this request, so we don't update
3798 // the session history again. We do this regardless of whether this is
3799 // a session history navigation, because if we attempted a session history
3800 // navigation without valid HistoryItem state, WebCore will think it is a
3801 // new navigation.
3802 navigation_state->set_request_committed(true);
3803
3804 UpdateURL(frame);
3805
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003806 // Check whether we have new encoding name.
3807 UpdateEncoding(frame, frame->view()->pageEncoding().utf8());
3808
3809 if (!frame->parent()) { // Only for top frames.
3810 RenderThreadImpl* render_thread_impl = RenderThreadImpl::current();
3811 if (render_thread_impl) { // Can be NULL in tests.
3812 render_thread_impl->histogram_customizer()->
3813 RenderViewNavigatedToHost(GURL(GetLoadingUrl(frame)).host(),
3814 g_view_map.Get().size());
3815 }
3816 }
3817}
3818
3819void RenderViewImpl::didClearWindowObject(WebFrame* frame) {
3820 FOR_EACH_OBSERVER(RenderViewObserver, observers_,
3821 DidClearWindowObject(frame));
3822
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003823 if (enabled_bindings_ & BINDINGS_POLICY_DOM_AUTOMATION) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003824 if (!dom_automation_controller_)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003825 dom_automation_controller_.reset(new DomAutomationController());
3826 dom_automation_controller_->set_message_sender(
3827 static_cast<RenderView*>(this));
3828 dom_automation_controller_->set_routing_id(routing_id());
3829 dom_automation_controller_->BindToJavascript(frame,
3830 "domAutomationController");
3831 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01003832
3833 if (enabled_bindings_ & BINDINGS_POLICY_STATS_COLLECTION) {
3834 if (!stats_collection_controller_.get())
3835 stats_collection_controller_.reset(new StatsCollectionController());
3836 stats_collection_controller_->set_message_sender(
3837 static_cast<RenderView*>(this));
3838 stats_collection_controller_->BindToJavascript(frame,
3839 "statsCollectionController");
3840 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003841}
3842
3843void RenderViewImpl::didCreateDocumentElement(WebFrame* frame) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003844 FOR_EACH_OBSERVER(RenderViewObserver, observers_,
3845 DidCreateDocumentElement(frame));
3846}
3847
3848void RenderViewImpl::didReceiveTitle(WebFrame* frame, const WebString& title,
3849 WebTextDirection direction) {
3850 UpdateTitle(frame, title, direction);
3851
3852 // Also check whether we have new encoding name.
3853 UpdateEncoding(frame, frame->view()->pageEncoding().utf8());
3854}
3855
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003856void RenderViewImpl::didChangeIcon(WebFrame* frame,
3857 WebIconURL::Type icon_type) {
3858 if (frame->parent())
3859 return;
3860
3861 if (!TouchEnabled() && icon_type != WebIconURL::TypeFavicon)
3862 return;
3863
3864 WebVector<WebIconURL> icon_urls = frame->iconURLs(icon_type);
3865 std::vector<FaviconURL> urls;
3866 for (size_t i = 0; i < icon_urls.size(); i++) {
3867 urls.push_back(FaviconURL(icon_urls[i].iconURL(),
3868 ToFaviconType(icon_urls[i].iconType())));
3869 }
3870 SendUpdateFaviconURL(urls);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003871}
3872
3873void RenderViewImpl::didFinishDocumentLoad(WebFrame* frame) {
3874 WebDataSource* ds = frame->dataSource();
3875 DocumentState* document_state = DocumentState::FromDataSource(ds);
3876 document_state->set_finish_document_load_time(Time::Now());
3877
3878 Send(new ViewHostMsg_DocumentLoadedInFrame(routing_id_, frame->identifier()));
3879
3880 FOR_EACH_OBSERVER(RenderViewObserver, observers_,
3881 DidFinishDocumentLoad(frame));
3882
3883 // Check whether we have new encoding name.
3884 UpdateEncoding(frame, frame->view()->pageEncoding().utf8());
3885}
3886
3887void RenderViewImpl::didHandleOnloadEvents(WebFrame* frame) {
3888 if (webview()->mainFrame() == frame) {
3889 Send(new ViewHostMsg_DocumentOnLoadCompletedInMainFrame(routing_id_,
3890 page_id_));
3891 }
3892}
3893
3894void RenderViewImpl::didFailLoad(WebFrame* frame, const WebURLError& error) {
3895 WebDataSource* ds = frame->dataSource();
3896 DCHECK(ds);
3897
3898
3899 FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidFailLoad(frame, error));
3900
3901 const WebURLRequest& failed_request = ds->request();
3902 string16 error_description;
3903 GetContentClient()->renderer()->GetNavigationErrorStrings(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003904 frame,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003905 failed_request,
3906 error,
3907 NULL,
3908 &error_description);
3909 Send(new ViewHostMsg_DidFailLoadWithError(routing_id_,
3910 frame->identifier(),
3911 failed_request.url(),
3912 !frame->parent(),
3913 error.reason,
3914 error_description));
3915}
3916
3917void RenderViewImpl::didFinishLoad(WebFrame* frame) {
3918 WebDataSource* ds = frame->dataSource();
3919 DocumentState* document_state = DocumentState::FromDataSource(ds);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01003920 if (document_state->finish_load_time().is_null()) {
3921 if (!frame->parent()) {
3922 TRACE_EVENT_INSTANT0("WebCore", "LoadFinished",
3923 TRACE_EVENT_SCOPE_PROCESS);
3924 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003925 document_state->set_finish_load_time(Time::Now());
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01003926 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003927
3928 FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidFinishLoad(frame));
3929
3930 Send(new ViewHostMsg_DidFinishLoad(routing_id_,
3931 frame->identifier(),
3932 ds->request().url(),
3933 !frame->parent()));
3934}
3935
3936void RenderViewImpl::didNavigateWithinPage(
3937 WebFrame* frame, bool is_new_navigation) {
3938 // If this was a reference fragment navigation that we initiated, then we
3939 // could end up having a non-null pending navigation params. We just need to
3940 // update the ExtraData on the datasource so that others who read the
3941 // ExtraData will get the new NavigationState. Similarly, if we did not
3942 // initiate this navigation, then we need to take care to reset any pre-
3943 // existing navigation state to a content-initiated navigation state.
3944 // DidCreateDataSource conveniently takes care of this for us.
3945 didCreateDataSource(frame, frame->dataSource());
3946
3947 DocumentState* document_state =
3948 DocumentState::FromDataSource(frame->dataSource());
3949 NavigationState* new_state = document_state->navigation_state();
3950 new_state->set_was_within_same_page(true);
3951
3952 didCommitProvisionalLoad(frame, is_new_navigation);
3953
3954 WebDataSource* datasource = frame->view()->mainFrame()->dataSource();
3955 UpdateTitle(frame, datasource->pageTitle(), datasource->pageTitleDirection());
3956}
3957
3958void RenderViewImpl::didUpdateCurrentHistoryItem(WebFrame* frame) {
3959 StartNavStateSyncTimerIfNecessary();
3960}
3961
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003962void RenderViewImpl::willSendRequest(WebFrame* frame,
3963 unsigned identifier,
3964 WebURLRequest& request,
3965 const WebURLResponse& redirect_response) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01003966 NOTREACHED();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003967}
3968
3969void RenderViewImpl::didReceiveResponse(
3970 WebFrame* frame, unsigned identifier, const WebURLResponse& response) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01003971 NOTREACHED();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003972}
3973
3974void RenderViewImpl::didFinishResourceLoad(
3975 WebFrame* frame, unsigned identifier) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003976 InternalDocumentStateData* internal_data =
3977 InternalDocumentStateData::FromDataSource(frame->dataSource());
3978 if (!internal_data->use_error_page())
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003979 return;
3980
3981 // Do not show error page when DevTools is attached.
3982 if (devtools_agent_->IsAttached())
3983 return;
3984
3985 // Display error page, if appropriate.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003986 int http_status_code = internal_data->http_status_code();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00003987 if (http_status_code == 404) {
3988 // On 404s, try a remote search page as a fallback.
3989 const GURL& document_url = frame->document().url();
3990
3991 const GURL& error_page_url =
3992 GetAlternateErrorPageURL(document_url, HTTP_404);
3993 if (error_page_url.is_valid()) {
3994 WebURLError original_error;
3995 original_error.domain = "http";
3996 original_error.reason = 404;
3997 original_error.unreachableURL = document_url;
3998
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01003999 internal_data->set_alt_error_page_fetcher(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004000 new AltErrorPageResourceFetcher(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01004001 error_page_url, frame, frame->dataSource()->request(),
4002 original_error,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004003 base::Bind(&RenderViewImpl::AltErrorPageFinished,
4004 base::Unretained(this))));
4005 return;
4006 }
4007 }
4008
4009 std::string error_domain;
4010 if (GetContentClient()->renderer()->HasErrorPage(
4011 http_status_code, &error_domain)) {
4012 WebURLError error;
4013 error.unreachableURL = frame->document().url();
4014 error.domain = WebString::fromUTF8(error_domain);
4015 error.reason = http_status_code;
4016
4017 LoadNavigationErrorPage(
4018 frame, frame->dataSource()->request(), error, std::string(), true);
4019 }
4020}
4021
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004022void RenderViewImpl::didLoadResourceFromMemoryCache(
4023 WebFrame* frame, const WebURLRequest& request,
4024 const WebURLResponse& response) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01004025 NOTREACHED();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004026}
4027
4028void RenderViewImpl::didDisplayInsecureContent(WebFrame* frame) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01004029 NOTREACHED();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004030}
4031
4032void RenderViewImpl::didRunInsecureContent(
4033 WebFrame* frame, const WebSecurityOrigin& origin, const WebURL& target) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01004034 NOTREACHED();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004035}
4036
4037void RenderViewImpl::didExhaustMemoryAvailableForScript(WebFrame* frame) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01004038 NOTREACHED();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004039}
4040
4041void RenderViewImpl::didCreateScriptContext(WebFrame* frame,
4042 v8::Handle<v8::Context> context,
4043 int extension_group,
4044 int world_id) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01004045 NOTREACHED();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004046}
4047
4048void RenderViewImpl::willReleaseScriptContext(WebFrame* frame,
4049 v8::Handle<v8::Context> context,
4050 int world_id) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01004051 NOTREACHED();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004052}
4053
4054void RenderViewImpl::CheckPreferredSize() {
4055 // We don't always want to send the change messages over IPC, only if we've
4056 // been put in that mode by getting a |ViewMsg_EnablePreferredSizeChangedMode|
4057 // message.
4058 if (!send_preferred_size_changes_ || !webview())
4059 return;
4060
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01004061 gfx::Size size = webview()->contentsPreferredMinimumSize();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004062
Ben Murdoch58e6fbe2013-07-26 10:20:38 +01004063 // In the presence of zoom, these sizes are still reported as if unzoomed,
4064 // so we need to adjust.
4065 double zoom_factor = ZoomLevelToZoomFactor(webview()->zoomLevel());
4066 size.set_width(static_cast<int>(size.width() * zoom_factor));
4067 size.set_height(static_cast<int>(size.height() * zoom_factor));
4068
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004069 if (size == preferred_size_)
4070 return;
4071
4072 preferred_size_ = size;
4073 Send(new ViewHostMsg_DidContentsPreferredSizeChange(routing_id_,
4074 preferred_size_));
4075}
4076
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01004077BrowserPluginManager* RenderViewImpl::GetBrowserPluginManager() {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01004078 if (!browser_plugin_manager_.get())
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004079 browser_plugin_manager_ = BrowserPluginManager::Create(this);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01004080 return browser_plugin_manager_.get();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004081}
4082
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004083void RenderViewImpl::EnsureMediaStreamClient() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004084 if (!RenderThreadImpl::current()) // Will be NULL during unit tests.
4085 return;
4086
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004087#if defined(OS_ANDROID)
4088 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableWebRTC))
4089 return;
4090#endif
4091
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004092#if defined(ENABLE_WEBRTC)
4093 if (!media_stream_dispatcher_)
4094 media_stream_dispatcher_ = new MediaStreamDispatcher(this);
4095
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004096 if (!media_stream_client_) {
4097 MediaStreamImpl* media_stream_impl = new MediaStreamImpl(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004098 this,
4099 media_stream_dispatcher_,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004100 RenderThreadImpl::current()->GetMediaStreamDependencyFactory());
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01004101 media_stream_client_ = media_stream_impl;
4102 web_user_media_client_ = media_stream_impl;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004103 }
4104#endif
4105}
4106
4107void RenderViewImpl::didChangeContentsSize(WebFrame* frame,
4108 const WebSize& size) {
4109 if (webview()->mainFrame() != frame)
4110 return;
4111 WebView* frameView = frame->view();
4112 if (!frameView)
4113 return;
4114
4115 bool has_horizontal_scrollbar = frame->hasHorizontalScrollbar();
4116 bool has_vertical_scrollbar = frame->hasVerticalScrollbar();
4117
4118 if (has_horizontal_scrollbar != cached_has_main_frame_horizontal_scrollbar_ ||
4119 has_vertical_scrollbar != cached_has_main_frame_vertical_scrollbar_) {
4120 Send(new ViewHostMsg_DidChangeScrollbarsForMainFrame(
4121 routing_id_, has_horizontal_scrollbar, has_vertical_scrollbar));
4122
4123 cached_has_main_frame_horizontal_scrollbar_ = has_horizontal_scrollbar;
4124 cached_has_main_frame_vertical_scrollbar_ = has_vertical_scrollbar;
4125 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004126}
4127
4128void RenderViewImpl::UpdateScrollState(WebFrame* frame) {
4129 WebSize offset = frame->scrollOffset();
4130 WebSize minimum_offset = frame->minimumScrollOffset();
4131 WebSize maximum_offset = frame->maximumScrollOffset();
4132
4133 bool is_pinned_to_left = offset.width <= minimum_offset.width;
4134 bool is_pinned_to_right = offset.width >= maximum_offset.width;
4135
4136 if (is_pinned_to_left != cached_is_main_frame_pinned_to_left_ ||
4137 is_pinned_to_right != cached_is_main_frame_pinned_to_right_) {
4138 Send(new ViewHostMsg_DidChangeScrollOffsetPinningForMainFrame(
4139 routing_id_, is_pinned_to_left, is_pinned_to_right));
4140
4141 cached_is_main_frame_pinned_to_left_ = is_pinned_to_left;
4142 cached_is_main_frame_pinned_to_right_ = is_pinned_to_right;
4143 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004144
4145 Send(new ViewHostMsg_DidChangeScrollOffset(routing_id_));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004146}
4147
4148void RenderViewImpl::didChangeScrollOffset(WebFrame* frame) {
4149 StartNavStateSyncTimerIfNecessary();
4150
4151 if (webview()->mainFrame() == frame)
4152 UpdateScrollState(frame);
4153
4154 FOR_EACH_OBSERVER(
4155 RenderViewObserver, observers_, DidChangeScrollOffset(frame));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004156}
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004157
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004158void RenderViewImpl::willInsertBody(WebKit::WebFrame* frame) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01004159 NOTREACHED();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004160}
4161
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004162void RenderViewImpl::didFirstVisuallyNonEmptyLayout(WebFrame* frame) {
4163 if (frame != webview()->mainFrame())
4164 return;
4165
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01004166 InternalDocumentStateData* data =
4167 InternalDocumentStateData::FromDataSource(frame->dataSource());
4168 data->set_did_first_visually_non_empty_layout(true);
4169
4170#if defined(OS_ANDROID)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004171 // Update body background color if necessary.
4172 SkColor bg_color = webwidget_->backgroundColor();
4173
4174 // If not initialized, default to white. Note that 0 is different from black
4175 // as black still has alpha 0xFF.
4176 if (!bg_color)
4177 bg_color = SK_ColorWHITE;
4178
4179 if (bg_color != body_background_color_) {
4180 body_background_color_ = bg_color;
Ben Murdochbbcdd452013-07-25 10:06:34 +01004181 Send(new ViewHostMsg_DidChangeBodyBackgroundColor(
4182 GetRoutingID(), bg_color));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004183 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004184#endif
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01004185}
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004186
4187void RenderViewImpl::SendFindReply(int request_id,
4188 int match_count,
4189 int ordinal,
4190 const WebRect& selection_rect,
4191 bool final_status_update) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004192 Send(new ViewHostMsg_Find_Reply(routing_id_,
4193 request_id,
4194 match_count,
4195 selection_rect,
4196 ordinal,
4197 final_status_update));
4198}
4199
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004200// static
4201bool RenderViewImpl::ShouldUpdateSelectionTextFromContextMenuParams(
4202 const string16& selection_text,
4203 size_t selection_text_offset,
4204 const ui::Range& selection_range,
4205 const ContextMenuParams& params) {
4206 string16 trimmed_selection_text;
4207 if (!selection_text.empty() && !selection_range.is_empty()) {
4208 const int start = selection_range.GetMin() - selection_text_offset;
4209 const size_t length = selection_range.length();
4210 if (start >= 0 && start + length <= selection_text.length()) {
4211 TrimWhitespace(selection_text.substr(start, length), TRIM_ALL,
4212 &trimmed_selection_text);
4213 }
4214 }
4215 string16 trimmed_params_text;
4216 TrimWhitespace(params.selection_text, TRIM_ALL, &trimmed_params_text);
4217 return trimmed_params_text != trimmed_selection_text;
4218}
4219
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004220void RenderViewImpl::reportFindInPageMatchCount(int request_id,
4221 int count,
4222 bool final_update) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01004223 NOTREACHED();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004224}
4225
4226void RenderViewImpl::reportFindInPageSelection(int request_id,
4227 int active_match_ordinal,
4228 const WebRect& selection_rect) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01004229 NOTREACHED();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004230}
4231
4232void RenderViewImpl::openFileSystem(
4233 WebFrame* frame,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004234 WebKit::WebFileSystemType type,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004235 long long size,
4236 bool create,
4237 WebFileSystemCallbacks* callbacks) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01004238 NOTREACHED();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004239}
4240
4241void RenderViewImpl::deleteFileSystem(
4242 WebFrame* frame,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004243 WebKit::WebFileSystemType type ,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004244 WebFileSystemCallbacks* callbacks) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01004245 NOTREACHED();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004246}
4247
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004248void RenderViewImpl::requestStorageQuota(
4249 WebFrame* frame,
4250 WebStorageQuotaType type,
4251 unsigned long long requested_size,
4252 WebStorageQuotaCallbacks* callbacks) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01004253 NOTREACHED();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004254}
4255
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004256bool RenderViewImpl::willCheckAndDispatchMessageEvent(
4257 WebKit::WebFrame* sourceFrame,
4258 WebKit::WebFrame* targetFrame,
4259 WebKit::WebSecurityOrigin target_origin,
4260 WebKit::WebDOMMessageEvent event) {
4261 if (!is_swapped_out_)
4262 return false;
4263
4264 ViewMsg_PostMessage_Params params;
4265 params.data = event.data().toString();
4266 params.source_origin = event.origin();
4267 if (!target_origin.isNull())
4268 params.target_origin = target_origin.toString();
4269
4270 // Include the routing ID for the source frame, which the browser process
4271 // will translate into the routing ID for the equivalent frame in the target
4272 // process.
4273 params.source_routing_id = MSG_ROUTING_NONE;
4274 RenderViewImpl* source_view = FromWebView(sourceFrame->view());
4275 if (source_view)
4276 params.source_routing_id = source_view->routing_id();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004277
4278 Send(new ViewHostMsg_RouteMessageEvent(routing_id_, params));
4279 return true;
4280}
4281
4282void RenderViewImpl::willOpenSocketStream(
4283 WebSocketStreamHandle* handle) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01004284 NOTREACHED();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004285}
4286
4287void RenderViewImpl::willStartUsingPeerConnectionHandler(
4288 WebKit::WebFrame* frame, WebKit::WebRTCPeerConnectionHandler* handler) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01004289 NOTREACHED();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004290}
4291
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01004292WebKit::WebString RenderViewImpl::acceptLanguages() {
4293 return WebString::fromUTF8(renderer_preferences_.accept_languages);
4294}
4295
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004296WebKit::WebString RenderViewImpl::userAgentOverride(
4297 WebKit::WebFrame* frame,
4298 const WebKit::WebURL& url) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01004299 NOTREACHED();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01004300 return WebKit::WebString();
4301}
4302
4303WebString RenderViewImpl::doNotTrackValue(WebFrame* frame) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01004304 NOTREACHED();
4305 return WebKit::WebString();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004306}
4307
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004308bool RenderViewImpl::allowWebGL(WebFrame* frame, bool default_value) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01004309 NOTREACHED();
4310 return false;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004311}
4312
4313void RenderViewImpl::didLoseWebGLContext(
4314 WebKit::WebFrame* frame,
4315 int arb_robustness_status_code) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01004316 NOTREACHED();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004317}
4318
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004319// WebKit::WebPageSerializerClient implementation ------------------------------
4320
4321void RenderViewImpl::didSerializeDataForFrame(
4322 const WebURL& frame_url,
4323 const WebCString& data,
4324 WebPageSerializerClient::PageSerializationStatus status) {
4325 Send(new ViewHostMsg_SendSerializedHtmlData(
4326 routing_id(),
4327 frame_url,
4328 data.data(),
4329 static_cast<int32>(status)));
4330}
4331
4332// RenderView implementation ---------------------------------------------------
4333
4334bool RenderViewImpl::Send(IPC::Message* message) {
4335 return RenderWidget::Send(message);
4336}
4337
4338int RenderViewImpl::GetRoutingID() const {
4339 return routing_id_;
4340}
4341
4342int RenderViewImpl::GetPageId() const {
4343 return page_id_;
4344}
4345
4346gfx::Size RenderViewImpl::GetSize() const {
4347 return size();
4348}
4349
4350WebPreferences& RenderViewImpl::GetWebkitPreferences() {
4351 return webkit_preferences_;
4352}
4353
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004354void RenderViewImpl::SetWebkitPreferences(const WebPreferences& preferences) {
4355 OnUpdateWebPreferences(preferences);
4356}
4357
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004358WebKit::WebView* RenderViewImpl::GetWebView() {
4359 return webview();
4360}
4361
4362WebKit::WebNode RenderViewImpl::GetFocusedNode() const {
4363 if (!webview())
4364 return WebNode();
4365 WebFrame* focused_frame = webview()->focusedFrame();
4366 if (focused_frame) {
4367 WebDocument doc = focused_frame->document();
4368 if (!doc.isNull())
4369 return doc.focusedNode();
4370 }
4371
4372 return WebNode();
4373}
4374
4375WebKit::WebNode RenderViewImpl::GetContextMenuNode() const {
4376 return context_menu_node_;
4377}
4378
4379bool RenderViewImpl::IsEditableNode(const WebNode& node) const {
4380 if (node.isNull())
4381 return false;
4382
4383 if (node.isContentEditable())
4384 return true;
4385
4386 if (node.isElementNode()) {
4387 const WebElement& element = node.toConst<WebElement>();
4388 if (element.isTextFormControlElement())
4389 return true;
4390
4391 // Also return true if it has an ARIA role of 'textbox'.
4392 for (unsigned i = 0; i < element.attributeCount(); ++i) {
4393 if (LowerCaseEqualsASCII(element.attributeLocalName(i), "role")) {
4394 if (LowerCaseEqualsASCII(element.attributeValue(i), "textbox"))
4395 return true;
4396 break;
4397 }
4398 }
4399 }
4400
4401 return false;
4402}
4403
4404WebKit::WebPlugin* RenderViewImpl::CreatePlugin(
4405 WebKit::WebFrame* frame,
Ben Murdochca12bfa2013-07-23 11:17:05 +01004406 const WebPluginInfo& info,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004407 const WebKit::WebPluginParams& params) {
Ben Murdoch32409262013-08-07 11:04:47 +01004408#if defined(ENABLE_PLUGINS)
4409 bool pepper_plugin_was_registered = false;
4410 scoped_refptr<PluginModule> pepper_module(PluginModule::Create(
4411 this, info, &pepper_plugin_was_registered));
4412 if (pepper_plugin_was_registered) {
4413 if (pepper_module.get())
4414 return new PepperWebPluginImpl(pepper_module.get(), params, AsWeakPtr());
4415 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004416
Ben Murdochca12bfa2013-07-23 11:17:05 +01004417 return new WebPluginImpl(frame, params, info.path, AsWeakPtr());
Ben Murdoch32409262013-08-07 11:04:47 +01004418#else
4419 return NULL;
4420#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004421}
4422
4423void RenderViewImpl::EvaluateScript(const string16& frame_xpath,
4424 const string16& jscript,
4425 int id,
4426 bool notify_result) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004427 v8::HandleScope handle_scope;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004428 v8::Handle<v8::Value> result;
4429 WebFrame* web_frame = GetChildFrame(frame_xpath);
4430 if (web_frame)
4431 result = web_frame->executeScriptAndReturnValue(WebScriptSource(jscript));
4432 if (notify_result) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004433 base::ListValue list;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004434 if (!result.IsEmpty() && web_frame) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004435 v8::Local<v8::Context> context = web_frame->mainWorldScriptContext();
4436 v8::Context::Scope context_scope(context);
4437 V8ValueConverterImpl converter;
4438 converter.SetDateAllowed(true);
4439 converter.SetRegExpAllowed(true);
4440 base::Value* result_value = converter.FromV8Value(result, context);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004441 list.Set(0, result_value ? result_value : base::Value::CreateNullValue());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004442 } else {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004443 list.Set(0, base::Value::CreateNullValue());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004444 }
4445 Send(new ViewHostMsg_ScriptEvalResponse(routing_id_, id, list));
4446 }
4447}
4448
4449bool RenderViewImpl::ShouldDisplayScrollbars(int width, int height) const {
4450 return (!send_preferred_size_changes_ ||
4451 (disable_scrollbars_size_limit_.width() <= width ||
4452 disable_scrollbars_size_limit_.height() <= height));
4453}
4454
4455int RenderViewImpl::GetEnabledBindings() const {
4456 return enabled_bindings_;
4457}
4458
4459bool RenderViewImpl::GetContentStateImmediately() const {
4460 return send_content_state_immediately_;
4461}
4462
4463float RenderViewImpl::GetFilteredTimePerFrame() const {
4464 return filtered_time_per_frame();
4465}
4466
4467int RenderViewImpl::ShowContextMenu(ContextMenuClient* client,
4468 const ContextMenuParams& params) {
4469 DCHECK(client); // A null client means "internal" when we issue callbacks.
4470 ContextMenuParams our_params(params);
4471 our_params.custom_context.request_id = pending_context_menus_.Add(client);
4472 Send(new ViewHostMsg_ContextMenu(routing_id_, our_params));
4473 return our_params.custom_context.request_id;
4474}
4475
4476void RenderViewImpl::CancelContextMenu(int request_id) {
4477 DCHECK(pending_context_menus_.Lookup(request_id));
4478 pending_context_menus_.Remove(request_id);
4479}
4480
4481WebKit::WebPageVisibilityState RenderViewImpl::GetVisibilityState() const {
4482 return visibilityState();
4483}
4484
4485void RenderViewImpl::RunModalAlertDialog(WebKit::WebFrame* frame,
4486 const WebKit::WebString& message) {
4487 return runModalAlertDialog(frame, message);
4488}
4489
4490void RenderViewImpl::LoadURLExternally(
4491 WebKit::WebFrame* frame,
4492 const WebKit::WebURLRequest& request,
4493 WebKit::WebNavigationPolicy policy) {
Ben Murdochbbcdd452013-07-25 10:06:34 +01004494 main_render_frame_->loadURLExternally(frame, request, policy);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004495}
4496
Ben Murdochca12bfa2013-07-23 11:17:05 +01004497void RenderViewImpl::DidStartLoading() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004498 didStartLoading();
4499}
4500
Ben Murdochca12bfa2013-07-23 11:17:05 +01004501void RenderViewImpl::DidStopLoading() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004502 didStopLoading();
4503}
4504
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004505void RenderViewImpl::DidPlay(WebKit::WebMediaPlayer* player) {
4506 Send(new ViewHostMsg_MediaNotification(routing_id_,
4507 reinterpret_cast<int64>(player),
4508 player->hasVideo(),
4509 player->hasAudio(),
4510 true));
4511}
4512
4513void RenderViewImpl::DidPause(WebKit::WebMediaPlayer* player) {
4514 Send(new ViewHostMsg_MediaNotification(routing_id_,
4515 reinterpret_cast<int64>(player),
4516 player->hasVideo(),
4517 player->hasAudio(),
4518 false));
4519}
4520
4521void RenderViewImpl::PlayerGone(WebKit::WebMediaPlayer* player) {
4522 DidPause(player);
4523}
4524
4525void RenderViewImpl::SyncNavigationState() {
4526 if (!webview())
4527 return;
4528
4529 const WebHistoryItem& item = webview()->mainFrame()->currentHistoryItem();
4530 SendUpdateState(item);
4531}
4532
4533void RenderViewImpl::SyncSelectionIfRequired() {
4534 WebFrame* frame = webview()->focusedFrame();
4535 if (!frame)
4536 return;
4537
4538 string16 text;
4539 size_t offset;
4540 ui::Range range;
Ben Murdoch32409262013-08-07 11:04:47 +01004541#if defined(ENABLE_PLUGINS)
4542 if (focused_pepper_plugin_) {
4543 focused_pepper_plugin_->GetSurroundingText(&text, &range);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004544 offset = 0; // Pepper API does not support offset reporting.
4545 // TODO(kinaba): cut as needed.
Ben Murdoch32409262013-08-07 11:04:47 +01004546 } else
4547#endif
4548 {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004549 size_t location, length;
4550 if (!webview()->caretOrSelectionRange(&location, &length))
4551 return;
4552
4553 range = ui::Range(location, location + length);
4554
Ben Murdocheb525c52013-07-10 11:40:50 +01004555 if (webview()->textInputInfo().type != WebKit::WebTextInputTypeNone) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004556 // If current focused element is editable, we will send 100 more chars
4557 // before and after selection. It is for input method surrounding text
4558 // feature.
4559 if (location > kExtraCharsBeforeAndAfterSelection)
4560 offset = location - kExtraCharsBeforeAndAfterSelection;
4561 else
4562 offset = 0;
4563 length = location + length - offset + kExtraCharsBeforeAndAfterSelection;
4564 WebRange webrange = WebRange::fromDocumentRange(frame, offset, length);
4565 if (!webrange.isNull())
4566 text = WebRange::fromDocumentRange(frame, offset, length).toPlainText();
4567 } else {
4568 offset = location;
4569 text = frame->selectionAsText();
4570 // http://crbug.com/101435
4571 // In some case, frame->selectionAsText() returned text's length is not
4572 // equal to the length returned from webview()->caretOrSelectionRange().
4573 // So we have to set the range according to text.length().
4574 range.set_end(range.start() + text.length());
4575 }
4576 }
4577
4578 // Sometimes we get repeated didChangeSelection calls from webkit when
4579 // the selection hasn't actually changed. We don't want to report these
4580 // because it will cause us to continually claim the X clipboard.
4581 if (selection_text_offset_ != offset ||
4582 selection_range_ != range ||
4583 selection_text_ != text) {
4584 selection_text_ = text;
4585 selection_text_offset_ = offset;
4586 selection_range_ = range;
4587 Send(new ViewHostMsg_SelectionChanged(routing_id_, text, offset, range));
4588 }
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01004589 UpdateSelectionBounds();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004590}
4591
4592GURL RenderViewImpl::GetAlternateErrorPageURL(const GURL& failed_url,
4593 ErrorPageType error_type) {
4594 if (failed_url.SchemeIsSecure()) {
4595 // If the URL that failed was secure, then the embedding web page was not
4596 // expecting a network attacker to be able to manipulate its contents. As
4597 // we fetch alternate error pages over HTTP, we would be allowing a network
4598 // attacker to manipulate the contents of the response if we tried to use
4599 // the link doctor here.
4600 return GURL();
4601 }
4602
4603 // Grab the base URL from the browser process.
4604 if (!alternate_error_page_url_.is_valid())
4605 return GURL();
4606
4607 // Strip query params from the failed URL.
4608 GURL::Replacements remove_params;
4609 remove_params.ClearUsername();
4610 remove_params.ClearPassword();
4611 remove_params.ClearQuery();
4612 remove_params.ClearRef();
4613 const GURL url_to_send = failed_url.ReplaceComponents(remove_params);
4614 std::string spec_to_send = url_to_send.spec();
4615 // Notify link doctor of the url truncation by sending of "?" at the end.
4616 if (failed_url.has_query())
4617 spec_to_send.append("?");
4618
4619 // Construct the query params to send to link doctor.
4620 std::string params(alternate_error_page_url_.query());
4621 params.append("&url=");
4622 params.append(net::EscapeQueryParamValue(spec_to_send, true));
4623 params.append("&sourceid=chrome");
4624 params.append("&error=");
4625 switch (error_type) {
4626 case DNS_ERROR:
4627 params.append("dnserror");
4628 break;
4629
4630 case HTTP_404:
4631 params.append("http404");
4632 break;
4633
4634 case CONNECTION_ERROR:
4635 params.append("connectionfailure");
4636 break;
4637
4638 default:
4639 NOTREACHED() << "unknown ErrorPageType";
4640 }
4641
4642 // OK, build the final url to return.
4643 GURL::Replacements link_doctor_params;
4644 link_doctor_params.SetQueryStr(params);
4645 GURL url = alternate_error_page_url_.ReplaceComponents(link_doctor_params);
4646 return url;
4647}
4648
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004649GURL RenderViewImpl::GetLoadingUrl(WebKit::WebFrame* frame) const {
4650 WebDataSource* ds = frame->dataSource();
4651 if (ds->hasUnreachableURL())
4652 return ds->unreachableURL();
4653
4654 const WebURLRequest& request = ds->request();
4655 return request.url();
4656}
4657
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004658WebKit::WebPlugin* RenderViewImpl::GetWebPluginFromPluginDocument() {
4659 return webview()->mainFrame()->document().to<WebPluginDocument>().plugin();
4660}
4661
4662void RenderViewImpl::OnFind(int request_id,
4663 const string16& search_text,
4664 const WebFindOptions& options) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004665 WebFrame* main_frame = webview()->mainFrame();
4666
4667 // Check if the plugin still exists in the document.
4668 if (main_frame->document().isPluginDocument() &&
4669 GetWebPluginFromPluginDocument()) {
4670 if (options.findNext) {
4671 // Just navigate back/forward.
4672 GetWebPluginFromPluginDocument()->selectFindResult(options.forward);
4673 } else {
4674 if (!GetWebPluginFromPluginDocument()->startFind(
4675 search_text, options.matchCase, request_id)) {
4676 // Send "no results".
4677 SendFindReply(request_id, 0, 0, gfx::Rect(), true);
4678 }
4679 }
4680 return;
4681 }
4682
4683 WebFrame* frame_after_main = main_frame->traverseNext(true);
4684 WebFrame* focused_frame = webview()->focusedFrame();
4685 WebFrame* search_frame = focused_frame; // start searching focused frame.
4686
4687 bool multi_frame = (frame_after_main != main_frame);
4688
4689 // If we have multiple frames, we don't want to wrap the search within the
4690 // frame, so we check here if we only have main_frame in the chain.
4691 bool wrap_within_frame = !multi_frame;
4692
4693 WebRect selection_rect;
4694 bool result = false;
4695
4696 // If something is selected when we start searching it means we cannot just
4697 // increment the current match ordinal; we need to re-generate it.
4698 WebRange current_selection = focused_frame->selectionRange();
4699
4700 do {
4701 result = search_frame->find(
4702 request_id, search_text, options, wrap_within_frame, &selection_rect);
4703
4704 if (!result) {
4705 // don't leave text selected as you move to the next frame.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01004706 search_frame->executeCommand(WebString::fromUTF8("Unselect"),
4707 GetFocusedNode());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004708
4709 // Find the next frame, but skip the invisible ones.
4710 do {
4711 // What is the next frame to search? (we might be going backwards). Note
4712 // that we specify wrap=true so that search_frame never becomes NULL.
4713 search_frame = options.forward ?
4714 search_frame->traverseNext(true) :
4715 search_frame->traversePrevious(true);
4716 } while (!search_frame->hasVisibleContent() &&
4717 search_frame != focused_frame);
4718
4719 // Make sure selection doesn't affect the search operation in new frame.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01004720 search_frame->executeCommand(WebString::fromUTF8("Unselect"),
4721 GetFocusedNode());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004722
4723 // If we have multiple frames and we have wrapped back around to the
4724 // focused frame, we need to search it once more allowing wrap within
4725 // the frame, otherwise it will report 'no match' if the focused frame has
4726 // reported matches, but no frames after the focused_frame contain a
4727 // match for the search word(s).
4728 if (multi_frame && search_frame == focused_frame) {
4729 result = search_frame->find(
4730 request_id, search_text, options, true, // Force wrapping.
4731 &selection_rect);
4732 }
4733 }
4734
4735 webview()->setFocusedFrame(search_frame);
4736 } while (!result && search_frame != focused_frame);
4737
4738 if (options.findNext && current_selection.isNull()) {
4739 // Force the main_frame to report the actual count.
4740 main_frame->increaseMatchCount(0, request_id);
4741 } else {
4742 // If nothing is found, set result to "0 of 0", otherwise, set it to
4743 // "-1 of 1" to indicate that we found at least one item, but we don't know
4744 // yet what is active.
4745 int ordinal = result ? -1 : 0; // -1 here means, we might know more later.
4746 int match_count = result ? 1 : 0; // 1 here means possibly more coming.
4747
4748 // If we find no matches then this will be our last status update.
4749 // Otherwise the scoping effort will send more results.
4750 bool final_status_update = !result;
4751
4752 SendFindReply(request_id, match_count, ordinal, selection_rect,
4753 final_status_update);
4754
4755 // Scoping effort begins, starting with the mainframe.
4756 search_frame = main_frame;
4757
4758 main_frame->resetMatchCount();
4759
4760 do {
4761 // Cancel all old scoping requests before starting a new one.
4762 search_frame->cancelPendingScopingEffort();
4763
4764 // We don't start another scoping effort unless at least one match has
4765 // been found.
4766 if (result) {
4767 // Start new scoping request. If the scoping function determines that it
4768 // needs to scope, it will defer until later.
4769 search_frame->scopeStringMatches(request_id,
4770 search_text,
4771 options,
4772 true); // reset the tickmarks
4773 }
4774
4775 // Iterate to the next frame. The frame will not necessarily scope, for
4776 // example if it is not visible.
4777 search_frame = search_frame->traverseNext(true);
4778 } while (search_frame != main_frame);
4779 }
4780}
4781
4782void RenderViewImpl::OnStopFinding(StopFindAction action) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004783 WebView* view = webview();
4784 if (!view)
4785 return;
4786
4787 WebDocument doc = view->mainFrame()->document();
4788 if (doc.isPluginDocument() && GetWebPluginFromPluginDocument()) {
4789 GetWebPluginFromPluginDocument()->stopFind();
4790 return;
4791 }
4792
4793 bool clear_selection = action == STOP_FIND_ACTION_CLEAR_SELECTION;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01004794 if (clear_selection) {
4795 view->focusedFrame()->executeCommand(WebString::fromUTF8("Unselect"),
4796 GetFocusedNode());
4797 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004798
4799 WebFrame* frame = view->mainFrame();
4800 while (frame) {
4801 frame->stopFinding(clear_selection);
4802 frame = frame->traverseNext(false);
4803 }
4804
4805 if (action == STOP_FIND_ACTION_ACTIVATE_SELECTION) {
4806 WebFrame* focused_frame = view->focusedFrame();
4807 if (focused_frame) {
4808 WebDocument doc = focused_frame->document();
4809 if (!doc.isNull()) {
4810 WebNode node = doc.focusedNode();
4811 if (!node.isNull())
4812 node.simulateClick();
4813 }
4814 }
4815 }
4816}
4817
4818#if defined(OS_ANDROID)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004819void RenderViewImpl::OnActivateNearestFindResult(int request_id,
4820 float x, float y) {
4821 if (!webview())
4822 return;
4823
4824 WebFrame* main_frame = webview()->mainFrame();
4825 WebRect selection_rect;
4826 int ordinal = main_frame->selectNearestFindMatch(WebFloatPoint(x, y),
4827 &selection_rect);
4828 if (ordinal == -1) {
4829 // Something went wrong, so send a no-op reply (force the main_frame to
4830 // report the current match count) in case the host is waiting for a
4831 // response due to rate-limiting).
4832 main_frame->increaseMatchCount(0, request_id);
4833 return;
4834 }
4835
4836 SendFindReply(request_id,
4837 -1 /* number_of_matches */,
4838 ordinal,
4839 selection_rect,
4840 true /* final_update */);
4841}
4842
4843void RenderViewImpl::OnFindMatchRects(int current_version) {
4844 if (!webview())
4845 return;
4846
4847 WebFrame* main_frame = webview()->mainFrame();
4848 std::vector<gfx::RectF> match_rects;
4849
4850 int rects_version = main_frame->findMatchMarkersVersion();
4851 if (current_version != rects_version) {
4852 WebVector<WebFloatRect> web_match_rects;
4853 main_frame->findMatchRects(web_match_rects);
4854 match_rects.reserve(web_match_rects.size());
4855 for (size_t i = 0; i < web_match_rects.size(); ++i)
4856 match_rects.push_back(gfx::RectF(web_match_rects[i]));
4857 }
4858
4859 gfx::RectF active_rect = main_frame->activeFindMatchRect();
4860 Send(new ViewHostMsg_FindMatchRects_Reply(routing_id_,
4861 rects_version,
4862 match_rects,
4863 active_rect));
4864}
4865#endif
4866
4867void RenderViewImpl::OnZoom(PageZoom zoom) {
4868 if (!webview()) // Not sure if this can happen, but no harm in being safe.
4869 return;
4870
4871 webview()->hidePopups();
4872
4873 double old_zoom_level = webview()->zoomLevel();
4874 double zoom_level;
4875 if (zoom == PAGE_ZOOM_RESET) {
4876 zoom_level = 0;
4877 } else if (static_cast<int>(old_zoom_level) == old_zoom_level) {
4878 // Previous zoom level is a whole number, so just increment/decrement.
4879 zoom_level = old_zoom_level + zoom;
4880 } else {
4881 // Either the user hit the zoom factor limit and thus the zoom level is now
4882 // not a whole number, or a plugin changed it to a custom value. We want
4883 // to go to the next whole number so that the user can always get back to
4884 // 100% with the keyboard/menu.
4885 if ((old_zoom_level > 1 && zoom > 0) ||
4886 (old_zoom_level < 1 && zoom < 0)) {
4887 zoom_level = static_cast<int>(old_zoom_level + zoom);
4888 } else {
4889 // We're going towards 100%, so first go to the next whole number.
4890 zoom_level = static_cast<int>(old_zoom_level);
4891 }
4892 }
4893 webview()->setZoomLevel(false, zoom_level);
4894 zoomLevelChanged();
4895}
4896
4897void RenderViewImpl::OnZoomFactor(PageZoom zoom, int zoom_center_x,
4898 int zoom_center_y) {
4899 ZoomFactorHelper(zoom, zoom_center_x, zoom_center_y,
4900 kScalingIncrementForGesture);
4901}
4902
4903void RenderViewImpl::ZoomFactorHelper(PageZoom zoom,
4904 int zoom_center_x,
4905 int zoom_center_y,
4906 float scaling_increment) {
4907 if (!webview()) // Not sure if this can happen, but no harm in being safe.
4908 return;
4909
4910 double old_page_scale_factor = webview()->pageScaleFactor();
4911 double page_scale_factor;
4912 if (zoom == PAGE_ZOOM_RESET) {
4913 page_scale_factor = 1.0;
4914 } else {
4915 page_scale_factor = old_page_scale_factor +
4916 (zoom > 0 ? scaling_increment : -scaling_increment);
4917 }
4918 if (page_scale_factor > 0) {
4919 webview()->setPageScaleFactor(page_scale_factor,
4920 WebPoint(zoom_center_x, zoom_center_y));
4921 }
4922}
4923
4924void RenderViewImpl::OnSetZoomLevel(double zoom_level) {
4925 webview()->hidePopups();
4926 webview()->setZoomLevel(false, zoom_level);
4927 zoomLevelChanged();
4928}
4929
4930void RenderViewImpl::OnSetZoomLevelForLoadingURL(const GURL& url,
4931 double zoom_level) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004932#if !defined(OS_ANDROID)
4933 // On Android, page zoom isn't used, and in case of WebView, text zoom is used
4934 // for legacy WebView text scaling emulation. Thus, the code that resets
4935 // the zoom level from this map will be effectively resetting text zoom level.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004936 host_zoom_levels_[url] = zoom_level;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00004937#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004938}
4939
4940void RenderViewImpl::OnSetPageEncoding(const std::string& encoding_name) {
4941 webview()->setPageEncoding(WebString::fromUTF8(encoding_name));
4942}
4943
4944void RenderViewImpl::OnResetPageEncodingToDefault() {
4945 WebString no_encoding;
4946 webview()->setPageEncoding(no_encoding);
4947}
4948
4949WebFrame* RenderViewImpl::GetChildFrame(const string16& xpath) const {
4950 if (xpath.empty())
4951 return webview()->mainFrame();
4952
4953 // xpath string can represent a frame deep down the tree (across multiple
4954 // frame DOMs).
4955 // Example, /html/body/table/tbody/tr/td/iframe\n/frameset/frame[0]
4956 // should break into 2 xpaths
4957 // /html/body/table/tbody/tr/td/iframe & /frameset/frame[0]
4958 std::vector<string16> xpaths;
4959 base::SplitString(xpath, '\n', &xpaths);
4960
4961 WebFrame* frame = webview()->mainFrame();
4962 for (std::vector<string16>::const_iterator i = xpaths.begin();
4963 frame && i != xpaths.end(); ++i) {
4964 frame = frame->findChildByExpression(*i);
4965 }
4966
4967 return frame;
4968}
4969
4970void RenderViewImpl::OnScriptEvalRequest(const string16& frame_xpath,
4971 const string16& jscript,
4972 int id,
4973 bool notify_result) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01004974 TRACE_EVENT_INSTANT0("test_tracing", "OnScriptEvalRequest",
4975 TRACE_EVENT_SCOPE_THREAD);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004976 EvaluateScript(frame_xpath, jscript, id, notify_result);
4977}
4978
4979void RenderViewImpl::OnPostMessageEvent(
4980 const ViewMsg_PostMessage_Params& params) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01004981 // TODO(nasko): Support sending to subframes.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004982 WebFrame* frame = webview()->mainFrame();
4983
4984 // Find the source frame if it exists.
4985 WebFrame* source_frame = NULL;
4986 if (params.source_routing_id != MSG_ROUTING_NONE) {
4987 RenderViewImpl* source_view = FromRoutingID(params.source_routing_id);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00004988 if (source_view)
4989 source_frame = source_view->webview()->mainFrame();
4990 }
4991
4992 // Create an event with the message. The final parameter to initMessageEvent
4993 // is the last event ID, which is not used with postMessage.
4994 WebDOMEvent event = frame->document().createEvent("MessageEvent");
4995 WebDOMMessageEvent msg_event = event.to<WebDOMMessageEvent>();
4996 msg_event.initMessageEvent("message",
4997 // |canBubble| and |cancellable| are always false
4998 false, false,
4999 WebSerializedScriptValue::fromString(params.data),
5000 params.source_origin, source_frame, "");
5001
5002 // We must pass in the target_origin to do the security check on this side,
5003 // since it may have changed since the original postMessage call was made.
5004 WebSecurityOrigin target_origin;
5005 if (!params.target_origin.empty()) {
5006 target_origin =
5007 WebSecurityOrigin::createFromString(WebString(params.target_origin));
5008 }
5009 frame->dispatchMessageEventWithOriginCheck(target_origin, msg_event);
5010}
5011
5012void RenderViewImpl::OnCSSInsertRequest(const string16& frame_xpath,
5013 const std::string& css) {
5014 WebFrame* frame = GetChildFrame(frame_xpath);
5015 if (!frame)
5016 return;
5017
5018 frame->document().insertUserStyleSheet(
5019 WebString::fromUTF8(css),
5020 WebDocument::UserStyleAuthorLevel);
5021}
5022
5023void RenderViewImpl::OnAllowBindings(int enabled_bindings_flags) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005024 if ((enabled_bindings_flags & BINDINGS_POLICY_WEB_UI) &&
5025 !(enabled_bindings_ & BINDINGS_POLICY_WEB_UI)) {
5026 RenderThread::Get()->RegisterExtension(WebUIExtension::Get());
5027 new WebUIExtensionData(this);
5028 }
5029
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005030 enabled_bindings_ |= enabled_bindings_flags;
5031
5032 // Keep track of the total bindings accumulated in this process.
5033 RenderProcess::current()->AddBindings(enabled_bindings_flags);
5034}
5035
Ben Murdocheb525c52013-07-10 11:40:50 +01005036void RenderViewImpl::OnDragTargetDragEnter(const DropData& drop_data,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005037 const gfx::Point& client_point,
5038 const gfx::Point& screen_point,
5039 WebDragOperationsMask ops,
5040 int key_modifiers) {
5041 WebDragOperation operation = webview()->dragTargetDragEnter(
Ben Murdocheb525c52013-07-10 11:40:50 +01005042 DropDataToWebDragData(drop_data),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005043 client_point,
5044 screen_point,
5045 ops,
5046 key_modifiers);
5047
5048 Send(new DragHostMsg_UpdateDragCursor(routing_id_, operation));
5049}
5050
5051void RenderViewImpl::OnDragTargetDragOver(const gfx::Point& client_point,
5052 const gfx::Point& screen_point,
5053 WebDragOperationsMask ops,
5054 int key_modifiers) {
5055 WebDragOperation operation = webview()->dragTargetDragOver(
5056 client_point,
5057 screen_point,
5058 ops,
5059 key_modifiers);
5060
5061 Send(new DragHostMsg_UpdateDragCursor(routing_id_, operation));
5062}
5063
5064void RenderViewImpl::OnDragTargetDragLeave() {
5065 webview()->dragTargetDragLeave();
5066}
5067
5068void RenderViewImpl::OnDragTargetDrop(const gfx::Point& client_point,
5069 const gfx::Point& screen_point,
5070 int key_modifiers) {
5071 webview()->dragTargetDrop(client_point, screen_point, key_modifiers);
5072
5073 Send(new DragHostMsg_TargetDrop_ACK(routing_id_));
5074}
5075
5076void RenderViewImpl::OnDragSourceEndedOrMoved(const gfx::Point& client_point,
5077 const gfx::Point& screen_point,
5078 bool ended,
5079 WebDragOperation op) {
5080 if (ended) {
5081 webview()->dragSourceEndedAt(client_point, screen_point, op);
5082 } else {
5083 webview()->dragSourceMovedTo(client_point, screen_point, op);
5084 }
5085}
5086
5087void RenderViewImpl::OnDragSourceSystemDragEnded() {
5088 webview()->dragSourceSystemDragEnded();
5089}
5090
5091void RenderViewImpl::OnUpdateWebPreferences(const WebPreferences& prefs) {
5092 webkit_preferences_ = prefs;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01005093 webkit_glue::ApplyWebPreferences(webkit_preferences_, webview());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005094}
5095
5096void RenderViewImpl::OnUpdateTimezone() {
5097 if (webview())
5098 NotifyTimezoneChange(webview()->mainFrame());
5099}
5100
5101void RenderViewImpl::OnSetAltErrorPageURL(const GURL& url) {
5102 alternate_error_page_url_ = url;
5103}
5104
5105void RenderViewImpl::OnCustomContextMenuAction(
5106 const CustomContextMenuContext& custom_context,
5107 unsigned action) {
5108 if (custom_context.request_id) {
5109 // External context menu request, look in our map.
5110 ContextMenuClient* client =
5111 pending_context_menus_.Lookup(custom_context.request_id);
5112 if (client)
5113 client->OnMenuAction(custom_context.request_id, action);
5114 } else {
5115 // Internal request, forward to WebKit.
5116 webview()->performCustomContextMenuAction(action);
5117 }
5118}
5119
5120void RenderViewImpl::OnEnumerateDirectoryResponse(
5121 int id,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005122 const std::vector<base::FilePath>& paths) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005123 if (!enumeration_completions_[id])
5124 return;
5125
5126 WebVector<WebString> ws_file_names(paths.size());
5127 for (size_t i = 0; i < paths.size(); ++i)
Ben Murdocheb525c52013-07-10 11:40:50 +01005128 ws_file_names[i] = paths[i].AsUTF16Unsafe();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005129
5130 enumeration_completions_[id]->didChooseFile(ws_file_names);
5131 enumeration_completions_.erase(id);
5132}
5133
5134void RenderViewImpl::OnFileChooserResponse(
5135 const std::vector<ui::SelectedFileInfo>& files) {
5136 // This could happen if we navigated to a different page before the user
5137 // closed the chooser.
5138 if (file_chooser_completions_.empty())
5139 return;
5140
5141 // Convert Chrome's SelectedFileInfo list to WebKit's.
5142 WebVector<WebFileChooserCompletion::SelectedFileInfo> selected_files(
5143 files.size());
5144 for (size_t i = 0; i < files.size(); ++i) {
5145 WebFileChooserCompletion::SelectedFileInfo selected_file;
Ben Murdocheb525c52013-07-10 11:40:50 +01005146 selected_file.path = files[i].local_path.AsUTF16Unsafe();
5147 selected_file.displayName =
5148 base::FilePath(files[i].display_name).AsUTF16Unsafe();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005149 selected_files[i] = selected_file;
5150 }
5151
5152 if (file_chooser_completions_.front()->completion)
5153 file_chooser_completions_.front()->completion->didChooseFile(
5154 selected_files);
5155 file_chooser_completions_.pop_front();
5156
5157 // If there are more pending file chooser requests, schedule one now.
5158 if (!file_chooser_completions_.empty()) {
5159 Send(new ViewHostMsg_RunFileChooser(routing_id_,
5160 file_chooser_completions_.front()->params));
5161 }
5162}
5163
5164void RenderViewImpl::OnEnableAutoResize(const gfx::Size& min_size,
5165 const gfx::Size& max_size) {
5166 DCHECK(disable_scrollbars_size_limit_.IsEmpty());
5167 if (!webview())
5168 return;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005169 auto_resize_mode_ = true;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005170 webview()->enableAutoResizeMode(min_size, max_size);
5171}
5172
5173void RenderViewImpl::OnDisableAutoResize(const gfx::Size& new_size) {
5174 DCHECK(disable_scrollbars_size_limit_.IsEmpty());
5175 if (!webview())
5176 return;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005177 auto_resize_mode_ = false;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005178 webview()->disableAutoResizeMode();
5179
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01005180 if (!new_size.IsEmpty()) {
5181 Resize(new_size,
5182 physical_backing_size_,
5183 overdraw_bottom_height_,
5184 resizer_rect_,
5185 is_fullscreen_,
5186 NO_RESIZE_ACK);
5187 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005188}
5189
5190void RenderViewImpl::OnEnablePreferredSizeChangedMode() {
5191 if (send_preferred_size_changes_)
5192 return;
5193 send_preferred_size_changes_ = true;
5194
5195 // Start off with an initial preferred size notification (in case
5196 // |didUpdateLayout| was already called).
5197 didUpdateLayout();
5198}
5199
5200void RenderViewImpl::OnDisableScrollbarsForSmallWindows(
5201 const gfx::Size& disable_scrollbar_size_limit) {
5202 disable_scrollbars_size_limit_ = disable_scrollbar_size_limit;
5203}
5204
5205void RenderViewImpl::OnSetRendererPrefs(
5206 const RendererPreferences& renderer_prefs) {
5207 double old_zoom_level = renderer_preferences_.default_zoom_level;
5208 renderer_preferences_ = renderer_prefs;
5209 UpdateFontRenderingFromRendererPrefs();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005210
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005211#if defined(USE_DEFAULT_RENDER_THEME) || defined(TOOLKIT_GTK)
5212 if (renderer_prefs.use_custom_colors) {
5213 WebColorName name = WebKit::WebColorWebkitFocusRingColor;
5214 WebKit::setNamedColors(&name, &renderer_prefs.focus_ring_color, 1);
5215 WebKit::setCaretBlinkInterval(renderer_prefs.caret_blink_interval);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005216#if defined(TOOLKIT_GTK)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005217 ui::NativeTheme::instance()->SetScrollbarColors(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005218 renderer_prefs.thumb_inactive_color,
5219 renderer_prefs.thumb_active_color,
5220 renderer_prefs.track_color);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005221#endif // defined(TOOLKIT_GTK)
5222
5223 if (webview()) {
5224#if defined(TOOLKIT_GTK)
5225 webview()->setScrollbarColors(
5226 renderer_prefs.thumb_inactive_color,
5227 renderer_prefs.thumb_active_color,
5228 renderer_prefs.track_color);
5229#endif // defined(TOOLKIT_GTK)
5230 webview()->setSelectionColors(
5231 renderer_prefs.active_selection_bg_color,
5232 renderer_prefs.active_selection_fg_color,
5233 renderer_prefs.inactive_selection_bg_color,
5234 renderer_prefs.inactive_selection_fg_color);
5235 webview()->themeChanged();
5236 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005237 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005238#endif // defined(USE_DEFAULT_RENDER_THEME) || defined(TOOLKIT_GTK)
5239
5240 if (RenderThreadImpl::current()) // Will be NULL during unit tests.
5241 RenderThreadImpl::current()->SetFlingCurveParameters(
5242 renderer_prefs.touchpad_fling_profile,
5243 renderer_prefs.touchscreen_fling_profile);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005244
5245 // If the zoom level for this page matches the old zoom default, and this
5246 // is not a plugin, update the zoom level to match the new default.
5247 if (webview() && !webview()->mainFrame()->document().isPluginDocument() &&
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005248 !ZoomValuesEqual(old_zoom_level,
5249 renderer_preferences_.default_zoom_level) &&
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005250 ZoomValuesEqual(webview()->zoomLevel(), old_zoom_level)) {
5251 webview()->setZoomLevel(false, renderer_preferences_.default_zoom_level);
5252 zoomLevelChanged();
5253 }
5254}
5255
5256void RenderViewImpl::OnMediaPlayerActionAt(const gfx::Point& location,
5257 const WebMediaPlayerAction& action) {
5258 if (webview())
5259 webview()->performMediaPlayerAction(action, location);
5260}
5261
5262void RenderViewImpl::OnOrientationChangeEvent(int orientation) {
5263 webview()->mainFrame()->sendOrientationChangeEvent(orientation);
5264}
5265
5266void RenderViewImpl::OnPluginActionAt(const gfx::Point& location,
5267 const WebPluginAction& action) {
5268 if (webview())
5269 webview()->performPluginAction(action, location);
5270}
5271
5272void RenderViewImpl::OnGetAllSavableResourceLinksForCurrentPage(
5273 const GURL& page_url) {
5274 // Prepare list to storage all savable resource links.
5275 std::vector<GURL> resources_list;
5276 std::vector<GURL> referrer_urls_list;
5277 std::vector<WebKit::WebReferrerPolicy> referrer_policies_list;
5278 std::vector<GURL> frames_list;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01005279 SavableResourcesResult result(&resources_list,
5280 &referrer_urls_list,
5281 &referrer_policies_list,
5282 &frames_list);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005283
5284 // webkit/ doesn't know about Referrer.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01005285 if (!GetAllSavableResourceLinksForCurrentPage(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005286 webview(),
5287 page_url,
5288 &result,
5289 const_cast<const char**>(GetSavableSchemes()))) {
5290 // If something is wrong when collecting all savable resource links,
5291 // send empty list to embedder(browser) to tell it failed.
5292 referrer_urls_list.clear();
5293 referrer_policies_list.clear();
5294 resources_list.clear();
5295 frames_list.clear();
5296 }
5297
5298 std::vector<Referrer> referrers_list;
5299 CHECK_EQ(referrer_urls_list.size(), referrer_policies_list.size());
5300 for (unsigned i = 0; i < referrer_urls_list.size(); ++i) {
5301 referrers_list.push_back(
5302 Referrer(referrer_urls_list[i], referrer_policies_list[i]));
5303 }
5304
5305 // Send result of all savable resource links to embedder.
5306 Send(new ViewHostMsg_SendCurrentPageAllSavableResourceLinks(routing_id(),
5307 resources_list,
5308 referrers_list,
5309 frames_list));
5310}
5311
5312void RenderViewImpl::OnGetSerializedHtmlDataForCurrentPageWithLocalLinks(
5313 const std::vector<GURL>& links,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005314 const std::vector<base::FilePath>& local_paths,
5315 const base::FilePath& local_directory_name) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005316
5317 // Convert std::vector of GURLs to WebVector<WebURL>
5318 WebVector<WebURL> weburl_links(links);
5319
Ben Murdocheb525c52013-07-10 11:40:50 +01005320 // Convert std::vector of base::FilePath to WebVector<WebString>
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005321 WebVector<WebString> webstring_paths(local_paths.size());
5322 for (size_t i = 0; i < local_paths.size(); i++)
Ben Murdocheb525c52013-07-10 11:40:50 +01005323 webstring_paths[i] = local_paths[i].AsUTF16Unsafe();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005324
5325 WebPageSerializer::serialize(webview()->mainFrame(), true, this, weburl_links,
5326 webstring_paths,
Ben Murdocheb525c52013-07-10 11:40:50 +01005327 local_directory_name.AsUTF16Unsafe());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005328}
5329
5330void RenderViewImpl::OnShouldClose() {
5331 base::TimeTicks before_unload_start_time = base::TimeTicks::Now();
5332 bool should_close = webview()->dispatchBeforeUnloadEvent();
5333 base::TimeTicks before_unload_end_time = base::TimeTicks::Now();
5334 Send(new ViewHostMsg_ShouldClose_ACK(routing_id_, should_close,
5335 before_unload_start_time,
5336 before_unload_end_time));
5337}
5338
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01005339void RenderViewImpl::OnSwapOut() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005340 // Only run unload if we're not swapped out yet, but send the ack either way.
5341 if (!is_swapped_out_) {
5342 // Swap this RenderView out so the tab can navigate to a page rendered by a
5343 // different process. This involves running the unload handler and clearing
5344 // the page. Once WasSwappedOut is called, we also allow this process to
5345 // exit if there are no other active RenderViews in it.
5346
5347 // Send an UpdateState message before we get swapped out.
5348 SyncNavigationState();
5349
5350 // Synchronously run the unload handler before sending the ACK.
5351 webview()->dispatchUnloadEvent();
5352
5353 // Swap out and stop sending any IPC messages that are not ACKs.
5354 SetSwappedOut(true);
5355
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01005356 // Now that we're swapped out and filtering IPC messages, stop loading to
5357 // ensure that no other in-progress navigation continues. We do this here
5358 // to avoid sending a DidStopLoading message to the browser process.
5359 OnStop();
5360
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005361 // Replace the page with a blank dummy URL. The unload handler will not be
5362 // run a second time, thanks to a check in FrameLoader::stopLoading.
5363 // TODO(creis): Need to add a better way to do this that avoids running the
5364 // beforeunload handler. For now, we just run it a second time silently.
5365 NavigateToSwappedOutURL(webview()->mainFrame());
5366
5367 // Let WebKit know that this view is hidden so it can drop resources and
5368 // stop compositing.
5369 webview()->setVisibilityState(WebKit::WebPageVisibilityStateHidden, false);
5370 }
5371
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01005372 Send(new ViewHostMsg_SwapOut_ACK(routing_id_));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005373}
5374
5375void RenderViewImpl::NavigateToSwappedOutURL(WebKit::WebFrame* frame) {
5376 // We use loadRequest instead of loadHTMLString because the former commits
5377 // synchronously. Otherwise a new navigation can interrupt the navigation
5378 // to kSwappedOutURL. If that happens to be to the page we had been
5379 // showing, then WebKit will never send a commit and we'll be left spinning.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005380 CHECK(is_swapped_out_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005381 GURL swappedOutURL(kSwappedOutURL);
5382 WebURLRequest request(swappedOutURL);
5383 frame->loadRequest(request);
5384}
5385
5386void RenderViewImpl::OnClosePage() {
5387 FOR_EACH_OBSERVER(RenderViewObserver, observers_, ClosePage());
5388 // TODO(creis): We'd rather use webview()->Close() here, but that currently
5389 // sets the WebView's delegate_ to NULL, preventing any JavaScript dialogs
5390 // in the onunload handler from appearing. For now, we're bypassing that and
5391 // calling the FrameLoader's CloseURL method directly. This should be
5392 // revisited to avoid having two ways to close a page. Having a single way
5393 // to close that can run onunload is also useful for fixing
5394 // http://b/issue?id=753080.
5395 webview()->dispatchUnloadEvent();
5396
5397 Send(new ViewHostMsg_ClosePage_ACK(routing_id_));
5398}
5399
5400void RenderViewImpl::OnThemeChanged() {
5401#if defined(USE_AURA)
5402 // Aura doesn't care if we switch themes.
5403#elif defined(OS_WIN)
5404 ui::NativeThemeWin::instance()->CloseHandles();
5405 if (webview())
5406 webview()->themeChanged();
5407#else // defined(OS_WIN)
5408 // TODO(port): we don't support theming on non-Windows platforms yet
5409 NOTIMPLEMENTED();
5410#endif
5411}
5412
5413void RenderViewImpl::OnDisassociateFromPopupCount() {
5414 if (decrement_shared_popup_at_destruction_)
5415 shared_popup_counter_->data--;
5416 shared_popup_counter_ = new SharedRenderViewCounter(0);
5417 decrement_shared_popup_at_destruction_ = false;
5418}
5419
5420bool RenderViewImpl::MaybeLoadAlternateErrorPage(WebFrame* frame,
5421 const WebURLError& error,
5422 bool replace) {
5423 // We only show alternate error pages in the main frame. They are
5424 // intended to assist the user when navigating, so there is not much
5425 // value in showing them for failed subframes. Ideally, we would be
5426 // able to use the TYPED transition type for this, but that flag is
5427 // not preserved across page reloads.
5428 if (frame->parent())
5429 return false;
5430
5431 // Use the alternate error page service if this is a DNS failure or
5432 // connection failure.
5433 int ec = error.reason;
5434 if (ec != net::ERR_NAME_NOT_RESOLVED &&
5435 ec != net::ERR_CONNECTION_FAILED &&
5436 ec != net::ERR_CONNECTION_REFUSED &&
5437 ec != net::ERR_ADDRESS_UNREACHABLE &&
5438 ec != net::ERR_CONNECTION_TIMED_OUT) {
5439 return false;
5440 }
5441
5442 const GURL& error_page_url = GetAlternateErrorPageURL(error.unreachableURL,
5443 ec == net::ERR_NAME_NOT_RESOLVED ? DNS_ERROR : CONNECTION_ERROR);
5444 if (!error_page_url.is_valid())
5445 return false;
5446
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01005447 WebDataSource* ds = frame->provisionalDataSource();
5448 const WebURLRequest& failed_request = ds->request();
5449
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005450 // Load an empty page first so there is an immediate response to the error,
5451 // and then kick off a request for the alternate error page.
5452 frame->loadHTMLString(std::string(),
5453 GURL(kUnreachableWebDataURL),
5454 error.unreachableURL,
5455 replace);
5456
5457 // Now, create a fetcher for the error page and associate it with the data
5458 // source we just created via the LoadHTMLString call. That way if another
5459 // navigation occurs, the fetcher will get destroyed.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01005460 InternalDocumentStateData* internal_data =
5461 InternalDocumentStateData::FromDataSource(frame->provisionalDataSource());
5462 internal_data->set_alt_error_page_fetcher(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005463 new AltErrorPageResourceFetcher(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01005464 error_page_url, frame, failed_request, error,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005465 base::Bind(&RenderViewImpl::AltErrorPageFinished,
5466 base::Unretained(this))));
5467 return true;
5468}
5469
5470void RenderViewImpl::AltErrorPageFinished(WebFrame* frame,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01005471 const WebURLRequest& original_request,
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005472 const WebURLError& original_error,
5473 const std::string& html) {
5474 // Here, we replace the blank page we loaded previously.
5475 // If we failed to download the alternate error page, LoadNavigationErrorPage
5476 // will simply display a default error page.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01005477 LoadNavigationErrorPage(frame, original_request, original_error, html, true);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005478}
5479
5480void RenderViewImpl::OnMoveOrResizeStarted() {
5481 if (webview())
5482 webview()->hidePopups();
5483}
5484
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01005485void RenderViewImpl::OnResize(const ViewMsg_Resize_Params& params) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005486 if (webview()) {
5487 webview()->hidePopups();
5488 if (send_preferred_size_changes_) {
5489 webview()->mainFrame()->setCanHaveScrollbars(
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01005490 ShouldDisplayScrollbars(params.new_size.width(),
5491 params.new_size.height()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005492 }
5493 UpdateScrollState(webview()->mainFrame());
5494 }
5495
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01005496 RenderWidget::OnResize(params);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005497}
5498
5499void RenderViewImpl::WillInitiatePaint() {
Ben Murdoch32409262013-08-07 11:04:47 +01005500#if defined(ENABLE_PLUGINS)
5501 // Notify all of our instances that we started painting. This is used for
5502 // internal bookkeeping only, so we know that the set can not change under
5503 // us.
5504 for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
5505 i != active_pepper_instances_.end(); ++i)
5506 (*i)->ViewWillInitiatePaint();
5507#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005508}
5509
5510void RenderViewImpl::DidInitiatePaint() {
Ben Murdoch32409262013-08-07 11:04:47 +01005511#if defined(ENABLE_PLUGINS)
5512 // Notify all instances that we painted. The same caveats apply as for
5513 // ViewFlushedPaint regarding instances closing themselves, so we take
5514 // similar precautions.
5515 PepperPluginSet plugins = active_pepper_instances_;
5516 for (PepperPluginSet::iterator i = plugins.begin(); i != plugins.end(); ++i) {
5517 if (active_pepper_instances_.find(*i) != active_pepper_instances_.end())
5518 (*i)->ViewInitiatedPaint();
5519 }
5520#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005521}
5522
5523void RenderViewImpl::DidFlushPaint() {
Ben Murdoch32409262013-08-07 11:04:47 +01005524#if defined(ENABLE_PLUGINS)
5525 // Notify all instances that we flushed. This will call into the plugin, and
5526 // we it may ask to close itself as a result. This will, in turn, modify our
5527 // set, possibly invalidating the iterator. So we iterate on a copy that
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005528 // won't change out from under us.
Ben Murdoch32409262013-08-07 11:04:47 +01005529 PepperPluginSet plugins = active_pepper_instances_;
5530 for (PepperPluginSet::iterator i = plugins.begin(); i != plugins.end(); ++i) {
5531 // The copy above makes sure our iterator is never invalid if some plugins
5532 // are destroyed. But some plugin may decide to close all of its views in
5533 // response to a paint in one of them, so we need to make sure each one is
5534 // still "current" before using it.
5535 //
5536 // It's possible that a plugin was destroyed, but another one was created
5537 // with the same address. In this case, we'll call ViewFlushedPaint on that
5538 // new plugin. But that's OK for this particular case since we're just
5539 // notifying all of our instances that the view flushed, and the new one is
5540 // one of our instances.
5541 //
5542 // What about the case where a new one is created in a callback at a new
5543 // address and we don't issue the callback? We're still OK since this
5544 // callback is used for flush callbacks and we could not have possibly
5545 // started a new paint (ViewWillInitiatePaint) for the new plugin while
5546 // processing a previous paint for an existing one.
5547 if (active_pepper_instances_.find(*i) != active_pepper_instances_.end())
5548 (*i)->ViewFlushedPaint();
5549 }
5550#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005551
5552 // If the RenderWidget is closing down then early-exit, otherwise we'll crash.
5553 // See crbug.com/112921.
5554 if (!webview())
5555 return;
5556
5557 WebFrame* main_frame = webview()->mainFrame();
5558
5559 // If we have a provisional frame we are between the start and commit stages
5560 // of loading and we don't want to save stats.
5561 if (!main_frame->provisionalDataSource()) {
5562 WebDataSource* ds = main_frame->dataSource();
5563 DocumentState* document_state = DocumentState::FromDataSource(ds);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01005564 InternalDocumentStateData* data =
5565 InternalDocumentStateData::FromDocumentState(document_state);
5566 if (data->did_first_visually_non_empty_layout() &&
5567 !data->did_first_visually_non_empty_paint()) {
5568 data->set_did_first_visually_non_empty_paint(true);
5569 Send(new ViewHostMsg_DidFirstVisuallyNonEmptyPaint(routing_id_,
5570 page_id_));
5571 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005572
5573 // TODO(jar): The following code should all be inside a method, probably in
5574 // NavigatorState.
5575 Time now = Time::Now();
5576 if (document_state->first_paint_time().is_null()) {
5577 document_state->set_first_paint_time(now);
5578 }
5579 if (document_state->first_paint_after_load_time().is_null() &&
5580 !document_state->finish_load_time().is_null()) {
5581 document_state->set_first_paint_after_load_time(now);
5582 }
5583 }
5584}
5585
Ben Murdoch58e6fbe2013-07-26 10:20:38 +01005586PepperPluginInstanceImpl* RenderViewImpl::GetBitmapForOptimizedPluginPaint(
5587 const gfx::Rect& paint_bounds,
5588 TransportDIB** dib,
5589 gfx::Rect* location,
5590 gfx::Rect* clip,
5591 float* scale_factor) {
Ben Murdoch32409262013-08-07 11:04:47 +01005592#if defined(ENABLE_PLUGINS)
5593 for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
5594 i != active_pepper_instances_.end(); ++i) {
5595 PepperPluginInstanceImpl* instance = *i;
5596 // In Flash fullscreen , the plugin contents should be painted onto the
5597 // fullscreen widget instead of the web page.
5598 if (!instance->FlashIsFullscreenOrPending() &&
5599 instance->GetBitmapForOptimizedPluginPaint(paint_bounds, dib, location,
5600 clip, scale_factor))
5601 return *i;
5602 }
5603#endif
5604 return NULL;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005605}
5606
5607gfx::Vector2d RenderViewImpl::GetScrollOffset() {
5608 WebSize scroll_offset = webview()->mainFrame()->scrollOffset();
5609 return gfx::Vector2d(scroll_offset.width, scroll_offset.height);
5610}
5611
5612void RenderViewImpl::OnClearFocusedNode() {
5613 if (webview())
5614 webview()->clearFocusedNode();
5615}
5616
5617void RenderViewImpl::OnSetBackground(const SkBitmap& background) {
5618 if (webview())
5619 webview()->setIsTransparent(!background.empty());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005620 if (compositor_)
5621 compositor_->setHasTransparentBackground(!background.empty());
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005622
5623 SetBackground(background);
5624}
5625
5626void RenderViewImpl::OnSetAccessibilityMode(AccessibilityMode new_mode) {
5627 if (accessibility_mode_ == new_mode)
5628 return;
5629 accessibility_mode_ = new_mode;
5630 if (renderer_accessibility_) {
5631 delete renderer_accessibility_;
5632 renderer_accessibility_ = NULL;
5633 }
5634 if (accessibility_mode_ == AccessibilityModeComplete)
5635 renderer_accessibility_ = new RendererAccessibilityComplete(this);
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01005636#if !defined(OS_ANDROID)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005637 else if (accessibility_mode_ == AccessibilityModeEditableTextOnly)
5638 renderer_accessibility_ = new RendererAccessibilityFocusOnly(this);
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01005639#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005640}
5641
5642void RenderViewImpl::OnSetActive(bool active) {
5643 if (webview())
5644 webview()->setIsActive(active);
5645
Ben Murdochbb1529c2013-08-08 10:24:53 +01005646#if defined(ENABLE_PLUGINS) && defined(OS_MACOSX)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005647 std::set<WebPluginDelegateProxy*>::iterator plugin_it;
5648 for (plugin_it = plugin_delegates_.begin();
5649 plugin_it != plugin_delegates_.end(); ++plugin_it) {
5650 (*plugin_it)->SetWindowFocus(active);
5651 }
5652#endif
5653}
5654
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005655#if defined(OS_MACOSX)
5656void RenderViewImpl::OnSetWindowVisibility(bool visible) {
Ben Murdochbb1529c2013-08-08 10:24:53 +01005657#if defined(ENABLE_PLUGINS)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005658 // Inform plugins that their container has changed visibility.
5659 std::set<WebPluginDelegateProxy*>::iterator plugin_it;
5660 for (plugin_it = plugin_delegates_.begin();
5661 plugin_it != plugin_delegates_.end(); ++plugin_it) {
5662 (*plugin_it)->SetContainerVisibility(visible);
5663 }
Ben Murdochbb1529c2013-08-08 10:24:53 +01005664#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005665}
5666
5667void RenderViewImpl::OnWindowFrameChanged(const gfx::Rect& window_frame,
5668 const gfx::Rect& view_frame) {
Ben Murdochbb1529c2013-08-08 10:24:53 +01005669#if defined(ENABLE_PLUGINS)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005670 // Inform plugins that their window's frame has changed.
5671 std::set<WebPluginDelegateProxy*>::iterator plugin_it;
5672 for (plugin_it = plugin_delegates_.begin();
5673 plugin_it != plugin_delegates_.end(); ++plugin_it) {
5674 (*plugin_it)->WindowFrameChanged(window_frame, view_frame);
5675 }
Ben Murdochbb1529c2013-08-08 10:24:53 +01005676#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005677}
5678
5679void RenderViewImpl::OnPluginImeCompositionCompleted(const string16& text,
5680 int plugin_id) {
5681 // WebPluginDelegateProxy is responsible for figuring out if this event
5682 // applies to it or not, so inform all the delegates.
5683 std::set<WebPluginDelegateProxy*>::iterator plugin_it;
5684 for (plugin_it = plugin_delegates_.begin();
5685 plugin_it != plugin_delegates_.end(); ++plugin_it) {
5686 (*plugin_it)->ImeCompositionCompleted(text, plugin_id);
5687 }
5688}
5689#endif // OS_MACOSX
5690
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005691void RenderViewImpl::Close() {
5692 // We need to grab a pointer to the doomed WebView before we destroy it.
5693 WebView* doomed = webview();
5694 RenderWidget::Close();
5695 g_view_map.Get().erase(doomed);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005696 g_routing_id_view_map.Get().erase(routing_id_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005697}
5698
5699void RenderViewImpl::DidHandleKeyEvent() {
5700 ClearEditCommands();
5701}
5702
5703bool RenderViewImpl::WillHandleMouseEvent(const WebKit::WebMouseEvent& event) {
Ben Murdocheb525c52013-07-10 11:40:50 +01005704 context_menu_source_type_ = ui::MENU_SOURCE_MOUSE;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005705 possible_drag_event_info_.event_source =
5706 ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE;
5707 possible_drag_event_info_.event_location =
5708 gfx::Point(event.globalX, event.globalY);
Ben Murdoch32409262013-08-07 11:04:47 +01005709
5710#if defined(ENABLE_PLUGINS)
5711 // This method is called for every mouse event that the render view receives.
5712 // And then the mouse event is forwarded to WebKit, which dispatches it to the
5713 // event target. Potentially a Pepper plugin will receive the event.
5714 // In order to tell whether a plugin gets the last mouse event and which it
5715 // is, we set |pepper_last_mouse_event_target_| to NULL here. If a plugin gets
5716 // the event, it will notify us via DidReceiveMouseEvent() and set itself as
5717 // |pepper_last_mouse_event_target_|.
5718 pepper_last_mouse_event_target_ = NULL;
5719#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005720
5721 // If the mouse is locked, only the current owner of the mouse lock can
5722 // process mouse events.
5723 return mouse_lock_dispatcher_->WillHandleMouseEvent(event);
5724}
5725
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01005726bool RenderViewImpl::WillHandleKeyEvent(const WebKit::WebKeyboardEvent& event) {
Ben Murdocheb525c52013-07-10 11:40:50 +01005727 context_menu_source_type_ = ui::MENU_SOURCE_KEYBOARD;
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01005728 return false;
5729}
5730
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005731bool RenderViewImpl::WillHandleGestureEvent(
5732 const WebKit::WebGestureEvent& event) {
Ben Murdocheb525c52013-07-10 11:40:50 +01005733 context_menu_source_type_ = ui::MENU_SOURCE_TOUCH;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005734 possible_drag_event_info_.event_source =
5735 ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH;
5736 possible_drag_event_info_.event_location =
5737 gfx::Point(event.globalX, event.globalY);
5738 return false;
5739}
5740
5741void RenderViewImpl::DidHandleMouseEvent(const WebMouseEvent& event) {
5742 FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidHandleMouseEvent(event));
5743}
5744
5745void RenderViewImpl::DidHandleTouchEvent(const WebTouchEvent& event) {
5746 FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidHandleTouchEvent(event));
5747}
5748
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005749bool RenderViewImpl::HasTouchEventHandlersAt(const gfx::Point& point) const {
5750 if (!webview())
5751 return false;
5752 return webview()->hasTouchEventHandlersAt(point);
5753}
5754
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005755void RenderViewImpl::OnWasHidden() {
5756 RenderWidget::OnWasHidden();
5757
5758#if defined(OS_ANDROID)
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01005759 // Inform RendererMediaPlayerManager to release all media player resources.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005760 // unless some audio is playing.
5761 // If something is in progress the resource will not be freed, it will
5762 // only be freed once the tab is destroyed or if the user navigates away
5763 // via WebMediaPlayerAndroid::Destroy
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005764 media_player_manager_->ReleaseMediaResources();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01005765
5766#if defined(ENABLE_WEBRTC)
5767 RenderThreadImpl::current()->video_capture_impl_manager()->
5768 SuspendDevices(true);
5769#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005770#endif
5771
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01005772 if (webview())
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005773 webview()->setVisibilityState(visibilityState(), false);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005774
Ben Murdoch32409262013-08-07 11:04:47 +01005775#if defined(ENABLE_PLUGINS)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005776 // Inform PPAPI plugins that their page is no longer visible.
Ben Murdoch32409262013-08-07 11:04:47 +01005777 for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
5778 i != active_pepper_instances_.end(); ++i)
5779 (*i)->PageVisibilityChanged(false);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005780
5781#if defined(OS_MACOSX)
5782 // Inform NPAPI plugins that their container is no longer visible.
5783 std::set<WebPluginDelegateProxy*>::iterator plugin_it;
5784 for (plugin_it = plugin_delegates_.begin();
5785 plugin_it != plugin_delegates_.end(); ++plugin_it) {
5786 (*plugin_it)->SetContainerVisibility(false);
5787 }
5788#endif // OS_MACOSX
Ben Murdochbb1529c2013-08-08 10:24:53 +01005789#endif // ENABLE_PLUGINS
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005790}
5791
5792void RenderViewImpl::OnWasShown(bool needs_repainting) {
5793 RenderWidget::OnWasShown(needs_repainting);
5794
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01005795#if defined(OS_ANDROID) && defined(ENABLE_WEBRTC)
5796 RenderThreadImpl::current()->video_capture_impl_manager()->
5797 SuspendDevices(false);
5798#endif
5799
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01005800 if (webview())
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005801 webview()->setVisibilityState(visibilityState(), false);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005802
Ben Murdoch32409262013-08-07 11:04:47 +01005803#if defined(ENABLE_PLUGINS)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005804 // Inform PPAPI plugins that their page is visible.
Ben Murdoch32409262013-08-07 11:04:47 +01005805 for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
5806 i != active_pepper_instances_.end(); ++i)
5807 (*i)->PageVisibilityChanged(true);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005808
5809#if defined(OS_MACOSX)
5810 // Inform NPAPI plugins that their container is now visible.
5811 std::set<WebPluginDelegateProxy*>::iterator plugin_it;
5812 for (plugin_it = plugin_delegates_.begin();
5813 plugin_it != plugin_delegates_.end(); ++plugin_it) {
5814 (*plugin_it)->SetContainerVisibility(true);
5815 }
5816#endif // OS_MACOSX
Ben Murdochbb1529c2013-08-08 10:24:53 +01005817#endif // ENABLE_PLUGINS
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005818}
5819
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005820GURL RenderViewImpl::GetURLForGraphicsContext3D() {
5821 DCHECK(webview());
5822 if (webview()->mainFrame())
5823 return GURL(webview()->mainFrame()->document().url());
5824 else
5825 return GURL("chrome://gpu/RenderViewImpl::CreateGraphicsContext3D");
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005826}
5827
5828bool RenderViewImpl::ForceCompositingModeEnabled() {
5829 return webkit_preferences_.force_compositing_mode;
5830}
5831
5832void RenderViewImpl::OnSetFocus(bool enable) {
5833 RenderWidget::OnSetFocus(enable);
5834
Ben Murdochbb1529c2013-08-08 10:24:53 +01005835#if defined(ENABLE_PLUGINS)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005836 if (webview() && webview()->isActive()) {
5837 // Notify all NPAPI plugins.
5838 std::set<WebPluginDelegateProxy*>::iterator plugin_it;
5839 for (plugin_it = plugin_delegates_.begin();
5840 plugin_it != plugin_delegates_.end(); ++plugin_it) {
5841#if defined(OS_MACOSX)
5842 // RenderWidget's call to setFocus can cause the underlying webview's
5843 // activation state to change just like a call to setIsActive.
5844 if (enable)
5845 (*plugin_it)->SetWindowFocus(true);
5846#endif
5847 (*plugin_it)->SetContentAreaFocus(enable);
5848 }
5849 }
5850 // Notify all Pepper plugins.
Ben Murdoch32409262013-08-07 11:04:47 +01005851 for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
5852 i != active_pepper_instances_.end(); ++i)
5853 (*i)->SetContentAreaFocus(enable);
5854#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005855 // Notify all BrowserPlugins of the RenderView's focus state.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01005856 if (browser_plugin_manager_.get())
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01005857 browser_plugin_manager_->UpdateFocusState();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005858}
5859
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005860void RenderViewImpl::OnImeSetComposition(
5861 const string16& text,
5862 const std::vector<WebKit::WebCompositionUnderline>& underlines,
5863 int selection_start,
5864 int selection_end) {
Ben Murdoch32409262013-08-07 11:04:47 +01005865#if defined(ENABLE_PLUGINS)
5866 if (focused_pepper_plugin_) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005867 // When a PPAPI plugin has focus, we bypass WebKit.
Ben Murdoch32409262013-08-07 11:04:47 +01005868 if (!IsPepperAcceptingCompositionEvents()) {
5869 pepper_composition_text_ = text;
5870 } else {
5871 // TODO(kinaba) currently all composition events are sent directly to
5872 // plugins. Use DOM event mechanism after WebKit is made aware about
5873 // plugins that support composition.
5874 // The code below mimics the behavior of WebCore::Editor::setComposition.
5875
5876 // Empty -> nonempty: composition started.
5877 if (pepper_composition_text_.empty() && !text.empty())
5878 focused_pepper_plugin_->HandleCompositionStart(string16());
5879 // Nonempty -> empty: composition canceled.
5880 if (!pepper_composition_text_.empty() && text.empty())
5881 focused_pepper_plugin_->HandleCompositionEnd(string16());
5882 pepper_composition_text_ = text;
5883 // Nonempty: composition is ongoing.
5884 if (!pepper_composition_text_.empty()) {
5885 focused_pepper_plugin_->HandleCompositionUpdate(
5886 pepper_composition_text_, underlines, selection_start,
5887 selection_end);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005888 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005889 }
Ben Murdoch32409262013-08-07 11:04:47 +01005890 return;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005891 }
Ben Murdoch32409262013-08-07 11:04:47 +01005892
5893#if defined(OS_WIN)
5894 // When a plug-in has focus, we create platform-specific IME data used by
5895 // our IME emulator and send it directly to the focused plug-in, i.e. we
5896 // bypass WebKit. (WebPluginDelegate dispatches this IME data only when its
5897 // instance ID is the same one as the specified ID.)
5898 if (focused_plugin_id_ >= 0) {
5899 std::vector<int> clauses;
5900 std::vector<int> target;
5901 for (size_t i = 0; i < underlines.size(); ++i) {
5902 clauses.push_back(underlines[i].startOffset);
5903 clauses.push_back(underlines[i].endOffset);
5904 if (underlines[i].thick) {
5905 target.clear();
5906 target.push_back(underlines[i].startOffset);
5907 target.push_back(underlines[i].endOffset);
5908 }
5909 }
5910 std::set<WebPluginDelegateProxy*>::iterator it;
5911 for (it = plugin_delegates_.begin(); it != plugin_delegates_.end(); ++it) {
5912 (*it)->ImeCompositionUpdated(text, clauses, target, selection_end,
5913 focused_plugin_id_);
5914 }
5915 return;
5916 }
Ben Murdochbb1529c2013-08-08 10:24:53 +01005917#endif // OS_WIN
5918#endif // ENABLE_PLUGINS
Ben Murdoch32409262013-08-07 11:04:47 +01005919 RenderWidget::OnImeSetComposition(text,
5920 underlines,
5921 selection_start,
5922 selection_end);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005923}
5924
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01005925void RenderViewImpl::OnImeConfirmComposition(const string16& text,
5926 const ui::Range& replacement_range,
5927 bool keep_selection) {
Ben Murdoch32409262013-08-07 11:04:47 +01005928#if defined(ENABLE_PLUGINS)
5929 if (focused_pepper_plugin_) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005930 // When a PPAPI plugin has focus, we bypass WebKit.
Ben Murdoch32409262013-08-07 11:04:47 +01005931 // Here, text.empty() has a special meaning. It means to commit the last
5932 // update of composition text (see
5933 // RenderWidgetHost::ImeConfirmComposition()).
5934 const string16& last_text = text.empty() ? pepper_composition_text_ : text;
5935
5936 // last_text is empty only when both text and pepper_composition_text_ is.
5937 // Ignore it.
5938 if (last_text.empty())
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005939 return;
Ben Murdoch32409262013-08-07 11:04:47 +01005940
5941 if (!IsPepperAcceptingCompositionEvents()) {
5942 for (size_t i = 0; i < text.size(); ++i) {
5943 WebKit::WebKeyboardEvent char_event;
5944 char_event.type = WebKit::WebInputEvent::Char;
5945 char_event.timeStampSeconds = base::Time::Now().ToDoubleT();
5946 char_event.modifiers = 0;
5947 char_event.windowsKeyCode = last_text[i];
5948 char_event.nativeKeyCode = last_text[i];
5949 char_event.text[0] = last_text[i];
5950 char_event.unmodifiedText[0] = last_text[i];
5951 if (webwidget())
5952 webwidget()->handleInputEvent(char_event);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005953 }
Ben Murdoch32409262013-08-07 11:04:47 +01005954 } else {
5955 // Mimics the order of events sent by WebKit.
5956 // See WebCore::Editor::setComposition() for the corresponding code.
5957 focused_pepper_plugin_->HandleCompositionEnd(last_text);
5958 focused_pepper_plugin_->HandleTextInput(last_text);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005959 }
Ben Murdoch32409262013-08-07 11:04:47 +01005960 pepper_composition_text_.clear();
5961 return;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005962 }
Ben Murdoch32409262013-08-07 11:04:47 +01005963#if defined(OS_WIN)
5964 // Same as OnImeSetComposition(), we send the text from IMEs directly to
5965 // plug-ins. When we send IME text directly to plug-ins, we should not send
5966 // it to WebKit to prevent WebKit from controlling IMEs.
5967 // TODO(thakis): Honor |replacement_range| for plugins?
5968 if (focused_plugin_id_ >= 0) {
5969 std::set<WebPluginDelegateProxy*>::iterator it;
5970 for (it = plugin_delegates_.begin();
5971 it != plugin_delegates_.end(); ++it) {
5972 (*it)->ImeCompositionCompleted(text, focused_plugin_id_);
5973 }
5974 return;
5975 }
Ben Murdochbb1529c2013-08-08 10:24:53 +01005976#endif // OS_WIN
5977#endif // ENABLE_PLUGINS
Ben Murdoch32409262013-08-07 11:04:47 +01005978 if (replacement_range.IsValid() && webview()) {
5979 // Select the text in |replacement_range|, it will then be replaced by
5980 // text added by the call to RenderWidget::OnImeConfirmComposition().
5981 if (WebFrame* frame = webview()->focusedFrame()) {
5982 WebRange webrange = WebRange::fromDocumentRange(
5983 frame, replacement_range.start(), replacement_range.length());
5984 if (!webrange.isNull())
5985 frame->selectRange(webrange);
5986 }
5987 }
5988 RenderWidget::OnImeConfirmComposition(text,
5989 replacement_range,
5990 keep_selection);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005991}
5992
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005993void RenderViewImpl::SetDeviceScaleFactor(float device_scale_factor) {
5994 RenderWidget::SetDeviceScaleFactor(device_scale_factor);
5995 if (webview()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00005996 webview()->setDeviceScaleFactor(device_scale_factor);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00005997 webview()->settings()->setAcceleratedCompositingForFixedPositionEnabled(
5998 ShouldUseFixedPositionCompositing(device_scale_factor_));
Ben Murdocheb525c52013-07-10 11:40:50 +01005999 webview()->settings()->setAcceleratedCompositingForOverflowScrollEnabled(
6000 ShouldUseAcceleratedCompositingForOverflowScroll(device_scale_factor_));
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01006001 webview()->settings()->setAcceleratedCompositingForTransitionEnabled(
6002 ShouldUseTransitionCompositing(device_scale_factor_));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01006003 webview()->settings()->
6004 setAcceleratedCompositingForFixedRootBackgroundEnabled(
6005 ShouldUseAcceleratedFixedRootBackground(device_scale_factor_));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006006 }
6007 if (auto_resize_mode_)
6008 AutoResizeCompositor();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01006009
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01006010 if (browser_plugin_manager_.get())
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01006011 browser_plugin_manager_->UpdateDeviceScaleFactor(device_scale_factor_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006012}
6013
6014ui::TextInputType RenderViewImpl::GetTextInputType() {
Ben Murdoch32409262013-08-07 11:04:47 +01006015#if defined(ENABLE_PLUGINS)
6016 if (focused_pepper_plugin_)
6017 return focused_pepper_plugin_->text_input_type();
6018#endif
6019 return RenderWidget::GetTextInputType();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006020}
6021
6022void RenderViewImpl::GetSelectionBounds(gfx::Rect* start, gfx::Rect* end) {
Ben Murdoch32409262013-08-07 11:04:47 +01006023#if defined(ENABLE_PLUGINS)
6024 if (focused_pepper_plugin_) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006025 // TODO(kinaba) http://crbug.com/101101
6026 // Current Pepper IME API does not handle selection bounds. So we simply
6027 // use the caret position as an empty range for now. It will be updated
6028 // after Pepper API equips features related to surrounding text retrieval.
Ben Murdoch32409262013-08-07 11:04:47 +01006029 gfx::Rect caret = focused_pepper_plugin_->GetCaretBounds();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006030 *start = caret;
6031 *end = caret;
6032 return;
6033 }
Ben Murdoch32409262013-08-07 11:04:47 +01006034#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006035 RenderWidget::GetSelectionBounds(start, end);
6036}
6037
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01006038#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006039void RenderViewImpl::GetCompositionCharacterBounds(
6040 std::vector<gfx::Rect>* bounds) {
6041 DCHECK(bounds);
6042 bounds->clear();
6043
Ben Murdoch32409262013-08-07 11:04:47 +01006044#if defined(ENABLE_PLUGINS)
6045 if (focused_pepper_plugin_) {
Ben Murdocheb525c52013-07-10 11:40:50 +01006046 return;
6047 }
Ben Murdoch32409262013-08-07 11:04:47 +01006048#endif
6049
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006050 if (!webview())
6051 return;
6052 size_t start_offset = 0;
6053 size_t character_count = 0;
6054 if (!webview()->compositionRange(&start_offset, &character_count))
6055 return;
6056 if (character_count == 0)
6057 return;
6058
6059 WebKit::WebFrame* frame = webview()->focusedFrame();
6060 if (!frame)
6061 return;
6062
6063 bounds->reserve(character_count);
6064 WebKit::WebRect webrect;
6065 for (size_t i = 0; i < character_count; ++i) {
6066 if (!frame->firstRectForCharacterRange(start_offset + i, 1, webrect)) {
6067 DLOG(ERROR) << "Could not retrieve character rectangle at " << i;
6068 bounds->clear();
6069 return;
6070 }
6071 bounds->push_back(webrect);
6072 }
6073}
6074
Ben Murdocheb525c52013-07-10 11:40:50 +01006075void RenderViewImpl::GetCompositionRange(ui::Range* range) {
Ben Murdoch32409262013-08-07 11:04:47 +01006076#if defined(ENABLE_PLUGINS)
6077 if (focused_pepper_plugin_) {
Ben Murdocheb525c52013-07-10 11:40:50 +01006078 return;
6079 }
Ben Murdoch32409262013-08-07 11:04:47 +01006080#endif
Ben Murdocheb525c52013-07-10 11:40:50 +01006081 RenderWidget::GetCompositionRange(range);
6082}
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01006083#endif
Ben Murdocheb525c52013-07-10 11:40:50 +01006084
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006085bool RenderViewImpl::CanComposeInline() {
Ben Murdoch32409262013-08-07 11:04:47 +01006086#if defined(ENABLE_PLUGINS)
6087 if (focused_pepper_plugin_)
6088 return IsPepperAcceptingCompositionEvents();
6089#endif
6090 return true;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006091}
6092
6093void RenderViewImpl::InstrumentWillBeginFrame() {
6094 if (!webview())
6095 return;
6096 if (!webview()->devToolsAgent())
6097 return;
6098 webview()->devToolsAgent()->didBeginFrame();
6099}
6100
6101void RenderViewImpl::InstrumentDidBeginFrame() {
6102 if (!webview())
6103 return;
6104 if (!webview()->devToolsAgent())
6105 return;
6106 // TODO(jamesr/caseq): Decide if this needs to be renamed.
6107 webview()->devToolsAgent()->didComposite();
6108}
6109
6110void RenderViewImpl::InstrumentDidCancelFrame() {
6111 if (!webview())
6112 return;
6113 if (!webview()->devToolsAgent())
6114 return;
6115 webview()->devToolsAgent()->didCancelFrame();
6116}
6117
6118void RenderViewImpl::InstrumentWillComposite() {
6119 if (!webview())
6120 return;
6121 if (!webview()->devToolsAgent())
6122 return;
6123 webview()->devToolsAgent()->willComposite();
6124}
6125
6126bool RenderViewImpl::AllowPartialSwap() const {
6127 return allow_partial_swap_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006128}
6129
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006130bool RenderViewImpl::ScheduleFileChooser(
6131 const FileChooserParams& params,
6132 WebFileChooserCompletion* completion) {
6133 static const size_t kMaximumPendingFileChooseRequests = 4;
6134 if (file_chooser_completions_.size() > kMaximumPendingFileChooseRequests) {
6135 // This sanity check prevents too many file choose requests from getting
6136 // queued which could DoS the user. Getting these is most likely a
6137 // programming error (there are many ways to DoS the user so it's not
6138 // considered a "real" security check), either in JS requesting many file
6139 // choosers to pop up, or in a plugin.
6140 //
6141 // TODO(brettw) we might possibly want to require a user gesture to open
6142 // a file picker, which will address this issue in a better way.
6143 return false;
6144 }
6145
6146 file_chooser_completions_.push_back(linked_ptr<PendingFileChooser>(
6147 new PendingFileChooser(params, completion)));
6148 if (file_chooser_completions_.size() == 1) {
6149 // Actually show the browse dialog when this is the first request.
6150 Send(new ViewHostMsg_RunFileChooser(routing_id_, params));
6151 }
6152 return true;
6153}
6154
6155WebKit::WebGeolocationClient* RenderViewImpl::geolocationClient() {
6156 if (!geolocation_dispatcher_)
6157 geolocation_dispatcher_ = new GeolocationDispatcher(this);
6158 return geolocation_dispatcher_;
6159}
6160
6161WebKit::WebSpeechInputController* RenderViewImpl::speechInputController(
6162 WebKit::WebSpeechInputListener* listener) {
6163#if defined(ENABLE_INPUT_SPEECH)
6164 if (!input_tag_speech_dispatcher_)
6165 input_tag_speech_dispatcher_ =
6166 new InputTagSpeechDispatcher(this, listener);
6167#endif
6168 return input_tag_speech_dispatcher_;
6169}
6170
6171WebKit::WebSpeechRecognizer* RenderViewImpl::speechRecognizer() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006172 if (!speech_recognition_dispatcher_)
6173 speech_recognition_dispatcher_ = new SpeechRecognitionDispatcher(this);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006174 return speech_recognition_dispatcher_;
6175}
6176
6177WebKit::WebDeviceOrientationClient* RenderViewImpl::deviceOrientationClient() {
6178 if (!device_orientation_dispatcher_)
6179 device_orientation_dispatcher_ = new DeviceOrientationDispatcher(this);
6180 return device_orientation_dispatcher_;
6181}
6182
6183void RenderViewImpl::zoomLimitsChanged(double minimum_level,
6184 double maximum_level) {
6185 // For now, don't remember plugin zoom values. We don't want to mix them with
6186 // normal web content (i.e. a fixed layout plugin would usually want them
6187 // different).
6188 bool remember = !webview()->mainFrame()->document().isPluginDocument();
6189
6190 int minimum_percent = static_cast<int>(
Ben Murdoch58e6fbe2013-07-26 10:20:38 +01006191 ZoomLevelToZoomFactor(minimum_level) * 100);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006192 int maximum_percent = static_cast<int>(
Ben Murdoch58e6fbe2013-07-26 10:20:38 +01006193 ZoomLevelToZoomFactor(maximum_level) * 100);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006194
6195 Send(new ViewHostMsg_UpdateZoomLimits(
6196 routing_id_, minimum_percent, maximum_percent, remember));
6197}
6198
6199void RenderViewImpl::zoomLevelChanged() {
6200 bool remember = !webview()->mainFrame()->document().isPluginDocument();
6201 float zoom_level = webview()->zoomLevel();
6202
6203 FOR_EACH_OBSERVER(RenderViewObserver, observers_, ZoomLevelChanged());
6204
6205 // Tell the browser which url got zoomed so it can update the menu and the
6206 // saved values if necessary
6207 Send(new ViewHostMsg_DidZoomURL(
6208 routing_id_, zoom_level, remember,
6209 GURL(webview()->mainFrame()->document().url())));
6210}
6211
Ben Murdoch58e6fbe2013-07-26 10:20:38 +01006212double RenderViewImpl::zoomLevelToZoomFactor(double zoom_level) const {
6213 return ZoomLevelToZoomFactor(zoom_level);
6214}
6215
6216double RenderViewImpl::zoomFactorToZoomLevel(double factor) const {
6217 return ZoomFactorToZoomLevel(factor);
6218}
6219
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006220void RenderViewImpl::registerProtocolHandler(const WebString& scheme,
6221 const WebString& base_url,
6222 const WebString& url,
6223 const WebString& title) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006224 bool user_gesture = WebUserGestureIndicator::isProcessingUserGesture();
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006225 GURL base(base_url);
6226 GURL absolute_url = base.Resolve(UTF16ToUTF8(url));
6227 if (base.GetOrigin() != absolute_url.GetOrigin()) {
6228 return;
6229 }
6230 Send(new ViewHostMsg_RegisterProtocolHandler(routing_id_,
6231 UTF16ToUTF8(scheme),
6232 absolute_url,
6233 title,
6234 user_gesture));
6235}
6236
6237WebKit::WebPageVisibilityState RenderViewImpl::visibilityState() const {
6238 WebKit::WebPageVisibilityState current_state = is_hidden() ?
6239 WebKit::WebPageVisibilityStateHidden :
6240 WebKit::WebPageVisibilityStateVisible;
6241 WebKit::WebPageVisibilityState override_state = current_state;
6242 if (GetContentClient()->renderer()->
6243 ShouldOverridePageVisibilityState(this,
6244 &override_state))
6245 return override_state;
6246 return current_state;
6247}
6248
6249WebKit::WebUserMediaClient* RenderViewImpl::userMediaClient() {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01006250 EnsureMediaStreamClient();
6251 return web_user_media_client_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006252}
6253
Ben Murdoch58e6fbe2013-07-26 10:20:38 +01006254WebKit::WebMIDIClient* RenderViewImpl::webMIDIClient() {
6255 if (!midi_dispatcher_)
6256 midi_dispatcher_ = new MIDIDispatcher(this);
6257 return midi_dispatcher_;
6258}
6259
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006260void RenderViewImpl::draggableRegionsChanged() {
6261 FOR_EACH_OBSERVER(
6262 RenderViewObserver,
6263 observers_,
6264 DraggableRegionsChanged(webview()->mainFrame()));
6265}
6266
6267#if defined(OS_ANDROID)
6268WebContentDetectionResult RenderViewImpl::detectContentAround(
6269 const WebHitTestResult& touch_hit) {
6270 DCHECK(!touch_hit.isNull());
6271 DCHECK(!touch_hit.node().isNull());
6272 DCHECK(touch_hit.node().isTextNode());
6273
6274 // Process the position with all the registered content detectors until
6275 // a match is found. Priority is provided by their relative order.
6276 for (ContentDetectorList::const_iterator it = content_detectors_.begin();
6277 it != content_detectors_.end(); ++it) {
6278 ContentDetector::Result content = (*it)->FindTappedContent(touch_hit);
6279 if (content.valid) {
6280 return WebContentDetectionResult(content.content_boundaries,
6281 UTF8ToUTF16(content.text), content.intent_url);
6282 }
6283 }
6284 return WebContentDetectionResult();
6285}
6286
6287void RenderViewImpl::scheduleContentIntent(const WebURL& intent) {
6288 // Introduce a short delay so that the user can notice the content.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01006289 base::MessageLoop::current()->PostDelayedTask(
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006290 FROM_HERE,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01006291 base::Bind(&RenderViewImpl::LaunchAndroidContentIntent,
6292 AsWeakPtr(),
6293 intent,
6294 expected_content_intent_id_),
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006295 base::TimeDelta::FromMilliseconds(kContentIntentDelayMilliseconds));
6296}
6297
6298void RenderViewImpl::cancelScheduledContentIntents() {
6299 ++expected_content_intent_id_;
6300}
6301
6302void RenderViewImpl::LaunchAndroidContentIntent(const GURL& intent,
6303 size_t request_id) {
6304 if (request_id != expected_content_intent_id_)
6305 return;
6306
6307 // Remove the content highlighting if any.
6308 scheduleComposite();
6309
6310 if (!intent.is_empty())
6311 Send(new ViewHostMsg_StartContentIntent(routing_id_, intent));
6312}
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006313
6314bool RenderViewImpl::openDateTimeChooser(
6315 const WebKit::WebDateTimeChooserParams& params,
6316 WebKit::WebDateTimeChooserCompletion* completion) {
6317 date_time_picker_client_.reset(
6318 new RendererDateTimePicker(this, params, completion));
6319 return date_time_picker_client_->Open();
6320}
6321
6322#endif // defined(OS_ANDROID)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006323
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006324#if defined(OS_MACOSX)
6325void RenderViewImpl::OnSelectPopupMenuItem(int selected_index) {
6326 if (external_popup_menu_ == NULL) {
6327 // Crash reports from the field indicate that we can be notified with a
6328 // NULL external popup menu (we probably get notified twice).
6329 // If you hit this please file a bug against jcivelli and include the page
6330 // and steps to repro.
6331 NOTREACHED();
6332 return;
6333 }
6334 external_popup_menu_->DidSelectItem(selected_index);
6335 external_popup_menu_.reset();
6336}
6337#endif
6338
6339#if defined(OS_ANDROID)
6340void RenderViewImpl::OnSelectPopupMenuItems(
6341 bool canceled,
6342 const std::vector<int>& selected_indices) {
6343 // It is possible to receive more than one of these calls if the user presses
6344 // a select faster than it takes for the show-select-popup IPC message to make
6345 // it to the browser UI thread. Ignore the extra-messages.
6346 // TODO(jcivelli): http:/b/5793321 Implement a better fix, as detailed in bug.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01006347 if (!external_popup_menu_)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006348 return;
6349
6350 external_popup_menu_->DidSelectItems(canceled, selected_indices);
6351 external_popup_menu_.reset();
6352}
6353#endif
6354
6355void RenderViewImpl::OnContextMenuClosed(
6356 const CustomContextMenuContext& custom_context) {
6357 if (custom_context.request_id) {
6358 // External request, should be in our map.
6359 ContextMenuClient* client =
6360 pending_context_menus_.Lookup(custom_context.request_id);
6361 if (client) {
6362 client->OnMenuClosed(custom_context.request_id);
6363 pending_context_menus_.Remove(custom_context.request_id);
6364 }
6365 } else {
6366 // Internal request, forward to WebKit.
6367 context_menu_node_.reset();
6368 }
6369}
6370
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01006371void RenderViewImpl::OnShowContextMenu(const gfx::Point& location) {
Ben Murdocheb525c52013-07-10 11:40:50 +01006372 context_menu_source_type_ = ui::MENU_SOURCE_TOUCH_EDIT_MENU;
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01006373 touch_editing_context_menu_location_ = location;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01006374 if (webview())
6375 webview()->showContextMenu();
6376}
6377
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006378void RenderViewImpl::OnEnableViewSourceMode() {
6379 if (!webview())
6380 return;
6381 WebFrame* main_frame = webview()->mainFrame();
6382 if (!main_frame)
6383 return;
6384 main_frame->enableViewSourceMode(true);
6385}
6386
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01006387#if defined(OS_ANDROID)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006388void RenderViewImpl::OnJavaBridgeInit() {
6389 DCHECK(!java_bridge_dispatcher_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006390 java_bridge_dispatcher_ = new JavaBridgeDispatcher(this);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006391}
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01006392#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006393
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006394void RenderViewImpl::OnDisownOpener() {
6395 if (!webview())
6396 return;
6397
6398 WebFrame* main_frame = webview()->mainFrame();
6399 if (main_frame && main_frame->opener())
6400 main_frame->setOpener(NULL);
6401}
6402
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006403#if defined(OS_ANDROID)
6404bool RenderViewImpl::didTapMultipleTargets(
6405 const WebKit::WebGestureEvent& event,
6406 const WebVector<WebRect>& target_rects) {
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01006407 // Never show a disambiguation popup when accessibility is enabled,
6408 // as this interferes with "touch exploration".
6409 if (accessibility_mode_ == AccessibilityModeComplete)
6410 return false;
6411
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006412 gfx::Rect finger_rect(
6413 event.x - event.data.tap.width / 2, event.y - event.data.tap.height / 2,
6414 event.data.tap.width, event.data.tap.height);
6415 gfx::Rect zoom_rect;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006416 float new_total_scale =
6417 DisambiguationPopupHelper::ComputeZoomAreaAndScaleFactor(
6418 finger_rect, target_rects, GetSize(),
6419 gfx::Rect(webview()->mainFrame()->visibleContentRect()).size(),
6420 device_scale_factor_ * webview()->pageScaleFactor(), &zoom_rect);
6421 if (!new_total_scale)
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006422 return false;
6423
Ben Murdoch2385ea32013-08-06 11:01:04 +01006424 TapMultipleTargetsStrategy multitarget_strategy =
6425 renderer_preferences_.tap_multiple_targets_strategy;
6426 if (multitarget_strategy == TAP_MULTIPLE_TARGETS_STRATEGY_ZOOM) {
6427 return webview()->zoomToMultipleTargetsRect(zoom_rect);
6428 } else if (multitarget_strategy == TAP_MULTIPLE_TARGETS_STRATEGY_POPUP) {
6429 gfx::Size canvas_size =
6430 gfx::ToCeiledSize(gfx::ScaleSize(zoom_rect.size(), new_total_scale));
6431 TransportDIB* transport_dib = NULL;
6432 {
6433 scoped_ptr<skia::PlatformCanvas> canvas(
6434 RenderProcess::current()->GetDrawingCanvas(&transport_dib,
6435 gfx::Rect(canvas_size)));
6436 if (!canvas)
6437 return false;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006438
Ben Murdoch2385ea32013-08-06 11:01:04 +01006439 // TODO(trchen): Cleanup the device scale factor mess.
6440 // device scale will be applied in WebKit
6441 // --> zoom_rect doesn't include device scale,
6442 // but WebKit will still draw on zoom_rect * device_scale_factor_
6443 canvas->scale(new_total_scale / device_scale_factor_,
6444 new_total_scale / device_scale_factor_);
6445 canvas->translate(-zoom_rect.x() * device_scale_factor_,
6446 -zoom_rect.y() * device_scale_factor_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006447
Ben Murdoch2385ea32013-08-06 11:01:04 +01006448 webwidget_->paint(
6449 canvas.get(),
6450 zoom_rect,
6451 WebWidget::ForceSoftwareRenderingAndIgnoreGPUResidentContent);
6452 }
6453
6454 gfx::Rect physical_window_zoom_rect = gfx::ToEnclosingRect(
6455 ClientRectToPhysicalWindowRect(gfx::RectF(zoom_rect)));
6456 Send(new ViewHostMsg_ShowDisambiguationPopup(routing_id_,
6457 physical_window_zoom_rect,
6458 canvas_size,
6459 transport_dib->id()));
6460 } else {
6461 return false;
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006462 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006463
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006464 return true;
6465}
6466#endif
6467
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006468unsigned RenderViewImpl::GetLocalSessionHistoryLengthForTesting() const {
6469 return history_list_length_;
6470}
6471
6472void RenderViewImpl::SetFocusAndActivateForTesting(bool enable) {
6473 if (enable) {
6474 if (has_focus())
6475 return;
6476 OnSetActive(true);
6477 OnSetFocus(true);
6478 } else {
6479 if (!has_focus())
6480 return;
6481 OnSetFocus(false);
6482 OnSetActive(false);
6483 }
6484}
6485
6486void RenderViewImpl::SetDeviceScaleFactorForTesting(float factor) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01006487 ViewMsg_Resize_Params params;
6488 params.screen_info = screen_info_;
6489 params.screen_info.deviceScaleFactor = factor;
6490 params.new_size = size();
6491 params.physical_backing_size =
6492 gfx::ToCeiledSize(gfx::ScaleSize(size(), factor));
6493 params.overdraw_bottom_height = 0.f;
6494 params.resizer_rect = WebRect();
6495 params.is_fullscreen = is_fullscreen();
6496 OnResize(params);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006497}
6498
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01006499void RenderViewImpl::EnableAutoResizeForTesting(const gfx::Size& min_size,
6500 const gfx::Size& max_size) {
6501 OnEnableAutoResize(min_size, max_size);
6502}
6503
6504void RenderViewImpl::DisableAutoResizeForTesting(const gfx::Size& new_size) {
6505 OnDisableAutoResize(new_size);
6506}
6507
Ben Murdoch7dbb3d52013-07-17 14:55:54 +01006508void RenderViewImpl::SetMediaStreamClientForTesting(
6509 MediaStreamClient* media_stream_client) {
6510 DCHECK(!media_stream_client_);
6511 DCHECK(!web_user_media_client_);
6512 media_stream_client_ = media_stream_client;
6513}
6514
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006515void RenderViewImpl::OnReleaseDisambiguationPopupDIB(
6516 TransportDIB::Handle dib_handle) {
6517 TransportDIB* dib = TransportDIB::CreateWithHandle(dib_handle);
6518 RenderProcess::current()->ReleaseTransportDIB(dib);
6519}
6520
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00006521void RenderViewImpl::DidCommitCompositorFrame() {
6522 RenderWidget::DidCommitCompositorFrame();
6523 FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidCommitCompositorFrame());
6524}
6525
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01006526void RenderViewImpl::SendUpdateFaviconURL(const std::vector<FaviconURL>& urls) {
6527 if (!urls.empty())
6528 Send(new ViewHostMsg_UpdateFaviconURL(routing_id_, page_id_, urls));
6529}
6530
6531void RenderViewImpl::DidStopLoadingIcons() {
6532 int icon_types = WebIconURL::TypeFavicon;
6533 if (TouchEnabled())
6534 icon_types |= WebIconURL::TypeTouchPrecomposed | WebIconURL::TypeTouch;
6535
6536 WebVector<WebIconURL> icon_urls =
6537 webview()->mainFrame()->iconURLs(icon_types);
6538
6539 std::vector<FaviconURL> urls;
6540 for (size_t i = 0; i < icon_urls.size(); i++) {
6541 WebURL url = icon_urls[i].iconURL();
6542 if (!url.isEmpty())
6543 urls.push_back(FaviconURL(url,
6544 ToFaviconType(icon_urls[i].iconType())));
6545 }
6546 SendUpdateFaviconURL(urls);
6547}
6548
6549
Torne (Richard Coles)58218062012-11-14 11:43:16 +00006550} // namespace content