blob: 9e14c5501803dea8f4eff26f62e4d9aafa3d8bce [file] [log] [blame]
[email protected]1b4209f2011-01-07 00:25:401// Copyright (c) 2011 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]6e24cf12011-03-18 19:57:025#include "content/renderer/render_view.h"
initial.commit09911bf2008-07-26 23:55:296
7#include <algorithm>
[email protected]b75b8292010-10-01 07:28:258#include <cmath>
initial.commit09911bf2008-07-26 23:55:299#include <string>
10#include <vector>
11
[email protected]2041cf342010-02-19 03:15:5912#include "base/callback.h"
initial.commit09911bf2008-07-26 23:55:2913#include "base/command_line.h"
[email protected]bb063b72009-03-27 23:18:5014#include "base/compiler_specific.h"
[email protected]625332e02010-12-14 07:48:4915#include "base/lazy_instance.h"
[email protected]835d7c82010-10-14 04:38:3816#include "base/metrics/histogram.h"
[email protected]7bf795d92010-05-22 00:14:2817#include "base/path_service.h"
[email protected]8380c092009-06-25 17:45:5118#include "base/process_util.h"
initial.commit09911bf2008-07-26 23:55:2919#include "base/string_piece.h"
20#include "base/string_util.h"
[email protected]55126132010-08-19 14:53:2821#include "base/sys_string_conversions.h"
[email protected]6fdd4182010-10-14 23:59:2622#include "base/time.h"
[email protected]be1ce6a72010-08-03 14:35:2223#include "base/utf_string_conversions.h"
[email protected]c4a9e932011-03-05 04:05:5524#include "chrome/common/autofill_messages.h"
[email protected]81e63782009-02-27 19:35:0925#include "chrome/common/bindings_policy.h"
[email protected]ef916272009-07-08 21:40:5526#include "chrome/common/child_process_logging.h"
[email protected]f0af6a72009-05-30 05:25:1727#include "chrome/common/chrome_constants.h"
[email protected]7bf795d92010-05-22 00:14:2828#include "chrome/common/chrome_paths.h"
29#include "chrome/common/chrome_switches.h"
[email protected]39ec12f2011-03-25 23:02:2830#include "chrome/common/devtools_messages.h"
[email protected]a0cf04a2010-06-23 03:29:5531#include "chrome/common/extensions/extension.h"
[email protected]46fd1ea42011-02-16 15:59:3332#include "chrome/common/extensions/extension_constants.h"
[email protected]44c49c92011-03-28 16:17:2333#include "chrome/common/extensions/extension_messages.h"
[email protected]ec7db282011-01-29 01:11:3634#include "chrome/common/extensions/extension_set.h"
[email protected]bb461532010-11-26 21:50:2335#include "chrome/common/json_value_serializer.h"
[email protected]4e0616e2010-05-28 14:55:5336#include "chrome/common/pepper_plugin_registry.h"
[email protected]e09ba552009-02-05 03:26:2937#include "chrome/common/render_messages.h"
[email protected]13a1e4c3c2011-02-03 21:07:0938#include "chrome/common/render_view_commands.h"
initial.commit09911bf2008-07-26 23:55:2939#include "chrome/common/thumbnail_score.h"
[email protected]6de74452009-02-25 18:04:5940#include "chrome/common/url_constants.h"
[email protected]38789d82010-11-17 06:03:4441#include "chrome/common/web_apps.h"
initial.commit09911bf2008-07-26 23:55:2942#include "chrome/renderer/about_handler.h"
[email protected]78192082011-01-29 05:43:4443#include "chrome/renderer/autofill/autofill_agent.h"
44#include "chrome/renderer/autofill/form_manager.h"
45#include "chrome/renderer/autofill/password_autofill_manager.h"
[email protected]2f979172010-09-16 21:54:0346#include "chrome/renderer/automation/dom_automation_controller.h"
[email protected]e4ac5df2009-03-17 15:33:1147#include "chrome/renderer/devtools_agent.h"
48#include "chrome/renderer/devtools_client.h"
[email protected]f816c012009-06-26 21:48:3249#include "chrome/renderer/extensions/event_bindings.h"
[email protected]6779aa12011-03-29 17:32:2450#include "chrome/renderer/extensions/extension_dispatcher.h"
[email protected]44c49c92011-03-28 16:17:2351#include "chrome/renderer/extensions/extension_helper.h"
[email protected]0f6053962009-07-09 19:26:3552#include "chrome/renderer/extensions/extension_process_bindings.h"
[email protected]78d5cfe2011-02-04 08:43:2253#include "chrome/renderer/extensions/extension_resource_request_policy.h"
[email protected]7120f132009-07-20 21:05:3754#include "chrome/renderer/extensions/renderer_extension_bindings.h"
[email protected]2f979172010-09-16 21:54:0355#include "chrome/renderer/external_host_bindings.h"
initial.commit09911bf2008-07-26 23:55:2956#include "chrome/renderer/localized_error.h"
[email protected]6a8ddba52010-09-05 04:38:0657#include "chrome/renderer/page_click_tracker.h"
[email protected]a5a65ac2010-11-05 18:14:3658#include "chrome/renderer/page_load_histograms.h"
[email protected]d81c1e52009-06-03 22:09:5059#include "chrome/renderer/print_web_view_helper.h"
[email protected]39008c02009-02-11 23:59:2560#include "chrome/renderer/render_process.h"
[email protected]00c39612010-03-06 02:53:2861#include "chrome/renderer/render_thread.h"
[email protected]32ca14682011-02-16 19:05:1062#include "chrome/renderer/safe_browsing/malware_dom_details.h"
[email protected]3ead1322010-11-19 20:01:0063#include "chrome/renderer/safe_browsing/phishing_classifier_delegate.h"
[email protected]6c2f73202011-02-14 20:21:5464#include "chrome/renderer/searchbox.h"
[email protected]85c55dc2009-11-06 03:05:4665#include "chrome/renderer/spellchecker/spellcheck.h"
[email protected]c4a9e932011-03-05 04:05:5566#include "chrome/renderer/spellchecker/spellcheck_provider.h"
[email protected]81273622011-02-02 03:56:1367#include "chrome/renderer/translate_helper.h"
[email protected]0938d3c2009-01-09 20:37:3568#include "chrome/renderer/user_script_slave.h"
initial.commit09911bf2008-07-26 23:55:2969#include "chrome/renderer/visitedlink_slave.h"
[email protected]e93e04e2011-03-14 00:27:1070#include "content/common/appcache/appcache_dispatcher.h"
[email protected]127dd582011-03-16 21:32:1071#include "content/common/clipboard_messages.h"
[email protected]db803aae2011-03-05 02:00:4272#include "content/common/content_constants.h"
[email protected]37666cf2011-03-13 21:51:4273#include "content/common/database_messages.h"
[email protected]59f4f2fa2011-03-23 01:00:5574#include "content/common/drag_messages.h"
[email protected]7ef40ffe12011-03-08 05:05:2875#include "content/common/file_system/file_system_dispatcher.h"
76#include "content/common/file_system/webfilesystem_callback_dispatcher.h"
[email protected]7f070d42011-03-09 20:25:3277#include "content/common/notification_service.h"
[email protected]127dd582011-03-16 21:32:1078#include "content/common/pepper_messages.h"
[email protected]60916042011-03-19 00:43:3679#include "content/common/renderer_preferences.h"
[email protected]778574e2011-03-21 22:03:5080#include "content/common/view_messages.h"
[email protected]230b7ef2011-03-16 22:30:1981#include "content/renderer/audio_message_filter.h"
[email protected]21d61e52011-03-18 19:08:2582#include "content/renderer/content_renderer_client.h"
[email protected]230b7ef2011-03-16 22:30:1983#include "content/renderer/device_orientation_dispatcher.h"
[email protected]55722152011-03-22 01:33:5384#include "content/renderer/external_popup_menu.h"
[email protected]230b7ef2011-03-16 22:30:1985#include "content/renderer/geolocation_dispatcher.h"
[email protected]ccc70d8e2011-03-16 20:40:3786#include "content/renderer/ggl.h"
[email protected]921f1592011-03-18 00:41:0287#include "content/renderer/load_progress_tracker.h"
[email protected]ccc70d8e2011-03-16 20:40:3788#include "content/renderer/media/audio_renderer_impl.h"
89#include "content/renderer/media/ipc_video_decoder.h"
[email protected]921f1592011-03-18 00:41:0290#include "content/renderer/navigation_state.h"
[email protected]230b7ef2011-03-16 22:30:1991#include "content/renderer/notification_provider.h"
[email protected]ccc70d8e2011-03-16 20:40:3792#include "content/renderer/p2p/socket_dispatcher.h"
[email protected]6f516082011-03-17 19:15:3593#include "content/renderer/plugin_channel_host.h"
[email protected]60916042011-03-19 00:43:3694#include "content/renderer/render_view_observer.h"
95#include "content/renderer/render_view_visitor.h"
[email protected]2cff0052011-03-18 16:51:4496#include "content/renderer/render_widget_fullscreen.h"
97#include "content/renderer/render_widget_fullscreen_pepper.h"
[email protected]663bd9e2011-03-21 01:07:0198#include "content/renderer/renderer_webapplicationcachehost_impl.h"
99#include "content/renderer/renderer_webstoragenamespace_impl.h"
[email protected]230b7ef2011-03-16 22:30:19100#include "content/renderer/speech_input_dispatcher.h"
[email protected]663bd9e2011-03-21 01:07:01101#include "content/renderer/web_ui_bindings.h"
[email protected]6f516082011-03-17 19:15:35102#include "content/renderer/webgraphicscontext3d_command_buffer_impl.h"
103#include "content/renderer/webplugin_delegate_proxy.h"
104#include "content/renderer/websharedworker_proxy.h"
105#include "content/renderer/webworker_proxy.h"
[email protected]f8db8132010-12-03 00:27:49106#include "media/base/filter_collection.h"
[email protected]ee68378a2010-08-10 01:05:41107#include "media/base/media_switches.h"
[email protected]f78d1dfc2011-01-15 07:09:27108#include "media/base/message_loop_factory_impl.h"
[email protected]f11ca0732009-04-11 00:09:34109#include "net/base/data_url.h"
initial.commit09911bf2008-07-26 23:55:29110#include "net/base/escape.h"
111#include "net/base/net_errors.h"
[email protected]52c68652010-12-07 17:47:04112#include "net/http/http_util.h"
[email protected]9d9f1bb2011-02-23 22:10:57113#include "ppapi/c/private/ppb_flash_net_connector.h"
[email protected]c399a8a2008-11-22 19:38:00114#include "skia/ext/bitmap_platform_device.h"
[email protected]83c9e6552008-12-03 16:22:10115#include "skia/ext/image_operations.h"
[email protected]8bd0fe62011-01-17 06:44:37116#include "third_party/WebKit/Source/WebKit/chromium/public/WebAccessibilityCache.h"
117#include "third_party/WebKit/Source/WebKit/chromium/public/WebAccessibilityObject.h"
118#include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h"
119#include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h"
120#include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsAgent.h"
121#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
122#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragData.h"
123#include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
124#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileChooserParams.h"
[email protected]8bd0fe62011-01-17 06:44:37125#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileSystemCallbacks.h"
126#include "third_party/WebKit/Source/WebKit/chromium/public/WebFindOptions.h"
127#include "third_party/WebKit/Source/WebKit/chromium/public/WebFormControlElement.h"
128#include "third_party/WebKit/Source/WebKit/chromium/public/WebFormElement.h"
129#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
130#include "third_party/WebKit/Source/WebKit/chromium/public/WebGraphicsContext3D.h"
131#include "third_party/WebKit/Source/WebKit/chromium/public/WebHistoryItem.h"
132#include "third_party/WebKit/Source/WebKit/chromium/public/WebImage.h"
133#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h"
[email protected]69f110d62011-03-17 19:01:14134#include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayerAction.h"
[email protected]232a5812011-03-04 22:42:08135#include "third_party/WebKit/Source/WebKit/chromium/public/WebNetworkStateNotifier.h"
[email protected]8bd0fe62011-01-17 06:44:37136#include "third_party/WebKit/Source/WebKit/chromium/public/WebNodeList.h"
137#include "third_party/WebKit/Source/WebKit/chromium/public/WebPageSerializer.h"
138#include "third_party/WebKit/Source/WebKit/chromium/public/WebPlugin.h"
139#include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h"
140#include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginDocument.h"
141#include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginParams.h"
142#include "third_party/WebKit/Source/WebKit/chromium/public/WebPoint.h"
143#include "third_party/WebKit/Source/WebKit/chromium/public/WebRange.h"
144#include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h"
145#include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h"
146#include "third_party/WebKit/Source/WebKit/chromium/public/WebSearchableFormData.h"
147#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
148#include "third_party/WebKit/Source/WebKit/chromium/public/WebSettings.h"
149#include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h"
150#include "third_party/WebKit/Source/WebKit/chromium/public/WebStorageNamespace.h"
151#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
152#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
153#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLError.h"
154#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h"
155#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
156#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h"
157#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
158#include "third_party/WebKit/Source/WebKit/chromium/public/WebWindowFeatures.h"
[email protected]6fdd4182010-10-14 23:59:26159#include "third_party/skia/include/core/SkBitmap.h"
[email protected]c4a9e932011-03-05 04:05:55160#include "ui/base/message_box_flags.h"
[email protected]08397d52011-02-05 01:53:38161#include "ui/gfx/color_utils.h"
162#include "ui/gfx/favicon_size.h"
163#include "ui/gfx/native_widget_types.h"
164#include "ui/gfx/point.h"
165#include "ui/gfx/rect.h"
166#include "ui/gfx/skbitmap_operations.h"
[email protected]a6097f42011-01-10 08:50:51167#include "v8/include/v8-testing.h"
[email protected]c4a9e932011-03-05 04:05:55168#include "v8/include/v8.h"
[email protected]80f584d92010-01-21 03:59:04169#include "webkit/appcache/web_application_cache_host_impl.h"
[email protected]25e18f82010-10-27 16:38:43170#include "webkit/glue/alt_error_page_resource_fetcher.h"
[email protected]7a4de7a62010-08-17 18:38:24171#include "webkit/glue/context_menu.h"
initial.commit09911bf2008-07-26 23:55:29172#include "webkit/glue/dom_operations.h"
[email protected]b1438212010-04-03 00:30:59173#include "webkit/glue/form_data.h"
[email protected]95056b582010-02-18 01:29:24174#include "webkit/glue/form_field.h"
[email protected]95056b582010-02-18 01:29:24175#include "webkit/glue/glue_serialize.h"
[email protected]f11ca0732009-04-11 00:09:34176#include "webkit/glue/image_decoder.h"
[email protected]4d51d5bf2010-07-26 18:48:26177#include "webkit/glue/image_resource_fetcher.h"
[email protected]85cc78c2010-05-04 18:30:09178#include "webkit/glue/media/video_renderer_impl.h"
[email protected]4d51d5bf2010-07-26 18:48:26179#include "webkit/glue/password_form_dom_manager.h"
[email protected]bb461532010-11-26 21:50:23180#include "webkit/glue/resource_fetcher.h"
[email protected]85cc78c2010-05-04 18:30:09181#include "webkit/glue/site_isolation_metrics.h"
[email protected]7a4de7a62010-08-17 18:38:24182#include "webkit/glue/webaccessibility.h"
initial.commit09911bf2008-07-26 23:55:29183#include "webkit/glue/webdropdata.h"
[email protected]a6939ca42011-02-18 17:58:07184#include "webkit/glue/webkit_constants.h"
initial.commit09911bf2008-07-26 23:55:29185#include "webkit/glue/webkit_glue.h"
[email protected]add51772009-06-11 18:25:17186#include "webkit/glue/webmediaplayer_impl.h"
[email protected]191eb3f72010-12-21 06:27:50187#include "webkit/plugins/npapi/default_plugin_shared.h"
188#include "webkit/plugins/npapi/plugin_list.h"
189#include "webkit/plugins/npapi/webplugin_delegate.h"
190#include "webkit/plugins/npapi/webplugin_delegate_impl.h"
191#include "webkit/plugins/npapi/webplugin_impl.h"
192#include "webkit/plugins/npapi/webview_plugin.h"
[email protected]0bd753682010-12-16 18:15:52193#include "webkit/plugins/ppapi/ppapi_webplugin_impl.h"
initial.commit09911bf2008-07-26 23:55:29194
[email protected]6c8afae52009-01-22 02:24:57195#if defined(OS_WIN)
196// TODO(port): these files are currently Windows only because they concern:
[email protected]6c8afae52009-01-22 02:24:57197// * theming
[email protected]08397d52011-02-05 01:53:38198#include "ui/gfx/native_theme_win.h"
[email protected]6981f7f2010-03-09 00:53:03199#elif defined(USE_X11)
[email protected]8bd0fe62011-01-17 06:44:37200#include "third_party/WebKit/Source/WebKit/chromium/public/linux/WebRenderTheme.h"
[email protected]08397d52011-02-05 01:53:38201#include "ui/gfx/native_theme_linux.h"
[email protected]78043bdd2010-04-05 18:45:33202#elif defined(OS_MACOSX)
203#include "skia/ext/skia_utils_mac.h"
[email protected]6c8afae52009-01-22 02:24:57204#endif
205
[email protected]c7287a92009-11-04 20:06:15206using WebKit::WebAccessibilityCache;
[email protected]9892b472010-09-16 00:23:42207using WebKit::WebAccessibilityNotification;
[email protected]cc0445f2009-10-13 16:09:08208using WebKit::WebAccessibilityObject;
[email protected]035545f2010-04-09 13:10:21209using WebKit::WebApplicationCacheHost;
210using WebKit::WebApplicationCacheHostClient;
[email protected]6fdd4182010-10-14 23:59:26211using WebKit::WebCString;
[email protected]1c83eb42009-09-11 21:08:41212using WebKit::WebColor;
213using WebKit::WebColorName;
[email protected]0dea3ea2009-03-31 23:30:59214using WebKit::WebConsoleMessage;
[email protected]79e37442009-10-09 18:17:44215using WebKit::WebContextMenuData;
[email protected]b921cfd22010-02-25 16:57:51216using WebKit::WebCookieJar;
[email protected]e6f546c32009-07-01 17:12:55217using WebKit::WebData;
[email protected]726985e22009-06-18 21:09:28218using WebKit::WebDataSource;
[email protected]2661b332009-11-03 18:42:29219using WebKit::WebDevToolsAgent;
[email protected]5bc8fe92010-03-11 18:19:00220using WebKit::WebDocument;
[email protected]e80c73b2009-04-07 23:24:58221using WebKit::WebDragData;
[email protected]1d9f4132009-09-08 17:29:25222using WebKit::WebDragOperation;
223using WebKit::WebDragOperationsMask;
[email protected]79dbc662009-09-04 05:42:51224using WebKit::WebEditingAction;
[email protected]9b66f34bf2010-10-27 20:45:51225using WebKit::WebElement;
[email protected]caf706f2010-10-26 17:54:08226using WebKit::WebExternalPopupMenu;
227using WebKit::WebExternalPopupMenuClient;
[email protected]cdaf8d02010-03-30 19:52:47228using WebKit::WebFileChooserCompletion;
[email protected]2b06a992010-08-21 05:48:22229using WebKit::WebFileSystem;
230using WebKit::WebFileSystemCallbacks;
[email protected]6069da8c2009-10-20 20:33:49231using WebKit::WebFindOptions;
[email protected]b1438212010-04-03 00:30:59232using WebKit::WebFormControlElement;
[email protected]979c28b2009-11-07 01:30:48233using WebKit::WebFormElement;
[email protected]dd7daa82009-08-10 05:46:45234using WebKit::WebFrame;
[email protected]ca948a22009-06-25 19:36:17235using WebKit::WebHistoryItem;
[email protected]c27ae592010-03-18 15:24:41236using WebKit::WebImage;
[email protected]e6efd022010-03-31 09:34:50237using WebKit::WebInputElement;
[email protected]3d9689372009-09-10 04:29:17238using WebKit::WebMediaPlayer;
[email protected]952cb702009-10-07 05:50:28239using WebKit::WebMediaPlayerAction;
[email protected]3d9689372009-09-10 04:29:17240using WebKit::WebMediaPlayerClient;
[email protected]4873c7d2009-07-16 06:36:28241using WebKit::WebNavigationPolicy;
[email protected]726985e22009-06-18 21:09:28242using WebKit::WebNavigationType;
[email protected]232a5812011-03-04 22:42:08243using WebKit::WebNetworkStateNotifier;
[email protected]79dbc662009-09-04 05:42:51244using WebKit::WebNode;
[email protected]d9ec5c0f2009-12-23 11:55:07245using WebKit::WebPageSerializer;
246using WebKit::WebPageSerializerClient;
[email protected]3d9689372009-09-10 04:29:17247using WebKit::WebPlugin;
[email protected]00152e92010-07-19 11:47:40248using WebKit::WebPluginContainer;
[email protected]24a7f3c2010-03-25 08:26:49249using WebKit::WebPluginDocument;
[email protected]aad51d1c2010-08-05 08:38:09250using WebKit::WebPluginParams;
[email protected]48c9cf2d2009-09-16 16:47:52251using WebKit::WebPoint;
[email protected]88efb7ec2009-07-14 16:32:59252using WebKit::WebPopupMenuInfo;
[email protected]79dbc662009-09-04 05:42:51253using WebKit::WebRange;
[email protected]b3f2b912009-04-09 16:18:52254using WebKit::WebRect;
[email protected]4f999132009-03-31 18:08:40255using WebKit::WebScriptSource;
[email protected]ce0e250d2009-10-23 21:00:35256using WebKit::WebSearchableFormData;
[email protected]e3d60e5d2009-09-25 21:08:29257using WebKit::WebSecurityOrigin;
[email protected]2fab253a2009-08-17 23:00:59258using WebKit::WebSettings;
[email protected]9c00f002009-11-05 22:37:42259using WebKit::WebSharedWorker;
[email protected]8649fb32009-06-26 17:51:02260using WebKit::WebSize;
[email protected]bd92c3a2010-01-13 05:02:34261using WebKit::WebStorageNamespace;
[email protected]726985e22009-06-18 21:09:28262using WebKit::WebString;
[email protected]79dbc662009-09-04 05:42:51263using WebKit::WebTextAffinity;
[email protected]de570ef2009-07-29 18:27:52264using WebKit::WebTextDirection;
[email protected]726985e22009-06-18 21:09:28265using WebKit::WebURL;
266using WebKit::WebURLError;
267using WebKit::WebURLRequest;
268using WebKit::WebURLResponse;
[email protected]4873c7d2009-07-16 06:36:28269using WebKit::WebVector;
[email protected]50ae00ef2009-10-19 05:11:03270using WebKit::WebView;
[email protected]4873c7d2009-07-16 06:36:28271using WebKit::WebWidget;
[email protected]6fdd4182010-10-14 23:59:26272using WebKit::WebWindowFeatures;
[email protected]27ba8532009-04-24 20:22:43273using WebKit::WebWorker;
274using WebKit::WebWorkerClient;
[email protected]6fdd4182010-10-14 23:59:26275using appcache::WebApplicationCacheHostImpl;
[email protected]663bd9e2011-03-21 01:07:01276using autofill::AutofillAgent;
[email protected]78192082011-01-29 05:43:44277using autofill::FormManager;
[email protected]c4a9e932011-03-05 04:05:55278using autofill::PasswordAutofillManager;
[email protected]6fdd4182010-10-14 23:59:26279using base::Time;
280using base::TimeDelta;
281using webkit_glue::AltErrorPageResourceFetcher;
282using webkit_glue::FormData;
283using webkit_glue::FormField;
284using webkit_glue::ImageResourceFetcher;
285using webkit_glue::PasswordForm;
286using webkit_glue::PasswordFormDomManager;
[email protected]bb461532010-11-26 21:50:23287using webkit_glue::ResourceFetcher;
[email protected]6fdd4182010-10-14 23:59:26288using webkit_glue::SiteIsolationMetrics;
289using webkit_glue::WebAccessibility;
[email protected]e1acf6f2008-10-27 20:43:33290
initial.commit09911bf2008-07-26 23:55:29291//-----------------------------------------------------------------------------
292
[email protected]3354d3e2010-06-10 19:53:02293typedef std::map<WebKit::WebView*, RenderView*> ViewMap;
[email protected]625332e02010-12-14 07:48:49294static base::LazyInstance<ViewMap> g_view_map(base::LINKER_INITIALIZED);
[email protected]3354d3e2010-06-10 19:53:02295
initial.commit09911bf2008-07-26 23:55:29296// define to write the time necessary for thumbnail/DOM text retrieval,
297// respectively, into the system debug log
initial.commit09911bf2008-07-26 23:55:29298// #define TIME_TEXT_RETRIEVAL
299
300// maximum number of characters in the document to index, any text beyond this
301// point will be clipped
[email protected]6c8afae52009-01-22 02:24:57302static const size_t kMaxIndexChars = 65535;
initial.commit09911bf2008-07-26 23:55:29303
304// Size of the thumbnails that we'll generate
[email protected]8b4f4892009-09-04 21:52:37305static const int kThumbnailWidth = 212;
306static const int kThumbnailHeight = 132;
initial.commit09911bf2008-07-26 23:55:29307
308// Delay in milliseconds that we'll wait before capturing the page contents
309// and thumbnail.
310static const int kDelayForCaptureMs = 500;
311
312// Typically, we capture the page data once the page is loaded.
313// Sometimes, the page never finishes to load, preventing the page capture
314// To workaround this problem, we always perform a capture after the following
315// delay.
316static const int kDelayForForcedCaptureMs = 6000;
317
[email protected]882daa92009-11-05 16:31:31318// Time, in seconds, we delay before sending content state changes (such as form
319// state and scroll position) to the browser. We delay sending changes to avoid
320// spamming the browser.
321// To avoid having tab/session restore require sending a message to get the
322// current content state during tab closing we use a shorter timeout for the
323// foreground renderer. This means there is a small window of time from which
324// content state is modified and not sent to session restore, but this is
325// better than having to wake up all renderers during shutdown.
326static const int kDelaySecondsForContentStateSyncHidden = 5;
327static const int kDelaySecondsForContentStateSync = 1;
initial.commit09911bf2008-07-26 23:55:29328
[email protected]0aa55312008-10-17 21:53:08329// The maximum number of popups that can be spawned from one page.
330static const int kMaximumNumberOfUnacknowledgedPopups = 25;
331
[email protected]6fdd4182010-10-14 23:59:26332static const char kBackForwardNavigationScheme[] = "history";
[email protected]50b691c2008-10-31 19:08:35333
[email protected]726985e22009-06-18 21:09:28334static void GetRedirectChain(WebDataSource* ds, std::vector<GURL>* result) {
335 WebVector<WebURL> urls;
336 ds->redirectChain(urls);
337 result->reserve(urls.size());
338 for (size_t i = 0; i < urls.size(); ++i)
339 result->push_back(urls[i]);
340}
341
[email protected]30507922010-01-15 16:48:23342static bool PaintViewIntoCanvas(WebView* view,
343 skia::PlatformCanvas& canvas) {
344 view->layout();
345 const WebSize& size = view->size();
346
347 if (!canvas.initialize(size.width, size.height, true))
348 return false;
349
350 view->paint(webkit_glue::ToWebCanvas(&canvas),
351 WebRect(0, 0, size.width, size.height));
352 // TODO: Add a way to snapshot the whole page, not just the currently
353 // visible part.
354
355 return true;
356}
357
358// Calculates how "boring" a thumbnail is. The boring score is the
359// 0,1 ranged percentage of pixels that are the most common
360// luma. Higher boring scores indicate that a higher percentage of a
361// bitmap are all the same brightness.
362static double CalculateBoringScore(SkBitmap* bitmap) {
363 int histogram[256] = {0};
364 color_utils::BuildLumaHistogram(bitmap, histogram);
365
366 int color_count = *std::max_element(histogram, histogram + 256);
367 int pixel_count = bitmap->width() * bitmap->height();
368 return static_cast<double>(color_count) / pixel_count;
369}
370
[email protected]12bc8472010-04-15 07:29:40371// True if |frame| contains content that is white-listed for content settings.
372static bool IsWhitelistedForContentSettings(WebFrame* frame) {
373 WebSecurityOrigin origin = frame->securityOrigin();
374 if (origin.isEmpty())
375 return false; // Uninitialized document?
376
377 if (EqualsASCII(origin.protocol(), chrome::kChromeUIScheme))
378 return true; // Browser UI elements should still work.
379
380 // If the scheme is ftp: or file:, an empty file name indicates a directory
381 // listing, which requires JavaScript to function properly.
382 GURL frame_url = frame->url();
383 const char* kDirProtocols[] = { "ftp", "file" };
384 for (size_t i = 0; i < arraysize(kDirProtocols); ++i) {
385 if (EqualsASCII(origin.protocol(), kDirProtocols[i])) {
386 return frame_url.SchemeIs(kDirProtocols[i]) &&
387 frame_url.ExtractFileName().empty();
388 }
389 }
390
391 return false;
392}
393
[email protected]3a8eecb2010-04-22 23:56:30394// Returns true if the frame is navigating to an URL either into or out of an
395// extension app's extent.
[email protected]08e94b82010-12-15 22:51:04396// TODO(creis): Temporary workaround for crbug.com/65953: Only return true if
[email protected]88c15e972011-02-05 04:19:53397// we would enter an extension app's extent from a non-app, or if we leave an
398// extension with no web extent. We avoid swapping processes to exit a hosted
399// app with a web extent for now, since we do not yet restore context (such
[email protected]08e94b82010-12-15 22:51:04400// as window.opener) if the window navigates back.
[email protected]88c15e972011-02-05 04:19:53401static bool CrossesExtensionExtents(const ExtensionSet* extensions,
402 WebFrame* frame,
403 const GURL& new_url) {
[email protected]3a8eecb2010-04-22 23:56:30404 // If the URL is still empty, this is a window.open navigation. Check the
405 // opener's URL.
406 GURL old_url(frame->url());
407 if (old_url.is_empty() && frame->opener())
408 old_url = frame->opener()->url();
409
[email protected]88c15e972011-02-05 04:19:53410 bool old_url_is_hosted_app = extensions->GetByURL(old_url) &&
411 !extensions->GetByURL(old_url)->web_extent().is_empty();
[email protected]2a521c52011-01-26 18:45:21412 return !extensions->InSameExtent(old_url, new_url) &&
[email protected]88c15e972011-02-05 04:19:53413 !old_url_is_hosted_app;
[email protected]3a8eecb2010-04-22 23:56:30414}
415
[email protected]9b66f34bf2010-10-27 20:45:51416// Returns true if the parameter node is a textfield, text area or a content
417// editable div.
418static bool IsEditableNode(const WebNode& node) {
419 bool is_editable_node = false;
420 if (!node.isNull()) {
421 if (node.isContentEditable()) {
422 is_editable_node = true;
423 } else if (node.isElementNode()) {
424 is_editable_node =
425 node.toConst<WebElement>().isTextFormControlElement();
426 }
427 }
428 return is_editable_node;
429}
430
[email protected]54ec7f82010-10-21 22:32:51431static bool WebAccessibilityNotificationToViewHostMsg(
432 WebAccessibilityNotification notification,
[email protected]fffaf972011-03-24 01:34:35433 ViewHostMsg_AccessibilityNotification_Type::Value* type) {
[email protected]54ec7f82010-10-21 22:32:51434 switch (notification) {
435 case WebKit::WebAccessibilityNotificationCheckedStateChanged:
[email protected]fffaf972011-03-24 01:34:35436 *type = ViewHostMsg_AccessibilityNotification_Type::
[email protected]54ec7f82010-10-21 22:32:51437 NOTIFICATION_TYPE_CHECK_STATE_CHANGED;
438 break;
439 case WebKit::WebAccessibilityNotificationChildrenChanged:
[email protected]fffaf972011-03-24 01:34:35440 *type = ViewHostMsg_AccessibilityNotification_Type::
[email protected]54ec7f82010-10-21 22:32:51441 NOTIFICATION_TYPE_CHILDREN_CHANGED;
442 break;
443 case WebKit::WebAccessibilityNotificationFocusedUIElementChanged:
[email protected]fffaf972011-03-24 01:34:35444 *type = ViewHostMsg_AccessibilityNotification_Type::
[email protected]54ec7f82010-10-21 22:32:51445 NOTIFICATION_TYPE_FOCUS_CHANGED;
446 break;
447 case WebKit::WebAccessibilityNotificationLoadComplete:
[email protected]fffaf972011-03-24 01:34:35448 *type = ViewHostMsg_AccessibilityNotification_Type::
[email protected]54ec7f82010-10-21 22:32:51449 NOTIFICATION_TYPE_LOAD_COMPLETE;
450 break;
451 case WebKit::WebAccessibilityNotificationValueChanged:
[email protected]fffaf972011-03-24 01:34:35452 *type = ViewHostMsg_AccessibilityNotification_Type::
[email protected]54ec7f82010-10-21 22:32:51453 NOTIFICATION_TYPE_VALUE_CHANGED;
454 break;
455 case WebKit::WebAccessibilityNotificationSelectedTextChanged:
[email protected]fffaf972011-03-24 01:34:35456 *type = ViewHostMsg_AccessibilityNotification_Type::
[email protected]54ec7f82010-10-21 22:32:51457 NOTIFICATION_TYPE_SELECTED_TEXT_CHANGED;
458 break;
459 default:
460 // TODO(ctguil): Support additional webkit notifications.
461 return false;
462 }
463 return true;
464}
465
[email protected]81f9fe0b2010-12-07 00:35:29466// Conversion for the incoming value. The map isn't perfect; v8 has Uint32,
467// and int64 which don't fit as Value::TYPE_INTEGER, so we let them fall into
[email protected]fb534c92011-02-01 01:02:07468// being TYPE_DOUBLEs. Dates are converted to a string (which can then be
469// parsed into a base::Time), as are regexps. Arrays are converted into lists,
[email protected]81f9fe0b2010-12-07 00:35:29470// recursively. We don't deal with binary objects or functions - they become
471// null values.
472static Value* ConvertV8Value(const v8::Handle<v8::Value>& v8value) {
473 if (v8value->IsBoolean()) {
474 return Value::CreateBooleanValue(v8value->BooleanValue());
475 } else if (v8value->IsInt32()) {
476 return Value::CreateIntegerValue(v8value->Int32Value());
477 } else if (v8value->IsNumber()) {
[email protected]fb534c92011-02-01 01:02:07478 return Value::CreateDoubleValue(v8value->NumberValue());
[email protected]81f9fe0b2010-12-07 00:35:29479 } else if (v8value->IsString()) {
480 return Value::CreateStringValue(*v8::String::Utf8Value(v8value));
481 } else if (v8value->IsDate()) {
482 v8::Date* date = v8::Date::Cast(*v8value);
[email protected]fb534c92011-02-01 01:02:07483 return Value::CreateDoubleValue(date->NumberValue() / 1000.0);
[email protected]81f9fe0b2010-12-07 00:35:29484 } else if (v8value->IsRegExp()) {
485 return Value::CreateStringValue(
486 *v8::String::Utf8Value(v8value->ToString()));
487 } else if (v8value->IsArray()) {
488 v8::Array* array = v8::Array::Cast(*v8value);
489 uint32_t length = array->Length();
490 scoped_ptr<ListValue> list(new ListValue);
491 for (uint32_t i = 0 ; i < length ; ++i) {
492 list->Set(i, ConvertV8Value(array->Get(i)));
493 }
494 return list.release();
495 }
496 return Value::CreateNullValue();
497}
498
initial.commit09911bf2008-07-26 23:55:29499///////////////////////////////////////////////////////////////////////////////
500
[email protected]60c42a8c72009-10-09 04:08:59501int32 RenderView::next_page_id_ = 1;
502
[email protected]cdaf8d02010-03-30 19:52:47503struct RenderView::PendingFileChooser {
504 PendingFileChooser(const ViewHostMsg_RunFileChooser_Params& p,
505 WebFileChooserCompletion* c)
506 : params(p),
507 completion(c) {
508 }
509 ViewHostMsg_RunFileChooser_Params params;
510 WebFileChooserCompletion* completion; // MAY BE NULL to skip callback.
511};
512
[email protected]2fab253a2009-08-17 23:00:59513RenderView::RenderView(RenderThreadBase* render_thread,
[email protected]676126f72011-01-15 00:03:51514 gfx::NativeViewId parent_hwnd,
515 int32 opener_id,
516 const RendererPreferences& renderer_prefs,
517 const WebPreferences& webkit_prefs,
518 SharedRenderViewCounter* counter,
519 int32 routing_id,
520 int64 session_storage_namespace_id,
521 const string16& frame_name)
[email protected]3e2b375b2010-04-07 17:03:12522 : RenderWidget(render_thread, WebKit::WebPopupTypeNone),
[email protected]676126f72011-01-15 00:03:51523 webkit_preferences_(webkit_prefs),
[email protected]3354d3e2010-06-10 19:53:02524 send_content_state_immediately_(false),
[email protected]81e63782009-02-27 19:35:09525 enabled_bindings_(0),
[email protected]3354d3e2010-06-10 19:53:02526 send_preferred_size_changes_(false),
527 script_can_close_(true),
[email protected]81a34412009-01-05 19:17:24528 is_loading_(false),
[email protected]e75cb49e2009-01-05 23:13:21529 navigation_gesture_(NavigationGestureUnknown),
[email protected]3354d3e2010-06-10 19:53:02530 opened_by_user_gesture_(true),
531 opener_suppressed_(false),
[email protected]987d51af2011-02-24 17:50:18532 is_prerendering_(false),
[email protected]81a34412009-01-05 19:17:24533 page_id_(-1),
534 last_page_id_sent_to_browser_(-1),
535 last_indexed_page_id_(-1),
[email protected]3cc72b12010-03-18 23:03:00536 history_list_offset_(-1),
537 history_list_length_(0),
[email protected]81a34412009-01-05 19:17:24538 has_unload_listener_(false),
[email protected]3354d3e2010-06-10 19:53:02539 target_url_status_(TARGET_NONE),
[email protected]3354d3e2010-06-10 19:53:02540 view_type_(ViewType::INVALID),
541 browser_window_id_(-1),
[email protected]18ca9a6b2010-06-02 19:05:18542 ALLOW_THIS_IN_INITIALIZER_LIST(pepper_delegate_(this)),
[email protected]e47aec52010-08-12 00:50:30543 ALLOW_THIS_IN_INITIALIZER_LIST(page_info_method_factory_(this)),
[email protected]54ec7f82010-10-21 22:32:51544 ALLOW_THIS_IN_INITIALIZER_LIST(accessibility_method_factory_(this)),
[email protected]3354d3e2010-06-10 19:53:02545 ALLOW_THIS_IN_INITIALIZER_LIST(cookie_jar_(this)),
[email protected]676126f72011-01-15 00:03:51546 devtools_client_(NULL),
547 geolocation_dispatcher_(NULL),
548 speech_input_dispatcher_(NULL),
549 device_orientation_dispatcher_(NULL),
[email protected]dec1f292011-02-11 20:20:20550 print_helper_(NULL),
[email protected]6c2f73202011-02-14 20:21:54551 searchbox_(NULL),
[email protected]5efcef62011-02-22 09:00:13552 spellcheck_provider_(NULL),
[email protected]54ec7f82010-10-21 22:32:51553 accessibility_ack_pending_(false),
[email protected]cae8c8492011-03-03 11:12:18554 p2p_socket_dispatcher_(NULL),
[email protected]bb461532010-11-26 21:50:23555 pending_app_icon_requests_(0),
[email protected]5ee0cfd02011-01-18 05:42:22556 session_storage_namespace_id_(session_storage_namespace_id) {
[email protected]676126f72011-01-15 00:03:51557
[email protected]71b0d5d2010-02-15 05:43:07558 ClearBlockedContentSettings();
[email protected]676126f72011-01-15 00:03:51559
560 routing_id_ = routing_id;
561 if (opener_id != MSG_ROUTING_NONE)
562 opener_id_ = opener_id;
563
[email protected]11fee2332011-03-29 20:36:35564 webwidget_ = WebView::create(this);
565
[email protected]676126f72011-01-15 00:03:51566 if (counter) {
567 shared_popup_counter_ = counter;
568 shared_popup_counter_->data++;
569 decrement_shared_popup_at_destruction_ = true;
570 } else {
571 shared_popup_counter_ = new SharedRenderViewCounter(0);
572 decrement_shared_popup_at_destruction_ = false;
573 }
574
575 notification_provider_ = new NotificationProvider(this);
576
577 devtools_agent_ = new DevToolsAgent(this);
[email protected]11fee2332011-03-29 20:36:35578 webview()->setDevToolsAgentClient(devtools_agent_);
579
[email protected]c4a9e932011-03-05 04:05:55580 PasswordAutofillManager* password_autofill_manager =
581 new PasswordAutofillManager(this);
[email protected]663bd9e2011-03-21 01:07:01582 AutofillAgent* autofill_agent = new AutofillAgent(this,
[email protected]78192082011-01-29 05:43:44583 password_autofill_manager);
[email protected]11fee2332011-03-29 20:36:35584 webview()->setAutoFillClient(autofill_agent);
[email protected]676126f72011-01-15 00:03:51585
[email protected]676126f72011-01-15 00:03:51586 g_view_map.Get().insert(std::make_pair(webview(), this));
587 webkit_preferences_.Apply(webview());
588 webview()->initializeMainFrame(this);
589 if (!frame_name.empty())
590 webview()->mainFrame()->setName(frame_name);
[email protected]1ee59cb2011-02-23 02:45:51591 webview()->settings()->setMinimumTimerInterval(
592 is_hidden() ? webkit_glue::kBackgroundTabTimerInterval :
593 webkit_glue::kForegroundTabTimerInterval);
[email protected]676126f72011-01-15 00:03:51594
595 OnSetRendererPrefs(renderer_prefs);
596
597 render_thread_->AddRoute(routing_id_, this);
598 // Take a reference on behalf of the RenderThread. This will be balanced
599 // when we receive ViewMsg_Close.
600 AddRef();
601
602 // If this is a popup, we must wait for the CreatingNew_ACK message before
603 // completing initialization. Otherwise, we can finish it now.
604 if (opener_id == MSG_ROUTING_NONE) {
605 did_show_ = true;
606 CompleteInit(parent_hwnd);
607 }
608
609 host_window_ = parent_hwnd;
610
611 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
612 if (command_line.HasSwitch(switches::kDomAutomationController))
613 enabled_bindings_ |= BindingsPolicy::DOM_AUTOMATION;
614 if (command_line.HasSwitch(switches::kEnableAccessibility))
615 WebAccessibilityCache::enableAccessibility();
616
617 audio_message_filter_ = new AudioMessageFilter(routing_id_);
618 render_thread_->AddFilter(audio_message_filter_);
619
620 PageClickTracker* page_click_tracker = new PageClickTracker(this);
621 // Note that the order of insertion of the listeners is important.
622 // The password_autocomplete_manager takes the first shot at processing the
623 // notification and can stop the propagation.
[email protected]78192082011-01-29 05:43:44624 page_click_tracker->AddListener(password_autofill_manager);
625 page_click_tracker->AddListener(autofill_agent);
[email protected]81273622011-02-02 03:56:13626 new TranslateHelper(this);
[email protected]dec1f292011-02-11 20:20:20627 print_helper_ = new PrintWebViewHelper(this);
[email protected]6c2f73202011-02-14 20:21:54628 searchbox_ = new SearchBox(this);
[email protected]28685da92011-02-07 21:49:17629
[email protected]5efcef62011-02-22 09:00:13630 RenderThread* current_thread = RenderThread::current();
631 SpellCheck* spellcheck = current_thread ? current_thread->spellchecker() : 0;
632 spellcheck_provider_ = new SpellCheckProvider(this, spellcheck);
[email protected]11fee2332011-03-29 20:36:35633 webview()->setSpellCheckClient(spellcheck_provider_);
[email protected]5efcef62011-02-22 09:00:13634
[email protected]28685da92011-02-07 21:49:17635 if (CommandLine::ForCurrentProcess()->HasSwitch(
[email protected]cae8c8492011-03-03 11:12:18636 switches::kEnableP2PApi)) {
637 p2p_socket_dispatcher_ = new P2PSocketDispatcher(this);
638 }
639
[email protected]5f700cd2011-03-31 07:55:56640 if (CommandLine::ForCurrentProcess()->HasSwitch(
641 switches::kEnableClientSidePhishingDetection)) {
[email protected]28685da92011-02-07 21:49:17642 new safe_browsing::PhishingClassifierDelegate(this, NULL);
643 }
[email protected]32ca14682011-02-16 19:05:10644
645 // Observer for Malware DOM details messages.
646 new safe_browsing::MalwareDOMDetails(this);
[email protected]44c49c92011-03-28 16:17:23647
648 new ExtensionHelper(this);
initial.commit09911bf2008-07-26 23:55:29649}
650
651RenderView::~RenderView() {
[email protected]0aa55312008-10-17 21:53:08652 if (decrement_shared_popup_at_destruction_)
653 shared_popup_counter_->data--;
654
[email protected]a1128322009-10-06 18:38:46655 // If file chooser is still waiting for answer, dispatch empty answer.
[email protected]cdaf8d02010-03-30 19:52:47656 while (!file_chooser_completions_.empty()) {
657 if (file_chooser_completions_.front()->completion) {
658 file_chooser_completions_.front()->completion->didChooseFile(
659 WebVector<WebString>());
660 }
661 file_chooser_completions_.pop_front();
662 }
[email protected]a1128322009-10-06 18:38:46663
[email protected]83dde542009-09-11 20:59:55664#if defined(OS_MACOSX)
[email protected]c36a9b62010-10-14 00:41:11665 // Destroy all fake plugin window handles on the browser side.
666 while (!fake_plugin_window_handles_.empty()) {
667 // Make sure no NULL plugin window handles were inserted into this list.
668 DCHECK(*fake_plugin_window_handles_.begin());
669 // DestroyFakePluginWindowHandle modifies fake_plugin_window_handles_.
670 DestroyFakePluginWindowHandle(*fake_plugin_window_handles_.begin());
671 }
[email protected]83dde542009-09-11 20:59:55672#endif
[email protected]98324892009-09-09 21:16:05673
[email protected]5fb88962009-04-16 19:03:25674 render_thread_->RemoveFilter(audio_message_filter_);
[email protected]60c42a8c72009-10-09 04:08:59675
676#ifndef NDEBUG
677 // Make sure we are no longer referenced by the ViewMap.
[email protected]625332e02010-12-14 07:48:49678 ViewMap* views = g_view_map.Pointer();
[email protected]60c42a8c72009-10-09 04:08:59679 for (ViewMap::iterator it = views->begin(); it != views->end(); ++it)
680 DCHECK_NE(this, it->second) << "Failed to call Close?";
681#endif
[email protected]676126f72011-01-15 00:03:51682
683 FOR_EACH_OBSERVER(RenderViewObserver, observers_, set_render_view(NULL));
684 FOR_EACH_OBSERVER(RenderViewObserver, observers_, OnDestruct());
[email protected]60c42a8c72009-10-09 04:08:59685}
686
687/*static*/
688void RenderView::ForEach(RenderViewVisitor* visitor) {
[email protected]625332e02010-12-14 07:48:49689 ViewMap* views = g_view_map.Pointer();
[email protected]60c42a8c72009-10-09 04:08:59690 for (ViewMap::iterator it = views->begin(); it != views->end(); ++it) {
691 if (!visitor->Visit(it->second))
692 return;
693 }
694}
695
696/*static*/
697RenderView* RenderView::FromWebView(WebView* webview) {
[email protected]625332e02010-12-14 07:48:49698 ViewMap* views = g_view_map.Pointer();
[email protected]60c42a8c72009-10-09 04:08:59699 ViewMap::iterator it = views->find(webview);
700 return it == views->end() ? NULL : it->second;
initial.commit09911bf2008-07-26 23:55:29701}
702
703/*static*/
[email protected]0aa55312008-10-17 21:53:08704RenderView* RenderView::Create(
[email protected]81a34412009-01-05 19:17:24705 RenderThreadBase* render_thread,
[email protected]18bcc3c2009-01-27 21:39:15706 gfx::NativeViewId parent_hwnd,
[email protected]0aa55312008-10-17 21:53:08707 int32 opener_id,
[email protected]80d96fa2009-06-10 22:34:51708 const RendererPreferences& renderer_prefs,
[email protected]0aa55312008-10-17 21:53:08709 const WebPreferences& webkit_prefs,
710 SharedRenderViewCounter* counter,
[email protected]4e6419c2010-01-15 04:50:34711 int32 routing_id,
[email protected]8ab04652010-06-12 02:47:26712 int64 session_storage_namespace_id,
713 const string16& frame_name) {
initial.commit09911bf2008-07-26 23:55:29714 DCHECK(routing_id != MSG_ROUTING_NONE);
[email protected]676126f72011-01-15 00:03:51715 return new RenderView(
716 render_thread,
717 parent_hwnd,
718 opener_id,
719 renderer_prefs,
720 webkit_prefs,
721 counter,
722 routing_id,
723 session_storage_namespace_id,
724 frame_name); // adds reference
initial.commit09911bf2008-07-26 23:55:29725}
726
[email protected]bb461532010-11-26 21:50:23727// static
initial.commit09911bf2008-07-26 23:55:29728void RenderView::SetNextPageID(int32 next_page_id) {
729 // This method should only be called during process startup, and the given
730 // page id had better not exceed our current next page id!
[email protected]4646f292009-05-20 03:49:05731 DCHECK_EQ(next_page_id_, 1);
initial.commit09911bf2008-07-26 23:55:29732 DCHECK(next_page_id >= next_page_id_);
733 next_page_id_ = next_page_id;
734}
735
[email protected]676126f72011-01-15 00:03:51736void RenderView::AddObserver(RenderViewObserver* observer) {
737 observers_.AddObserver(observer);
738}
739
740void RenderView::RemoveObserver(RenderViewObserver* observer) {
741 observer->set_render_view(NULL);
742 observers_.RemoveObserver(observer);
743}
744
[email protected]70eee342010-11-05 01:59:37745bool RenderView::RendererAccessibilityNotification::ShouldIncludeChildren() {
746 typedef ViewHostMsg_AccessibilityNotification_Params params;
[email protected]a527a022011-02-10 02:32:36747 if (type == WebKit::WebAccessibilityNotificationChildrenChanged ||
748 type == WebKit::WebAccessibilityNotificationLoadComplete) {
[email protected]70eee342010-11-05 01:59:37749 return true;
750 }
751 return false;
752}
753
[email protected]8a3125a712010-08-09 18:58:51754WebKit::WebView* RenderView::webview() const {
[email protected]4d51d5bf2010-07-26 18:48:26755 return static_cast<WebKit::WebView*>(webwidget());
756}
757
[email protected]afe3a1672009-11-17 19:04:12758void RenderView::UserMetricsRecordAction(const std::string& action) {
[email protected]15d04ae2010-10-30 01:04:50759 Send(new ViewHostMsg_UserMetricsRecordAction(action));
[email protected]1dbafaf72009-09-23 19:43:56760}
761
[email protected]bb461532010-11-26 21:50:23762bool RenderView::InstallWebApplicationUsingDefinitionFile(WebFrame* frame,
763 string16* error) {
764 // There is an issue of drive-by installs with the below implementation. A web
765 // site could force a user to install an app by timing the dialog to come up
766 // just before the user clicks.
767 //
768 // We do show a success UI that allows users to uninstall, but it seems that
769 // we might still want to put up an infobar before showing the install dialog.
770 //
771 // TODO(aa): Figure out this issue before removing the kEnableCrxlessWebApps
772 // switch.
773 if (!CommandLine::ForCurrentProcess()->HasSwitch(
774 switches::kEnableCrxlessWebApps)) {
775 *error = ASCIIToUTF16("CRX-less web apps aren't enabled.");
776 return false;
777 }
778
779 if (frame != frame->top()) {
780 *error = ASCIIToUTF16("Applications can only be installed from the top "
781 "frame.");
782 return false;
783 }
784
785 if (pending_app_info_.get()) {
786 *error = ASCIIToUTF16("An application install is already in progress.");
787 return false;
788 }
789
790 pending_app_info_.reset(new WebApplicationInfo());
791 if (!web_apps::ParseWebAppFromWebDocument(frame, pending_app_info_.get(),
792 error)) {
793 return false;
794 }
795
796 if (!pending_app_info_->manifest_url.is_valid()) {
797 *error = ASCIIToUTF16("Web application definition not found or invalid.");
798 return false;
799 }
800
801 app_definition_fetcher_.reset(new ResourceFetcher(
802 pending_app_info_->manifest_url, webview()->mainFrame(),
803 NewCallback(this, &RenderView::DidDownloadApplicationDefinition)));
804 return true;
805}
806
[email protected]1a3c3cb2010-12-16 21:03:40807void RenderView::SetReportLoadProgressEnabled(bool enabled) {
808 if (!enabled) {
809 load_progress_tracker_.reset(NULL);
810 return;
811 }
812 if (load_progress_tracker_ == NULL)
813 load_progress_tracker_.reset(new LoadProgressTracker(this));
814}
815
[email protected]bb461532010-11-26 21:50:23816void RenderView::DidDownloadApplicationDefinition(
817 const WebKit::WebURLResponse& response,
818 const std::string& data) {
819 scoped_ptr<WebApplicationInfo> app_info(
820 pending_app_info_.release());
821
822 JSONStringValueSerializer serializer(data);
823 int error_code = 0;
824 std::string error_message;
825 scoped_ptr<Value> result(serializer.Deserialize(&error_code, &error_message));
826 if (!result.get()) {
827 AddErrorToRootConsole(UTF8ToUTF16(error_message));
828 return;
829 }
830
831 string16 error_message_16;
832 if (!web_apps::ParseWebAppFromDefinitionFile(result.get(), app_info.get(),
833 &error_message_16)) {
834 AddErrorToRootConsole(error_message_16);
835 return;
836 }
837
838 if (!app_info->icons.empty()) {
839 pending_app_info_.reset(app_info.release());
840 pending_app_icon_requests_ =
841 static_cast<int>(pending_app_info_->icons.size());
842 for (size_t i = 0; i < pending_app_info_->icons.size(); ++i) {
843 app_icon_fetchers_.push_back(linked_ptr<ImageResourceFetcher>(
844 new ImageResourceFetcher(
845 pending_app_info_->icons[i].url,
846 webview()->mainFrame(),
847 static_cast<int>(i),
848 pending_app_info_->icons[i].width,
849 NewCallback(this, &RenderView::DidDownloadApplicationIcon))));
850 }
851 } else {
[email protected]44c49c92011-03-28 16:17:23852 Send(new ExtensionHostMsg_InstallApplication(routing_id_, *app_info));
[email protected]bb461532010-11-26 21:50:23853 }
854}
855
856void RenderView::DidDownloadApplicationIcon(ImageResourceFetcher* fetcher,
857 const SkBitmap& image) {
858 pending_app_info_->icons[fetcher->id()].data = image;
859
860 // Remove the image fetcher from our pending list. We're in the callback from
861 // ImageResourceFetcher, best to delay deletion.
862 for (ImageResourceFetcherList::iterator iter = app_icon_fetchers_.begin();
863 iter != app_icon_fetchers_.end(); ++iter) {
864 if (iter->get() == fetcher) {
865 iter->release();
866 app_icon_fetchers_.erase(iter);
867 break;
868 }
869 }
870
871 // We're in the callback from the ImageResourceFetcher, best to delay
872 // deletion.
873 MessageLoop::current()->DeleteSoon(FROM_HERE, fetcher);
874
875 if (--pending_app_icon_requests_ > 0)
876 return;
877
878 // There is a maximum size of IPC on OS X and Linux that we have run into in
879 // some situations. We're not sure what it is, but our hypothesis is in the
880 // neighborhood of 1 MB.
881 //
882 // To be on the safe side, we give ourselves 128 KB for just the image data.
883 // This should be more than enough for 128, 48, and 16 px 32-bit icons. If we
884 // want to start allowing larger icons (see bug 63406), we'll have to either
885 // experiment mor ewith this and find the real limit, or else come up with
886 // some alternative way to transmit the icon data to the browser process.
887 //
888 // See also: bug 63729.
[email protected]678a7d72011-01-05 20:37:32889 const size_t kMaxIconSize = 1024 * 128;
890 size_t actual_icon_size = 0;
[email protected]bb461532010-11-26 21:50:23891 for (size_t i = 0; i < pending_app_info_->icons.size(); ++i) {
[email protected]678a7d72011-01-05 20:37:32892 size_t current_size = pending_app_info_->icons[i].data.getSize();
893 if (current_size > kMaxIconSize - actual_icon_size) {
894 AddErrorToRootConsole(ASCIIToUTF16(
[email protected]bb461532010-11-26 21:50:23895 "Icons are too large. Maximum total size for app icons is 128 KB."));
[email protected]678a7d72011-01-05 20:37:32896 return;
897 }
898 actual_icon_size += current_size;
[email protected]bb461532010-11-26 21:50:23899 }
900
[email protected]44c49c92011-03-28 16:17:23901 Send(new ExtensionHostMsg_InstallApplication(
902 routing_id_, *pending_app_info_));
[email protected]bb461532010-11-26 21:50:23903 pending_app_info_.reset(NULL);
904}
905
[email protected]a3a8fb6d2009-10-22 20:12:51906void RenderView::PluginCrashed(const FilePath& plugin_path) {
907 Send(new ViewHostMsg_CrashedPlugin(routing_id_, plugin_path));
initial.commit09911bf2008-07-26 23:55:29908}
909
[email protected]aad51d1c2010-08-05 08:38:09910WebPlugin* RenderView::CreatePluginNoCheck(WebFrame* frame,
911 const WebPluginParams& params) {
[email protected]191eb3f72010-12-21 06:27:50912 webkit::npapi::WebPluginInfo info;
[email protected]6fdd4182010-10-14 23:59:26913 bool found;
[email protected]0aed2f52011-03-23 18:06:36914 int content_setting;
[email protected]6fdd4182010-10-14 23:59:26915 std::string mime_type;
916 Send(new ViewHostMsg_GetPluginInfo(
[email protected]c8f73ab2011-01-22 00:05:17917 routing_id_, params.url, frame->top()->url(), params.mimeType.utf8(),
[email protected]0aed2f52011-03-23 18:06:36918 &found, &info, &content_setting, &mime_type));
[email protected]b83ff222011-01-24 17:37:12919 if (!found || !webkit::npapi::IsPluginEnabled(info))
[email protected]aad51d1c2010-08-05 08:38:09920 return NULL;
[email protected]1a78d9f32010-12-08 06:38:45921
[email protected]0bd753682010-12-16 18:15:52922 scoped_refptr<webkit::ppapi::PluginModule> pepper_module(
[email protected]1a78d9f32010-12-08 06:38:45923 pepper_delegate_.CreatePepperPlugin(info.path));
[email protected]aad51d1c2010-08-05 08:38:09924 if (pepper_module)
[email protected]6fdd4182010-10-14 23:59:26925 return CreatePepperPlugin(frame, params, info.path, pepper_module.get());
[email protected]1a78d9f32010-12-08 06:38:45926 return CreateNPAPIPlugin(frame, params, info.path, mime_type);
[email protected]aad51d1c2010-08-05 08:38:09927}
928
[email protected]d8fd6fa2010-02-01 15:54:26929void RenderView::RegisterPluginDelegate(WebPluginDelegateProxy* delegate) {
930 plugin_delegates_.insert(delegate);
[email protected]49232292010-09-03 19:07:30931 // If the renderer is visible, set initial visibility and focus state.
932 if (!is_hidden()) {
[email protected]784ea1ab2010-09-18 00:02:34933#if defined(OS_MACOSX)
[email protected]49232292010-09-03 19:07:30934 delegate->SetContainerVisibility(true);
935 if (webview() && webview()->isActive())
936 delegate->SetWindowFocus(true);
[email protected]784ea1ab2010-09-18 00:02:34937#endif
[email protected]49232292010-09-03 19:07:30938 }
[email protected]784ea1ab2010-09-18 00:02:34939 // Plugins start assuming the content has focus (so that they work in
940 // environments where RenderView isn't hosting them), so we always have to
941 // set the initial state. See webplugin_delegate_impl.h for details.
942 delegate->SetContentAreaFocus(has_focus());
[email protected]d8fd6fa2010-02-01 15:54:26943}
944
945void RenderView::UnregisterPluginDelegate(WebPluginDelegateProxy* delegate) {
946 plugin_delegates_.erase(delegate);
947}
[email protected]d8fd6fa2010-02-01 15:54:26948
[email protected]a95986a82010-12-24 06:19:28949bool RenderView::OnMessageReceived(const IPC::Message& message) {
[email protected]26aa0482009-09-30 16:55:27950 WebFrame* main_frame = webview() ? webview()->mainFrame() : NULL;
[email protected]a9f607e2009-10-23 19:59:27951 if (main_frame)
952 child_process_logging::SetActiveURL(main_frame->url());
[email protected]f8b6b6f2009-03-10 16:48:26953
[email protected]676126f72011-01-15 00:03:51954 ObserverListBase<RenderViewObserver>::Iterator it(observers_);
955 RenderViewObserver* observer;
956 while ((observer = it.GetNext()) != NULL)
957 if (observer->OnMessageReceived(message))
958 return true;
[email protected]b2abac72009-02-26 12:39:28959
[email protected]a95986a82010-12-24 06:19:28960 bool handled = true;
initial.commit09911bf2008-07-26 23:55:29961 IPC_BEGIN_MESSAGE_MAP(RenderView, message)
[email protected]9b18a84f2010-06-10 15:54:04962 IPC_MESSAGE_HANDLER(ViewMsg_CaptureSnapshot, OnCaptureSnapshot)
initial.commit09911bf2008-07-26 23:55:29963 IPC_MESSAGE_HANDLER(ViewMsg_Navigate, OnNavigate)
964 IPC_MESSAGE_HANDLER(ViewMsg_Stop, OnStop)
[email protected]1dda4022010-01-28 18:24:56965 IPC_MESSAGE_HANDLER(ViewMsg_ReloadFrame, OnReloadFrame)
initial.commit09911bf2008-07-26 23:55:29966 IPC_MESSAGE_HANDLER(ViewMsg_Undo, OnUndo)
967 IPC_MESSAGE_HANDLER(ViewMsg_Redo, OnRedo)
968 IPC_MESSAGE_HANDLER(ViewMsg_Cut, OnCut)
969 IPC_MESSAGE_HANDLER(ViewMsg_Copy, OnCopy)
[email protected]c0cc3092009-09-12 08:27:27970#if defined(OS_MACOSX)
[email protected]a954bf72009-09-12 07:30:35971 IPC_MESSAGE_HANDLER(ViewMsg_CopyToFindPboard, OnCopyToFindPboard)
[email protected]c0cc3092009-09-12 08:27:27972#endif
initial.commit09911bf2008-07-26 23:55:29973 IPC_MESSAGE_HANDLER(ViewMsg_Paste, OnPaste)
974 IPC_MESSAGE_HANDLER(ViewMsg_Replace, OnReplace)
975 IPC_MESSAGE_HANDLER(ViewMsg_Delete, OnDelete)
976 IPC_MESSAGE_HANDLER(ViewMsg_SelectAll, OnSelectAll)
977 IPC_MESSAGE_HANDLER(ViewMsg_CopyImageAt, OnCopyImageAt)
[email protected]4b59ae602009-06-23 20:58:15978 IPC_MESSAGE_HANDLER(ViewMsg_ExecuteEditCommand, OnExecuteEditCommand)
initial.commit09911bf2008-07-26 23:55:29979 IPC_MESSAGE_HANDLER(ViewMsg_Find, OnFind)
[email protected]24a7f3c2010-03-25 08:26:49980 IPC_MESSAGE_HANDLER(ViewMsg_StopFinding, OnStopFinding)
981 IPC_MESSAGE_HANDLER(ViewMsg_FindReplyACK, OnFindReplyAck)
[email protected]630e26b2008-10-14 22:55:17982 IPC_MESSAGE_HANDLER(ViewMsg_Zoom, OnZoom)
[email protected]9d797f32010-04-23 07:17:54983 IPC_MESSAGE_HANDLER(ViewMsg_SetContentSettingsForLoadingURL,
984 OnSetContentSettingsForLoadingURL)
[email protected]d0b8d092010-10-25 04:05:17985 IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevel, OnSetZoomLevel)
[email protected]9d797f32010-04-23 07:17:54986 IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevelForLoadingURL,
987 OnSetZoomLevelForLoadingURL)
initial.commit09911bf2008-07-26 23:55:29988 IPC_MESSAGE_HANDLER(ViewMsg_SetPageEncoding, OnSetPageEncoding)
[email protected]a697f4c2009-09-14 22:30:18989 IPC_MESSAGE_HANDLER(ViewMsg_ResetPageEncodingToDefault,
990 OnResetPageEncodingToDefault)
[email protected]39ec12f2011-03-25 23:02:28991 IPC_MESSAGE_HANDLER(DevToolsMsg_SetupDevToolsClient, OnSetupDevToolsClient)
[email protected]d8e74e82011-03-15 19:38:48992 IPC_MESSAGE_HANDLER(ViewMsg_DownloadFavicon, OnDownloadFavicon)
initial.commit09911bf2008-07-26 23:55:29993 IPC_MESSAGE_HANDLER(ViewMsg_ScriptEvalRequest, OnScriptEvalRequest)
[email protected]1810e132009-03-24 23:35:48994 IPC_MESSAGE_HANDLER(ViewMsg_CSSInsertRequest, OnCSSInsertRequest)
initial.commit09911bf2008-07-26 23:55:29995 IPC_MESSAGE_HANDLER(ViewMsg_ReservePageIDRange, OnReservePageIDRange)
[email protected]59f4f2fa2011-03-23 01:00:55996 IPC_MESSAGE_HANDLER(DragMsg_TargetDragEnter, OnDragTargetDragEnter)
997 IPC_MESSAGE_HANDLER(DragMsg_TargetDragOver, OnDragTargetDragOver)
998 IPC_MESSAGE_HANDLER(DragMsg_TargetDragLeave, OnDragTargetDragLeave)
999 IPC_MESSAGE_HANDLER(DragMsg_TargetDrop, OnDragTargetDrop)
1000 IPC_MESSAGE_HANDLER(DragMsg_SourceEndedOrMoved, OnDragSourceEndedOrMoved)
1001 IPC_MESSAGE_HANDLER(DragMsg_SourceSystemDragEnded,
1002 OnDragSourceSystemDragEnded)
[email protected]18cb2572008-08-21 20:34:451003 IPC_MESSAGE_HANDLER(ViewMsg_AllowBindings, OnAllowBindings)
[email protected]d0980792011-02-13 19:41:401004 IPC_MESSAGE_HANDLER(ViewMsg_SetWebUIProperty, OnSetWebUIProperty)
initial.commit09911bf2008-07-26 23:55:291005 IPC_MESSAGE_HANDLER(ViewMsg_SetInitialFocus, OnSetInitialFocus)
[email protected]9b66f34bf2010-10-27 20:45:511006 IPC_MESSAGE_HANDLER(ViewMsg_ScrollFocusedEditableNodeIntoView,
1007 OnScrollFocusedEditableNodeIntoView)
initial.commit09911bf2008-07-26 23:55:291008 IPC_MESSAGE_HANDLER(ViewMsg_UpdateTargetURL_ACK, OnUpdateTargetURLAck)
1009 IPC_MESSAGE_HANDLER(ViewMsg_UpdateWebPreferences, OnUpdateWebPreferences)
1010 IPC_MESSAGE_HANDLER(ViewMsg_SetAltErrorPageURL, OnSetAltErrorPageURL)
1011 IPC_MESSAGE_HANDLER(ViewMsg_InstallMissingPlugin, OnInstallMissingPlugin)
[email protected]90dba072011-01-20 20:10:201012 IPC_MESSAGE_HANDLER(ViewMsg_DisplayPrerenderedPage,
1013 OnDisplayPrerenderedPage)
initial.commit09911bf2008-07-26 23:55:291014 IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse)
1015 IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode, OnEnableViewSourceMode)
initial.commit09911bf2008-07-26 23:55:291016 IPC_MESSAGE_HANDLER(ViewMsg_GetAllSavableResourceLinksForCurrentPage,
1017 OnGetAllSavableResourceLinksForCurrentPage)
[email protected]f09c7182009-03-10 12:54:041018 IPC_MESSAGE_HANDLER(
1019 ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks,
1020 OnGetSerializedHtmlDataForCurrentPageWithLocalLinks)
[email protected]44c49c92011-03-28 16:17:231021 IPC_MESSAGE_HANDLER(ExtensionMsg_GetApplicationInfo, OnGetApplicationInfo)
[email protected]9b18a84f2010-06-10 15:54:041022 IPC_MESSAGE_HANDLER(ViewMsg_ShouldClose, OnShouldClose)
initial.commit09911bf2008-07-26 23:55:291023 IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage)
1024 IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged)
[email protected]18cb2572008-08-21 20:34:451025 IPC_MESSAGE_HANDLER(ViewMsg_HandleMessageFromExternalHost,
[email protected]9b18a84f2010-06-10 15:54:041026 OnHandleMessageFromExternalHost)
[email protected]0aa55312008-10-17 21:53:081027 IPC_MESSAGE_HANDLER(ViewMsg_DisassociateFromPopupCount,
1028 OnDisassociateFromPopupCount)
[email protected]e8345242010-05-06 03:00:401029 IPC_MESSAGE_HANDLER(ViewMsg_AllowScriptToClose,
1030 OnAllowScriptToClose)
[email protected]30f75e62009-02-25 22:01:001031 IPC_MESSAGE_HANDLER(ViewMsg_MoveOrResizeStarted, OnMoveOrResizeStarted)
[email protected]05d478752009-04-08 23:38:161032 IPC_MESSAGE_HANDLER(ViewMsg_ClearFocusedNode, OnClearFocusedNode)
[email protected]699ab0d2009-04-23 23:19:141033 IPC_MESSAGE_HANDLER(ViewMsg_SetBackground, OnSetBackground)
[email protected]ab32b16c2009-10-16 14:57:251034 IPC_MESSAGE_HANDLER(ViewMsg_EnablePreferredSizeChangedMode,
1035 OnEnablePreferredSizeChangedMode)
[email protected]cda45c02010-02-25 19:28:101036 IPC_MESSAGE_HANDLER(ViewMsg_DisableScrollbarsForSmallWindows,
1037 OnDisableScrollbarsForSmallWindows)
[email protected]80d96fa2009-06-10 22:34:511038 IPC_MESSAGE_HANDLER(ViewMsg_SetRendererPrefs, OnSetRendererPrefs)
[email protected]7b291f92009-08-14 05:43:531039 IPC_MESSAGE_HANDLER(ViewMsg_UpdateBrowserWindowId,
1040 OnUpdateBrowserWindowId)
1041 IPC_MESSAGE_HANDLER(ViewMsg_NotifyRenderViewType,
1042 OnNotifyRendererViewType)
[email protected]581b87eb2009-07-23 23:06:561043 IPC_MESSAGE_HANDLER(ViewMsg_MediaPlayerActionAt, OnMediaPlayerActionAt)
[email protected]8c66c5a2009-07-22 17:26:341044 IPC_MESSAGE_HANDLER(ViewMsg_SetActive, OnSetActive)
[email protected]6ce7abc52010-02-02 18:40:141045#if defined(OS_MACOSX)
1046 IPC_MESSAGE_HANDLER(ViewMsg_SetWindowVisibility, OnSetWindowVisibility)
[email protected]1e6e3c992010-02-08 15:52:131047 IPC_MESSAGE_HANDLER(ViewMsg_WindowFrameChanged, OnWindowFrameChanged)
[email protected]b7f75862011-01-21 21:15:131048 IPC_MESSAGE_HANDLER(ViewMsg_PluginImeCompositionCompleted,
1049 OnPluginImeCompositionCompleted)
[email protected]6ce7abc52010-02-02 18:40:141050#endif
[email protected]446705872009-09-10 07:22:481051 IPC_MESSAGE_HANDLER(ViewMsg_SetEditCommandsForNextKeyEvent,
[email protected]a0c7153e2009-12-09 14:36:331052 OnSetEditCommandsForNextKeyEvent)
[email protected]a0c7153e2009-12-09 14:36:331053 IPC_MESSAGE_HANDLER(ViewMsg_CustomContextMenuAction,
1054 OnCustomContextMenuAction)
[email protected]dea2d372010-09-25 06:41:141055 IPC_MESSAGE_HANDLER(ViewMsg_EnableAccessibility, OnEnableAccessibility)
[email protected]aef92842010-05-21 16:54:361056 IPC_MESSAGE_HANDLER(ViewMsg_SetAccessibilityFocus, OnSetAccessibilityFocus)
1057 IPC_MESSAGE_HANDLER(ViewMsg_AccessibilityDoDefaultAction,
1058 OnAccessibilityDoDefaultAction)
[email protected]9892b472010-09-16 00:23:421059 IPC_MESSAGE_HANDLER(ViewMsg_AccessibilityNotifications_ACK,
1060 OnAccessibilityNotificationsAck)
[email protected]27a9ef32010-09-10 04:06:241061 IPC_MESSAGE_HANDLER(ViewMsg_AsyncOpenFile_ACK, OnAsyncFileOpened)
[email protected]caf706f2010-10-26 17:54:081062#if defined(OS_MACOSX)
1063 IPC_MESSAGE_HANDLER(ViewMsg_SelectPopupMenuItem, OnSelectPopupMenuItem)
1064#endif
[email protected]a6097f42011-01-10 08:50:511065 IPC_MESSAGE_HANDLER(ViewMsg_JavaScriptStressTestControl,
1066 OnJavaScriptStressTestControl)
[email protected]521b2482011-01-15 00:10:101067 IPC_MESSAGE_HANDLER(ViewMsg_ContextMenuClosed, OnContextMenuClosed)
[email protected]232a5812011-03-04 22:42:081068 IPC_MESSAGE_HANDLER(ViewMsg_NetworkStateChanged, OnNetworkStateChanged)
[email protected]634a6f92008-12-01 21:39:311069
[email protected]f0557932011-01-25 20:20:511070 // TODO(viettrungluu): Move to a separate message filter.
1071#if defined(ENABLE_FLAPPER_HACKS)
1072 IPC_MESSAGE_HANDLER(PepperMsg_ConnectTcpACK, OnConnectTcpACK)
1073#endif
1074
initial.commit09911bf2008-07-26 23:55:291075 // Have the super handle all other messages.
[email protected]a95986a82010-12-24 06:19:281076 IPC_MESSAGE_UNHANDLED(handled = RenderWidget::OnMessageReceived(message))
initial.commit09911bf2008-07-26 23:55:291077 IPC_END_MESSAGE_MAP()
[email protected]a95986a82010-12-24 06:19:281078 return handled;
initial.commit09911bf2008-07-26 23:55:291079}
1080
[email protected]9b18a84f2010-06-10 15:54:041081void RenderView::OnCaptureThumbnail() {
[email protected]26aa0482009-09-30 16:55:271082 WebFrame* main_frame = webview()->mainFrame();
initial.commit09911bf2008-07-26 23:55:291083 if (!main_frame)
1084 return;
1085
1086 // get the URL for this page
[email protected]dd7daa82009-08-10 05:46:451087 GURL url(main_frame->url());
initial.commit09911bf2008-07-26 23:55:291088 if (url.is_empty())
1089 return;
1090
1091 if (size_.IsEmpty())
1092 return; // Don't create an empty thumbnail!
1093
1094 ThumbnailScore score;
1095 SkBitmap thumbnail;
[email protected]8649fb32009-06-26 17:51:021096 if (!CaptureThumbnail(webview(), kThumbnailWidth, kThumbnailHeight,
[email protected]b6e4bec2008-11-12 01:17:151097 &thumbnail, &score))
1098 return;
1099
initial.commit09911bf2008-07-26 23:55:291100 // send the thumbnail message to the browser process
[email protected]674741932009-02-04 23:44:461101 Send(new ViewHostMsg_Thumbnail(routing_id_, url, score, thumbnail));
initial.commit09911bf2008-07-26 23:55:291102}
1103
[email protected]9b18a84f2010-06-10 15:54:041104void RenderView::OnCaptureSnapshot() {
[email protected]30507922010-01-15 16:48:231105 SkBitmap snapshot;
1106 bool error = false;
1107
1108 WebFrame* main_frame = webview()->mainFrame();
1109 if (!main_frame)
1110 error = true;
1111
1112 if (!error && !CaptureSnapshot(webview(), &snapshot))
1113 error = true;
1114
1115 DCHECK(error == snapshot.empty()) <<
1116 "Snapshot should be empty on error, non-empty otherwise.";
1117
1118 // Send the snapshot to the browser process.
1119 Send(new ViewHostMsg_Snapshot(routing_id_, snapshot));
1120}
1121
initial.commit09911bf2008-07-26 23:55:291122void RenderView::CapturePageInfo(int load_id, bool preliminary_capture) {
1123 if (load_id != page_id_)
1124 return; // this capture call is no longer relevant due to navigation
1125 if (load_id == last_indexed_page_id_)
1126 return; // we already indexed this page
1127
1128 if (!webview())
1129 return;
1130
[email protected]26aa0482009-09-30 16:55:271131 WebFrame* main_frame = webview()->mainFrame();
initial.commit09911bf2008-07-26 23:55:291132 if (!main_frame)
1133 return;
1134
1135 // Don't index/capture pages that are in view source mode.
[email protected]dd7daa82009-08-10 05:46:451136 if (main_frame->isViewSourceModeEnabled())
initial.commit09911bf2008-07-26 23:55:291137 return;
1138
1139 // Don't index/capture pages that failed to load. This only checks the top
1140 // level frame so the thumbnail may contain a frame that failed to load.
[email protected]dd7daa82009-08-10 05:46:451141 WebDataSource* ds = main_frame->dataSource();
[email protected]726985e22009-06-18 21:09:281142 if (ds && ds->hasUnreachableURL())
initial.commit09911bf2008-07-26 23:55:291143 return;
1144
1145 if (!preliminary_capture)
1146 last_indexed_page_id_ = load_id;
1147
[email protected]a8a81292010-01-21 00:32:451148 // Get the URL for this page.
[email protected]dd7daa82009-08-10 05:46:451149 GURL url(main_frame->url());
initial.commit09911bf2008-07-26 23:55:291150 if (url.is_empty())
1151 return;
1152
[email protected]a8a81292010-01-21 00:32:451153 // Retrieve the frame's full text.
[email protected]e5106202010-06-11 21:12:361154 string16 contents;
initial.commit09911bf2008-07-26 23:55:291155 CaptureText(main_frame, &contents);
1156 if (contents.size()) {
[email protected]1c57b7b2010-07-12 17:38:101157 WebKit::WebDocument document = main_frame->document();
[email protected]5ddfd63e2010-09-01 15:48:371158 // If the page explicitly specifies a language, use it, otherwise we'll
1159 // determine it based on the text content using the CLD.
1160 std::string language =
1161 TranslateHelper::GetPageLanguageFromMetaTag(&document);
1162 if (language.empty()) {
1163 base::TimeTicks begin_time = base::TimeTicks::Now();
[email protected]6e24cf12011-03-18 19:57:021164 language = content::GetContentClient()->renderer()->
1165 DetermineTextLanguage(contents);
[email protected]5ddfd63e2010-09-01 15:48:371166 UMA_HISTOGRAM_MEDIUM_TIMES("Renderer4.LanguageDetection",
1167 base::TimeTicks::Now() - begin_time);
1168 }
[email protected]a8a81292010-01-21 00:32:451169 // Send the text to the browser for indexing (the browser might decide not
1170 // to index, if the URL is HTTPS for instance) and language discovery.
[email protected]5ddfd63e2010-09-01 15:48:371171 Send(new ViewHostMsg_PageContents(
1172 routing_id_, url, load_id, contents, language,
1173 TranslateHelper::IsPageTranslatable(&document)));
[email protected]5c4266922009-07-10 16:41:271174 }
1175
[email protected]d54169e92011-01-21 09:19:521176 // Generate the thumbnail here if the in-browser thumbnailing isn't
1177 // enabled. TODO(satorux): Remove this and related code once
1178 // crbug.com/65936 is complete.
1179 if (!CommandLine::ForCurrentProcess()->HasSwitch(
1180 switches::kEnableInBrowserThumbnailing)) {
1181 OnCaptureThumbnail();
1182 }
[email protected]3ead1322010-11-19 20:01:001183
[email protected]28685da92011-02-07 21:49:171184 FOR_EACH_OBSERVER(RenderViewObserver, observers_, PageCaptured(contents));
initial.commit09911bf2008-07-26 23:55:291185}
1186
[email protected]e5106202010-06-11 21:12:361187void RenderView::CaptureText(WebFrame* frame, string16* contents) {
initial.commit09911bf2008-07-26 23:55:291188 contents->clear();
1189 if (!frame)
1190 return;
1191
1192#ifdef TIME_TEXT_RETRIEVAL
1193 double begin = time_util::GetHighResolutionTimeNow();
1194#endif
1195
1196 // get the contents of the frame
[email protected]e5106202010-06-11 21:12:361197 *contents = frame->contentAsText(kMaxIndexChars);
initial.commit09911bf2008-07-26 23:55:291198
1199#ifdef TIME_TEXT_RETRIEVAL
1200 double end = time_util::GetHighResolutionTimeNow();
1201 char buf[128];
1202 sprintf_s(buf, "%d chars retrieved for indexing in %gms\n",
1203 contents.size(), (end - begin)*1000);
1204 OutputDebugStringA(buf);
1205#endif
1206
1207 // When the contents are clipped to the maximum, we don't want to have a
1208 // partial word indexed at the end that might have been clipped. Therefore,
1209 // terminate the string at the last space to ensure no words are clipped.
1210 if (contents->size() == kMaxIndexChars) {
[email protected]e5106202010-06-11 21:12:361211 size_t last_space_index = contents->find_last_of(kWhitespaceUTF16);
initial.commit09911bf2008-07-26 23:55:291212 if (last_space_index == std::wstring::npos)
1213 return; // don't index if we got a huge block of text with no spaces
1214 contents->resize(last_space_index);
1215 }
1216}
1217
[email protected]8649fb32009-06-26 17:51:021218bool RenderView::CaptureThumbnail(WebView* view,
initial.commit09911bf2008-07-26 23:55:291219 int w,
1220 int h,
1221 SkBitmap* thumbnail,
1222 ThumbnailScore* score) {
[email protected]30507922010-01-15 16:48:231223 base::TimeTicks beginning_time = base::TimeTicks::Now();
[email protected]b6e4bec2008-11-12 01:17:151224
[email protected]8649fb32009-06-26 17:51:021225 skia::PlatformCanvas canvas;
[email protected]30507922010-01-15 16:48:231226
1227 // Paint |view| into |canvas|.
1228 if (!PaintViewIntoCanvas(view, canvas))
[email protected]8649fb32009-06-26 17:51:021229 return false;
[email protected]8649fb32009-06-26 17:51:021230
1231 skia::BitmapPlatformDevice& device =
1232 static_cast<skia::BitmapPlatformDevice&>(canvas.getTopPlatformDevice());
1233
1234 const SkBitmap& src_bmp = device.accessBitmap(false);
initial.commit09911bf2008-07-26 23:55:291235
[email protected]cab34d6a2009-09-24 01:14:521236 SkRect dest_rect = { 0, 0, SkIntToScalar(w), SkIntToScalar(h) };
initial.commit09911bf2008-07-26 23:55:291237 float dest_aspect = dest_rect.width() / dest_rect.height();
1238
1239 // Get the src rect so that we can preserve the aspect ratio while filling
1240 // the destination.
1241 SkIRect src_rect;
1242 if (src_bmp.width() < dest_rect.width() ||
1243 src_bmp.height() < dest_rect.height()) {
1244 // Source image is smaller: we clip the part of source image within the
1245 // dest rect, and then stretch it to fill the dest rect. We don't respect
1246 // the aspect ratio in this case.
1247 src_rect.set(0, 0, static_cast<S16CPU>(dest_rect.width()),
1248 static_cast<S16CPU>(dest_rect.height()));
1249 score->good_clipping = false;
1250 } else {
1251 float src_aspect = static_cast<float>(src_bmp.width()) / src_bmp.height();
1252 if (src_aspect > dest_aspect) {
1253 // Wider than tall, clip horizontally: we center the smaller thumbnail in
1254 // the wider screen.
1255 S16CPU new_width = static_cast<S16CPU>(src_bmp.height() * dest_aspect);
1256 S16CPU x_offset = (src_bmp.width() - new_width) / 2;
1257 src_rect.set(x_offset, 0, new_width + x_offset, src_bmp.height());
1258 score->good_clipping = false;
1259 } else {
1260 src_rect.set(0, 0, src_bmp.width(),
1261 static_cast<S16CPU>(src_bmp.width() / dest_aspect));
1262 score->good_clipping = true;
1263 }
1264 }
1265
[email protected]26aa0482009-09-30 16:55:271266 score->at_top = (view->mainFrame()->scrollOffset().height == 0);
initial.commit09911bf2008-07-26 23:55:291267
1268 SkBitmap subset;
[email protected]8649fb32009-06-26 17:51:021269 device.accessBitmap(false).extractSubset(&subset, src_rect);
initial.commit09911bf2008-07-26 23:55:291270
[email protected]82afe4b2010-11-12 20:36:221271 // First do a fast downsample by powers of two to get close to the final size.
1272 SkBitmap downsampled_subset =
1273 SkBitmapOperations::DownsampleByTwoUntilSize(subset, w, h);
1274
1275 // Do a high-quality resize from the downscaled size to the final size.
[email protected]465b34b72008-12-12 20:19:141276 *thumbnail = skia::ImageOperations::Resize(
[email protected]82afe4b2010-11-12 20:36:221277 downsampled_subset, skia::ImageOperations::RESIZE_LANCZOS3, w, h);
initial.commit09911bf2008-07-26 23:55:291278
1279 score->boring_score = CalculateBoringScore(thumbnail);
1280
[email protected]30507922010-01-15 16:48:231281 HISTOGRAM_TIMES("Renderer4.Thumbnail",
1282 base::TimeTicks::Now() - beginning_time);
[email protected]82afe4b2010-11-12 20:36:221283
[email protected]b6e4bec2008-11-12 01:17:151284 return true;
initial.commit09911bf2008-07-26 23:55:291285}
1286
[email protected]30507922010-01-15 16:48:231287bool RenderView::CaptureSnapshot(WebView* view, SkBitmap* snapshot) {
1288 base::TimeTicks beginning_time = base::TimeTicks::Now();
initial.commit09911bf2008-07-26 23:55:291289
[email protected]30507922010-01-15 16:48:231290 skia::PlatformCanvas canvas;
1291 if (!PaintViewIntoCanvas(view, canvas))
1292 return false;
1293
1294 skia::BitmapPlatformDevice& device =
1295 static_cast<skia::BitmapPlatformDevice&>(canvas.getTopPlatformDevice());
1296
1297 const SkBitmap& bitmap = device.accessBitmap(false);
1298 if (!bitmap.copyTo(snapshot, SkBitmap::kARGB_8888_Config))
1299 return false;
1300
1301 HISTOGRAM_TIMES("Renderer4.Snapshot",
1302 base::TimeTicks::Now() - beginning_time);
1303 return true;
initial.commit09911bf2008-07-26 23:55:291304}
1305
1306void RenderView::OnNavigate(const ViewMsg_Navigate_Params& params) {
1307 if (!webview())
1308 return;
1309
[email protected]3cc72b12010-03-18 23:03:001310 history_list_offset_ = params.current_history_list_offset;
1311 history_list_length_ = params.current_history_list_length;
1312
[email protected]a9f607e2009-10-23 19:59:271313 child_process_logging::SetActiveURL(params.url);
[email protected]f8b6b6f2009-03-10 16:48:261314
initial.commit09911bf2008-07-26 23:55:291315 AboutHandler::MaybeHandle(params.url);
1316
[email protected]ecbf10d2010-02-18 13:03:291317 bool is_reload =
[email protected]2c5569662011-03-22 20:45:021318 params.navigation_type == ViewMsg_Navigate_Type::RELOAD ||
1319 params.navigation_type == ViewMsg_Navigate_Type::RELOAD_IGNORING_CACHE;
initial.commit09911bf2008-07-26 23:55:291320
[email protected]26aa0482009-09-30 16:55:271321 WebFrame* main_frame = webview()->mainFrame();
[email protected]dd7daa82009-08-10 05:46:451322 if (is_reload && main_frame->currentHistoryItem().isNull()) {
initial.commit09911bf2008-07-26 23:55:291323 // We cannot reload if we do not have any history state. This happens, for
1324 // example, when recovering from a crash. Our workaround here is a bit of
1325 // a hack since it means that reload after a crashed tab does not cause an
1326 // end-to-end cache validation.
1327 is_reload = false;
1328 }
1329
[email protected]77f17a82009-05-21 04:42:541330 // A navigation resulting from loading a javascript URL should not be treated
1331 // as a browser initiated event. Instead, we want it to look as if the page
1332 // initiated any load resulting from JS execution.
1333 if (!params.url.SchemeIs(chrome::kJavaScriptScheme)) {
[email protected]5e369672009-11-03 23:48:301334 NavigationState* state = NavigationState::CreateBrowserInitiated(
[email protected]3cc72b12010-03-18 23:03:001335 params.page_id,
1336 params.pending_history_list_offset,
1337 params.transition,
1338 params.request_time);
[email protected]2c5569662011-03-22 20:45:021339 if (params.navigation_type == ViewMsg_Navigate_Type::RESTORE) {
[email protected]5e369672009-11-03 23:48:301340 // We're doing a load of a page that was restored from the last session.
1341 // By default this prefers the cache over loading (LOAD_PREFERRING_CACHE)
1342 // which can result in stale data for pages that are set to expire. We
1343 // explicitly override that by setting the policy here so that as
1344 // necessary we load from the network.
1345 state->set_cache_policy_override(WebURLRequest::UseProtocolCachePolicy);
1346 }
1347 pending_navigation_state_.reset(state);
[email protected]77f17a82009-05-21 04:42:541348 }
initial.commit09911bf2008-07-26 23:55:291349
[email protected]a7ccc4d2010-01-27 08:14:481350 NavigationState* navigation_state = pending_navigation_state_.get();
1351
[email protected]04d3c6e2009-05-22 17:00:131352 // If we are reloading, then WebKit will use the history state of the current
1353 // page, so we should just ignore any given history state. Otherwise, if we
1354 // have history state, then we need to navigate to it, which corresponds to a
1355 // back/forward navigation event.
[email protected]e6f546c32009-07-01 17:12:551356 if (is_reload) {
[email protected]a7ccc4d2010-01-27 08:14:481357 if (navigation_state)
1358 navigation_state->set_load_type(NavigationState::RELOAD);
[email protected]ecbf10d2010-02-18 13:03:291359 bool ignore_cache = (params.navigation_type ==
[email protected]2c5569662011-03-22 20:45:021360 ViewMsg_Navigate_Type::RELOAD_IGNORING_CACHE);
[email protected]ecbf10d2010-02-18 13:03:291361 main_frame->reload(ignore_cache);
[email protected]e6f546c32009-07-01 17:12:551362 } else if (!params.state.empty()) {
[email protected]04d3c6e2009-05-22 17:00:131363 // We must know the page ID of the page we are navigating back to.
[email protected]f929f2f22009-06-12 16:56:581364 DCHECK_NE(params.page_id, -1);
[email protected]a7ccc4d2010-01-27 08:14:481365 if (navigation_state)
1366 navigation_state->set_load_type(NavigationState::HISTORY_LOAD);
[email protected]dd7daa82009-08-10 05:46:451367 main_frame->loadHistoryItem(
[email protected]ca948a22009-06-25 19:36:171368 webkit_glue::HistoryItemFromString(params.state));
[email protected]04d3c6e2009-05-22 17:00:131369 } else {
1370 // Navigate to the given URL.
[email protected]726985e22009-06-18 21:09:281371 WebURLRequest request(params.url);
initial.commit09911bf2008-07-26 23:55:291372
[email protected]e6f546c32009-07-01 17:12:551373 // A session history navigation should have been accompanied by state.
1374 DCHECK_EQ(params.page_id, -1);
[email protected]04d3c6e2009-05-22 17:00:131375
[email protected]dd7daa82009-08-10 05:46:451376 if (main_frame->isViewSourceModeEnabled())
[email protected]e6f546c32009-07-01 17:12:551377 request.setCachePolicy(WebURLRequest::ReturnCacheDataElseLoad);
[email protected]04d3c6e2009-05-22 17:00:131378
[email protected]726985e22009-06-18 21:09:281379 if (params.referrer.is_valid()) {
1380 request.setHTTPHeaderField(WebString::fromUTF8("Referer"),
1381 WebString::fromUTF8(params.referrer.spec()));
1382 }
[email protected]04d3c6e2009-05-22 17:00:131383
[email protected]52c68652010-12-07 17:47:041384 if (!params.extra_headers.empty()) {
1385 for (net::HttpUtil::HeadersIterator i(params.extra_headers.begin(),
1386 params.extra_headers.end(), "\n");
1387 i.GetNext(); ) {
1388 request.addHTTPHeaderField(WebString::fromUTF8(i.name()),
1389 WebString::fromUTF8(i.values()));
1390 }
1391 }
1392
[email protected]90dba072011-01-20 20:10:201393 if (navigation_state) {
[email protected]2c5569662011-03-22 20:45:021394 if (params.navigation_type != ViewMsg_Navigate_Type::PRERENDER) {
[email protected]90dba072011-01-20 20:10:201395 navigation_state->set_load_type(NavigationState::NORMAL_LOAD);
1396 } else {
1397 navigation_state->set_load_type(NavigationState::PRERENDER_LOAD);
[email protected]987d51af2011-02-24 17:50:181398 is_prerendering_ = true;
[email protected]90dba072011-01-20 20:10:201399 }
1400 }
[email protected]dd7daa82009-08-10 05:46:451401 main_frame->loadRequest(request);
[email protected]c0588052008-10-27 23:01:501402 }
1403
[email protected]77f17a82009-05-21 04:42:541404 // In case LoadRequest failed before DidCreateDataSource was called.
1405 pending_navigation_state_.reset();
initial.commit09911bf2008-07-26 23:55:291406}
1407
1408// Stop loading the current page
1409void RenderView::OnStop() {
1410 if (webview())
[email protected]b4bb2502009-10-01 22:35:271411 webview()->mainFrame()->stopLoading();
initial.commit09911bf2008-07-26 23:55:291412}
1413
[email protected]ecbf10d2010-02-18 13:03:291414// Reload current focused frame.
1415// E.g. called by right-clicking on the frame and picking "reload this frame".
[email protected]1dda4022010-01-28 18:24:561416void RenderView::OnReloadFrame() {
[email protected]ecbf10d2010-02-18 13:03:291417 if (webview() && webview()->focusedFrame()) {
1418 // We always obey the cache (ignore_cache=false) here.
1419 // TODO(evanm): perhaps we could allow shift-clicking the menu item to do
1420 // a cache-ignoring reload of the frame.
1421 webview()->focusedFrame()->reload(false);
1422 }
[email protected]1dda4022010-01-28 18:24:561423}
1424
initial.commit09911bf2008-07-26 23:55:291425void RenderView::OnCopyImageAt(int x, int y) {
[email protected]26aa0482009-09-30 16:55:271426 webview()->copyImageAt(WebPoint(x, y));
initial.commit09911bf2008-07-26 23:55:291427}
1428
[email protected]68b1e922009-06-23 16:00:251429void RenderView::OnExecuteEditCommand(const std::string& name,
1430 const std::string& value) {
[email protected]26aa0482009-09-30 16:55:271431 if (!webview() || !webview()->focusedFrame())
[email protected]68b1e922009-06-23 16:00:251432 return;
1433
[email protected]26aa0482009-09-30 16:55:271434 webview()->focusedFrame()->executeCommand(
[email protected]dd7daa82009-08-10 05:46:451435 WebString::fromUTF8(name), WebString::fromUTF8(value));
[email protected]68b1e922009-06-23 16:00:251436}
1437
[email protected]b2abac72009-02-26 12:39:281438void RenderView::OnSetupDevToolsClient() {
[email protected]676126f72011-01-15 00:03:511439 DCHECK(!devtools_client_);
1440 devtools_client_ = new DevToolsClient(this);
[email protected]b2abac72009-02-26 12:39:281441}
1442
initial.commit09911bf2008-07-26 23:55:291443void RenderView::OnUpdateTargetURLAck() {
1444 // Check if there is a targeturl waiting to be sent.
1445 if (target_url_status_ == TARGET_PENDING) {
1446 Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_,
1447 pending_target_url_));
1448 }
1449
1450 target_url_status_ = TARGET_NONE;
1451}
1452
1453void RenderView::OnUndo() {
1454 if (!webview())
1455 return;
1456
[email protected]26aa0482009-09-30 16:55:271457 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Undo"));
[email protected]afe3a1672009-11-17 19:04:121458 UserMetricsRecordAction("Undo");
initial.commit09911bf2008-07-26 23:55:291459}
1460
1461void RenderView::OnRedo() {
1462 if (!webview())
1463 return;
1464
[email protected]26aa0482009-09-30 16:55:271465 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Redo"));
[email protected]afe3a1672009-11-17 19:04:121466 UserMetricsRecordAction("Redo");
initial.commit09911bf2008-07-26 23:55:291467}
1468
1469void RenderView::OnCut() {
1470 if (!webview())
1471 return;
1472
[email protected]26aa0482009-09-30 16:55:271473 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Cut"));
[email protected]afe3a1672009-11-17 19:04:121474 UserMetricsRecordAction("Cut");
initial.commit09911bf2008-07-26 23:55:291475}
1476
1477void RenderView::OnCopy() {
1478 if (!webview())
1479 return;
1480
[email protected]26aa0482009-09-30 16:55:271481 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Copy"));
[email protected]afe3a1672009-11-17 19:04:121482 UserMetricsRecordAction("Copy");
initial.commit09911bf2008-07-26 23:55:291483}
1484
[email protected]c0cc3092009-09-12 08:27:271485#if defined(OS_MACOSX)
[email protected]a954bf72009-09-12 07:30:351486void RenderView::OnCopyToFindPboard() {
1487 if (!webview())
1488 return;
1489
1490 // Since the find pasteboard supports only plain text, this can be simpler
1491 // than the |OnCopy()| case.
[email protected]26aa0482009-09-30 16:55:271492 WebFrame* frame = webview()->focusedFrame();
[email protected]a954bf72009-09-12 07:30:351493 if (frame->hasSelection()) {
1494 string16 selection = frame->selectionAsText();
1495 RenderThread::current()->Send(
[email protected]7e3589742011-03-10 18:49:171496 new ClipboardHostMsg_FindPboardWriteStringAsync(selection));
[email protected]a954bf72009-09-12 07:30:351497 }
1498
[email protected]afe3a1672009-11-17 19:04:121499 UserMetricsRecordAction("CopyToFindPboard");
[email protected]a954bf72009-09-12 07:30:351500}
[email protected]c0cc3092009-09-12 08:27:271501#endif
[email protected]a954bf72009-09-12 07:30:351502
initial.commit09911bf2008-07-26 23:55:291503void RenderView::OnPaste() {
1504 if (!webview())
1505 return;
1506
[email protected]26aa0482009-09-30 16:55:271507 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Paste"));
[email protected]afe3a1672009-11-17 19:04:121508 UserMetricsRecordAction("Paste");
initial.commit09911bf2008-07-26 23:55:291509}
1510
[email protected]2a3a7762009-10-19 19:17:321511void RenderView::OnReplace(const string16& text) {
initial.commit09911bf2008-07-26 23:55:291512 if (!webview())
1513 return;
1514
[email protected]1ff7a032010-02-03 02:46:031515 WebFrame* frame = webview()->focusedFrame();
1516 if (!frame->hasSelection())
1517 frame->selectWordAroundCaret();
1518 frame->replaceSelection(text);
initial.commit09911bf2008-07-26 23:55:291519}
1520
1521void RenderView::OnDelete() {
1522 if (!webview())
1523 return;
1524
[email protected]26aa0482009-09-30 16:55:271525 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Delete"));
[email protected]afe3a1672009-11-17 19:04:121526 UserMetricsRecordAction("DeleteSelection");
initial.commit09911bf2008-07-26 23:55:291527}
1528
1529void RenderView::OnSelectAll() {
1530 if (!webview())
1531 return;
1532
[email protected]26aa0482009-09-30 16:55:271533 webview()->focusedFrame()->executeCommand(
[email protected]a100d76bb2009-08-14 17:50:221534 WebString::fromUTF8("SelectAll"));
[email protected]afe3a1672009-11-17 19:04:121535 UserMetricsRecordAction("SelectAll");
initial.commit09911bf2008-07-26 23:55:291536}
1537
1538void RenderView::OnSetInitialFocus(bool reverse) {
1539 if (!webview())
1540 return;
[email protected]26aa0482009-09-30 16:55:271541 webview()->setInitialFocus(reverse);
initial.commit09911bf2008-07-26 23:55:291542}
1543
[email protected]9b66f34bf2010-10-27 20:45:511544void RenderView::OnScrollFocusedEditableNodeIntoView() {
[email protected]13a1e4c3c2011-02-03 21:07:091545 WebKit::WebNode node = GetFocusedNode();
1546 if (!node.isNull()) {
1547 if (IsEditableNode(node))
1548 // TODO(varunjain): Change webkit API to scroll a particular node into
1549 // view and use that API here instead.
1550 webview()->scrollFocusedNodeIntoView();
[email protected]9b66f34bf2010-10-27 20:45:511551 }
1552}
1553
initial.commit09911bf2008-07-26 23:55:291554///////////////////////////////////////////////////////////////////////////////
1555
[email protected]433819d2010-01-30 20:20:011556void RenderView::SetContentSettings(const ContentSettings& settings) {
1557 current_content_settings_ = settings;
[email protected]f85f0702010-01-30 09:31:011558}
1559
initial.commit09911bf2008-07-26 23:55:291560// Tell the embedding application that the URL of the active page has changed
1561void RenderView::UpdateURL(WebFrame* frame) {
[email protected]dd7daa82009-08-10 05:46:451562 WebDataSource* ds = frame->dataSource();
initial.commit09911bf2008-07-26 23:55:291563 DCHECK(ds);
1564
[email protected]726985e22009-06-18 21:09:281565 const WebURLRequest& request = ds->request();
1566 const WebURLRequest& original_request = ds->originalRequest();
1567 const WebURLResponse& response = ds->response();
initial.commit09911bf2008-07-26 23:55:291568
[email protected]daa8c58e2009-06-15 17:21:101569 NavigationState* navigation_state = NavigationState::FromDataSource(ds);
1570 DCHECK(navigation_state);
initial.commit09911bf2008-07-26 23:55:291571
1572 ViewHostMsg_FrameNavigate_Params params;
[email protected]726985e22009-06-18 21:09:281573 params.http_status_code = response.httpStatusCode();
initial.commit09911bf2008-07-26 23:55:291574 params.is_post = false;
1575 params.page_id = page_id_;
[email protected]dabb0d12010-10-05 12:50:071576 params.frame_id = frame->identifier();
[email protected]6d81b482011-02-22 19:47:191577 params.socket_address.set_host(response.remoteIPAddress().utf8());
1578 params.socket_address.set_port(response.remotePort());
[email protected]b9a7c6d42011-02-25 02:13:031579 params.was_fetched_via_proxy = response.wasFetchedViaProxy();
[email protected]af15bed2010-08-25 21:12:091580 params.was_within_same_page = navigation_state->was_within_same_page();
[email protected]e6f546c32009-07-01 17:12:551581 if (!navigation_state->security_info().empty()) {
initial.commit09911bf2008-07-26 23:55:291582 // SSL state specified in the request takes precedence over the one in the
1583 // response.
1584 // So far this is only intended for error pages that are not expected to be
1585 // over ssl, so we should not get any clash.
[email protected]726985e22009-06-18 21:09:281586 DCHECK(response.securityInfo().isEmpty());
[email protected]e6f546c32009-07-01 17:12:551587 params.security_info = navigation_state->security_info();
initial.commit09911bf2008-07-26 23:55:291588 } else {
[email protected]726985e22009-06-18 21:09:281589 params.security_info = response.securityInfo();
initial.commit09911bf2008-07-26 23:55:291590 }
1591
1592 // Set the URL to be displayed in the browser UI to the user.
[email protected]726985e22009-06-18 21:09:281593 if (ds->hasUnreachableURL()) {
1594 params.url = ds->unreachableURL();
initial.commit09911bf2008-07-26 23:55:291595 } else {
[email protected]726985e22009-06-18 21:09:281596 params.url = request.url();
initial.commit09911bf2008-07-26 23:55:291597 }
1598
[email protected]726985e22009-06-18 21:09:281599 GetRedirectChain(ds, &params.redirects);
[email protected]d94dc1e2010-03-04 09:29:241600 params.should_update_history = !ds->hasUnreachableURL() &&
[email protected]b7df1b72011-02-10 00:08:041601 !response.isMultipartPayload() && (response.httpStatusCode() != 404);
initial.commit09911bf2008-07-26 23:55:291602
[email protected]ce0e250d2009-10-23 21:00:351603 params.searchable_form_url = navigation_state->searchable_form_url();
1604 params.searchable_form_encoding =
1605 navigation_state->searchable_form_encoding();
initial.commit09911bf2008-07-26 23:55:291606
1607 const PasswordForm* password_form_data =
[email protected]daa8c58e2009-06-15 17:21:101608 navigation_state->password_form_data();
initial.commit09911bf2008-07-26 23:55:291609 if (password_form_data)
1610 params.password_form = *password_form_data;
1611
1612 params.gesture = navigation_gesture_;
1613 navigation_gesture_ = NavigationGestureUnknown;
1614
[email protected]0f38dc4552011-02-25 11:24:001615 // Make navigation state a part of the FrameNavigate message so that commited
1616 // entry had it at all times.
1617 const WebHistoryItem& item = frame->currentHistoryItem();
1618 if (!item.isNull()) {
1619 params.content_state = webkit_glue::HistoryItemToString(item);
1620 } else {
1621 params.content_state =
1622 webkit_glue::CreateHistoryStateForURL(GURL(request.url()));
1623 }
1624
[email protected]dd7daa82009-08-10 05:46:451625 if (!frame->parent()) {
initial.commit09911bf2008-07-26 23:55:291626 // Top-level navigation.
1627
[email protected]71b0d5d2010-02-15 05:43:071628 // Clear "block" flags for the new page. This needs to happen before any of
1629 // allowScripts(), allowImages(), allowPlugins() is called for the new page
1630 // so that these functions can correctly detect that a piece of content
1631 // flipped from "not blocked" to "blocked".
1632 ClearBlockedContentSettings();
1633
[email protected]62d2a112010-04-07 00:53:021634 // Set content settings. Default them from the parent window if one exists.
1635 // This makes sure about:blank windows work as expected.
[email protected]f85f0702010-01-30 09:31:011636 HostContentSettings::iterator host_content_settings =
[email protected]9d797f32010-04-23 07:17:541637 host_content_settings_.find(GURL(request.url()));
[email protected]f85f0702010-01-30 09:31:011638 if (host_content_settings != host_content_settings_.end()) {
[email protected]433819d2010-01-30 20:20:011639 SetContentSettings(host_content_settings->second);
[email protected]f85f0702010-01-30 09:31:011640
1641 // These content settings were merely recorded transiently for this load.
1642 // We can erase them now. If at some point we reload this page, the
1643 // browser will send us new, up-to-date content settings.
1644 host_content_settings_.erase(host_content_settings);
[email protected]3a387ae2010-04-08 01:58:401645 } else if (frame->opener()) {
[email protected]8128cdd02010-07-21 20:40:101646 // The opener's view is not guaranteed to be non-null (it could be
1647 // detached from its page but not yet destructed).
1648 if (WebView* opener_view = frame->opener()->view()) {
1649 RenderView* opener = FromWebView(opener_view);
1650 SetContentSettings(opener->current_content_settings_);
1651 }
[email protected]f85f0702010-01-30 09:31:011652 }
1653
[email protected]b75b8292010-10-01 07:28:251654 // Set zoom level, but don't do it for full-page plugin since they don't use
1655 // the same zoom settings.
[email protected]f85f0702010-01-30 09:31:011656 HostZoomLevels::iterator host_zoom =
[email protected]9d797f32010-04-23 07:17:541657 host_zoom_levels_.find(GURL(request.url()));
[email protected]b75b8292010-10-01 07:28:251658 if (webview()->mainFrame()->document().isPluginDocument()) {
1659 // Reset the zoom levels for plugins.
[email protected]b75b8292010-10-01 07:28:251660 webview()->setZoomLevel(false, 0);
[email protected]b75b8292010-10-01 07:28:251661 } else {
1662 if (host_zoom != host_zoom_levels_.end())
[email protected]b75b8292010-10-01 07:28:251663 webview()->setZoomLevel(false, host_zoom->second);
[email protected]b75b8292010-10-01 07:28:251664 }
1665
[email protected]f85f0702010-01-30 09:31:011666 if (host_zoom != host_zoom_levels_.end()) {
[email protected]40bd6582009-12-04 23:49:511667 // This zoom level was merely recorded transiently for this load. We can
1668 // erase it now. If at some point we reload this page, the browser will
1669 // send us a new, up-to-date zoom level.
[email protected]f85f0702010-01-30 09:31:011670 host_zoom_levels_.erase(host_zoom);
[email protected]40bd6582009-12-04 23:49:511671 }
1672
[email protected]b75b8292010-10-01 07:28:251673 // Reset the zoom limits in case a plugin had changed them previously. This
1674 // will also call us back which will cause us to send a message to
1675 // update TabContents.
[email protected]b75b8292010-10-01 07:28:251676 webview()->zoomLimitsChanged(
1677 WebView::zoomFactorToZoomLevel(WebView::minTextSizeMultiplier),
1678 WebView::zoomFactorToZoomLevel(WebView::maxTextSizeMultiplier));
[email protected]b75b8292010-10-01 07:28:251679
initial.commit09911bf2008-07-26 23:55:291680 // Update contents MIME type for main frame.
[email protected]9c5645b2009-08-11 03:37:551681 params.contents_mime_type = ds->response().mimeType().utf8();
initial.commit09911bf2008-07-26 23:55:291682
[email protected]daa8c58e2009-06-15 17:21:101683 params.transition = navigation_state->transition_type();
initial.commit09911bf2008-07-26 23:55:291684 if (!PageTransition::IsMainFrame(params.transition)) {
1685 // If the main frame does a load, it should not be reported as a subframe
1686 // navigation. This can occur in the following case:
1687 // 1. You're on a site with frames.
1688 // 2. You do a subframe navigation. This is stored with transition type
1689 // MANUAL_SUBFRAME.
1690 // 3. You navigate to some non-frame site, say, google.com.
1691 // 4. You navigate back to the page from step 2. Since it was initially
1692 // MANUAL_SUBFRAME, it will be that same transition type here.
1693 // We don't want that, because any navigation that changes the toplevel
1694 // frame should be tracked as a toplevel navigation (this allows us to
1695 // update the URL bar, etc).
1696 params.transition = PageTransition::LINK;
1697 }
1698
initial.commit09911bf2008-07-26 23:55:291699 // If we have a valid consumed client redirect source,
1700 // the page contained a client redirect (meta refresh, document.loc...),
1701 // so we set the referrer and transition to match.
1702 if (completed_client_redirect_src_.is_valid()) {
[email protected]77e09a92008-08-01 18:11:041703 DCHECK(completed_client_redirect_src_ == params.redirects[0]);
initial.commit09911bf2008-07-26 23:55:291704 params.referrer = completed_client_redirect_src_;
1705 params.transition = static_cast<PageTransition::Type>(
1706 params.transition | PageTransition::CLIENT_REDIRECT);
1707 } else {
1708 // Bug 654101: the referrer will be empty on https->http transitions. It
1709 // would be nice if we could get the real referrer from somewhere.
[email protected]726985e22009-06-18 21:09:281710 params.referrer = GURL(
1711 original_request.httpHeaderField(WebString::fromUTF8("Referer")));
initial.commit09911bf2008-07-26 23:55:291712 }
1713
[email protected]726985e22009-06-18 21:09:281714 string16 method = request.httpMethod();
1715 if (EqualsASCII(method, "POST"))
initial.commit09911bf2008-07-26 23:55:291716 params.is_post = true;
1717
[email protected]c2a797d2009-09-21 16:46:321718 // Save some histogram data so we can compute the average memory used per
1719 // page load of the glyphs.
1720 UMA_HISTOGRAM_COUNTS_10000("Memory.GlyphPagesPerLoad",
1721 webkit_glue::GetGlyphPageCount());
1722
[email protected]15cf526b2010-02-12 06:33:491723 // This message needs to be sent before any of allowScripts(),
1724 // allowImages(), allowPlugins() is called for the new page, so that when
1725 // these functions send a ViewHostMsg_ContentBlocked message, it arrives
1726 // after the ViewHostMsg_FrameNavigate message.
initial.commit09911bf2008-07-26 23:55:291727 Send(new ViewHostMsg_FrameNavigate(routing_id_, params));
1728 } else {
1729 // Subframe navigation: the type depends on whether this navigation
1730 // generated a new session history entry. When they do generate a session
1731 // history entry, it means the user initiated the navigation and we should
1732 // mark it as such. This test checks if this is the first time UpdateURL
1733 // has been called since WillNavigateToURL was called to initiate the load.
1734 if (page_id_ > last_page_id_sent_to_browser_)
1735 params.transition = PageTransition::MANUAL_SUBFRAME;
1736 else
1737 params.transition = PageTransition::AUTO_SUBFRAME;
1738
initial.commit09911bf2008-07-26 23:55:291739 Send(new ViewHostMsg_FrameNavigate(routing_id_, params));
1740 }
1741
1742 last_page_id_sent_to_browser_ =
1743 std::max(last_page_id_sent_to_browser_, page_id_);
1744
1745 // If we end up reusing this WebRequest (for example, due to a #ref click),
[email protected]daa8c58e2009-06-15 17:21:101746 // we don't want the transition type to persist. Just clear it.
1747 navigation_state->set_transition_type(PageTransition::LINK);
[email protected]266eb6f2008-09-30 23:56:501748
[email protected]af15bed2010-08-25 21:12:091749 // Check if the navigation was within the same page, in which case we don't
1750 // want to clear the accessibility cache.
1751 if (accessibility_.get() && !navigation_state->was_within_same_page()) {
[email protected]17455962010-02-24 01:39:351752 accessibility_.reset();
[email protected]dea2d372010-09-25 06:41:141753 pending_accessibility_notifications_.clear();
[email protected]266eb6f2008-09-30 23:56:501754 }
initial.commit09911bf2008-07-26 23:55:291755}
1756
1757// Tell the embedding application that the title of the active page has changed
[email protected]3d9689372009-09-10 04:29:171758void RenderView::UpdateTitle(WebFrame* frame, const string16& title) {
initial.commit09911bf2008-07-26 23:55:291759 // Ignore all but top level navigations...
[email protected]3d9689372009-09-10 04:29:171760 if (!frame->parent()) {
[email protected]f0af6a72009-05-30 05:25:171761 Send(new ViewHostMsg_UpdateTitle(
[email protected]3d9689372009-09-10 04:29:171762 routing_id_,
1763 page_id_,
1764 UTF16ToWideHack(title.length() > chrome::kMaxTitleChars ?
1765 title.substr(0, chrome::kMaxTitleChars) : title)));
[email protected]f0af6a72009-05-30 05:25:171766 }
initial.commit09911bf2008-07-26 23:55:291767}
1768
1769void RenderView::UpdateEncoding(WebFrame* frame,
[email protected]41fc0322009-09-04 22:23:401770 const std::string& encoding_name) {
initial.commit09911bf2008-07-26 23:55:291771 // Only update main frame's encoding_name.
[email protected]26aa0482009-09-30 16:55:271772 if (webview()->mainFrame() == frame &&
initial.commit09911bf2008-07-26 23:55:291773 last_encoding_name_ != encoding_name) {
[email protected]e38f40152008-09-12 23:08:301774 // Save the encoding name for later comparing.
initial.commit09911bf2008-07-26 23:55:291775 last_encoding_name_ = encoding_name;
1776
[email protected]e38f40152008-09-12 23:08:301777 Send(new ViewHostMsg_UpdateEncoding(routing_id_, last_encoding_name_));
initial.commit09911bf2008-07-26 23:55:291778 }
1779}
1780
[email protected]e15f680732010-11-23 22:30:201781// Sends the last committed session history state to the browser so it will be
1782// saved before we navigate to a new page. This must be called *before* the
1783// page ID has been updated so we know what it was.
initial.commit09911bf2008-07-26 23:55:291784void RenderView::UpdateSessionHistory(WebFrame* frame) {
1785 // If we have a valid page ID at this point, then it corresponds to the page
1786 // we are navigating away from. Otherwise, this is the first navigation, so
1787 // there is no past session history to record.
1788 if (page_id_ == -1)
1789 return;
1790
[email protected]ca948a22009-06-25 19:36:171791 const WebHistoryItem& item =
[email protected]26aa0482009-09-30 16:55:271792 webview()->mainFrame()->previousHistoryItem();
[email protected]ca948a22009-06-25 19:36:171793 if (item.isNull())
initial.commit09911bf2008-07-26 23:55:291794 return;
[email protected]ca948a22009-06-25 19:36:171795
1796 Send(new ViewHostMsg_UpdateState(
1797 routing_id_, page_id_, webkit_glue::HistoryItemToString(item)));
initial.commit09911bf2008-07-26 23:55:291798}
1799
[email protected]3d9689372009-09-10 04:29:171800void RenderView::OpenURL(
1801 const GURL& url, const GURL& referrer, WebNavigationPolicy policy) {
1802 Send(new ViewHostMsg_OpenURL(
1803 routing_id_, url, referrer, NavigationPolicyToDisposition(policy)));
1804}
1805
[email protected]79dbc662009-09-04 05:42:511806// WebViewDelegate ------------------------------------------------------------
initial.commit09911bf2008-07-26 23:55:291807
initial.commit09911bf2008-07-26 23:55:291808void RenderView::LoadNavigationErrorPage(WebFrame* frame,
[email protected]726985e22009-06-18 21:09:281809 const WebURLRequest& failed_request,
1810 const WebURLError& error,
initial.commit09911bf2008-07-26 23:55:291811 const std::string& html,
1812 bool replace) {
[email protected]21d61e52011-03-18 19:08:251813 std::string alt_html = !html.empty() ? html :
1814 content::GetContentClient()->renderer()->GetNavigationErrorHtml(
1815 failed_request, error);
[email protected]dd7daa82009-08-10 05:46:451816 frame->loadHTMLString(alt_html,
[email protected]144143c2010-10-28 08:17:361817 GURL(chrome::kUnreachableWebDataURL),
[email protected]21d61e52011-03-18 19:08:251818 error.unreachableURL,
[email protected]e6f546c32009-07-01 17:12:551819 replace);
initial.commit09911bf2008-07-26 23:55:291820}
1821
[email protected]7ccddb8c2009-08-04 17:36:551822void RenderView::BindDOMAutomationController(WebFrame* frame) {
[email protected]2f979172010-09-16 21:54:031823 if (!dom_automation_controller_.get()) {
1824 dom_automation_controller_.reset(new DomAutomationController());
1825 }
1826 dom_automation_controller_->set_message_sender(this);
1827 dom_automation_controller_->set_routing_id(routing_id_);
1828 dom_automation_controller_->BindToJavascript(frame,
[email protected]906690b2010-12-03 18:11:251829 "domAutomationController");
initial.commit09911bf2008-07-26 23:55:291830}
1831
initial.commit09911bf2008-07-26 23:55:291832bool RenderView::RunJavaScriptMessage(int type,
1833 const std::wstring& message,
1834 const std::wstring& default_value,
[email protected]a455d3812009-03-05 20:18:071835 const GURL& frame_url,
initial.commit09911bf2008-07-26 23:55:291836 std::wstring* result) {
1837 bool success = false;
1838 std::wstring result_temp;
1839 if (!result)
1840 result = &result_temp;
initial.commit09911bf2008-07-26 23:55:291841
[email protected]12636df2009-09-28 22:32:211842 SendAndRunNestedMessageLoop(new ViewHostMsg_RunJavaScriptMessage(
1843 routing_id_, message, default_value, frame_url, type, &success, result));
initial.commit09911bf2008-07-26 23:55:291844 return success;
1845}
1846
[email protected]c1f50aa2010-02-18 03:46:571847bool RenderView::SendAndRunNestedMessageLoop(IPC::SyncMessage* message) {
1848 // Before WebKit asks us to show an alert (etc.), it takes care of doing the
1849 // equivalent of WebView::willEnterModalLoop. In the case of showModalDialog
1850 // it is particularly important that we do not call willEnterModalLoop as
1851 // that would defer resource loads for the dialog itself.
1852 if (RenderThread::current()) // Will be NULL during unit tests.
1853 RenderThread::current()->DoNotNotifyWebKitOfModalLoop();
1854
1855 message->EnableMessagePumping(); // Runs a nested message loop.
1856 return Send(message);
1857}
1858
[email protected]2de7e002010-10-11 22:58:201859void RenderView::AddGURLSearchProvider(
1860 const GURL& osd_url,
[email protected]c08e7932011-03-29 04:08:141861 search_provider::OSDDType provider_type) {
initial.commit09911bf2008-07-26 23:55:291862 if (!osd_url.is_empty())
1863 Send(new ViewHostMsg_PageHasOSDD(routing_id_, page_id_, osd_url,
[email protected]2de7e002010-10-11 22:58:201864 provider_type));
initial.commit09911bf2008-07-26 23:55:291865}
1866
[email protected]e8345242010-05-06 03:00:401867void RenderView::OnAllowScriptToClose(bool script_can_close) {
1868 script_can_close_ = script_can_close;
[email protected]634a6f92008-12-01 21:39:311869}
1870
[email protected]2de7e002010-10-11 22:58:201871void RenderView::AddSearchProvider(
1872 const std::string& url,
[email protected]c08e7932011-03-29 04:08:141873 search_provider::OSDDType provider_type) {
1874 if (provider_type == search_provider::EXPLICIT_DEFAULT_PROVIDER &&
[email protected]2de7e002010-10-11 22:58:201875 !webview()->mainFrame()->isProcessingUserGesture())
1876 return;
1877
1878 AddGURLSearchProvider(GURL(url), provider_type);
initial.commit09911bf2008-07-26 23:55:291879}
1880
[email protected]c08e7932011-03-29 04:08:141881search_provider::InstallState
[email protected]52ded452010-08-23 22:01:251882RenderView::GetSearchProviderInstallState(WebFrame* frame,
1883 const std::string& url) {
[email protected]155f35e2010-07-17 00:30:181884 GURL inquiry_url = GURL(url);
1885 if (inquiry_url.is_empty())
[email protected]c08e7932011-03-29 04:08:141886 return search_provider::DENIED;
[email protected]52ded452010-08-23 22:01:251887
[email protected]c08e7932011-03-29 04:08:141888 search_provider::InstallState install;
[email protected]155f35e2010-07-17 00:30:181889 Send(new ViewHostMsg_GetSearchProviderInstallState(routing_id_,
[email protected]52ded452010-08-23 22:01:251890 frame->url(),
[email protected]155f35e2010-07-17 00:30:181891 inquiry_url,
1892 &install));
1893 return install;
1894}
1895
[email protected]f103ab72009-09-02 17:10:591896void RenderView::OnMissingPluginStatus(
1897 WebPluginDelegateProxy* delegate,
1898 int status) {
[email protected]6c8afae52009-01-22 02:24:571899#if defined(OS_WIN)
[email protected]f103ab72009-09-02 17:10:591900 if (!first_default_plugin_) {
initial.commit09911bf2008-07-26 23:55:291901 // Show the InfoBar for the first available plugin.
[email protected]191eb3f72010-12-21 06:27:501902 if (status == webkit::npapi::default_plugin::MISSING_PLUGIN_AVAILABLE) {
[email protected]f103ab72009-09-02 17:10:591903 first_default_plugin_ = delegate->AsWeakPtr();
initial.commit09911bf2008-07-26 23:55:291904 Send(new ViewHostMsg_MissingPluginStatus(routing_id_, status));
1905 }
1906 } else {
1907 // Closes the InfoBar if user clicks on the plugin (instead of the InfoBar)
1908 // to start the download/install.
[email protected]191eb3f72010-12-21 06:27:501909 if (status ==
1910 webkit::npapi::default_plugin::MISSING_PLUGIN_USER_STARTED_DOWNLOAD) {
initial.commit09911bf2008-07-26 23:55:291911 Send(new ViewHostMsg_MissingPluginStatus(routing_id_, status));
1912 }
1913 }
[email protected]6c8afae52009-01-22 02:24:571914#else
[email protected]76c3b312010-05-20 21:38:291915 // TODO(port): Implement the infobar that accompanies the default plugin.
1916 // Linux: http://crbug.com/10952
1917 // Mac: http://crbug.com/17392
[email protected]6c8afae52009-01-22 02:24:571918 NOTIMPLEMENTED();
1919#endif
initial.commit09911bf2008-07-26 23:55:291920}
1921
[email protected]48c9cf2d2009-09-16 16:47:521922// WebKit::WebViewClient ------------------------------------------------------
1923
[email protected]844acf372011-01-14 10:49:271924WebView* RenderView::createView(
1925 WebFrame* creator,
1926 const WebURLRequest& request,
1927 const WebWindowFeatures& features,
1928 const WebString& frame_name) {
[email protected]48c9cf2d2009-09-16 16:47:521929 // Check to make sure we aren't overloading on popups.
1930 if (shared_popup_counter_->data > kMaximumNumberOfUnacknowledgedPopups)
1931 return NULL;
1932
1933 // This window can't be closed from a window.close() call until we receive a
1934 // message from the Browser process explicitly allowing it.
[email protected]e8345242010-05-06 03:00:401935 script_can_close_ = false;
[email protected]48c9cf2d2009-09-16 16:47:521936
[email protected]8ab04652010-06-12 02:47:261937 ViewHostMsg_CreateWindow_Params params;
1938 params.opener_id = routing_id_;
1939 params.user_gesture = creator->isProcessingUserGesture();
1940 params.window_container_type = WindowFeaturesToContainerType(features);
1941 params.session_storage_namespace_id = session_storage_namespace_id_;
1942 params.frame_name = frame_name;
[email protected]41e65502011-01-21 09:29:111943 params.opener_frame_id = creator->identifier();
1944 params.opener_url = creator->url();
1945 params.opener_security_origin = creator->securityOrigin().toString().utf8();
1946 if (!request.isNull())
1947 params.target_url = request.url();
[email protected]8ab04652010-06-12 02:47:261948
[email protected]48c9cf2d2009-09-16 16:47:521949 int32 routing_id = MSG_ROUTING_NONE;
[email protected]4e6419c2010-01-15 04:50:341950 int64 cloned_session_storage_namespace_id;
[email protected]8ab04652010-06-12 02:47:261951 bool opener_suppressed = creator->willSuppressOpenerInNewFrame();
[email protected]48c9cf2d2009-09-16 16:47:521952
[email protected]48c9cf2d2009-09-16 16:47:521953 render_thread_->Send(
[email protected]8ab04652010-06-12 02:47:261954 new ViewHostMsg_CreateWindow(params,
1955 &routing_id,
1956 &cloned_session_storage_namespace_id));
[email protected]12636df2009-09-28 22:32:211957 if (routing_id == MSG_ROUTING_NONE)
[email protected]48c9cf2d2009-09-16 16:47:521958 return NULL;
[email protected]48c9cf2d2009-09-16 16:47:521959
[email protected]48c9cf2d2009-09-16 16:47:521960 RenderView* view = RenderView::Create(render_thread_,
[email protected]659f73fa2009-10-13 13:43:421961 0,
[email protected]12636df2009-09-28 22:32:211962 routing_id_,
[email protected]48c9cf2d2009-09-16 16:47:521963 renderer_preferences_,
1964 webkit_preferences_,
[email protected]12636df2009-09-28 22:32:211965 shared_popup_counter_,
[email protected]4e6419c2010-01-15 04:50:341966 routing_id,
[email protected]8ab04652010-06-12 02:47:261967 cloned_session_storage_namespace_id,
1968 frame_name);
1969 view->opened_by_user_gesture_ = params.user_gesture;
[email protected]48c9cf2d2009-09-16 16:47:521970
[email protected]007a848b2009-10-26 15:55:461971 // Record whether the creator frame is trying to suppress the opener field.
1972 view->opener_suppressed_ = opener_suppressed;
1973
[email protected]48c9cf2d2009-09-16 16:47:521974 // Record the security origin of the creator.
[email protected]91733b62009-09-18 06:21:091975 GURL creator_url(creator->securityOrigin().toString().utf8());
[email protected]48c9cf2d2009-09-16 16:47:521976 if (!creator_url.is_valid() || !creator_url.IsStandard())
1977 creator_url = GURL();
1978 view->creator_url_ = creator_url;
1979
1980 // Copy over the alternate error page URL so we can have alt error pages in
1981 // the new render view (we don't need the browser to send the URL back down).
1982 view->alternate_error_page_url_ = alternate_error_page_url_;
1983
1984 return view->webview();
1985}
1986
[email protected]3e2b375b2010-04-07 17:03:121987WebWidget* RenderView::createPopupMenu(WebKit::WebPopupType popup_type) {
[email protected]48c9cf2d2009-09-16 16:47:521988 RenderWidget* widget = RenderWidget::Create(routing_id_,
1989 render_thread_,
[email protected]3e2b375b2010-04-07 17:03:121990 popup_type);
[email protected]48c9cf2d2009-09-16 16:47:521991 return widget->webwidget();
1992}
1993
1994WebWidget* RenderView::createPopupMenu(const WebPopupMenuInfo& info) {
[email protected]8de12d942010-11-17 20:42:441995 // TODO(jcivelli): Remove this deprecated method when its been removed from
1996 // the WebViewClient interface. It's been replaced by
1997 // createExternalPopupMenu.
1998 NOTREACHED();
1999 return NULL;
[email protected]48c9cf2d2009-09-16 16:47:522000}
2001
[email protected]caf706f2010-10-26 17:54:082002WebExternalPopupMenu* RenderView::createExternalPopupMenu(
2003 const WebPopupMenuInfo& popup_menu_info,
2004 WebExternalPopupMenuClient* popup_menu_client) {
2005 DCHECK(!external_popup_menu_.get());
2006 external_popup_menu_.reset(
2007 new ExternalPopupMenu(this, popup_menu_info, popup_menu_client));
2008 return external_popup_menu_.get();
2009}
2010
[email protected]0bd753682010-12-16 18:15:522011webkit::ppapi::FullscreenContainer*
2012RenderView::CreatePepperFullscreenContainer(
2013 webkit::ppapi::PluginInstance* plugin) {
[email protected]d91233b7e2011-03-29 20:33:532014 GURL active_url;
2015 if(webview() && webview()->mainFrame())
2016 active_url = GURL(webview()->mainFrame()->url());
2017 RenderWidgetFullscreenPepper* widget = RenderWidgetFullscreenPepper::Create(
2018 routing_id_, render_thread_, plugin, active_url);
[email protected]79c7bed2010-09-14 22:28:392019 widget->show(WebKit::WebNavigationPolicyIgnore);
[email protected]92abcb832011-01-06 20:39:562020 return widget;
[email protected]79c7bed2010-09-14 22:28:392021}
2022
[email protected]68c50e52010-05-12 11:14:392023WebStorageNamespace* RenderView::createSessionStorageNamespace(unsigned quota) {
[email protected]bd92c3a2010-01-13 05:02:342024 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess))
[email protected]68c50e52010-05-12 11:14:392025 return WebStorageNamespace::createSessionStorageNamespace(quota);
[email protected]59afea12010-01-20 04:48:292026 CHECK(session_storage_namespace_id_ != kInvalidSessionStorageNamespaceId);
2027 return new RendererWebStorageNamespaceImpl(DOM_STORAGE_SESSION,
2028 session_storage_namespace_id_);
[email protected]bd92c3a2010-01-13 05:02:342029}
2030
[email protected]48c9cf2d2009-09-16 16:47:522031void RenderView::didAddMessageToConsole(
2032 const WebConsoleMessage& message, const WebString& source_name,
2033 unsigned source_line) {
2034 Send(new ViewHostMsg_AddMessageToConsole(routing_id_,
2035 UTF16ToWideHack(message.text),
2036 static_cast<int32>(source_line),
2037 UTF16ToWideHack(source_name)));
2038}
2039
2040void RenderView::printPage(WebFrame* frame) {
[email protected]09285ec2011-03-11 21:04:342041 print_helper_->ScriptInitiatedPrint(frame);
[email protected]48c9cf2d2009-09-16 16:47:522042}
2043
[email protected]3354d3e2010-06-10 19:53:022044WebKit::WebNotificationPresenter* RenderView::notificationPresenter() {
[email protected]676126f72011-01-15 00:03:512045 return notification_provider_;
[email protected]3354d3e2010-06-10 19:53:022046}
2047
[email protected]48c9cf2d2009-09-16 16:47:522048void RenderView::didStartLoading() {
2049 if (is_loading_) {
2050 DLOG(WARNING) << "didStartLoading called while loading";
2051 return;
2052 }
2053
2054 is_loading_ = true;
2055 // Clear the pointer so that we can assign it only when there is an unknown
2056 // plugin on a page.
2057 first_default_plugin_.reset();
2058
2059 Send(new ViewHostMsg_DidStartLoading(routing_id_));
2060}
2061
2062void RenderView::didStopLoading() {
2063 if (!is_loading_) {
2064 DLOG(WARNING) << "DidStopLoading called while not loading";
2065 return;
2066 }
2067
2068 is_loading_ = false;
2069
2070 // NOTE: For now we're doing the safest thing, and sending out notification
2071 // when done loading. This currently isn't an issue as the favicon is only
2072 // displayed when done loading. Ideally we would send notification when
2073 // finished parsing the head, but webkit doesn't support that yet.
2074 // The feed discovery code would also benefit from access to the head.
[email protected]26aa0482009-09-30 16:55:272075 GURL favicon_url(webview()->mainFrame()->favIconURL());
[email protected]48c9cf2d2009-09-16 16:47:522076 if (!favicon_url.is_empty())
[email protected]d8e74e82011-03-15 19:38:482077 Send(new ViewHostMsg_UpdateFaviconURL(routing_id_, page_id_, favicon_url));
[email protected]48c9cf2d2009-09-16 16:47:522078
[email protected]26aa0482009-09-30 16:55:272079 AddGURLSearchProvider(webview()->mainFrame()->openSearchDescriptionURL(),
[email protected]c08e7932011-03-29 04:08:142080 search_provider::AUTODETECTED_PROVIDER);
[email protected]48c9cf2d2009-09-16 16:47:522081
2082 Send(new ViewHostMsg_DidStopLoading(routing_id_));
2083
[email protected]90109412010-12-15 17:14:242084 if (load_progress_tracker_ != NULL)
2085 load_progress_tracker_->DidStopLoading();
2086
[email protected]f9f4841b2010-03-20 05:41:422087 MessageLoop::current()->PostDelayedTask(
2088 FROM_HERE,
[email protected]e47aec52010-08-12 00:50:302089 page_info_method_factory_.NewRunnableMethod(
2090 &RenderView::CapturePageInfo, page_id_, false),
[email protected]5ddfd63e2010-09-01 15:48:372091 send_content_state_immediately_ ? 0 : kDelayForCaptureMs);
[email protected]48c9cf2d2009-09-16 16:47:522092}
2093
[email protected]90109412010-12-15 17:14:242094void RenderView::didChangeLoadProgress(WebFrame* frame, double load_progress) {
2095 if (load_progress_tracker_ != NULL)
2096 load_progress_tracker_->DidChangeLoadProgress(frame, load_progress);
2097}
2098
[email protected]f55039a2010-02-17 14:12:062099bool RenderView::isSmartInsertDeleteEnabled() {
2100#if defined(OS_MACOSX)
2101 return true;
2102#else
2103 return false;
2104#endif
2105}
2106
[email protected]04fc9482009-09-18 22:13:032107bool RenderView::isSelectTrailingWhitespaceEnabled() {
2108#if defined(OS_WIN)
2109 return true;
2110#else
2111 return false;
2112#endif
2113}
2114
[email protected]04fc9482009-09-18 22:13:032115void RenderView::didChangeSelection(bool is_empty_selection) {
[email protected]0ff0ff32010-12-21 19:34:422116#if defined(OS_POSIX)
[email protected]04fc9482009-09-18 22:13:032117 if (!handling_input_event_)
2118 return;
2119 // TODO(estade): investigate incremental updates to the selection so that we
2120 // don't send the entire selection over IPC every time.
2121 if (!is_empty_selection) {
2122 // Sometimes we get repeated didChangeSelection calls from webkit when
2123 // the selection hasn't actually changed. We don't want to report these
2124 // because it will cause us to continually claim the X clipboard.
2125 const std::string& this_selection =
[email protected]26aa0482009-09-30 16:55:272126 webview()->focusedFrame()->selectionAsText().utf8();
[email protected]04fc9482009-09-18 22:13:032127 if (this_selection == last_selection_)
2128 return;
2129
2130 Send(new ViewHostMsg_SelectionChanged(routing_id_,
2131 this_selection));
2132 last_selection_ = this_selection;
2133 } else {
2134 last_selection_.clear();
[email protected]eef99c22010-08-17 05:55:162135 Send(new ViewHostMsg_SelectionChanged(routing_id_,
2136 last_selection_));
[email protected]04fc9482009-09-18 22:13:032137 }
[email protected]0ff0ff32010-12-21 19:34:422138#endif // defined(OS_POSIX)
[email protected]04fc9482009-09-18 22:13:032139}
2140
2141void RenderView::didExecuteCommand(const WebString& command_name) {
[email protected]afe3a1672009-11-17 19:04:122142 const std::string& name = UTF16ToUTF8(command_name);
2143 if (StartsWithASCII(name, "Move", true) ||
2144 StartsWithASCII(name, "Insert", true) ||
2145 StartsWithASCII(name, "Delete", true))
[email protected]04fc9482009-09-18 22:13:032146 return;
2147 UserMetricsRecordAction(name);
2148}
2149
[email protected]54ec7f82010-10-21 22:32:512150void RenderView::SendPendingAccessibilityNotifications() {
2151 if (!accessibility_.get())
2152 return;
2153
2154 if (pending_accessibility_notifications_.empty())
2155 return;
2156
2157 // Send all pending accessibility notifications.
2158 std::vector<ViewHostMsg_AccessibilityNotification_Params> notifications;
2159 for (size_t i = 0; i < pending_accessibility_notifications_.size(); i++) {
2160 RendererAccessibilityNotification& notification =
2161 pending_accessibility_notifications_[i];
2162 WebAccessibilityObject obj = accessibility_->getObjectById(notification.id);
2163 if (!obj.isValid())
2164 continue;
2165
2166 ViewHostMsg_AccessibilityNotification_Params param;
[email protected]a527a022011-02-10 02:32:362167 WebAccessibilityNotificationToViewHostMsg(
2168 pending_accessibility_notifications_[i].type, &param.notification_type);
[email protected]70eee342010-11-05 01:59:372169 param.acc_obj = WebAccessibility(
2170 obj, accessibility_.get(), notification.ShouldIncludeChildren());
[email protected]54ec7f82010-10-21 22:32:512171 notifications.push_back(param);
2172 }
2173 pending_accessibility_notifications_.clear();
2174 Send(new ViewHostMsg_AccessibilityNotifications(routing_id_, notifications));
2175 accessibility_ack_pending_ = true;
2176}
2177
[email protected]b2528b72009-09-24 06:57:102178bool RenderView::handleCurrentKeyboardEvent() {
2179 if (edit_commands_.empty())
2180 return false;
2181
[email protected]26aa0482009-09-30 16:55:272182 WebFrame* frame = webview()->focusedFrame();
[email protected]b2528b72009-09-24 06:57:102183 if (!frame)
2184 return false;
2185
2186 EditCommands::iterator it = edit_commands_.begin();
2187 EditCommands::iterator end = edit_commands_.end();
2188
[email protected]507b33ea2009-09-29 03:56:512189 bool did_execute_command = false;
[email protected]b2528b72009-09-24 06:57:102190 for (; it != end; ++it) {
[email protected]e6e15012009-09-30 14:59:332191 // In gtk and cocoa, it's possible to bind multiple edit commands to one
2192 // key (but it's the exception). Once one edit command is not executed, it
2193 // seems safest to not execute the rest.
[email protected]b2528b72009-09-24 06:57:102194 if (!frame->executeCommand(WebString::fromUTF8(it->name),
2195 WebString::fromUTF8(it->value)))
2196 break;
[email protected]507b33ea2009-09-29 03:56:512197 did_execute_command = true;
[email protected]b2528b72009-09-24 06:57:102198 }
2199
[email protected]507b33ea2009-09-29 03:56:512200 return did_execute_command;
[email protected]b2528b72009-09-24 06:57:102201}
2202
[email protected]a1128322009-10-06 18:38:462203bool RenderView::runFileChooser(
[email protected]01178b52010-01-15 06:59:352204 const WebKit::WebFileChooserParams& params,
[email protected]cdaf8d02010-03-30 19:52:472205 WebFileChooserCompletion* chooser_completion) {
[email protected]7ef03e02010-10-23 11:58:352206 // Do not open the file dialog in a hidden RenderView.
2207 if (is_hidden())
2208 return false;
[email protected]cdaf8d02010-03-30 19:52:472209 ViewHostMsg_RunFileChooser_Params ipc_params;
[email protected]b5977a0c2010-08-24 19:46:262210 if (params.directory)
[email protected]0aed2f52011-03-23 18:06:362211 ipc_params.mode = ViewHostMsg_RunFileChooser_Mode::OpenFolder;
[email protected]b5977a0c2010-08-24 19:46:262212 else if (params.multiSelect)
[email protected]0aed2f52011-03-23 18:06:362213 ipc_params.mode = ViewHostMsg_RunFileChooser_Mode::OpenMultiple;
[email protected]b5977a0c2010-08-24 19:46:262214 else
[email protected]0aed2f52011-03-23 18:06:362215 ipc_params.mode = ViewHostMsg_RunFileChooser_Mode::Open;
[email protected]cdaf8d02010-03-30 19:52:472216 ipc_params.title = params.title;
2217 ipc_params.default_file_name =
2218 webkit_glue::WebStringToFilePath(params.initialValue);
[email protected]099949132010-09-08 20:24:592219 ipc_params.accept_types = params.acceptTypes;
[email protected]cdaf8d02010-03-30 19:52:472220
2221 return ScheduleFileChooser(ipc_params, chooser_completion);
[email protected]a1128322009-10-06 18:38:462222}
2223
[email protected]48c9cf2d2009-09-16 16:47:522224void RenderView::runModalAlertDialog(
2225 WebFrame* frame, const WebString& message) {
[email protected]9dd7e3d72011-01-20 18:27:062226 RunJavaScriptMessage(ui::MessageBoxFlags::kIsJavascriptAlert,
[email protected]48c9cf2d2009-09-16 16:47:522227 UTF16ToWideHack(message),
2228 std::wstring(),
2229 frame->url(),
2230 NULL);
2231}
2232
2233bool RenderView::runModalConfirmDialog(
2234 WebFrame* frame, const WebString& message) {
[email protected]9dd7e3d72011-01-20 18:27:062235 return RunJavaScriptMessage(ui::MessageBoxFlags::kIsJavascriptConfirm,
[email protected]48c9cf2d2009-09-16 16:47:522236 UTF16ToWideHack(message),
2237 std::wstring(),
2238 frame->url(),
2239 NULL);
2240}
2241
2242bool RenderView::runModalPromptDialog(
2243 WebFrame* frame, const WebString& message, const WebString& default_value,
2244 WebString* actual_value) {
2245 std::wstring result;
[email protected]9dd7e3d72011-01-20 18:27:062246 bool ok = RunJavaScriptMessage(ui::MessageBoxFlags::kIsJavascriptPrompt,
[email protected]48c9cf2d2009-09-16 16:47:522247 UTF16ToWideHack(message),
2248 UTF16ToWideHack(default_value),
2249 frame->url(),
2250 &result);
2251 if (ok)
2252 actual_value->assign(WideToUTF16Hack(result));
2253 return ok;
2254}
2255
2256bool RenderView::runModalBeforeUnloadDialog(
2257 WebFrame* frame, const WebString& message) {
2258 bool success = false;
2259 // This is an ignored return value, but is included so we can accept the same
2260 // response as RunJavaScriptMessage.
2261 std::wstring ignored_result;
[email protected]12636df2009-09-28 22:32:212262 SendAndRunNestedMessageLoop(new ViewHostMsg_RunBeforeUnloadConfirm(
[email protected]48c9cf2d2009-09-16 16:47:522263 routing_id_, frame->url(), UTF16ToWideHack(message), &success,
[email protected]12636df2009-09-28 22:32:212264 &ignored_result));
[email protected]48c9cf2d2009-09-16 16:47:522265 return success;
2266}
2267
[email protected]79e37442009-10-09 18:17:442268void RenderView::showContextMenu(
2269 WebFrame* frame, const WebContextMenuData& data) {
[email protected]c27324b2009-11-19 22:44:292270 ContextMenuParams params = ContextMenuParams(data);
2271 if (!params.misspelled_word.empty() && RenderThread::current()) {
2272 int misspelled_offset, misspelled_length;
[email protected]c76a36a2010-01-26 22:44:042273 bool spelled_right = RenderThread::current()->spellchecker()->
2274 SpellCheckWord(
2275 params.misspelled_word.c_str(), params.misspelled_word.size(),
[email protected]11fee2332011-03-29 20:36:352276 spellcheck_provider_->document_tag(),
[email protected]c76a36a2010-01-26 22:44:042277 &misspelled_offset, &misspelled_length,
2278 &params.dictionary_suggestions);
2279 if (spelled_right)
[email protected]c27324b2009-11-19 22:44:292280 params.misspelled_word.clear();
2281 }
[email protected]db803aae2011-03-05 02:00:422282 // Serializing a GURL longer than content::kMaxURLChars will fail, so don't do
[email protected]216932c2010-08-26 21:44:272283 // it. We replace it with an empty GURL so the appropriate items are disabled
2284 // in the context menu.
2285 // TODO(jcivelli): http://crbug.com/45160 This prevents us from saving large
2286 // data encoded images. We should have a way to save them.
[email protected]db803aae2011-03-05 02:00:422287 if (params.src_url.spec().size() > content::kMaxURLChars)
[email protected]216932c2010-08-26 21:44:272288 params.src_url = GURL();
[email protected]521b2482011-01-15 00:10:102289 context_menu_node_ = data.node;
[email protected]c27324b2009-11-19 22:44:292290 Send(new ViewHostMsg_ContextMenu(routing_id_, params));
[email protected]79e37442009-10-09 18:17:442291}
2292
[email protected]52f139e2c2010-06-11 16:56:092293bool RenderView::supportsFullscreen() {
2294 return CommandLine::ForCurrentProcess()->HasSwitch(
2295 switches::kEnableVideoFullscreen);
2296}
2297
2298void RenderView::enterFullscreenForNode(const WebKit::WebNode& node) {
2299 NOTIMPLEMENTED();
2300}
2301
2302void RenderView::exitFullscreenForNode(const WebKit::WebNode& node) {
2303 NOTIMPLEMENTED();
2304}
2305
[email protected]48c9cf2d2009-09-16 16:47:522306void RenderView::setStatusText(const WebString& text) {
2307}
2308
[email protected]163f8242009-10-30 20:19:552309void RenderView::UpdateTargetURL(const GURL& url, const GURL& fallback_url) {
[email protected]aa6b90b32010-04-26 15:49:582310 GURL latest_url = url.is_empty() ? fallback_url : url;
[email protected]48c9cf2d2009-09-16 16:47:522311 if (latest_url == target_url_)
2312 return;
[email protected]163f8242009-10-30 20:19:552313
[email protected]48c9cf2d2009-09-16 16:47:522314 // Tell the browser to display a destination link.
2315 if (target_url_status_ == TARGET_INFLIGHT ||
2316 target_url_status_ == TARGET_PENDING) {
2317 // If we have a request in-flight, save the URL to be sent when we
2318 // receive an ACK to the in-flight request. We can happily overwrite
2319 // any existing pending sends.
2320 pending_target_url_ = latest_url;
2321 target_url_status_ = TARGET_PENDING;
2322 } else {
2323 Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_, latest_url));
2324 target_url_ = latest_url;
2325 target_url_status_ = TARGET_INFLIGHT;
2326 }
2327}
2328
[email protected]13a1e4c3c2011-02-03 21:07:092329void RenderView::UpdateToggleSpellCheckCommandState() {
2330 bool is_enabled = false;
2331 WebKit::WebNode node = GetFocusedNode();
2332 if (!node.isNull())
2333 is_enabled = IsEditableNode(node);
2334
2335 RenderViewCommandCheckedState checked_state =
2336 RENDER_VIEW_COMMAND_CHECKED_STATE_UNCHECKED;
2337 if (is_enabled && webview()) {
2338 WebFrame* frame = webview()->focusedFrame();
2339 if (frame->isContinuousSpellCheckingEnabled())
2340 checked_state = RENDER_VIEW_COMMAND_CHECKED_STATE_CHECKED;
2341 }
2342
2343 Send(new ViewHostMsg_CommandStateChanged(
2344 routing_id_,
2345 RENDER_VIEW_COMMAND_TOGGLE_SPELL_CHECK,
2346 is_enabled,
2347 checked_state));
2348}
2349
[email protected]882daa92009-11-05 16:31:312350void RenderView::StartNavStateSyncTimerIfNecessary() {
2351 int delay;
2352 if (send_content_state_immediately_)
2353 delay = 0;
2354 else if (is_hidden())
2355 delay = kDelaySecondsForContentStateSyncHidden;
2356 else
2357 delay = kDelaySecondsForContentStateSync;
2358
2359 if (nav_state_sync_timer_.IsRunning()) {
2360 // The timer is already running. If the delay of the timer maches the amount
2361 // we want to delay by, then return. Otherwise stop the timer so that it
2362 // gets started with the right delay.
2363 if (nav_state_sync_timer_.GetCurrentDelay().InSeconds() == delay)
2364 return;
2365 nav_state_sync_timer_.Stop();
2366 }
2367
2368 nav_state_sync_timer_.Start(
2369 TimeDelta::FromSeconds(delay), this, &RenderView::SyncNavigationState);
2370}
2371
[email protected]163f8242009-10-30 20:19:552372void RenderView::setMouseOverURL(const WebURL& url) {
2373 mouse_over_url_ = GURL(url);
2374 UpdateTargetURL(mouse_over_url_, focus_url_);
2375}
2376
2377void RenderView::setKeyboardFocusURL(const WebURL& url) {
2378 focus_url_ = GURL(url);
2379 UpdateTargetURL(focus_url_, mouse_over_url_);
2380}
2381
[email protected]48c9cf2d2009-09-16 16:47:522382void RenderView::setToolTipText(const WebString& text, WebTextDirection hint) {
2383 Send(new ViewHostMsg_SetTooltipText(routing_id_, UTF16ToWideHack(text),
2384 hint));
2385}
2386
[email protected]c27ae592010-03-18 15:24:412387void RenderView::startDragging(const WebDragData& data,
2388 WebDragOperationsMask mask,
2389 const WebImage& image,
2390 const WebPoint& imageOffset) {
2391#if WEBKIT_USING_SKIA
2392 SkBitmap bitmap(image.getSkBitmap());
2393#elif WEBKIT_USING_CG
[email protected]78043bdd2010-04-05 18:45:332394 SkBitmap bitmap = gfx::CGImageToSkBitmap(image.getCGImageRef());
[email protected]c27ae592010-03-18 15:24:412395#endif
2396
[email protected]59f4f2fa2011-03-23 01:00:552397 Send(new DragHostMsg_StartDragging(routing_id_,
[email protected]48c9cf2d2009-09-16 16:47:522398 WebDropData(data),
[email protected]c27ae592010-03-18 15:24:412399 mask,
2400 bitmap,
2401 imageOffset));
[email protected]48c9cf2d2009-09-16 16:47:522402}
2403
[email protected]28b92df2009-09-25 17:35:452404bool RenderView::acceptsLoadDrops() {
2405 return renderer_preferences_.can_accept_load_drops;
2406}
2407
[email protected]48c9cf2d2009-09-16 16:47:522408void RenderView::focusNext() {
2409 Send(new ViewHostMsg_TakeFocus(routing_id_, false));
2410}
2411
2412void RenderView::focusPrevious() {
2413 Send(new ViewHostMsg_TakeFocus(routing_id_, true));
2414}
2415
[email protected]08e9e132010-06-01 16:58:492416void RenderView::focusedNodeChanged(const WebNode& node) {
[email protected]9b66f34bf2010-10-27 20:45:512417 Send(new ViewHostMsg_FocusedNodeChanged(routing_id_, IsEditableNode(node)));
[email protected]a4b103b2010-10-05 18:46:072418
2419 if (WebAccessibilityCache::accessibilityEnabled() && node.isNull()) {
2420 // TODO(ctguil): Make WebKit send this notification.
2421 // When focus is cleared notify accessibility that the document is focused.
2422 postAccessibilityNotification(
2423 webview()->accessibilityObject(),
2424 WebKit::WebAccessibilityNotificationFocusedUIElementChanged);
2425 }
[email protected]13a1e4c3c2011-02-03 21:07:092426
2427 UpdateToggleSpellCheckCommandState();
[email protected]08e9e132010-06-01 16:58:492428}
2429
[email protected]48c9cf2d2009-09-16 16:47:522430void RenderView::navigateBackForwardSoon(int offset) {
[email protected]48c9cf2d2009-09-16 16:47:522431 Send(new ViewHostMsg_GoToEntryAtOffset(routing_id_, offset));
2432}
2433
2434int RenderView::historyBackListCount() {
[email protected]3cc72b12010-03-18 23:03:002435 return history_list_offset_ < 0 ? 0 : history_list_offset_;
[email protected]48c9cf2d2009-09-16 16:47:522436}
2437
2438int RenderView::historyForwardListCount() {
[email protected]3cc72b12010-03-18 23:03:002439 return history_list_length_ - historyBackListCount() - 1;
[email protected]48c9cf2d2009-09-16 16:47:522440}
2441
[email protected]c4e98902010-06-01 10:20:142442void RenderView::didUpdateInspectorSetting(const WebString& key,
2443 const WebString& value) {
2444 Send(new ViewHostMsg_UpdateInspectorSetting(routing_id_,
2445 key.utf8(),
2446 value.utf8()));
[email protected]8922e1f2009-10-03 05:01:262447}
2448
[email protected]79dbc662009-09-04 05:42:512449// WebKit::WebWidgetClient ----------------------------------------------------
2450
[email protected]ea42e7782010-08-23 23:58:122451void RenderView::didFocus() {
2452 // TODO(jcivelli): when https://bugs.webkit.org/show_bug.cgi?id=33389 is fixed
2453 // we won't have to test for user gesture anymore and we can
2454 // move that code back to render_widget.cc
2455 if (webview() && webview()->mainFrame() &&
2456 webview()->mainFrame()->isProcessingUserGesture()) {
2457 Send(new ViewHostMsg_Focus(routing_id_));
2458 }
2459}
2460
2461void RenderView::didBlur() {
2462 // TODO(jcivelli): see TODO above in didFocus().
2463 if (webview() && webview()->mainFrame() &&
2464 webview()->mainFrame()->isProcessingUserGesture()) {
2465 Send(new ViewHostMsg_Blur(routing_id_));
2466 }
2467}
2468
initial.commit09911bf2008-07-26 23:55:292469// We are supposed to get a single call to Show for a newly created RenderView
2470// that was created via RenderView::CreateWebView. So, we wait until this
2471// point to dispatch the ShowView message.
2472//
2473// This method provides us with the information about how to display the newly
2474// created RenderView (i.e., as a constrained popup or as a new tab).
2475//
[email protected]4873c7d2009-07-16 06:36:282476void RenderView::show(WebNavigationPolicy policy) {
initial.commit09911bf2008-07-26 23:55:292477 DCHECK(!did_show_) << "received extraneous Show call";
2478 DCHECK(opener_id_ != MSG_ROUTING_NONE);
2479
2480 if (did_show_)
2481 return;
2482 did_show_ = true;
2483
[email protected]6779aa12011-03-29 17:32:242484 if (content::GetContentClient()->renderer()->AllowPopup(creator_url_))
[email protected]4026ce1e2010-09-14 19:35:042485 opened_by_user_gesture_ = true;
[email protected]4026ce1e2010-09-14 19:35:042486
[email protected]28295ec2009-10-16 05:34:332487 // Force new windows to a popup if they were not opened with a user gesture.
2488 if (!opened_by_user_gesture_) {
2489 // We exempt background tabs for compat with older versions of Chrome.
2490 // TODO(darin): This seems bogus. These should have a user gesture, so
2491 // we probably don't need this check.
2492 if (policy != WebKit::WebNavigationPolicyNewBackgroundTab)
2493 policy = WebKit::WebNavigationPolicyNewPopup;
2494 }
2495
initial.commit09911bf2008-07-26 23:55:292496 // NOTE: initial_pos_ may still have its default values at this point, but
2497 // that's okay. It'll be ignored if disposition is not NEW_POPUP, or the
2498 // browser process will impose a default position otherwise.
[email protected]4873c7d2009-07-16 06:36:282499 Send(new ViewHostMsg_ShowView(opener_id_, routing_id_,
2500 NavigationPolicyToDisposition(policy), initial_pos_,
[email protected]7e7414ae2010-01-26 20:19:292501 opened_by_user_gesture_));
[email protected]2533ce12009-05-09 00:02:242502 SetPendingWindowRect(initial_pos_);
initial.commit09911bf2008-07-26 23:55:292503}
2504
[email protected]4873c7d2009-07-16 06:36:282505void RenderView::runModal() {
initial.commit09911bf2008-07-26 23:55:292506 DCHECK(did_show_) << "should already have shown the view";
2507
[email protected]c1f50aa2010-02-18 03:46:572508 // We must keep WebKit's shared timer running in this case in order to allow
2509 // showModalDialog to function properly.
2510 //
2511 // TODO(darin): WebKit should really be smarter about suppressing events and
2512 // timers so that we do not need to manage the shared timer in such a heavy
2513 // handed manner.
2514 //
2515 if (RenderThread::current()) // Will be NULL during unit tests.
2516 RenderThread::current()->DoNotSuspendWebKitSharedTimer();
2517
[email protected]12636df2009-09-28 22:32:212518 SendAndRunNestedMessageLoop(new ViewHostMsg_RunModal(routing_id_));
initial.commit09911bf2008-07-26 23:55:292519}
2520
[email protected]3d9689372009-09-10 04:29:172521// WebKit::WebFrameClient -----------------------------------------------------
2522
[email protected]00152e92010-07-19 11:47:402523WebPlugin* RenderView::createPlugin(WebFrame* frame,
2524 const WebPluginParams& params) {
[email protected]e7c21b812011-03-19 18:03:302525 return content::GetContentClient()->renderer()->CreatePlugin(
[email protected]21d61e52011-03-18 19:08:252526 this, frame, params);
[email protected]3d9689372009-09-10 04:29:172527}
2528
2529WebWorker* RenderView::createWorker(WebFrame* frame, WebWorkerClient* client) {
[email protected]14396e92010-05-06 20:40:562530 WebApplicationCacheHostImpl* appcache_host =
2531 WebApplicationCacheHostImpl::FromFrame(frame);
2532 int appcache_host_id = appcache_host ? appcache_host->host_id() : 0;
2533 return new WebWorkerProxy(client, RenderThread::current(), routing_id_,
2534 appcache_host_id);
[email protected]3d9689372009-09-10 04:29:172535}
2536
[email protected]9c00f002009-11-05 22:37:422537WebSharedWorker* RenderView::createSharedWorker(
2538 WebFrame* frame, const WebURL& url, const WebString& name,
[email protected]30447b62009-11-13 01:13:372539 unsigned long long document_id) {
[email protected]9c00f002009-11-05 22:37:422540
[email protected]30447b62009-11-13 01:13:372541 int route_id = MSG_ROUTING_NONE;
[email protected]6de0bcf2010-02-17 22:00:512542 bool exists = false;
[email protected]30447b62009-11-13 01:13:372543 bool url_mismatch = false;
[email protected]6de0bcf2010-02-17 22:00:512544 ViewHostMsg_CreateWorker_Params params;
2545 params.url = url;
2546 params.is_shared = true;
2547 params.name = name;
2548 params.document_id = document_id;
2549 params.render_view_route_id = routing_id_;
2550 params.route_id = MSG_ROUTING_NONE;
[email protected]f9bc9c02010-05-24 19:19:232551 params.parent_appcache_host_id = 0;
2552 params.script_resource_appcache_id = 0;
[email protected]30447b62009-11-13 01:13:372553 Send(new ViewHostMsg_LookupSharedWorker(
[email protected]6de0bcf2010-02-17 22:00:512554 params, &exists, &route_id, &url_mismatch));
[email protected]30447b62009-11-13 01:13:372555 if (url_mismatch) {
2556 return NULL;
2557 } else {
2558 return new WebSharedWorkerProxy(RenderThread::current(),
[email protected]0791d3a2010-01-28 01:28:492559 document_id,
[email protected]6de0bcf2010-02-17 22:00:512560 exists,
[email protected]30447b62009-11-13 01:13:372561 route_id,
2562 routing_id_);
2563 }
[email protected]9c00f002009-11-05 22:37:422564}
2565
[email protected]3d9689372009-09-10 04:29:172566WebMediaPlayer* RenderView::createMediaPlayer(
2567 WebFrame* frame, WebMediaPlayerClient* client) {
[email protected]f78d1dfc2011-01-15 07:09:272568 scoped_ptr<media::MessageLoopFactory> message_loop_factory(
2569 new media::MessageLoopFactoryImpl());
[email protected]f8db8132010-12-03 00:27:492570 scoped_ptr<media::FilterCollection> collection(
2571 new media::FilterCollection());
[email protected]457d8342010-10-23 01:20:372572
[email protected]3d9689372009-09-10 04:29:172573 // Add in any custom filter factories first.
2574 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
2575 if (!cmd_line->HasSwitch(switches::kDisableAudio)) {
2576 // Add the chrome specific audio renderer.
[email protected]b7ba5b52010-11-15 22:04:492577 collection->AddAudioRenderer(new AudioRendererImpl(audio_message_filter()));
[email protected]3d9689372009-09-10 04:29:172578 }
2579
[email protected]3bb08602010-10-07 21:47:172580 if (cmd_line->HasSwitch(switches::kEnableAcceleratedDecoding) &&
[email protected]11c4c812010-10-22 19:50:122581 !cmd_line->HasSwitch(switches::kDisableAcceleratedCompositing)) {
[email protected]5aa6a312010-11-06 00:00:072582 WebGraphicsContext3DCommandBufferImpl* context =
2583 static_cast<WebGraphicsContext3DCommandBufferImpl*>(
2584 frame->view()->graphicsContext3D());
2585 if (!context)
2586 return NULL;
[email protected]a9a43012010-11-05 01:54:062587
[email protected]5aa6a312010-11-06 00:00:072588 // Add the hardware video decoder factory.
2589 // TODO(hclam): This will cause the renderer process to crash on context
2590 // lost.
2591 bool ret = context->makeContextCurrent();
2592 CHECK(ret) << "Failed to switch context";
[email protected]b7ba5b52010-11-15 22:04:492593 collection->AddVideoDecoder(new IpcVideoDecoder(
[email protected]5aa6a312010-11-06 00:00:072594 MessageLoop::current(), context->context()));
[email protected]3bb08602010-10-07 21:47:172595 }
2596
[email protected]457d8342010-10-23 01:20:372597 scoped_refptr<webkit_glue::WebVideoRenderer> video_renderer;
[email protected]77128dec2010-11-08 17:05:312598 bool pts_logging = cmd_line->HasSwitch(switches::kEnableVideoLogging);
2599 scoped_refptr<webkit_glue::VideoRendererImpl> renderer(
2600 new webkit_glue::VideoRendererImpl(pts_logging));
[email protected]b7ba5b52010-11-15 22:04:492601 collection->AddVideoRenderer(renderer);
[email protected]77128dec2010-11-08 17:05:312602 video_renderer = renderer;
[email protected]8400e032010-02-26 18:50:112603
[email protected]a8e24d522010-12-01 07:13:582604 scoped_ptr<webkit_glue::WebMediaPlayerImpl> result(
[email protected]f78d1dfc2011-01-15 07:09:272605 new webkit_glue::WebMediaPlayerImpl(client,
2606 collection.release(),
2607 message_loop_factory.release()));
[email protected]79684282010-12-06 21:15:462608 if (!result->Initialize(frame,
[email protected]a8e24d522010-12-01 07:13:582609 cmd_line->HasSwitch(switches::kSimpleDataSource),
2610 video_renderer)) {
2611 return NULL;
2612 }
2613 return result.release();
[email protected]3d9689372009-09-10 04:29:172614}
2615
[email protected]035545f2010-04-09 13:10:212616WebApplicationCacheHost* RenderView::createApplicationCacheHost(
2617 WebFrame* frame, WebApplicationCacheHostClient* client) {
2618 return new RendererWebApplicationCacheHostImpl(
2619 FromWebView(frame->view()), client,
2620 RenderThread::current()->appcache_dispatcher()->backend_proxy());
2621}
2622
[email protected]8ff181072010-11-29 17:09:382623WebCookieJar* RenderView::cookieJar(WebFrame* frame) {
2624 return &cookie_jar_;
2625}
2626
[email protected]5041f982010-08-11 21:40:452627void RenderView::frameDetached(WebFrame* frame) {
[email protected]676126f72011-01-15 00:03:512628 FOR_EACH_OBSERVER(RenderViewObserver, observers_, FrameDetached(frame));
[email protected]5041f982010-08-11 21:40:452629}
2630
[email protected]3d9689372009-09-10 04:29:172631void RenderView::willClose(WebFrame* frame) {
[email protected]a5a65ac2010-11-05 18:14:362632 page_load_histograms_.Dump(frame);
[email protected]f3ce0a32011-01-11 08:18:182633
[email protected]676126f72011-01-15 00:03:512634 FOR_EACH_OBSERVER(RenderViewObserver, observers_, FrameWillClose(frame));
[email protected]3d9689372009-09-10 04:29:172635}
2636
[email protected]684e4a42010-01-30 06:44:112637bool RenderView::allowImages(WebFrame* frame, bool enabled_per_settings) {
[email protected]12bc8472010-04-15 07:29:402638 if (enabled_per_settings &&
2639 AllowContentType(CONTENT_SETTINGS_TYPE_IMAGES))
2640 return true;
2641
2642 if (IsWhitelistedForContentSettings(frame))
2643 return true;
2644
[email protected]55126132010-08-19 14:53:282645 DidBlockContentType(CONTENT_SETTINGS_TYPE_IMAGES, std::string());
[email protected]12bc8472010-04-15 07:29:402646 return false; // Other protocols fall through here.
[email protected]684e4a42010-01-30 06:44:112647}
2648
[email protected]d5f9e4f2010-07-28 08:31:302649bool RenderView::allowPlugins(WebFrame* frame, bool enabled_per_settings) {
[email protected]3627b06d2010-11-12 16:36:162650 return WebFrameClient::allowPlugins(frame, enabled_per_settings);
[email protected]d5f9e4f2010-07-28 08:31:302651}
2652
[email protected]3d9689372009-09-10 04:29:172653void RenderView::loadURLExternally(
2654 WebFrame* frame, const WebURLRequest& request,
2655 WebNavigationPolicy policy) {
[email protected]efce17b2009-09-11 18:04:592656 GURL referrer(request.httpHeaderField(WebString::fromUTF8("Referer")));
2657 if (policy == WebKit::WebNavigationPolicyDownload) {
2658 Send(new ViewHostMsg_DownloadUrl(routing_id_, request.url(), referrer));
2659 } else {
2660 OpenURL(request.url(), referrer, policy);
2661 }
[email protected]3d9689372009-09-10 04:29:172662}
2663
2664WebNavigationPolicy RenderView::decidePolicyForNavigation(
2665 WebFrame* frame, const WebURLRequest& request, WebNavigationType type,
[email protected]65b95cd2009-10-09 05:10:222666 const WebNode&, WebNavigationPolicy default_policy, bool is_redirect) {
[email protected]3d9689372009-09-10 04:29:172667 // Webkit is asking whether to navigate to a new URL.
2668 // This is fine normally, except if we're showing UI from one security
2669 // context and they're trying to navigate to a different context.
2670 const GURL& url = request.url();
2671
2672 // If the browser is interested, then give it a chance to look at top level
[email protected]3a8eecb2010-04-22 23:56:302673 // navigations.
[email protected]8079b362010-05-07 18:37:452674 if (renderer_preferences_.browser_handles_top_level_requests &&
2675 IsNonLocalTopLevelNavigation(url, frame, type)) {
[email protected]61c9f032010-03-31 23:04:192676 GURL referrer(request.httpHeaderField(WebString::fromUTF8("Referer")));
[email protected]a58db8b2010-08-24 01:51:232677 // Reset these counters as the RenderView could be reused for the next
2678 // navigation.
2679 page_id_ = -1;
[email protected]a58db8b2010-08-24 01:51:232680 last_page_id_sent_to_browser_ = -1;
[email protected]61c9f032010-03-31 23:04:192681 OpenURL(url, referrer, default_policy);
2682 return WebKit::WebNavigationPolicyIgnore; // Suppress the load here.
[email protected]3d9689372009-09-10 04:29:172683 }
2684
2685 // A content initiated navigation may have originated from a link-click,
2686 // script, drag-n-drop operation, etc.
2687 bool is_content_initiated =
2688 NavigationState::FromDataSource(frame->provisionalDataSource())->
2689 is_content_initiated();
[email protected]a6b960ad972010-09-01 19:53:582690 GURL old_url(frame->url());
[email protected]3d9689372009-09-10 04:29:172691
[email protected]6101c342010-12-16 22:44:372692 // Detect when we're crossing a permission-based boundary (e.g. into or out of
[email protected]c39f9bf2011-02-12 00:43:552693 // an extension or app origin, leaving a WebUI page, etc). We only care about
[email protected]8f4da8c2011-02-09 19:49:572694 // top-level navigations within the current tab (as opposed to, for example,
[email protected]6101c342010-12-16 22:44:372695 // opening a new window). But we sometimes navigate to about:blank to clear a
2696 // tab, and we want to still allow that.
2697 //
[email protected]8f4da8c2011-02-09 19:49:572698 // Note: we do this only for GET requests because our mechanism for switching
2699 // processes only issues GET requests. In particular, POST requests don't
2700 // work, because this mechanism does not preserve form POST data. If it
2701 // becomes necessary to support process switching for POST requests, we will
2702 // need to send the request's httpBody data up to the browser process, and
2703 // issue a special POST navigation in WebKit (via
2704 // FrameLoader::loadFrameRequest). See ResourceDispatcher and WebURLLoaderImpl
2705 // for examples of how to send the httpBody data.
2706 // Note2: We normally don't do this for browser-initiated navigations, since
2707 // it's pointless to tell the browser about navigations it gave us. But
2708 // we do potentially ask the browser to handle a redirect that was originally
2709 // initiated by the browser. See http://crbug.com/70943
2710 //
2711 // TODO(creis): Move this redirect check to the browser process to avoid
2712 // ping-ponging. See http://crbug.com/72380.
2713 if (!frame->parent() && (is_content_initiated || is_redirect) &&
[email protected]6101c342010-12-16 22:44:372714 default_policy == WebKit::WebNavigationPolicyCurrentTab &&
2715 request.httpMethod() == "GET" && !url.SchemeIs(chrome::kAboutScheme)) {
2716 bool send_referrer = false;
2717 bool should_fork =
[email protected]c09163a2011-02-15 00:05:552718 BindingsPolicy::is_web_ui_enabled(enabled_bindings_) ||
[email protected]3d9689372009-09-10 04:29:172719 frame->isViewSourceModeEnabled() ||
[email protected]6101c342010-12-16 22:44:372720 url.SchemeIs(chrome::kViewSourceScheme);
[email protected]5351dbc2010-08-27 15:22:112721
2722 // If the navigation would cross an app extent boundary, we also need
2723 // to defer to the browser to ensure process isolation.
2724 // TODO(erikkay) This is happening inside of a check to is_content_initiated
2725 // which means that things like the back button won't trigger it. Is that
2726 // OK?
[email protected]88c15e972011-02-05 04:19:532727 // TODO(creis): For hosted apps, we currently only swap processes to enter
2728 // the app and not exit it, since we currently lose context (e.g.,
2729 // window.opener) if the window navigates back. See crbug.com/65953.
[email protected]2a521c52011-01-26 18:45:212730 if (!should_fork &&
[email protected]88c15e972011-02-05 04:19:532731 CrossesExtensionExtents(
[email protected]6779aa12011-03-29 17:32:242732 ExtensionDispatcher::Get()->extensions(), frame, url)) {
[email protected]5351dbc2010-08-27 15:22:112733 // Include the referrer in this case since we're going from a hosted web
2734 // page. (the packaged case is handled previously by the extension
2735 // navigation test)
[email protected]6101c342010-12-16 22:44:372736 should_fork = true;
2737 send_referrer = true;
[email protected]46fd1ea42011-02-16 15:59:332738
2739 if (is_content_initiated) {
2740 const Extension* extension =
[email protected]6779aa12011-03-29 17:32:242741 ExtensionDispatcher::Get()->extensions()->GetByURL(url);
[email protected]46fd1ea42011-02-16 15:59:332742 if (extension && extension->is_app()) {
2743 UMA_HISTOGRAM_ENUMERATION(
2744 extension_misc::kAppLaunchHistogram,
2745 extension_misc::APP_LAUNCH_CONTENT_NAVIGATION,
2746 extension_misc::APP_LAUNCH_BUCKET_BOUNDARY);
2747 }
2748 }
[email protected]6101c342010-12-16 22:44:372749 }
2750
2751 if (should_fork) {
[email protected]5351dbc2010-08-27 15:22:112752 GURL referrer(request.httpHeaderField(WebString::fromUTF8("Referer")));
[email protected]6101c342010-12-16 22:44:372753 OpenURL(url, send_referrer ? referrer : GURL(), default_policy);
[email protected]5351dbc2010-08-27 15:22:112754 return WebKit::WebNavigationPolicyIgnore; // Suppress the load here.
2755 }
[email protected]3d9689372009-09-10 04:29:172756 }
2757
2758 // Detect when a page is "forking" a new tab that can be safely rendered in
2759 // its own process. This is done by sites like Gmail that try to open links
2760 // in new windows without script connections back to the original page. We
2761 // treat such cases as browser navigations (in which we will create a new
2762 // renderer for a cross-site navigation), rather than WebKit navigations.
2763 //
2764 // We use the following heuristic to decide whether to fork a new page in its
2765 // own process:
2766 // The parent page must open a new tab to about:blank, set the new tab's
2767 // window.opener to null, and then redirect the tab to a cross-site URL using
2768 // JavaScript.
[email protected]007a848b2009-10-26 15:55:462769 //
2770 // TODO(creis): Deprecate this logic once we can rely on rel=noreferrer
2771 // (see below).
[email protected]3d9689372009-09-10 04:29:172772 bool is_fork =
2773 // Must start from a tab showing about:blank, which is later redirected.
[email protected]a6b960ad972010-09-01 19:53:582774 old_url == GURL(chrome::kAboutBlankURL) &&
[email protected]3d9689372009-09-10 04:29:172775 // Must be the first real navigation of the tab.
[email protected]48c9cf2d2009-09-16 16:47:522776 historyBackListCount() < 1 &&
2777 historyForwardListCount() < 1 &&
[email protected]3d9689372009-09-10 04:29:172778 // The parent page must have set the child's window.opener to null before
2779 // redirecting to the desired URL.
2780 frame->opener() == NULL &&
2781 // Must be a top-level frame.
2782 frame->parent() == NULL &&
2783 // Must not have issued the request from this page.
2784 is_content_initiated &&
2785 // Must be targeted at the current tab.
2786 default_policy == WebKit::WebNavigationPolicyCurrentTab &&
2787 // Must be a JavaScript navigation, which appears as "other".
2788 type == WebKit::WebNavigationTypeOther;
[email protected]007a848b2009-10-26 15:55:462789
2790 // Recognize if this navigation is from a link with rel=noreferrer and
2791 // target=_blank attributes, in which case the opener will be suppressed. If
2792 // so, it is safe to load cross-site pages in a separate process, so we
2793 // should let the browser handle it.
2794 bool is_noreferrer_and_blank_target =
2795 // Frame should be top level and not yet navigated.
2796 frame->parent() == NULL &&
2797 frame->url().isEmpty() &&
2798 historyBackListCount() < 1 &&
2799 historyForwardListCount() < 1 &&
2800 // Links with rel=noreferrer will have no Referer field, and their
2801 // resulting frame will have its window.opener suppressed.
2802 // TODO(creis): should add a request.httpReferrer() method to help avoid
2803 // typos on the unusual spelling of Referer.
2804 request.httpHeaderField(WebString::fromUTF8("Referer")).isNull() &&
2805 opener_suppressed_ &&
2806 frame->opener() == NULL &&
2807 // Links with target=_blank will have no name.
2808 frame->name().isNull() &&
2809 // Another frame (with a non-empty creator) should have initiated the
2810 // request, targeted at this frame.
2811 !creator_url_.is_empty() &&
2812 is_content_initiated &&
2813 default_policy == WebKit::WebNavigationPolicyCurrentTab &&
2814 type == WebKit::WebNavigationTypeOther;
2815
2816 if (is_fork || is_noreferrer_and_blank_target) {
[email protected]3d9689372009-09-10 04:29:172817 // Open the URL via the browser, not via WebKit.
2818 OpenURL(url, GURL(), default_policy);
2819 return WebKit::WebNavigationPolicyIgnore;
2820 }
2821
2822 return default_policy;
2823}
2824
[email protected]6069da8c2009-10-20 20:33:492825bool RenderView::canHandleRequest(
2826 WebFrame* frame, const WebURLRequest& request) {
2827 // We allow WebKit to think that everything can be handled even though
2828 // browser-side we limit what we load.
[email protected]7b7a7dc2009-10-19 02:23:342829 return true;
2830}
2831
[email protected]6069da8c2009-10-20 20:33:492832WebURLError RenderView::cannotHandleRequestError(
2833 WebFrame* frame, const WebURLRequest& request) {
2834 NOTREACHED(); // Since we said we can handle all requests.
2835 return WebURLError();
2836}
2837
2838WebURLError RenderView::cancelledError(
2839 WebFrame* frame, const WebURLRequest& request) {
2840 WebURLError error;
2841 error.domain = WebString::fromUTF8(net::kErrorDomain);
2842 error.reason = net::ERR_ABORTED;
2843 error.unreachableURL = request.url();
2844 return error;
[email protected]7b7a7dc2009-10-19 02:23:342845}
2846
2847void RenderView::unableToImplementPolicyWithError(
[email protected]6069da8c2009-10-20 20:33:492848 WebFrame*, const WebURLError&) {
2849 NOTREACHED(); // Since we said we can handle all requests.
[email protected]7b7a7dc2009-10-19 02:23:342850}
2851
[email protected]90eeddb2010-05-06 21:06:432852void RenderView::willSendSubmitEvent(WebKit::WebFrame* frame,
2853 const WebKit::WebFormElement& form) {
2854 // Some login forms have onSubmit handlers that put a hash of the password
2855 // into a hidden field and then clear the password. (Issue 28910.)
2856 // This method gets called before any of those handlers run, so save away
2857 // a copy of the password in case it gets lost.
2858 NavigationState* navigation_state =
2859 NavigationState::FromDataSource(frame->dataSource());
2860 navigation_state->set_password_form_data(
2861 PasswordFormDomManager::CreatePasswordForm(form));
2862}
2863
[email protected]979c28b2009-11-07 01:30:482864void RenderView::willSubmitForm(WebFrame* frame, const WebFormElement& form) {
[email protected]3d9689372009-09-10 04:29:172865 NavigationState* navigation_state =
2866 NavigationState::FromDataSource(frame->provisionalDataSource());
2867
2868 if (navigation_state->transition_type() == PageTransition::LINK)
2869 navigation_state->set_transition_type(PageTransition::FORM_SUBMIT);
2870
2871 // Save these to be processed when the ensuing navigation is committed.
[email protected]ce0e250d2009-10-23 21:00:352872 WebSearchableFormData web_searchable_form_data(form);
2873 navigation_state->set_searchable_form_url(web_searchable_form_data.url());
2874 navigation_state->set_searchable_form_encoding(
[email protected]b7910b3a2010-01-13 18:33:212875 web_searchable_form_data.encoding().utf8());
[email protected]90eeddb2010-05-06 21:06:432876 PasswordForm* password_form_data =
2877 PasswordFormDomManager::CreatePasswordForm(form);
2878 navigation_state->set_password_form_data(password_form_data);
2879
2880 // If the password has been cleared, recover it from the form contents already
2881 // stored by willSendSubmitEvent into the dataSource's NavigationState (as
2882 // opposed to the provisionalDataSource's, which is what we're storing into
2883 // now.)
2884 if (password_form_data && password_form_data->password_value.empty()) {
2885 NavigationState* old_navigation_state =
2886 NavigationState::FromDataSource(frame->dataSource());
2887 if (old_navigation_state) {
2888 PasswordForm* old_form_data = old_navigation_state->password_form_data();
2889 if (old_form_data && old_form_data->action == password_form_data->action)
2890 password_form_data->password_value = old_form_data->password_value;
2891 }
2892 }
[email protected]3d9689372009-09-10 04:29:172893
[email protected]b1438212010-04-03 00:30:592894 FormData form_data;
[email protected]b715f7f2010-04-05 22:01:042895 if (FormManager::WebFormElementToFormData(
[email protected]5af80432010-11-01 01:25:222896 form,
2897 FormManager::REQUIRE_AUTOCOMPLETE,
[email protected]78192082011-01-29 05:43:442898 static_cast<FormManager::ExtractMask>(
2899 FormManager::EXTRACT_VALUE | FormManager::EXTRACT_OPTION_TEXT),
[email protected]5af80432010-11-01 01:25:222900 &form_data)) {
[email protected]663bd9e2011-03-21 01:07:012901 Send(new AutofillHostMsg_FormSubmitted(routing_id_, form_data));
[email protected]5af80432010-11-01 01:25:222902 }
[email protected]3d9689372009-09-10 04:29:172903}
2904
2905void RenderView::willPerformClientRedirect(
2906 WebFrame* frame, const WebURL& from, const WebURL& to, double interval,
2907 double fire_time) {
2908 // Ignore
2909}
2910
2911void RenderView::didCancelClientRedirect(WebFrame* frame) {
2912 // Ignore
2913}
2914
2915void RenderView::didCompleteClientRedirect(
2916 WebFrame* frame, const WebURL& from) {
2917 if (!frame->parent())
2918 completed_client_redirect_src_ = from;
2919}
2920
2921void RenderView::didCreateDataSource(WebFrame* frame, WebDataSource* ds) {
[email protected]bb461532010-11-26 21:50:232922 // If there are any app-related fetches in progress, they can be cancelled now
2923 // since we have navigated away from the page that created them.
2924 if (!frame->parent()) {
2925 app_icon_fetchers_.clear();
2926 app_definition_fetcher_.reset(NULL);
2927 }
2928
[email protected]3d9689372009-09-10 04:29:172929 // The rest of RenderView assumes that a WebDataSource will always have a
2930 // non-null NavigationState.
[email protected]a7ccc4d2010-01-27 08:14:482931 bool content_initiated = !pending_navigation_state_.get();
2932 NavigationState* state = content_initiated ?
2933 NavigationState::CreateContentInitiated() :
2934 pending_navigation_state_.release();
[email protected]8a3125a712010-08-09 18:58:512935
[email protected]8a3125a712010-08-09 18:58:512936 // NavigationState::referred_by_prefetcher_ is true if we are
2937 // navigating from a page that used prefetching using a link on that
2938 // page. We are early enough in the request process here that we
2939 // can still see the NavigationState of the previous page and set
2940 // this value appropriately.
2941 // TODO(gavinp): catch the important case of navigation in a new
2942 // renderer process.
2943 if (webview()) {
[email protected]e47aec52010-08-12 00:50:302944 if (WebFrame* old_frame = webview()->mainFrame()) {
[email protected]05c8e502010-08-15 15:13:522945 const WebURLRequest& original_request = ds->originalRequest();
[email protected]8a3125a712010-08-09 18:58:512946 const GURL referrer(
2947 original_request.httpHeaderField(WebString::fromUTF8("Referer")));
2948 if (!referrer.is_empty() &&
2949 NavigationState::FromDataSource(
2950 old_frame->dataSource())->was_prefetcher()) {
2951 for (;old_frame;old_frame = old_frame->traverseNext(false)) {
2952 WebDataSource* old_frame_ds = old_frame->dataSource();
2953 if (old_frame_ds && referrer == GURL(old_frame_ds->request().url())) {
2954 state->set_was_referred_by_prefetcher(true);
2955 break;
2956 }
2957 }
2958 }
2959 }
2960 }
2961
[email protected]4c1b6f0b2010-02-07 16:38:182962 if (content_initiated) {
[email protected]05c8e502010-08-15 15:13:522963 const WebURLRequest& request = ds->request();
[email protected]8a3125a712010-08-09 18:58:512964 switch (request.cachePolicy()) {
[email protected]4c1b6f0b2010-02-07 16:38:182965 case WebURLRequest::UseProtocolCachePolicy: // normal load.
2966 state->set_load_type(NavigationState::LINK_LOAD_NORMAL);
2967 break;
2968 case WebURLRequest::ReloadIgnoringCacheData: // reload.
2969 state->set_load_type(NavigationState::LINK_LOAD_RELOAD);
2970 break;
2971 case WebURLRequest::ReturnCacheDataElseLoad: // allow stale data.
2972 state->set_load_type(NavigationState::LINK_LOAD_CACHE_STALE_OK);
2973 break;
2974 case WebURLRequest::ReturnCacheDataDontLoad: // Don't re-post.
2975 state->set_load_type(NavigationState::LINK_LOAD_CACHE_ONLY);
2976 break;
2977 }
2978 }
[email protected]fa7b6b542009-11-03 05:02:302979
[email protected]946a0032011-03-31 18:42:282980 FOR_EACH_OBSERVER(
2981 RenderViewObserver, observers_, DidCreateDataSource(frame, ds));
[email protected]375e8bd2011-02-07 19:15:352982
[email protected]987d51af2011-02-24 17:50:182983 state->set_was_started_as_prerender(is_prerendering_);
[email protected]375e8bd2011-02-07 19:15:352984
[email protected]fa7b6b542009-11-03 05:02:302985 ds->setExtraData(state);
[email protected]3d9689372009-09-10 04:29:172986}
2987
2988void RenderView::didStartProvisionalLoad(WebFrame* frame) {
2989 WebDataSource* ds = frame->provisionalDataSource();
2990 NavigationState* navigation_state = NavigationState::FromDataSource(ds);
2991
[email protected]3d9689372009-09-10 04:29:172992 // Update the request time if WebKit has better knowledge of it.
2993 if (navigation_state->request_time().is_null()) {
2994 double event_time = ds->triggeringEventTime();
2995 if (event_time != 0.0)
2996 navigation_state->set_request_time(Time::FromDoubleT(event_time));
2997 }
2998
[email protected]05c8e502010-08-15 15:13:522999 // Start time is only set after request time.
3000 navigation_state->set_start_load_time(Time::Now());
3001
[email protected]3d9689372009-09-10 04:29:173002 bool is_top_most = !frame->parent();
3003 if (is_top_most) {
3004 navigation_gesture_ = frame->isProcessingUserGesture() ?
[email protected]cd448092010-12-06 23:49:133005 NavigationGestureUser : NavigationGestureAuto;
[email protected]3d9689372009-09-10 04:29:173006
3007 // Make sure redirect tracking state is clear for the new load.
3008 completed_client_redirect_src_ = GURL();
3009 } else if (frame->parent()->isLoading()) {
3010 // Take note of AUTO_SUBFRAME loads here, so that we can know how to
[email protected]4fb66842009-12-04 21:41:003011 // load an error page. See didFailProvisionalLoad.
[email protected]3d9689372009-09-10 04:29:173012 navigation_state->set_transition_type(PageTransition::AUTO_SUBFRAME);
3013 }
3014
[email protected]28685da92011-02-07 21:49:173015 FOR_EACH_OBSERVER(
3016 RenderViewObserver, observers_, DidStartProvisionalLoad(frame));
3017
[email protected]3d9689372009-09-10 04:29:173018 Send(new ViewHostMsg_DidStartProvisionalLoadForFrame(
[email protected]dabb0d12010-10-05 12:50:073019 routing_id_, frame->identifier(), is_top_most, ds->request().url()));
[email protected]3d9689372009-09-10 04:29:173020}
3021
3022void RenderView::didReceiveServerRedirectForProvisionalLoad(WebFrame* frame) {
3023 if (frame->parent())
3024 return;
3025 // Received a redirect on the main frame.
3026 WebDataSource* data_source = frame->provisionalDataSource();
3027 if (!data_source) {
3028 // Should only be invoked when we have a data source.
3029 NOTREACHED();
3030 return;
3031 }
3032 std::vector<GURL> redirects;
3033 GetRedirectChain(data_source, &redirects);
3034 if (redirects.size() >= 2) {
[email protected]40bd6582009-12-04 23:49:513035 Send(new ViewHostMsg_DidRedirectProvisionalLoad(routing_id_, page_id_,
3036 redirects[redirects.size() - 2], redirects.back()));
[email protected]3d9689372009-09-10 04:29:173037 }
3038}
3039
[email protected]40bd6582009-12-04 23:49:513040void RenderView::didFailProvisionalLoad(WebFrame* frame,
3041 const WebURLError& error) {
[email protected]3d9689372009-09-10 04:29:173042 // Notify the browser that we failed a provisional load with an error.
3043 //
3044 // Note: It is important this notification occur before DidStopLoading so the
3045 // SSL manager can react to the provisional load failure before being
3046 // notified the load stopped.
3047 //
3048 WebDataSource* ds = frame->provisionalDataSource();
3049 DCHECK(ds);
3050
3051 const WebURLRequest& failed_request = ds->request();
3052
[email protected]28685da92011-02-07 21:49:173053 FOR_EACH_OBSERVER(
3054 RenderViewObserver, observers_, DidFailProvisionalLoad(frame, error));
3055
[email protected]3d9689372009-09-10 04:29:173056 bool show_repost_interstitial =
3057 (error.reason == net::ERR_CACHE_MISS &&
3058 EqualsASCII(failed_request.httpMethod(), "POST"));
3059 Send(new ViewHostMsg_DidFailProvisionalLoadWithError(
[email protected]dabb0d12010-10-05 12:50:073060 routing_id_, frame->identifier(), !frame->parent(), error.reason,
3061 error.unreachableURL, show_repost_interstitial));
[email protected]3d9689372009-09-10 04:29:173062
3063 // Don't display an error page if this is simply a cancelled load. Aside
3064 // from being dumb, WebCore doesn't expect it and it will cause a crash.
3065 if (error.reason == net::ERR_ABORTED)
3066 return;
3067
3068 // Make sure we never show errors in view source mode.
3069 frame->enableViewSourceMode(false);
3070
3071 NavigationState* navigation_state = NavigationState::FromDataSource(ds);
3072
3073 // If this is a failed back/forward/reload navigation, then we need to do a
3074 // 'replace' load. This is necessary to avoid messing up session history.
3075 // Otherwise, we do a normal load, which simulates a 'go' navigation as far
3076 // as session history is concerned.
3077 //
3078 // AUTO_SUBFRAME loads should always be treated as loads that do not advance
3079 // the page id.
3080 //
3081 bool replace =
3082 navigation_state->pending_page_id() != -1 ||
3083 navigation_state->transition_type() == PageTransition::AUTO_SUBFRAME;
3084
3085 // If we failed on a browser initiated request, then make sure that our error
3086 // page load is regarded as the same browser initiated request.
3087 if (!navigation_state->is_content_initiated()) {
3088 pending_navigation_state_.reset(NavigationState::CreateBrowserInitiated(
3089 navigation_state->pending_page_id(),
[email protected]3cc72b12010-03-18 23:03:003090 navigation_state->pending_history_list_offset(),
[email protected]3d9689372009-09-10 04:29:173091 navigation_state->transition_type(),
3092 navigation_state->request_time()));
3093 }
3094
3095 // Provide the user with a more helpful error page?
3096 if (MaybeLoadAlternateErrorPage(frame, error, replace))
3097 return;
3098
3099 // Fallback to a local error page.
[email protected]3f853a52010-09-13 19:15:083100 LoadNavigationErrorPage(frame, failed_request, error, std::string(), replace);
[email protected]3d9689372009-09-10 04:29:173101}
3102
3103void RenderView::didReceiveDocumentData(
3104 WebFrame* frame, const char* data, size_t data_len,
3105 bool& prevent_default) {
3106 NavigationState* navigation_state =
3107 NavigationState::FromDataSource(frame->dataSource());
[email protected]06333afe2011-02-24 14:55:093108 navigation_state->set_use_error_page(false);
[email protected]3d9689372009-09-10 04:29:173109}
3110
[email protected]40bd6582009-12-04 23:49:513111void RenderView::didCommitProvisionalLoad(WebFrame* frame,
3112 bool is_new_navigation) {
[email protected]3d9689372009-09-10 04:29:173113 NavigationState* navigation_state =
3114 NavigationState::FromDataSource(frame->dataSource());
3115
3116 navigation_state->set_commit_load_time(Time::Now());
3117 if (is_new_navigation) {
[email protected]e15f680732010-11-23 22:30:203118 // When we perform a new navigation, we need to update the last committed
3119 // session history entry with state for the page we are leaving.
[email protected]3d9689372009-09-10 04:29:173120 UpdateSessionHistory(frame);
3121
3122 // We bump our Page ID to correspond with the new session history entry.
3123 page_id_ = next_page_id_++;
3124
[email protected]3cc72b12010-03-18 23:03:003125 // Advance our offset in session history, applying the length limit. There
3126 // is now no forward history.
3127 history_list_offset_++;
3128 if (history_list_offset_ >= chrome::kMaxSessionHistoryEntries)
3129 history_list_offset_ = chrome::kMaxSessionHistoryEntries - 1;
3130 history_list_length_ = history_list_offset_ + 1;
3131
[email protected]f9f4841b2010-03-20 05:41:423132 MessageLoop::current()->PostDelayedTask(
3133 FROM_HERE,
[email protected]e47aec52010-08-12 00:50:303134 page_info_method_factory_.NewRunnableMethod(
3135 &RenderView::CapturePageInfo, page_id_, true),
[email protected]3d9689372009-09-10 04:29:173136 kDelayForForcedCaptureMs);
3137 } else {
3138 // Inspect the navigation_state on this frame to see if the navigation
3139 // corresponds to a session history navigation... Note: |frame| may or
3140 // may not be the toplevel frame, but for the case of capturing session
3141 // history, the first committed frame suffices. We keep track of whether
3142 // we've seen this commit before so that only capture session history once
3143 // per navigation.
3144 //
3145 // Note that we need to check if the page ID changed. In the case of a
3146 // reload, the page ID doesn't change, and UpdateSessionHistory gets the
3147 // previous URL and the current page ID, which would be wrong.
3148 if (navigation_state->pending_page_id() != -1 &&
3149 navigation_state->pending_page_id() != page_id_ &&
3150 !navigation_state->request_committed()) {
3151 // This is a successful session history navigation!
3152 UpdateSessionHistory(frame);
3153 page_id_ = navigation_state->pending_page_id();
[email protected]3cc72b12010-03-18 23:03:003154
3155 history_list_offset_ = navigation_state->pending_history_list_offset();
[email protected]3d9689372009-09-10 04:29:173156 }
3157 }
3158
[email protected]28685da92011-02-07 21:49:173159 FOR_EACH_OBSERVER(RenderViewObserver, observers_,
3160 DidCommitProvisionalLoad(frame, is_new_navigation));
3161
[email protected]3d9689372009-09-10 04:29:173162 // Remember that we've already processed this request, so we don't update
3163 // the session history again. We do this regardless of whether this is
3164 // a session history navigation, because if we attempted a session history
3165 // navigation without valid HistoryItem state, WebCore will think it is a
3166 // new navigation.
3167 navigation_state->set_request_committed(true);
3168
3169 UpdateURL(frame);
3170
3171 // If this committed load was initiated by a client redirect, we're
3172 // at the last stop now, so clear it.
3173 completed_client_redirect_src_ = GURL();
3174
3175 // Check whether we have new encoding name.
[email protected]26aa0482009-09-30 16:55:273176 UpdateEncoding(frame, frame->view()->pageEncoding().utf8());
[email protected]3d9689372009-09-10 04:29:173177}
3178
3179void RenderView::didClearWindowObject(WebFrame* frame) {
3180 if (BindingsPolicy::is_dom_automation_enabled(enabled_bindings_))
3181 BindDOMAutomationController(frame);
[email protected]0d7ae862010-10-01 13:52:453182 GURL frame_url = frame->url();
[email protected]c09163a2011-02-15 00:05:553183 if (BindingsPolicy::is_web_ui_enabled(enabled_bindings_) &&
[email protected]bfa83eb82010-10-06 08:41:253184 (frame_url.SchemeIs(chrome::kChromeUIScheme) ||
3185 frame_url.SchemeIs(chrome::kDataScheme))) {
[email protected]c50008512011-02-03 01:17:273186 GetWebUIBindings()->set_message_sender(this);
3187 GetWebUIBindings()->set_routing_id(routing_id_);
3188 GetWebUIBindings()->BindToJavascript(frame, "chrome");
[email protected]3d9689372009-09-10 04:29:173189 }
3190 if (BindingsPolicy::is_external_host_enabled(enabled_bindings_)) {
[email protected]c091c2c2010-09-17 19:05:463191 GetExternalHostBindings()->set_message_sender(this);
3192 GetExternalHostBindings()->set_routing_id(routing_id_);
[email protected]906690b2010-12-03 18:11:253193 GetExternalHostBindings()->BindToJavascript(frame, "externalHost");
[email protected]3d9689372009-09-10 04:29:173194 }
3195}
3196
3197void RenderView::didCreateDocumentElement(WebFrame* frame) {
3198 if (RenderThread::current()) { // Will be NULL during unit tests.
[email protected]6779aa12011-03-29 17:32:243199 ExtensionDispatcher::Get()->user_script_slave()->InjectScripts(
[email protected]3d9689372009-09-10 04:29:173200 frame, UserScript::DOCUMENT_START);
3201 }
3202
3203 // Notify the browser about non-blank documents loading in the top frame.
3204 GURL url = frame->url();
[email protected]e0d481582009-09-15 21:06:253205 if (url.is_valid() && url.spec() != chrome::kAboutBlankURL) {
[email protected]26aa0482009-09-30 16:55:273206 if (frame == webview()->mainFrame())
[email protected]3d9689372009-09-10 04:29:173207 Send(new ViewHostMsg_DocumentAvailableInMainFrame(routing_id_));
3208 }
3209}
3210
3211void RenderView::didReceiveTitle(WebFrame* frame, const WebString& title) {
3212 UpdateTitle(frame, title);
3213
3214 // Also check whether we have new encoding name.
[email protected]26aa0482009-09-30 16:55:273215 UpdateEncoding(frame, frame->view()->pageEncoding().utf8());
[email protected]3d9689372009-09-10 04:29:173216}
3217
[email protected]5019ef12010-04-27 17:26:583218void RenderView::didChangeIcons(WebFrame* frame) {
3219 if (!frame->parent()) {
[email protected]d8e74e82011-03-15 19:38:483220 Send(new ViewHostMsg_UpdateFaviconURL(
[email protected]5019ef12010-04-27 17:26:583221 routing_id_,
3222 page_id_,
3223 frame->favIconURL()));
3224 }
3225}
3226
[email protected]3d9689372009-09-10 04:29:173227void RenderView::didFinishDocumentLoad(WebFrame* frame) {
3228 WebDataSource* ds = frame->dataSource();
3229 NavigationState* navigation_state = NavigationState::FromDataSource(ds);
3230 DCHECK(navigation_state);
3231 navigation_state->set_finish_document_load_time(Time::Now());
3232
[email protected]622474d2010-11-04 09:21:083233 Send(new ViewHostMsg_DocumentLoadedInFrame(routing_id_, frame->identifier()));
[email protected]3d9689372009-09-10 04:29:173234
[email protected]28685da92011-02-07 21:49:173235 FOR_EACH_OBSERVER(RenderViewObserver, observers_,
3236 DidFinishDocumentLoad(frame));
[email protected]3d9689372009-09-10 04:29:173237
3238 // Check whether we have new encoding name.
[email protected]26aa0482009-09-30 16:55:273239 UpdateEncoding(frame, frame->view()->pageEncoding().utf8());
[email protected]3d9689372009-09-10 04:29:173240
3241 if (RenderThread::current()) { // Will be NULL during unit tests.
[email protected]6779aa12011-03-29 17:32:243242 ExtensionDispatcher::Get()->user_script_slave()->InjectScripts(
[email protected]3d9689372009-09-10 04:29:173243 frame, UserScript::DOCUMENT_END);
3244 }
[email protected]3d9689372009-09-10 04:29:173245}
3246
3247void RenderView::didHandleOnloadEvents(WebFrame* frame) {
[email protected]25497492010-09-11 15:15:083248 if (webview()->mainFrame() == frame) {
3249 Send(new ViewHostMsg_DocumentOnLoadCompletedInMainFrame(routing_id_,
3250 page_id_));
3251 }
[email protected]3d9689372009-09-10 04:29:173252}
3253
3254void RenderView::didFailLoad(WebFrame* frame, const WebURLError& error) {
[email protected]28685da92011-02-07 21:49:173255 FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidFailLoad(frame, error));
[email protected]3d9689372009-09-10 04:29:173256}
3257
3258void RenderView::didFinishLoad(WebFrame* frame) {
3259 WebDataSource* ds = frame->dataSource();
3260 NavigationState* navigation_state = NavigationState::FromDataSource(ds);
3261 DCHECK(navigation_state);
3262 navigation_state->set_finish_load_time(Time::Now());
[email protected]4d44a1c2010-04-28 19:20:413263
[email protected]676126f72011-01-15 00:03:513264 FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidFinishLoad(frame));
[email protected]fdd94a02010-11-05 08:07:173265
3266 Send(new ViewHostMsg_DidFinishLoad(routing_id_, frame->identifier()));
[email protected]3d9689372009-09-10 04:29:173267}
3268
[email protected]ccbe04e2010-03-17 17:58:433269void RenderView::didNavigateWithinPage(
[email protected]3d9689372009-09-10 04:29:173270 WebFrame* frame, bool is_new_navigation) {
3271 // If this was a reference fragment navigation that we initiated, then we
3272 // could end up having a non-null pending navigation state. We just need to
3273 // update the ExtraData on the datasource so that others who read the
3274 // ExtraData will get the new NavigationState. Similarly, if we did not
3275 // initiate this navigation, then we need to take care to reset any pre-
3276 // existing navigation state to a content-initiated navigation state.
3277 // DidCreateDataSource conveniently takes care of this for us.
3278 didCreateDataSource(frame, frame->dataSource());
3279
[email protected]af15bed2010-08-25 21:12:093280 NavigationState* new_state =
3281 NavigationState::FromDataSource(frame->dataSource());
3282 new_state->set_was_within_same_page(true);
3283
[email protected]3d9689372009-09-10 04:29:173284 didCommitProvisionalLoad(frame, is_new_navigation);
3285
[email protected]26aa0482009-09-30 16:55:273286 UpdateTitle(frame, frame->view()->mainFrame()->dataSource()->pageTitle());
[email protected]3d9689372009-09-10 04:29:173287}
3288
[email protected]476b6f82009-09-10 21:00:593289void RenderView::didUpdateCurrentHistoryItem(WebFrame* frame) {
[email protected]882daa92009-11-05 16:31:313290 StartNavStateSyncTimerIfNecessary();
[email protected]476b6f82009-09-10 21:00:593291}
3292
[email protected]3d9689372009-09-10 04:29:173293void RenderView::assignIdentifierToRequest(
3294 WebFrame* frame, unsigned identifier, const WebURLRequest& request) {
3295 // Ignore
3296}
3297
3298void RenderView::willSendRequest(
3299 WebFrame* frame, unsigned identifier, WebURLRequest& request,
3300 const WebURLResponse& redirect_response) {
[email protected]5e369672009-11-03 23:48:303301 WebFrame* top_frame = frame->top();
3302 if (!top_frame)
3303 top_frame = frame;
[email protected]8a3125a712010-08-09 18:58:513304 WebDataSource* provisional_data_source = top_frame->provisionalDataSource();
3305 WebDataSource* top_data_source = top_frame->dataSource();
3306 WebDataSource* data_source =
3307 provisional_data_source ? provisional_data_source : top_data_source;
[email protected]78d5cfe2011-02-04 08:43:223308
3309 // If the request is for an extension resource, check whether it should be
3310 // allowed. If not allowed, we reset the URL to something invalid to prevent
3311 // the request and cause an error.
3312 GURL request_url(request.url());
3313 if (request_url.SchemeIs(chrome::kExtensionScheme) &&
3314 !ExtensionResourceRequestPolicy::CanRequestResource(
3315 request_url,
3316 GURL(frame->url()),
[email protected]6779aa12011-03-29 17:32:243317 ExtensionDispatcher::Get()->extensions())) {
[email protected]78d5cfe2011-02-04 08:43:223318 request.setURL(WebURL(GURL("chrome-extension://invalid/")));
3319 }
3320
[email protected]5e369672009-11-03 23:48:303321 if (data_source) {
3322 NavigationState* state = NavigationState::FromDataSource(data_source);
3323 if (state && state->is_cache_policy_override_set())
3324 request.setCachePolicy(state->cache_policy_override());
3325 }
[email protected]8a3125a712010-08-09 18:58:513326
3327 if (top_data_source) {
3328 NavigationState* state = NavigationState::FromDataSource(top_data_source);
3329 if (state && request.targetType() == WebURLRequest::TargetIsPrefetch)
3330 state->set_was_prefetcher(true);
3331 }
3332
[email protected]3d9689372009-09-10 04:29:173333 request.setRequestorID(routing_id_);
[email protected]cd448092010-12-06 23:49:133334 request.setHasUserGesture(frame->isProcessingUserGesture());
3335
[email protected]c5bbc2452010-03-08 08:33:503336 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoReferrers))
[email protected]7deade42010-03-05 09:33:133337 request.clearHTTPHeaderField("Referer");
[email protected]fa0a3432010-03-30 16:53:493338
[email protected]85cc78c2010-05-04 18:30:093339 // Temporary metrics, see site_isolation_metrics.h
3340 SiteIsolationMetrics::AddRequest(identifier, request.targetType());
[email protected]3d9689372009-09-10 04:29:173341}
3342
3343void RenderView::didReceiveResponse(
3344 WebFrame* frame, unsigned identifier, const WebURLResponse& response) {
[email protected]fa0a3432010-03-30 16:53:493345
[email protected]85cc78c2010-05-04 18:30:093346 // Temporary metrics, see site_isolation_metrics.h
3347 SiteIsolationMetrics::LogMimeTypeForCrossOriginRequest(frame,
3348 identifier,
3349 response);
[email protected]fa0a3432010-03-30 16:53:493350
[email protected]3d9689372009-09-10 04:29:173351 // Only do this for responses that correspond to a provisional data source
3352 // of the top-most frame. If we have a provisional data source, then we
3353 // can't have any sub-resources yet, so we know that this response must
3354 // correspond to a frame load.
3355 if (!frame->provisionalDataSource() || frame->parent())
3356 return;
3357
3358 // If we are in view source mode, then just let the user see the source of
[email protected]3f853a52010-09-13 19:15:083359 // the server's error page.
[email protected]3d9689372009-09-10 04:29:173360 if (frame->isViewSourceModeEnabled())
3361 return;
3362
[email protected]65041fa2010-05-21 06:56:533363 NavigationState* navigation_state =
3364 NavigationState::FromDataSource(frame->provisionalDataSource());
3365 CHECK(navigation_state);
[email protected]3f853a52010-09-13 19:15:083366 int http_status_code = response.httpStatusCode();
[email protected]65041fa2010-05-21 06:56:533367
[email protected]972ebdff2010-06-10 22:59:073368 // Record page load flags.
3369 navigation_state->set_was_fetched_via_spdy(response.wasFetchedViaSPDY());
3370 navigation_state->set_was_npn_negotiated(response.wasNpnNegotiated());
[email protected]193b0b892010-06-26 03:57:573371 navigation_state->set_was_alternate_protocol_available(
3372 response.wasAlternateProtocolAvailable());
[email protected]972ebdff2010-06-10 22:59:073373 navigation_state->set_was_fetched_via_proxy(response.wasFetchedViaProxy());
[email protected]3f853a52010-09-13 19:15:083374 navigation_state->set_http_status_code(http_status_code);
[email protected]06333afe2011-02-24 14:55:093375 // Whether or not the http status code actually corresponds to an error is
3376 // only checked when the page is done loading, if |use_error_page| is
3377 // still true.
3378 navigation_state->set_use_error_page(true);
[email protected]3d9689372009-09-10 04:29:173379}
3380
3381void RenderView::didFinishResourceLoad(
3382 WebFrame* frame, unsigned identifier) {
3383 NavigationState* navigation_state =
3384 NavigationState::FromDataSource(frame->dataSource());
[email protected]06333afe2011-02-24 14:55:093385 if (!navigation_state->use_error_page())
[email protected]3d9689372009-09-10 04:29:173386 return;
3387
[email protected]06333afe2011-02-24 14:55:093388 // Display error page, if appropriate.
[email protected]3f853a52010-09-13 19:15:083389 int http_status_code = navigation_state->http_status_code();
3390 if (http_status_code == 404) {
3391 // On 404s, try a remote search page as a fallback.
3392 const GURL& frame_url = frame->url();
[email protected]3d9689372009-09-10 04:29:173393
[email protected]3f853a52010-09-13 19:15:083394 const GURL& error_page_url = GetAlternateErrorPageURL(frame_url, HTTP_404);
[email protected]06333afe2011-02-24 14:55:093395 if (error_page_url.is_valid()) {
3396 WebURLError original_error;
3397 original_error.unreachableURL = frame_url;
[email protected]3d9689372009-09-10 04:29:173398
[email protected]06333afe2011-02-24 14:55:093399 navigation_state->set_alt_error_page_fetcher(
3400 new AltErrorPageResourceFetcher(
3401 error_page_url, frame, original_error,
3402 NewCallback(this, &RenderView::AltErrorPageFinished)));
3403 return;
3404 }
3405 }
[email protected]3d9689372009-09-10 04:29:173406
[email protected]06333afe2011-02-24 14:55:093407 // Use an internal error page, if we have one for the status code.
3408 if (LocalizedError::HasStrings(LocalizedError::kHttpErrorDomain,
3409 http_status_code)) {
[email protected]3f853a52010-09-13 19:15:083410 WebURLError error;
3411 error.unreachableURL = frame->url();
3412 error.domain = WebString::fromUTF8(LocalizedError::kHttpErrorDomain);
3413 error.reason = http_status_code;
[email protected]3d9689372009-09-10 04:29:173414
[email protected]3f853a52010-09-13 19:15:083415 LoadNavigationErrorPage(frame, frame->dataSource()->request(), error,
3416 std::string(), true);
3417 }
[email protected]3d9689372009-09-10 04:29:173418}
3419
3420void RenderView::didFailResourceLoad(
3421 WebFrame* frame, unsigned identifier, const WebURLError& error) {
3422 // Ignore
3423}
3424
3425void RenderView::didLoadResourceFromMemoryCache(
3426 WebFrame* frame, const WebURLRequest& request,
3427 const WebURLResponse& response) {
3428 // Let the browser know we loaded a resource from the memory cache. This
3429 // message is needed to display the correct SSL indicators.
3430 Send(new ViewHostMsg_DidLoadResourceFromMemoryCache(
3431 routing_id_,
3432 request.url(),
[email protected]3d9689372009-09-10 04:29:173433 response.securityInfo()));
3434}
3435
[email protected]6069da8c2009-10-20 20:33:493436void RenderView::didDisplayInsecureContent(WebFrame* frame) {
[email protected]e3d60e5d2009-09-25 21:08:293437 Send(new ViewHostMsg_DidDisplayInsecureContent(routing_id_));
3438}
3439
[email protected]92771112011-01-20 00:13:023440void RenderView::didRunInsecureContent(
3441 WebFrame* frame, const WebSecurityOrigin& origin, const WebURL& target) {
[email protected]e3d60e5d2009-09-25 21:08:293442 Send(new ViewHostMsg_DidRunInsecureContent(
3443 routing_id_,
[email protected]92771112011-01-20 00:13:023444 origin.toString().utf8(),
3445 target));
[email protected]e3d60e5d2009-09-25 21:08:293446}
3447
[email protected]7ea093ba2009-11-03 05:54:593448bool RenderView::allowScript(WebFrame* frame, bool enabled_per_settings) {
[email protected]12bc8472010-04-15 07:29:403449 if (enabled_per_settings &&
3450 AllowContentType(CONTENT_SETTINGS_TYPE_JAVASCRIPT))
3451 return true;
[email protected]7ea093ba2009-11-03 05:54:593452
[email protected]12bc8472010-04-15 07:29:403453 if (IsWhitelistedForContentSettings(frame))
3454 return true;
[email protected]7ea093ba2009-11-03 05:54:593455
3456 return false; // Other protocols fall through here.
3457}
3458
[email protected]0a1a45432010-03-31 08:09:453459bool RenderView::allowDatabase(
3460 WebFrame* frame, const WebString& name, const WebString& display_name,
3461 unsigned long estimated_size) {
3462 WebSecurityOrigin origin = frame->securityOrigin();
3463 if (origin.isEmpty())
3464 return false; // Uninitialized document?
3465
3466 bool result;
[email protected]26a9acf2010-12-13 19:35:053467 if (!Send(new DatabaseHostMsg_Allow(routing_id_,
[email protected]0a1a45432010-03-31 08:09:453468 origin.toString().utf8(), name, display_name, estimated_size, &result)))
3469 return false;
[email protected]9fb83e82010-07-02 18:24:553470 Send(new ViewHostMsg_WebDatabaseAccessed(routing_id_,
3471 GURL(origin.toString().utf8()),
3472 name,
3473 display_name,
3474 estimated_size,
3475 !result));
[email protected]0a1a45432010-03-31 08:09:453476 return result;
3477}
[email protected]8934a3b2010-02-25 00:34:003478void RenderView::didNotAllowScript(WebKit::WebFrame* frame) {
[email protected]55126132010-08-19 14:53:283479 DidBlockContentType(CONTENT_SETTINGS_TYPE_JAVASCRIPT, std::string());
[email protected]8934a3b2010-02-25 00:34:003480}
3481
[email protected]c21f1d52010-03-04 03:19:433482void RenderView::didNotAllowPlugins(WebKit::WebFrame* frame) {
[email protected]55126132010-08-19 14:53:283483 DidBlockContentType(CONTENT_SETTINGS_TYPE_PLUGINS, std::string());
[email protected]c21f1d52010-03-04 03:19:433484}
3485
[email protected]3d9689372009-09-10 04:29:173486void RenderView::didExhaustMemoryAvailableForScript(WebFrame* frame) {
3487 Send(new ViewHostMsg_JSOutOfMemory(routing_id_));
3488}
3489
[email protected]0c882b282009-10-07 17:01:283490void RenderView::didCreateScriptContext(WebFrame* frame) {
3491 EventBindings::HandleContextCreated(frame, false);
3492}
3493
3494void RenderView::didDestroyScriptContext(WebFrame* frame) {
3495 EventBindings::HandleContextDestroyed(frame);
3496}
3497
3498void RenderView::didCreateIsolatedScriptContext(WebFrame* frame) {
3499 EventBindings::HandleContextCreated(frame, true);
3500}
3501
[email protected]af7eb3fb2010-09-23 21:31:063502bool RenderView::allowScriptExtension(WebFrame* frame,
3503 const WebString& extension_name,
3504 int extension_group) {
3505 // NULL in unit tests.
3506 if (!RenderThread::current())
3507 return true;
3508
3509 // Note: we prefer the provisional URL here instead of the document URL
3510 // because we might be currently loading an URL into a blank page.
3511 // See http://code.google.com/p/chromium/issues/detail?id=10924
3512 WebDataSource* ds = frame->provisionalDataSource();
3513 if (!ds)
3514 ds = frame->dataSource();
3515 return RenderThread::current()->AllowScriptExtension(
3516 extension_name.utf8(), ds->request().url(), extension_group);
3517}
3518
[email protected]fc86daa2010-03-30 23:52:533519void RenderView::logCrossFramePropertyAccess(WebFrame* frame,
3520 WebFrame* target,
3521 bool cross_origin,
3522 const WebString& property_name,
3523 unsigned long long event_id) {
[email protected]ab9eabac2010-03-16 16:54:103524 // TODO(johnnyg): track the individual properties and repeat event_ids.
[email protected]a5a65ac2010-11-05 18:14:363525 page_load_histograms_.IncrementCrossFramePropertyAccess(cross_origin);
[email protected]ab9eabac2010-03-16 16:54:103526}
3527
[email protected]3d9689372009-09-10 04:29:173528void RenderView::didChangeContentsSize(WebFrame* frame, const WebSize& size) {
[email protected]d8a179c2010-01-31 00:58:143529 CheckPreferredSize();
3530}
3531
3532void RenderView::CheckPreferredSize() {
[email protected]3d9689372009-09-10 04:29:173533 // We don't always want to send the change messages over IPC, only if we've
[email protected]ab32b16c2009-10-16 14:57:253534 // be put in that mode by getting a |ViewMsg_EnablePreferredSizeChangedMode|
[email protected]3d9689372009-09-10 04:29:173535 // message.
[email protected]705243f2010-05-05 19:58:073536 if (!send_preferred_size_changes_ || !webview())
3537 return;
[email protected]dfca5acf2010-03-22 03:28:433538
[email protected]705243f2010-05-05 19:58:073539 // WebCore likes to tell us things have changed even when they haven't, so
3540 // cache the width and height and only send the IPC message when we're sure
3541 // they're different.
3542 gfx::Size size(webview()->mainFrame()->contentsPreferredWidth(),
3543 webview()->mainFrame()->documentElementScrollHeight());
[email protected]8205d742010-10-22 23:51:533544
3545 // In the presence of zoom, these sizes are still reported as if unzoomed,
3546 // so we need to adjust.
3547 double zoom_factor = WebView::zoomLevelToZoomFactor(webview()->zoomLevel());
3548 size.set_width(static_cast<int>(size.width() * zoom_factor));
3549 size.set_height(static_cast<int>(size.height() * zoom_factor));
3550
[email protected]705243f2010-05-05 19:58:073551 if (size == preferred_size_)
3552 return;
[email protected]c27324b2009-11-19 22:44:293553
[email protected]705243f2010-05-05 19:58:073554 preferred_size_ = size;
3555 Send(new ViewHostMsg_DidContentsPreferredSizeChange(routing_id_,
3556 preferred_size_));
[email protected]3d9689372009-09-10 04:29:173557}
3558
[email protected]143dcd592009-11-06 21:33:493559void RenderView::didChangeScrollOffset(WebFrame* frame) {
3560 StartNavStateSyncTimerIfNecessary();
3561}
3562
[email protected]8922e1f2009-10-03 05:01:263563void RenderView::reportFindInPageMatchCount(int request_id, int count,
3564 bool final_update) {
[email protected]e7c58a32010-08-13 19:47:113565 int active_match_ordinal = -1; // -1 = don't update active match ordinal
3566 if (!count)
3567 active_match_ordinal = 0;
3568
3569 IPC::Message* msg = new ViewHostMsg_Find_Reply(
3570 routing_id_,
3571 request_id,
3572 count,
3573 gfx::Rect(),
3574 active_match_ordinal,
3575 final_update);
3576
[email protected]8922e1f2009-10-03 05:01:263577 // If we have a message that has been queued up, then we should just replace
3578 // it. The ACK from the browser will make sure it gets sent when the browser
3579 // wants it.
3580 if (queued_find_reply_message_.get()) {
[email protected]8922e1f2009-10-03 05:01:263581 queued_find_reply_message_.reset(msg);
3582 } else {
3583 // Send the search result over to the browser process.
[email protected]e7c58a32010-08-13 19:47:113584 Send(msg);
[email protected]8922e1f2009-10-03 05:01:263585 }
3586}
3587
3588void RenderView::reportFindInPageSelection(int request_id,
3589 int active_match_ordinal,
3590 const WebRect& selection_rect) {
3591 // Send the search result over to the browser process.
3592 Send(new ViewHostMsg_Find_Reply(routing_id_,
3593 request_id,
3594 -1,
3595 selection_rect,
3596 active_match_ordinal,
3597 false));
3598}
3599
[email protected]2b06a992010-08-21 05:48:223600void RenderView::openFileSystem(
3601 WebFrame* frame,
3602 WebFileSystem::Type type,
3603 long long size,
[email protected]d275d7a2010-11-03 01:34:493604 bool create,
[email protected]2b06a992010-08-21 05:48:223605 WebFileSystemCallbacks* callbacks) {
[email protected]c5a272d2010-09-27 18:37:083606 DCHECK(callbacks);
[email protected]2b06a992010-08-21 05:48:223607
3608 WebSecurityOrigin origin = frame->securityOrigin();
[email protected]c5a272d2010-09-27 18:37:083609 if (origin.isEmpty()) {
3610 // Uninitialized document?
3611 callbacks->didFail(WebKit::WebFileErrorAbort);
3612 return;
3613 }
[email protected]2b06a992010-08-21 05:48:223614
[email protected]c5a272d2010-09-27 18:37:083615 ChildThread::current()->file_system_dispatcher()->OpenFileSystem(
3616 GURL(origin.toString()), static_cast<fileapi::FileSystemType>(type),
[email protected]d275d7a2010-11-03 01:34:493617 size, create, new WebFileSystemCallbackDispatcher(callbacks));
[email protected]2b06a992010-08-21 05:48:223618}
3619
[email protected]79dbc662009-09-04 05:42:513620// webkit_glue::WebPluginPageDelegate -----------------------------------------
3621
[email protected]191eb3f72010-12-21 06:27:503622webkit::npapi::WebPluginDelegate* RenderView::CreatePluginDelegate(
[email protected]4e0616e2010-05-28 14:55:533623 const FilePath& file_path,
3624 const std::string& mime_type) {
[email protected]f103ab72009-09-02 17:10:593625 if (!PluginChannelHost::IsListening())
3626 return NULL;
3627
[email protected]00c39612010-03-06 02:53:283628 bool in_process_plugin = RenderProcess::current()->UseInProcessPlugins();
[email protected]d032f492009-09-29 00:33:463629 if (in_process_plugin) {
[email protected]6876dff2010-01-15 19:38:093630#if defined(OS_WIN) // In-proc plugins aren't supported on Linux or Mac.
[email protected]e8f7a182011-03-10 00:50:223631 return webkit::npapi::WebPluginDelegateImpl::Create(
3632 file_path, mime_type, gfx::NativeViewFromId(host_window_));
[email protected]6876dff2010-01-15 19:38:093633#else
[email protected]e8f7a182011-03-10 00:50:223634 NOTIMPLEMENTED();
3635 return NULL;
[email protected]7b6616f2010-01-14 18:07:553636#endif
[email protected]f103ab72009-09-02 17:10:593637 }
3638
[email protected]4e0616e2010-05-28 14:55:533639 return new WebPluginDelegateProxy(mime_type, AsWeakPtr());
[email protected]f103ab72009-09-02 17:10:593640}
3641
3642void RenderView::CreatedPluginWindow(gfx::PluginWindowHandle window) {
[email protected]6981f7f2010-03-09 00:53:033643#if defined(USE_X11)
[email protected]f103ab72009-09-02 17:10:593644 RenderThread::current()->Send(new ViewHostMsg_CreatePluginContainer(
3645 routing_id(), window));
3646#endif
3647}
3648
3649void RenderView::WillDestroyPluginWindow(gfx::PluginWindowHandle window) {
[email protected]6981f7f2010-03-09 00:53:033650#if defined(USE_X11)
[email protected]f103ab72009-09-02 17:10:593651 RenderThread::current()->Send(new ViewHostMsg_DestroyPluginContainer(
3652 routing_id(), window));
3653#endif
3654 CleanupWindowInPluginMoves(window);
3655}
3656
[email protected]191eb3f72010-12-21 06:27:503657void RenderView::DidMovePlugin(const webkit::npapi::WebPluginGeometry& move) {
[email protected]f103ab72009-09-02 17:10:593658 SchedulePluginMove(move);
3659}
3660
3661void RenderView::DidStartLoadingForPlugin() {
3662 // TODO(darin): Make is_loading_ be a counter!
[email protected]48c9cf2d2009-09-16 16:47:523663 didStartLoading();
[email protected]f103ab72009-09-02 17:10:593664}
3665
3666void RenderView::DidStopLoadingForPlugin() {
3667 // TODO(darin): Make is_loading_ be a counter!
[email protected]48c9cf2d2009-09-16 16:47:523668 didStopLoading();
[email protected]f103ab72009-09-02 17:10:593669}
3670
[email protected]b921cfd22010-02-25 16:57:513671WebCookieJar* RenderView::GetCookieJar() {
3672 return &cookie_jar_;
3673}
3674
initial.commit09911bf2008-07-26 23:55:293675void RenderView::SyncNavigationState() {
3676 if (!webview())
3677 return;
3678
[email protected]26aa0482009-09-30 16:55:273679 const WebHistoryItem& item = webview()->mainFrame()->currentHistoryItem();
[email protected]ca948a22009-06-25 19:36:173680 if (item.isNull())
initial.commit09911bf2008-07-26 23:55:293681 return;
[email protected]ca948a22009-06-25 19:36:173682
3683 Send(new ViewHostMsg_UpdateState(
3684 routing_id_, page_id_, webkit_glue::HistoryItemToString(item)));
initial.commit09911bf2008-07-26 23:55:293685}
3686
[email protected]b0950a72009-09-29 23:16:173687bool RenderView::DownloadImage(int id, const GURL& image_url, int image_size) {
3688 // Make sure webview was not shut down.
3689 if (!webview())
3690 return false;
3691 // Create an image resource fetcher and assign it with a call back object.
[email protected]bb461532010-11-26 21:50:233692 image_fetchers_.push_back(linked_ptr<ImageResourceFetcher>(
3693 new ImageResourceFetcher(
3694 image_url, webview()->mainFrame(), id, image_size,
3695 NewCallback(this, &RenderView::DidDownloadImage))));
[email protected]b0950a72009-09-29 23:16:173696 return true;
3697}
3698
3699void RenderView::DidDownloadImage(ImageResourceFetcher* fetcher,
initial.commit09911bf2008-07-26 23:55:293700 const SkBitmap& image) {
[email protected]b0950a72009-09-29 23:16:173701 // Notify requester of image download status.
[email protected]d8e74e82011-03-15 19:38:483702 Send(new ViewHostMsg_DidDownloadFavicon(routing_id_,
[email protected]51bd36612009-10-20 22:49:473703 fetcher->id(),
3704 fetcher->image_url(),
3705 image.isNull(),
3706 image));
[email protected]bb461532010-11-26 21:50:233707
3708 // Remove the image fetcher from our pending list. We're in the callback from
3709 // ImageResourceFetcher, best to delay deletion.
3710 for (ImageResourceFetcherList::iterator iter = image_fetchers_.begin();
3711 iter != image_fetchers_.end(); ++iter) {
3712 if (iter->get() == fetcher) {
3713 iter->release();
3714 image_fetchers_.erase(iter);
3715 break;
3716 }
3717 }
[email protected]b0950a72009-09-29 23:16:173718 MessageLoop::current()->DeleteSoon(FROM_HERE, fetcher);
initial.commit09911bf2008-07-26 23:55:293719}
3720
[email protected]d8e74e82011-03-15 19:38:483721void RenderView::OnDownloadFavicon(int id,
[email protected]bf5c2ff392009-07-08 16:24:333722 const GURL& image_url,
3723 int image_size) {
[email protected]f11ca0732009-04-11 00:09:343724 bool data_image_failed = false;
3725 if (image_url.SchemeIs("data")) {
3726 SkBitmap data_image = ImageFromDataUrl(image_url);
3727 data_image_failed = data_image.empty();
3728 if (!data_image_failed) {
[email protected]d8e74e82011-03-15 19:38:483729 Send(new ViewHostMsg_DidDownloadFavicon(routing_id_, id, image_url, false,
[email protected]bf5c2ff392009-07-08 16:24:333730 data_image));
[email protected]f11ca0732009-04-11 00:09:343731 }
3732 }
3733
[email protected]bf5c2ff392009-07-08 16:24:333734 if (data_image_failed ||
[email protected]b0950a72009-09-29 23:16:173735 !DownloadImage(id, image_url, image_size)) {
[email protected]d8e74e82011-03-15 19:38:483736 Send(new ViewHostMsg_DidDownloadFavicon(routing_id_, id, image_url, true,
[email protected]bf5c2ff392009-07-08 16:24:333737 SkBitmap()));
3738 }
initial.commit09911bf2008-07-26 23:55:293739}
3740
[email protected]f11ca0732009-04-11 00:09:343741SkBitmap RenderView::ImageFromDataUrl(const GURL& url) const {
3742 std::string mime_type, char_set, data;
3743 if (net::DataURL::Parse(url, &mime_type, &char_set, &data) && !data.empty()) {
3744 // Decode the favicon using WebKit's image decoder.
[email protected]f23a8c12011-03-15 14:43:433745 webkit_glue::ImageDecoder decoder(gfx::Size(kFaviconSize, kFaviconSize));
[email protected]f11ca0732009-04-11 00:09:343746 const unsigned char* src_data =
3747 reinterpret_cast<const unsigned char*>(&data[0]);
3748
3749 return decoder.Decode(src_data, data.size());
3750 }
3751 return SkBitmap();
3752}
3753
initial.commit09911bf2008-07-26 23:55:293754void RenderView::OnGetApplicationInfo(int page_id) {
[email protected]38789d82010-11-17 06:03:443755 WebApplicationInfo app_info;
3756 if (page_id == page_id_) {
3757 string16 error;
3758 web_apps::ParseWebAppFromWebDocument(webview()->mainFrame(), &app_info,
3759 &error);
3760 }
initial.commit09911bf2008-07-26 23:55:293761
3762 // Prune out any data URLs in the set of icons. The browser process expects
3763 // any icon with a data URL to have originated from a favicon. We don't want
3764 // to decode arbitrary data URLs in the browser process. See
3765 // http://b/issue?id=1162972
3766 for (size_t i = 0; i < app_info.icons.size(); ++i) {
[email protected]6de74452009-02-25 18:04:593767 if (app_info.icons[i].url.SchemeIs(chrome::kDataScheme)) {
initial.commit09911bf2008-07-26 23:55:293768 app_info.icons.erase(app_info.icons.begin() + i);
3769 --i;
3770 }
3771 }
3772
[email protected]44c49c92011-03-28 16:17:233773 Send(new ExtensionHostMsg_DidGetApplicationInfo(
3774 routing_id_, page_id, app_info));
initial.commit09911bf2008-07-26 23:55:293775}
3776
[email protected]7ccddb8c2009-08-04 17:36:553777GURL RenderView::GetAlternateErrorPageURL(const GURL& failed_url,
initial.commit09911bf2008-07-26 23:55:293778 ErrorPageType error_type) {
[email protected]7ccddb8c2009-08-04 17:36:553779 if (failed_url.SchemeIsSecure()) {
initial.commit09911bf2008-07-26 23:55:293780 // If the URL that failed was secure, then the embedding web page was not
3781 // expecting a network attacker to be able to manipulate its contents. As
3782 // we fetch alternate error pages over HTTP, we would be allowing a network
3783 // attacker to manipulate the contents of the response if we tried to use
3784 // the link doctor here.
[email protected]810a52ef2010-01-08 01:22:153785 return GURL();
initial.commit09911bf2008-07-26 23:55:293786 }
3787
3788 // Grab the base URL from the browser process.
3789 if (!alternate_error_page_url_.is_valid())
[email protected]810a52ef2010-01-08 01:22:153790 return GURL();
initial.commit09911bf2008-07-26 23:55:293791
3792 // Strip query params from the failed URL.
3793 GURL::Replacements remove_params;
3794 remove_params.ClearUsername();
3795 remove_params.ClearPassword();
3796 remove_params.ClearQuery();
3797 remove_params.ClearRef();
[email protected]7ccddb8c2009-08-04 17:36:553798 const GURL url_to_send = failed_url.ReplaceComponents(remove_params);
[email protected]6fd28f642010-03-15 17:15:503799 std::string spec_to_send = url_to_send.spec();
3800 // Notify link doctor of the url truncation by sending of "?" at the end.
3801 if (failed_url.has_query())
3802 spec_to_send.append("?");
initial.commit09911bf2008-07-26 23:55:293803
3804 // Construct the query params to send to link doctor.
3805 std::string params(alternate_error_page_url_.query());
3806 params.append("&url=");
[email protected]6fd28f642010-03-15 17:15:503807 params.append(EscapeQueryParamValue(spec_to_send, true));
initial.commit09911bf2008-07-26 23:55:293808 params.append("&sourceid=chrome");
3809 params.append("&error=");
3810 switch (error_type) {
3811 case DNS_ERROR:
3812 params.append("dnserror");
3813 break;
3814
3815 case HTTP_404:
3816 params.append("http404");
3817 break;
3818
[email protected]5df266ac2008-10-15 19:50:133819 case CONNECTION_ERROR:
[email protected]e1f934b2009-01-26 20:41:333820 params.append("connectionfailure");
[email protected]5df266ac2008-10-15 19:50:133821 break;
3822
initial.commit09911bf2008-07-26 23:55:293823 default:
3824 NOTREACHED() << "unknown ErrorPageType";
3825 }
3826
3827 // OK, build the final url to return.
3828 GURL::Replacements link_doctor_params;
3829 link_doctor_params.SetQueryStr(params);
3830 GURL url = alternate_error_page_url_.ReplaceComponents(link_doctor_params);
3831 return url;
3832}
3833
[email protected]c50008512011-02-03 01:17:273834WebUIBindings* RenderView::GetWebUIBindings() {
3835 if (!web_ui_bindings_.get()) {
3836 web_ui_bindings_.reset(new WebUIBindings());
[email protected]c091c2c2010-09-17 19:05:463837 }
[email protected]c50008512011-02-03 01:17:273838 return web_ui_bindings_.get();
[email protected]c091c2c2010-09-17 19:05:463839}
3840
3841ExternalHostBindings* RenderView::GetExternalHostBindings() {
3842 if (!external_host_bindings_.get()) {
3843 external_host_bindings_.reset(new ExternalHostBindings());
3844 }
3845 return external_host_bindings_.get();
3846}
3847
[email protected]0fdbf8c2010-07-08 20:33:013848WebKit::WebPlugin* RenderView::GetWebPluginFromPluginDocument() {
3849 return webview()->mainFrame()->document().to<WebPluginDocument>().plugin();
[email protected]24a7f3c2010-03-25 08:26:493850}
3851
[email protected]6069da8c2009-10-20 20:33:493852void RenderView::OnFind(int request_id, const string16& search_text,
3853 const WebFindOptions& options) {
[email protected]26aa0482009-09-30 16:55:273854 WebFrame* main_frame = webview()->mainFrame();
[email protected]24a7f3c2010-03-25 08:26:493855
3856 if (main_frame->document().isPluginDocument()) {
[email protected]24a7f3c2010-03-25 08:26:493857 if (options.findNext) {
3858 // Just navigate back/forward.
[email protected]0fdbf8c2010-07-08 20:33:013859 GetWebPluginFromPluginDocument()->selectFindResult(options.forward);
[email protected]24a7f3c2010-03-25 08:26:493860 } else {
[email protected]afdbd142010-07-10 08:01:233861 if (GetWebPluginFromPluginDocument()->startFind(
3862 search_text, options.matchCase, request_id)) {
[email protected]24a7f3c2010-03-25 08:26:493863 } else {
[email protected]e7c58a32010-08-13 19:47:113864 // Send "no results".
3865 Send(new ViewHostMsg_Find_Reply(routing_id_,
3866 request_id,
3867 0,
3868 gfx::Rect(),
3869 0,
3870 true));
[email protected]24a7f3c2010-03-25 08:26:493871 }
3872 }
3873 return;
3874 }
3875
[email protected]b4bb2502009-10-01 22:35:273876 WebFrame* frame_after_main = main_frame->traverseNext(true);
[email protected]26aa0482009-09-30 16:55:273877 WebFrame* focused_frame = webview()->focusedFrame();
initial.commit09911bf2008-07-26 23:55:293878 WebFrame* search_frame = focused_frame; // start searching focused frame.
3879
3880 bool multi_frame = (frame_after_main != main_frame);
3881
3882 // If we have multiple frames, we don't want to wrap the search within the
3883 // frame, so we check here if we only have main_frame in the chain.
3884 bool wrap_within_frame = !multi_frame;
3885
[email protected]b3f2b912009-04-09 16:18:523886 WebRect selection_rect;
initial.commit09911bf2008-07-26 23:55:293887 bool result = false;
3888
[email protected]7830da3e2009-11-06 16:27:263889 // If something is selected when we start searching it means we cannot just
3890 // increment the current match ordinal; we need to re-generate it.
3891 WebRange current_selection = focused_frame->selectionRange();
3892
initial.commit09911bf2008-07-26 23:55:293893 do {
[email protected]dd7daa82009-08-10 05:46:453894 result = search_frame->find(
[email protected]7ea066a2009-04-06 20:21:593895 request_id, search_text, options, wrap_within_frame, &selection_rect);
initial.commit09911bf2008-07-26 23:55:293896
3897 if (!result) {
3898 // don't leave text selected as you move to the next frame.
[email protected]a100d76bb2009-08-14 17:50:223899 search_frame->executeCommand(WebString::fromUTF8("Unselect"));
initial.commit09911bf2008-07-26 23:55:293900
3901 // Find the next frame, but skip the invisible ones.
3902 do {
3903 // What is the next frame to search? (we might be going backwards). Note
3904 // that we specify wrap=true so that search_frame never becomes NULL.
[email protected]7ea066a2009-04-06 20:21:593905 search_frame = options.forward ?
[email protected]b4bb2502009-10-01 22:35:273906 search_frame->traverseNext(true) :
3907 search_frame->traversePrevious(true);
[email protected]dd7daa82009-08-10 05:46:453908 } while (!search_frame->hasVisibleContent() &&
3909 search_frame != focused_frame);
initial.commit09911bf2008-07-26 23:55:293910
[email protected]884db412008-11-24 23:46:503911 // Make sure selection doesn't affect the search operation in new frame.
[email protected]a100d76bb2009-08-14 17:50:223912 search_frame->executeCommand(WebString::fromUTF8("Unselect"));
initial.commit09911bf2008-07-26 23:55:293913
3914 // If we have multiple frames and we have wrapped back around to the
3915 // focused frame, we need to search it once more allowing wrap within
3916 // the frame, otherwise it will report 'no match' if the focused frame has
3917 // reported matches, but no frames after the focused_frame contain a
3918 // match for the search word(s).
3919 if (multi_frame && search_frame == focused_frame) {
[email protected]dd7daa82009-08-10 05:46:453920 result = search_frame->find(
[email protected]7ea066a2009-04-06 20:21:593921 request_id, search_text, options, true, // Force wrapping.
3922 &selection_rect);
initial.commit09911bf2008-07-26 23:55:293923 }
3924 }
3925
[email protected]26aa0482009-09-30 16:55:273926 webview()->setFocusedFrame(search_frame);
initial.commit09911bf2008-07-26 23:55:293927 } while (!result && search_frame != focused_frame);
3928
[email protected]7830da3e2009-11-06 16:27:263929 if (options.findNext && current_selection.isNull()) {
[email protected]4f3dc372009-02-24 00:10:293930 // Force the main_frame to report the actual count.
[email protected]dd7daa82009-08-10 05:46:453931 main_frame->increaseMatchCount(0, request_id);
[email protected]4f3dc372009-02-24 00:10:293932 } else {
3933 // If nothing is found, set result to "0 of 0", otherwise, set it to
3934 // "-1 of 1" to indicate that we found at least one item, but we don't know
3935 // yet what is active.
3936 int ordinal = result ? -1 : 0; // -1 here means, we might know more later.
3937 int match_count = result ? 1 : 0; // 1 here means possibly more coming.
initial.commit09911bf2008-07-26 23:55:293938
[email protected]4f3dc372009-02-24 00:10:293939 // If we find no matches then this will be our last status update.
3940 // Otherwise the scoping effort will send more results.
3941 bool final_status_update = !result;
initial.commit09911bf2008-07-26 23:55:293942
[email protected]4f3dc372009-02-24 00:10:293943 // Send the search result over to the browser process.
[email protected]4f999132009-03-31 18:08:403944 Send(new ViewHostMsg_Find_Reply(routing_id_,
[email protected]7ea066a2009-04-06 20:21:593945 request_id,
[email protected]4f3dc372009-02-24 00:10:293946 match_count,
3947 selection_rect,
3948 ordinal,
3949 final_status_update));
initial.commit09911bf2008-07-26 23:55:293950
initial.commit09911bf2008-07-26 23:55:293951 // Scoping effort begins, starting with the mainframe.
3952 search_frame = main_frame;
3953
[email protected]dd7daa82009-08-10 05:46:453954 main_frame->resetMatchCount();
initial.commit09911bf2008-07-26 23:55:293955
3956 do {
3957 // Cancel all old scoping requests before starting a new one.
[email protected]dd7daa82009-08-10 05:46:453958 search_frame->cancelPendingScopingEffort();
initial.commit09911bf2008-07-26 23:55:293959
3960 // We don't start another scoping effort unless at least one match has
3961 // been found.
3962 if (result) {
3963 // Start new scoping request. If the scoping function determines that it
3964 // needs to scope, it will defer until later.
[email protected]dd7daa82009-08-10 05:46:453965 search_frame->scopeStringMatches(request_id,
[email protected]7ea066a2009-04-06 20:21:593966 search_text,
3967 options,
initial.commit09911bf2008-07-26 23:55:293968 true); // reset the tickmarks
3969 }
3970
3971 // Iterate to the next frame. The frame will not necessarily scope, for
3972 // example if it is not visible.
[email protected]b4bb2502009-10-01 22:35:273973 search_frame = search_frame->traverseNext(true);
initial.commit09911bf2008-07-26 23:55:293974 } while (search_frame != main_frame);
3975 }
3976}
3977
[email protected]24a7f3c2010-03-25 08:26:493978void RenderView::OnStopFinding(const ViewMsg_StopFinding_Params& params) {
3979 WebView* view = webview();
3980 if (!view)
3981 return;
3982
3983 WebDocument doc = view->mainFrame()->document();
3984 if (doc.isPluginDocument()) {
[email protected]0fdbf8c2010-07-08 20:33:013985 GetWebPluginFromPluginDocument()->stopFind();
[email protected]24a7f3c2010-03-25 08:26:493986 return;
3987 }
3988
3989 bool clear_selection =
3990 params.action == ViewMsg_StopFinding_Params::kClearSelection;
3991 if (clear_selection)
3992 view->focusedFrame()->executeCommand(WebString::fromUTF8("Unselect"));
3993
3994 WebFrame* frame = view->mainFrame();
3995 while (frame) {
3996 frame->stopFinding(clear_selection);
3997 frame = frame->traverseNext(false);
3998 }
3999
4000 if (params.action == ViewMsg_StopFinding_Params::kActivateSelection) {
4001 WebFrame* focused_frame = view->focusedFrame();
4002 if (focused_frame) {
4003 WebDocument doc = focused_frame->document();
4004 if (!doc.isNull()) {
4005 WebNode node = doc.focusedNode();
4006 if (!node.isNull())
4007 node.simulateClick();
4008 }
4009 }
4010 }
4011}
4012
4013void RenderView::OnFindReplyAck() {
4014 // Check if there is any queued up request waiting to be sent.
4015 if (queued_find_reply_message_.get()) {
4016 // Send the search result over to the browser process.
[email protected]d22d8732010-05-04 19:24:424017 Send(queued_find_reply_message_.release());
[email protected]24a7f3c2010-03-25 08:26:494018 }
4019}
4020
[email protected]8934a3b2010-02-25 00:34:004021bool RenderView::AllowContentType(ContentSettingsType settings_type) {
[email protected]0de80162010-02-03 04:52:354022 // CONTENT_SETTING_ASK is only valid for cookies.
[email protected]8934a3b2010-02-25 00:34:004023 return current_content_settings_.settings[settings_type] !=
4024 CONTENT_SETTING_BLOCK;
4025}
4026
[email protected]55126132010-08-19 14:53:284027void RenderView::DidBlockContentType(ContentSettingsType settings_type,
4028 const std::string& resource_identifier) {
[email protected]8934a3b2010-02-25 00:34:004029 if (!content_blocked_[settings_type]) {
4030 content_blocked_[settings_type] = true;
[email protected]55126132010-08-19 14:53:284031 Send(new ViewHostMsg_ContentBlocked(routing_id_, settings_type,
4032 resource_identifier));
[email protected]0de80162010-02-03 04:52:354033 }
[email protected]0de80162010-02-03 04:52:354034}
4035
[email protected]71b0d5d2010-02-15 05:43:074036void RenderView::ClearBlockedContentSettings() {
4037 for (size_t i = 0; i < arraysize(content_blocked_); ++i)
4038 content_blocked_[i] = false;
4039}
4040
[email protected]0bd753682010-12-16 18:15:524041WebPlugin* RenderView::CreatePepperPlugin(
4042 WebFrame* frame,
4043 const WebPluginParams& params,
4044 const FilePath& path,
4045 webkit::ppapi::PluginModule* pepper_module) {
4046 return new webkit::ppapi::WebPluginImpl(
[email protected]b75b8292010-10-01 07:28:254047 pepper_module, params, pepper_delegate_.AsWeakPtr());
[email protected]aad51d1c2010-08-05 08:38:094048}
[email protected]00152e92010-07-19 11:47:404049
[email protected]191eb3f72010-12-21 06:27:504050WebPlugin* RenderView::CreateNPAPIPlugin(
4051 WebFrame* frame,
4052 const WebPluginParams& params,
4053 const FilePath& path,
4054 const std::string& mime_type) {
4055 return new webkit::npapi::WebPluginImpl(
[email protected]20a793e2010-10-12 06:50:084056 frame, params, path, mime_type, AsWeakPtr());
[email protected]00152e92010-07-19 11:47:404057}
4058
[email protected]40bd6582009-12-04 23:49:514059void RenderView::OnZoom(PageZoom::Function function) {
4060 if (!webview()) // Not sure if this can happen, but no harm in being safe.
4061 return;
4062
[email protected]258d31122010-05-09 10:59:414063 webview()->hidePopups();
[email protected]b03794d2010-03-26 19:57:524064
[email protected]b75b8292010-10-01 07:28:254065 double old_zoom_level = webview()->zoomLevel();
4066 double zoom_level;
4067 if (function == PageZoom::RESET) {
4068 zoom_level = 0;
4069 } else if (static_cast<int>(old_zoom_level) == old_zoom_level) {
4070 // Previous zoom level is a whole number, so just increment/decrement.
4071 zoom_level = old_zoom_level + function;
4072 } else {
4073 // Either the user hit the zoom factor limit and thus the zoom level is now
4074 // not a whole number, or a plugin changed it to a custom value. We want
4075 // to go to the next whole number so that the user can always get back to
4076 // 100% with the keyboard/menu.
4077 if ((old_zoom_level > 1 && function > 0) ||
4078 (old_zoom_level < 1 && function < 0)) {
[email protected]3209e7112010-10-01 23:53:454079 zoom_level = static_cast<int>(old_zoom_level + function);
[email protected]b75b8292010-10-01 07:28:254080 } else {
4081 // We're going towards 100%, so first go to the next whole number.
4082 zoom_level = static_cast<int>(old_zoom_level);
4083 }
4084 }
[email protected]40bd6582009-12-04 23:49:514085
[email protected]b75b8292010-10-01 07:28:254086 webview()->setZoomLevel(false, zoom_level);
4087 zoomLevelChanged();
[email protected]40bd6582009-12-04 23:49:514088}
4089
[email protected]d0b8d092010-10-25 04:05:174090void RenderView::OnSetZoomLevel(double zoom_level) {
4091 // Don't set zoom level for full-page plugin since they don't use the same
4092 // zoom settings.
4093 if (webview()->mainFrame()->document().isPluginDocument())
4094 return;
4095
4096 webview()->hidePopups();
4097 webview()->setZoomLevel(false, zoom_level);
4098 zoomLevelChanged();
4099}
4100
[email protected]9d797f32010-04-23 07:17:544101void RenderView::OnSetContentSettingsForLoadingURL(
4102 const GURL& url,
[email protected]f85f0702010-01-30 09:31:014103 const ContentSettings& content_settings) {
[email protected]9d797f32010-04-23 07:17:544104 host_content_settings_[url] = content_settings;
[email protected]f85f0702010-01-30 09:31:014105}
4106
[email protected]9d797f32010-04-23 07:17:544107void RenderView::OnSetZoomLevelForLoadingURL(const GURL& url,
[email protected]b75b8292010-10-01 07:28:254108 double zoom_level) {
[email protected]9d797f32010-04-23 07:17:544109 host_zoom_levels_[url] = zoom_level;
initial.commit09911bf2008-07-26 23:55:294110}
4111
[email protected]41fc0322009-09-04 22:23:404112void RenderView::OnSetPageEncoding(const std::string& encoding_name) {
[email protected]26aa0482009-09-30 16:55:274113 webview()->setPageEncoding(WebString::fromUTF8(encoding_name));
initial.commit09911bf2008-07-26 23:55:294114}
4115
[email protected]a697f4c2009-09-14 22:30:184116void RenderView::OnResetPageEncodingToDefault() {
[email protected]26aa0482009-09-30 16:55:274117 WebString no_encoding;
4118 webview()->setPageEncoding(no_encoding);
[email protected]a697f4c2009-09-14 22:30:184119}
4120
[email protected]dd7daa82009-08-10 05:46:454121WebFrame* RenderView::GetChildFrame(const std::wstring& xpath) const {
4122 if (xpath.empty())
[email protected]26aa0482009-09-30 16:55:274123 return webview()->mainFrame();
[email protected]dd7daa82009-08-10 05:46:454124
4125 // xpath string can represent a frame deep down the tree (across multiple
4126 // frame DOMs).
4127 // Example, /html/body/table/tbody/tr/td/iframe\n/frameset/frame[0]
4128 // should break into 2 xpaths
4129 // /html/body/table/tbody/tr/td/iframe & /frameset/frame[0]
4130
[email protected]26aa0482009-09-30 16:55:274131 WebFrame* frame = webview()->mainFrame();
[email protected]dd7daa82009-08-10 05:46:454132
4133 std::wstring xpath_remaining = xpath;
4134 while (!xpath_remaining.empty()) {
4135 std::wstring::size_type delim_pos = xpath_remaining.find_first_of(L'\n');
4136 std::wstring xpath_child;
4137 if (delim_pos != std::wstring::npos) {
4138 xpath_child = xpath_remaining.substr(0, delim_pos);
4139 xpath_remaining.erase(0, delim_pos + 1);
4140 } else {
4141 xpath_remaining.swap(xpath_child);
4142 }
4143 frame = frame->findChildByExpression(WideToUTF16Hack(xpath_child));
initial.commit09911bf2008-07-26 23:55:294144 }
4145
[email protected]dd7daa82009-08-10 05:46:454146 return frame;
initial.commit09911bf2008-07-26 23:55:294147}
4148
[email protected]13a1e4c3c2011-02-03 21:07:094149WebNode RenderView::GetFocusedNode() const {
4150 if (!webview())
4151 return WebNode();
4152 WebFrame* focused_frame = webview()->focusedFrame();
4153 if (focused_frame) {
4154 WebDocument doc = focused_frame->document();
4155 if (!doc.isNull())
4156 return doc.focusedNode();
4157 }
4158
4159 return WebNode();
4160}
4161
[email protected]882b7b22010-10-05 03:34:534162void RenderView::EvaluateScript(const string16& frame_xpath,
4163 const string16& script,
4164 int id,
4165 bool notify_result) {
4166 v8::Handle<v8::Value> result;
4167 WebFrame* web_frame = GetChildFrame(UTF16ToWideHack(frame_xpath));
4168 if (web_frame)
4169 result = web_frame->executeScriptAndReturnValue(WebScriptSource(script));
4170 if (notify_result) {
[email protected]81f9fe0b2010-12-07 00:35:294171 ListValue list;
4172 if (web_frame) {
4173 v8::HandleScope handle_scope;
4174 v8::Local<v8::Context> context = web_frame->mainWorldScriptContext();
4175 v8::Context::Scope context_scope(context);
4176 list.Set(0, ConvertV8Value(result));
4177 } else {
4178 list.Set(0, Value::CreateNullValue());
4179 }
4180 Send(new ViewHostMsg_ScriptEvalResponse(routing_id_, id, list));
[email protected]882b7b22010-10-05 03:34:534181 }
initial.commit09911bf2008-07-26 23:55:294182}
4183
[email protected]1810e132009-03-24 23:35:484184void RenderView::InsertCSS(const std::wstring& frame_xpath,
[email protected]ffaef0c2009-09-15 17:08:084185 const std::string& css,
4186 const std::string& id) {
[email protected]1810e132009-03-24 23:35:484187 WebFrame* web_frame = GetChildFrame(frame_xpath);
4188 if (!web_frame)
4189 return;
4190
[email protected]ffaef0c2009-09-15 17:08:084191 web_frame->insertStyleText(WebString::fromUTF8(css), WebString::fromUTF8(id));
[email protected]1810e132009-03-24 23:35:484192}
4193
[email protected]882b7b22010-10-05 03:34:534194void RenderView::OnScriptEvalRequest(const string16& frame_xpath,
4195 const string16& jscript,
4196 int id,
4197 bool notify_result) {
4198 EvaluateScript(frame_xpath, jscript, id, notify_result);
initial.commit09911bf2008-07-26 23:55:294199}
4200
[email protected]1810e132009-03-24 23:35:484201void RenderView::OnCSSInsertRequest(const std::wstring& frame_xpath,
[email protected]ffaef0c2009-09-15 17:08:084202 const std::string& css,
4203 const std::string& id) {
4204 InsertCSS(frame_xpath, css, id);
[email protected]ae461542009-06-19 19:03:414205
4206 // Notify RenderViewHost that css has been inserted into the frame.
4207 Send(new ViewHostMsg_OnCSSInserted(routing_id_));
[email protected]1810e132009-03-24 23:35:484208}
4209
[email protected]81e63782009-02-27 19:35:094210void RenderView::OnAllowBindings(int enabled_bindings_flags) {
4211 enabled_bindings_ |= enabled_bindings_flags;
initial.commit09911bf2008-07-26 23:55:294212}
4213
[email protected]d0980792011-02-13 19:41:404214void RenderView::OnSetWebUIProperty(const std::string& name,
initial.commit09911bf2008-07-26 23:55:294215 const std::string& value) {
[email protected]c09163a2011-02-15 00:05:554216 DCHECK(BindingsPolicy::is_web_ui_enabled(enabled_bindings_));
[email protected]c50008512011-02-03 01:17:274217 GetWebUIBindings()->SetProperty(name, value);
initial.commit09911bf2008-07-26 23:55:294218}
4219
4220void RenderView::OnReservePageIDRange(int size_of_range) {
4221 next_page_id_ += size_of_range + 1;
4222}
4223
[email protected]59f4f2fa2011-03-23 01:00:554224void RenderView::OnDragTargetDragEnter(const WebDropData& drop_data,
4225 const gfx::Point& client_point,
4226 const gfx::Point& screen_point,
4227 WebDragOperationsMask ops) {
4228 WebDragOperation operation = webview()->dragTargetDragEnter(
4229 drop_data.ToDragData(),
4230 0, // drag identity, unused
4231 client_point,
4232 screen_point,
4233 ops);
4234
4235 Send(new DragHostMsg_UpdateDragCursor(routing_id_, operation));
4236}
4237
4238void RenderView::OnDragTargetDragOver(const gfx::Point& client_point,
4239 const gfx::Point& screen_point,
4240 WebDragOperationsMask ops) {
4241 WebDragOperation operation = webview()->dragTargetDragOver(
4242 client_point,
4243 screen_point,
4244 ops);
4245
4246 Send(new DragHostMsg_UpdateDragCursor(routing_id_, operation));
4247}
4248
4249void RenderView::OnDragTargetDragLeave() {
4250 webview()->dragTargetDragLeave();
4251}
4252
4253void RenderView::OnDragTargetDrop(const gfx::Point& client_point,
4254 const gfx::Point& screen_point) {
4255 webview()->dragTargetDrop(client_point, screen_point);
4256}
4257
[email protected]e80c73b2009-04-07 23:24:584258void RenderView::OnDragSourceEndedOrMoved(const gfx::Point& client_point,
4259 const gfx::Point& screen_point,
[email protected]1d9f4132009-09-08 17:29:254260 bool ended,
4261 WebDragOperation op) {
[email protected]5f9ae6c2009-07-08 02:38:034262 if (ended) {
[email protected]26aa0482009-09-30 16:55:274263 webview()->dragSourceEndedAt(client_point, screen_point, op);
[email protected]daec5d62010-06-04 09:14:204264 } else {
4265 webview()->dragSourceMovedTo(client_point, screen_point, op);
[email protected]5f9ae6c2009-07-08 02:38:034266 }
initial.commit09911bf2008-07-26 23:55:294267}
4268
4269void RenderView::OnDragSourceSystemDragEnded() {
[email protected]26aa0482009-09-30 16:55:274270 webview()->dragSourceSystemDragEnded();
initial.commit09911bf2008-07-26 23:55:294271}
4272
initial.commit09911bf2008-07-26 23:55:294273void RenderView::OnUpdateWebPreferences(const WebPreferences& prefs) {
[email protected]2fab253a2009-08-17 23:00:594274 webkit_preferences_ = prefs;
4275 webkit_preferences_.Apply(webview());
initial.commit09911bf2008-07-26 23:55:294276}
4277
4278void RenderView::OnSetAltErrorPageURL(const GURL& url) {
4279 alternate_error_page_url_ = url;
4280}
4281
[email protected]b29aa74b2011-01-31 21:41:084282void RenderView::OnCustomContextMenuAction(
4283 const webkit_glue::CustomContextMenuContext& custom_context,
4284 unsigned action) {
4285 if (custom_context.is_pepper_menu)
4286 pepper_delegate_.OnCustomContextMenuAction(custom_context, action);
4287 else
4288 webview()->performCustomContextMenuAction(action);
[email protected]a0c7153e2009-12-09 14:36:334289}
4290
initial.commit09911bf2008-07-26 23:55:294291void RenderView::OnInstallMissingPlugin() {
4292 // This could happen when the first default plugin is deleted.
[email protected]f103ab72009-09-02 17:10:594293 if (first_default_plugin_)
4294 first_default_plugin_->InstallMissingPlugin();
initial.commit09911bf2008-07-26 23:55:294295}
4296
[email protected]90dba072011-01-20 20:10:204297void RenderView::OnDisplayPrerenderedPage() {
[email protected]987d51af2011-02-24 17:50:184298 DCHECK(is_prerendering_);
4299 is_prerendering_ = false;
[email protected]90dba072011-01-20 20:10:204300
[email protected]987d51af2011-02-24 17:50:184301 // Update NavigationState for histograms.
4302 WebDataSource* ds = webview()->mainFrame()->dataSource();
4303 NavigationState* navigation_state = NavigationState::FromDataSource(ds);
[email protected]e0b181752011-02-13 23:56:434304 navigation_state->set_prerendered_page_display_time(Time::Now());
[email protected]987d51af2011-02-24 17:50:184305
4306 // If there is a provisional data source, update its NavigationState, too.
4307 WebDataSource* provisional_ds =
4308 webview()->mainFrame()->provisionalDataSource();
4309 if (provisional_ds) {
4310 NavigationState* provisional_navigation_state =
4311 NavigationState::FromDataSource(provisional_ds);
4312 if (provisional_navigation_state) {
4313 provisional_navigation_state->set_prerendered_page_display_time(
4314 Time::Now());
4315 }
4316 }
[email protected]90dba072011-01-20 20:10:204317}
4318
[email protected]cdaf8d02010-03-30 19:52:474319void RenderView::OnFileChooserResponse(const std::vector<FilePath>& paths) {
[email protected]8029f5672009-03-20 22:33:364320 // This could happen if we navigated to a different page before the user
4321 // closed the chooser.
[email protected]cdaf8d02010-03-30 19:52:474322 if (file_chooser_completions_.empty())
[email protected]8029f5672009-03-20 22:33:364323 return;
4324
[email protected]cdaf8d02010-03-30 19:52:474325 WebVector<WebString> ws_file_names(paths.size());
4326 for (size_t i = 0; i < paths.size(); ++i)
4327 ws_file_names[i] = webkit_glue::FilePathToWebString(paths[i]);
[email protected]a1128322009-10-06 18:38:464328
[email protected]cdaf8d02010-03-30 19:52:474329 if (file_chooser_completions_.front()->completion)
4330 file_chooser_completions_.front()->completion->didChooseFile(ws_file_names);
4331 file_chooser_completions_.pop_front();
4332
4333 // If there are more pending file chooser requests, schedule one now.
4334 if (!file_chooser_completions_.empty()) {
4335 Send(new ViewHostMsg_RunFileChooser(routing_id_,
4336 file_chooser_completions_.front()->params));
4337 }
initial.commit09911bf2008-07-26 23:55:294338}
4339
4340void RenderView::OnEnableViewSourceMode() {
4341 if (!webview())
4342 return;
[email protected]26aa0482009-09-30 16:55:274343 WebFrame* main_frame = webview()->mainFrame();
initial.commit09911bf2008-07-26 23:55:294344 if (!main_frame)
4345 return;
4346
[email protected]dd7daa82009-08-10 05:46:454347 main_frame->enableViewSourceMode(true);
initial.commit09911bf2008-07-26 23:55:294348}
4349
[email protected]770dd8b2010-05-24 18:11:394350void RenderView::OnEnablePreferredSizeChangedMode(int flags) {
4351 DCHECK(flags != kPreferredSizeNothing);
[email protected]9fb325e2010-05-06 18:23:244352 if (send_preferred_size_changes_)
4353 return;
[email protected]9fb325e2010-05-06 18:23:244354 send_preferred_size_changes_ = true;
[email protected]770dd8b2010-05-24 18:11:394355
4356 // WebKit doesn't send a notification of the effective height of the page
4357 // changes, so poll for it.
4358 // TODO: Add a notification for this to WebKit, remove polling. After that's
4359 // done, rename kPreferredSizeHeightThisIsSlow to kPreferredSizeHeight.
4360 // http://crbug.com/44850
4361 if (flags & kPreferredSizeHeightThisIsSlow) {
4362 preferred_size_change_timer_.Start(TimeDelta::FromMilliseconds(10), this,
4363 &RenderView::CheckPreferredSize);
4364 }
[email protected]0666aef2009-05-13 19:48:084365}
4366
[email protected]cda45c02010-02-25 19:28:104367void RenderView::OnDisableScrollbarsForSmallWindows(
4368 const gfx::Size& disable_scrollbar_size_limit) {
4369 disable_scrollbars_size_limit_ = disable_scrollbar_size_limit;
4370}
4371
[email protected]80d96fa2009-06-10 22:34:514372void RenderView::OnSetRendererPrefs(const RendererPreferences& renderer_prefs) {
4373 renderer_preferences_ = renderer_prefs;
[email protected]6e282c92009-07-24 01:19:374374 UpdateFontRenderingFromRendererPrefs();
[email protected]0dd6f9b52010-10-14 16:39:134375#if defined(TOOLKIT_USES_GTK)
[email protected]1c83eb42009-09-11 21:08:414376 WebColorName name = WebKit::WebColorWebkitFocusRingColor;
4377 WebKit::setNamedColors(&name, &renderer_prefs.focus_ring_color, 1);
[email protected]39cd64ed2010-02-05 02:18:464378 WebKit::setCaretBlinkInterval(renderer_prefs.caret_blink_interval);
[email protected]8d1b864d12010-10-10 00:04:344379 gfx::NativeThemeLinux::instance()->SetScrollbarColors(
4380 renderer_prefs.thumb_inactive_color,
4381 renderer_prefs.thumb_active_color,
4382 renderer_prefs.track_color);
[email protected]93623c5d2009-12-10 21:40:324383
[email protected]644d77e2010-01-27 01:03:104384 if (webview()) {
[email protected]93623c5d2009-12-10 21:40:324385 webview()->setScrollbarColors(
4386 renderer_prefs.thumb_inactive_color,
4387 renderer_prefs.thumb_active_color,
4388 renderer_prefs.track_color);
[email protected]644d77e2010-01-27 01:03:104389 webview()->setSelectionColors(
4390 renderer_prefs.active_selection_bg_color,
4391 renderer_prefs.active_selection_fg_color,
4392 renderer_prefs.inactive_selection_bg_color,
4393 renderer_prefs.inactive_selection_fg_color);
[email protected]f98d7e3c2010-09-13 22:30:464394 webview()->themeChanged();
[email protected]644d77e2010-01-27 01:03:104395 }
[email protected]7a74e102009-09-03 00:16:564396#endif
[email protected]80d96fa2009-06-10 22:34:514397}
4398
[email protected]952cb702009-10-07 05:50:284399void RenderView::OnMediaPlayerActionAt(const gfx::Point& location,
4400 const WebMediaPlayerAction& action) {
4401 if (webview())
4402 webview()->performMediaPlayerAction(action, location);
[email protected]581b87eb2009-07-23 23:06:564403}
4404
[email protected]7b291f92009-08-14 05:43:534405void RenderView::OnNotifyRendererViewType(ViewType::Type type) {
4406 view_type_ = type;
4407}
4408
4409void RenderView::OnUpdateBrowserWindowId(int window_id) {
4410 browser_window_id_ = window_id;
4411}
4412
[email protected]dea2d372010-09-25 06:41:144413void RenderView::OnEnableAccessibility() {
4414 if (WebAccessibilityCache::accessibilityEnabled())
4415 return;
[email protected]9f4db512010-05-10 20:21:414416
[email protected]dea2d372010-09-25 06:41:144417 WebAccessibilityCache::enableAccessibility();
4418
4419 if (webview()) {
4420 // It's possible that the webview has already loaded a webpage without
4421 // accessibility being enabled. Initialize the browser's cached
4422 // accessibility tree by sending it a 'load complete' notification.
4423 postAccessibilityNotification(
4424 webview()->accessibilityObject(),
4425 WebKit::WebAccessibilityNotificationLoadComplete);
4426 }
[email protected]266eb6f2008-09-30 23:56:504427}
4428
[email protected]aef92842010-05-21 16:54:364429void RenderView::OnSetAccessibilityFocus(int acc_obj_id) {
4430 if (!accessibility_.get())
4431 return;
[email protected]02ea2f312010-09-27 17:03:364432
4433 WebAccessibilityObject obj = accessibility_->getObjectById(acc_obj_id);
4434 WebAccessibilityObject root = webview()->accessibilityObject();
4435 if (!obj.isValid() || !root.isValid())
4436 return;
4437
4438 // By convention, calling SetFocus on the root of the tree should clear the
4439 // current focus. Otherwise set the focus to the new node.
4440 if (accessibility_->addOrGetId(obj) == accessibility_->addOrGetId(root))
4441 webview()->clearFocusedNode();
4442 else
4443 obj.setFocused(true);
[email protected]aef92842010-05-21 16:54:364444}
4445
4446void RenderView::OnAccessibilityDoDefaultAction(int acc_obj_id) {
4447 if (!accessibility_.get())
4448 return;
[email protected]02ea2f312010-09-27 17:03:364449
4450 WebAccessibilityObject obj = accessibility_->getObjectById(acc_obj_id);
4451 if (!obj.isValid())
4452 return;
4453
4454 obj.performDefaultAction();
[email protected]aef92842010-05-21 16:54:364455}
4456
[email protected]9892b472010-09-16 00:23:424457void RenderView::OnAccessibilityNotificationsAck() {
[email protected]54ec7f82010-10-21 22:32:514458 DCHECK(accessibility_ack_pending_);
4459 accessibility_ack_pending_ = false;
4460 SendPendingAccessibilityNotifications();
[email protected]520cb7d72010-08-31 11:54:314461}
4462
initial.commit09911bf2008-07-26 23:55:294463void RenderView::OnGetAllSavableResourceLinksForCurrentPage(
4464 const GURL& page_url) {
4465 // Prepare list to storage all savable resource links.
4466 std::vector<GURL> resources_list;
4467 std::vector<GURL> referrers_list;
4468 std::vector<GURL> frames_list;
4469 webkit_glue::SavableResourcesResult result(&resources_list,
4470 &referrers_list,
4471 &frames_list);
4472
[email protected]dbeb3952009-10-13 18:01:184473 if (!webkit_glue::GetAllSavableResourceLinksForCurrentPage(
4474 webview(),
4475 page_url,
4476 &result,
4477 chrome::kSavableSchemes)) {
initial.commit09911bf2008-07-26 23:55:294478 // If something is wrong when collecting all savable resource links,
4479 // send empty list to embedder(browser) to tell it failed.
4480 referrers_list.clear();
4481 resources_list.clear();
4482 frames_list.clear();
4483 }
4484
4485 // Send result of all savable resource links to embedder.
4486 Send(new ViewHostMsg_SendCurrentPageAllSavableResourceLinks(routing_id_,
4487 resources_list,
4488 referrers_list,
4489 frames_list));
4490}
4491
4492void RenderView::OnGetSerializedHtmlDataForCurrentPageWithLocalLinks(
[email protected]f6b48532009-02-12 01:56:324493 const std::vector<GURL>& links,
[email protected]fde6714d12009-02-18 22:39:314494 const std::vector<FilePath>& local_paths,
4495 const FilePath& local_directory_name) {
[email protected]d9ec5c0f2009-12-23 11:55:074496
4497 // Convert std::vector of GURLs to WebVector<WebURL>
4498 WebVector<WebURL> weburl_links(links);
4499
4500 // Convert std::vector of std::strings to WebVector<WebString>
4501 WebVector<WebString> webstring_paths(local_paths.size());
4502 for (size_t i = 0; i < local_paths.size(); i++)
4503 webstring_paths[i] = webkit_glue::FilePathToWebString(local_paths[i]);
4504
4505 WebPageSerializer::serialize(webview()->mainFrame(),
4506 true, this, weburl_links, webstring_paths,
4507 webkit_glue::FilePathToWebString(
4508 local_directory_name));
initial.commit09911bf2008-07-26 23:55:294509}
4510
[email protected]d9ec5c0f2009-12-23 11:55:074511void RenderView::didSerializeDataForFrame(const WebURL& frame_url,
4512 const WebCString& data,
4513 WebPageSerializerClient::PageSerializationStatus status) {
4514 Send(new ViewHostMsg_SendSerializedHtmlData(
4515 routing_id_,
4516 frame_url,
4517 data.data(),
4518 static_cast<int32>(status)));
initial.commit09911bf2008-07-26 23:55:294519}
4520
[email protected]9b18a84f2010-06-10 15:54:044521void RenderView::OnShouldClose() {
[email protected]26aa0482009-09-30 16:55:274522 bool should_close = webview()->dispatchBeforeUnloadEvent();
[email protected]04b4a6c2008-08-02 00:44:474523 Send(new ViewHostMsg_ShouldClose_ACK(routing_id_, should_close));
initial.commit09911bf2008-07-26 23:55:294524}
4525
[email protected]eb6b87a2009-07-24 15:57:394526void RenderView::OnClosePage(const ViewMsg_ClosePage_Params& params) {
initial.commit09911bf2008-07-26 23:55:294527 // TODO(creis): We'd rather use webview()->Close() here, but that currently
4528 // sets the WebView's delegate_ to NULL, preventing any JavaScript dialogs
4529 // in the onunload handler from appearing. For now, we're bypassing that and
4530 // calling the FrameLoader's CloseURL method directly. This should be
4531 // revisited to avoid having two ways to close a page. Having a single way
4532 // to close that can run onunload is also useful for fixing
4533 // http://b/issue?id=753080.
[email protected]a5a65ac2010-11-05 18:14:364534 // TODO(davemoore) This code should be removed once willClose() gets
4535 // called when a page is destroyed. page_load_histograms_.Dump() is safe
4536 // to call multiple times for the same frame, but it will simplify things.
4537 page_load_histograms_.Dump(webview()->mainFrame());
4538 page_load_histograms_.ResetCrossFramePropertyAccess();
[email protected]26aa0482009-09-30 16:55:274539 webview()->dispatchUnloadEvent();
initial.commit09911bf2008-07-26 23:55:294540
[email protected]eb6b87a2009-07-24 15:57:394541 // Just echo back the params in the ACK.
4542 Send(new ViewHostMsg_ClosePage_ACK(routing_id_, params));
initial.commit09911bf2008-07-26 23:55:294543}
4544
4545void RenderView::OnThemeChanged() {
[email protected]6c8afae52009-01-22 02:24:574546#if defined(OS_WIN)
[email protected]c6d942212011-03-30 19:02:164547 gfx::NativeThemeWin::instance()->CloseHandles();
[email protected]f98d7e3c2010-09-13 22:30:464548 if (webview())
4549 webview()->themeChanged();
[email protected]6c8afae52009-01-22 02:24:574550#else // defined(OS_WIN)
4551 // TODO(port): we don't support theming on non-Windows platforms yet
4552 NOTIMPLEMENTED();
4553#endif
initial.commit09911bf2008-07-26 23:55:294554}
4555
[email protected]9b18a84f2010-06-10 15:54:044556void RenderView::OnHandleMessageFromExternalHost(const std::string& message,
4557 const std::string& origin,
4558 const std::string& target) {
[email protected]3ac14a052008-08-15 21:22:154559 if (message.empty())
4560 return;
[email protected]c091c2c2010-09-17 19:05:464561 GetExternalHostBindings()->ForwardMessageFromExternalHost(message, origin,
4562 target);
[email protected]3ac14a052008-08-15 21:22:154563}
4564
[email protected]0aa55312008-10-17 21:53:084565void RenderView::OnDisassociateFromPopupCount() {
4566 if (decrement_shared_popup_at_destruction_)
4567 shared_popup_counter_->data--;
4568 shared_popup_counter_ = new SharedRenderViewCounter(0);
4569 decrement_shared_popup_at_destruction_ = false;
4570}
4571
[email protected]15d79e12009-08-02 19:23:454572bool RenderView::MaybeLoadAlternateErrorPage(WebFrame* frame,
4573 const WebURLError& error,
4574 bool replace) {
4575 // We only show alternate error pages in the main frame. They are
4576 // intended to assist the user when navigating, so there is not much
4577 // value in showing them for failed subframes. Ideally, we would be
4578 // able to use the TYPED transition type for this, but that flag is
4579 // not preserved across page reloads.
[email protected]dd7daa82009-08-10 05:46:454580 if (frame->parent())
[email protected]15d79e12009-08-02 19:23:454581 return false;
4582
4583 // Use the alternate error page service if this is a DNS failure or
[email protected]c53976d52009-08-07 18:58:374584 // connection failure.
[email protected]15d79e12009-08-02 19:23:454585 int ec = error.reason;
4586 if (ec != net::ERR_NAME_NOT_RESOLVED &&
4587 ec != net::ERR_CONNECTION_FAILED &&
4588 ec != net::ERR_CONNECTION_REFUSED &&
4589 ec != net::ERR_ADDRESS_UNREACHABLE &&
[email protected]c53976d52009-08-07 18:58:374590 ec != net::ERR_CONNECTION_TIMED_OUT)
[email protected]15d79e12009-08-02 19:23:454591 return false;
4592
4593 const GURL& error_page_url = GetAlternateErrorPageURL(error.unreachableURL,
[email protected]7ccddb8c2009-08-04 17:36:554594 ec == net::ERR_NAME_NOT_RESOLVED ? DNS_ERROR : CONNECTION_ERROR);
[email protected]15d79e12009-08-02 19:23:454595 if (!error_page_url.is_valid())
4596 return false;
4597
4598 // Load an empty page first so there is an immediate response to the error,
4599 // and then kick off a request for the alternate error page.
[email protected]dd7daa82009-08-10 05:46:454600 frame->loadHTMLString(std::string(),
[email protected]144143c2010-10-28 08:17:364601 GURL(chrome::kUnreachableWebDataURL),
[email protected]15d79e12009-08-02 19:23:454602 error.unreachableURL,
4603 replace);
4604
4605 // Now, create a fetcher for the error page and associate it with the data
4606 // source we just created via the LoadHTMLString call. That way if another
4607 // navigation occurs, the fetcher will get destroyed.
4608 NavigationState* navigation_state =
[email protected]dd7daa82009-08-10 05:46:454609 NavigationState::FromDataSource(frame->provisionalDataSource());
[email protected]15d79e12009-08-02 19:23:454610 navigation_state->set_alt_error_page_fetcher(
4611 new AltErrorPageResourceFetcher(
4612 error_page_url, frame, error,
4613 NewCallback(this, &RenderView::AltErrorPageFinished)));
4614 return true;
4615}
4616
[email protected]15d79e12009-08-02 19:23:454617void RenderView::AltErrorPageFinished(WebFrame* frame,
4618 const WebURLError& original_error,
4619 const std::string& html) {
4620 // Here, we replace the blank page we loaded previously.
[email protected]06333afe2011-02-24 14:55:094621 // If we failed to download the alternate error page, LoadNavigationErrorPage
[email protected]7ccddb8c2009-08-04 17:36:554622 // will simply display a default error page.
[email protected]06333afe2011-02-24 14:55:094623 LoadNavigationErrorPage(frame, WebURLRequest(), original_error, html, true);
[email protected]15d79e12009-08-02 19:23:454624}
4625
[email protected]30f75e62009-02-25 22:01:004626void RenderView::OnMoveOrResizeStarted() {
4627 if (webview())
[email protected]a72a1fa2010-05-03 22:18:474628 webview()->hidePopups();
[email protected]30f75e62009-02-25 22:01:004629}
4630
[email protected]30f75e62009-02-25 22:01:004631void RenderView::OnResize(const gfx::Size& new_size,
4632 const gfx::Rect& resizer_rect) {
[email protected]cda45c02010-02-25 19:28:104633 if (webview()) {
[email protected]a72a1fa2010-05-03 22:18:474634 webview()->hidePopups();
[email protected]cda45c02010-02-25 19:28:104635 if (send_preferred_size_changes_) {
[email protected]7339cd22010-10-27 00:11:204636 webview()->mainFrame()->setCanHaveScrollbars(
4637 should_display_scrollbars(new_size.width(), new_size.height()));
[email protected]cda45c02010-02-25 19:28:104638 }
4639 }
4640
[email protected]30f75e62009-02-25 22:01:004641 RenderWidget::OnResize(new_size, resizer_rect);
4642}
[email protected]0aa477bd2009-03-23 22:21:434643
[email protected]00c39612010-03-06 02:53:284644void RenderView::DidInitiatePaint() {
[email protected]53900d52010-06-16 04:25:014645 // Notify the pepper plugins that we started painting.
4646 pepper_delegate_.ViewInitiatedPaint();
[email protected]00c39612010-03-06 02:53:284647}
4648
4649void RenderView::DidFlushPaint() {
4650 // Notify any pepper plugins that we painted. This will call into the plugin,
4651 // and we it may ask to close itself as a result. This will, in turn, modify
4652 // our set, possibly invalidating the iterator. So we iterate on a copy that
4653 // won't change out from under us.
[email protected]53900d52010-06-16 04:25:014654 pepper_delegate_.ViewFlushedPaint();
4655
[email protected]00c39612010-03-06 02:53:284656 WebFrame* main_frame = webview()->mainFrame();
4657
4658 // If we have a provisional frame we are between the start and commit stages
4659 // of loading and we don't want to save stats.
4660 if (!main_frame->provisionalDataSource()) {
4661 WebDataSource* ds = main_frame->dataSource();
4662 NavigationState* navigation_state = NavigationState::FromDataSource(ds);
4663 DCHECK(navigation_state);
4664
[email protected]05c8e502010-08-15 15:13:524665 // TODO(jar): The following code should all be inside a method, probably in
4666 // NavigatorState.
[email protected]00c39612010-03-06 02:53:284667 Time now = Time::Now();
4668 if (navigation_state->first_paint_time().is_null()) {
4669 navigation_state->set_first_paint_time(now);
4670 }
4671 if (navigation_state->first_paint_after_load_time().is_null() &&
4672 !navigation_state->finish_load_time().is_null()) {
4673 navigation_state->set_first_paint_after_load_time(now);
4674 }
4675 }
4676}
4677
[email protected]719b36f2010-12-22 20:36:464678webkit::ppapi::PluginInstance* RenderView::GetBitmapForOptimizedPluginPaint(
[email protected]ca4847f2010-09-24 05:39:154679 const gfx::Rect& paint_bounds,
4680 TransportDIB** dib,
4681 gfx::Rect* location,
4682 gfx::Rect* clip) {
4683 return pepper_delegate_.GetBitmapForOptimizedPluginPaint(
4684 paint_bounds, dib, location, clip);
4685}
4686
[email protected]bcaf2272011-02-15 15:29:434687gfx::Point RenderView::GetScrollOffset() {
[email protected]d54169e92011-01-21 09:19:524688 WebKit::WebSize scroll_offset = webview()->mainFrame()->scrollOffset();
[email protected]bcaf2272011-02-15 15:29:434689 return gfx::Point(scroll_offset.width, scroll_offset.height);
[email protected]d54169e92011-01-21 09:19:524690}
4691
[email protected]05d478752009-04-08 23:38:164692void RenderView::OnClearFocusedNode() {
4693 if (webview())
[email protected]26aa0482009-09-30 16:55:274694 webview()->clearFocusedNode();
[email protected]05d478752009-04-08 23:38:164695}
4696
[email protected]699ab0d2009-04-23 23:19:144697void RenderView::OnSetBackground(const SkBitmap& background) {
4698 if (webview())
[email protected]b4bb2502009-10-01 22:35:274699 webview()->setIsTransparent(!background.empty());
[email protected]699ab0d2009-04-23 23:19:144700
4701 SetBackground(background);
4702}
4703
[email protected]8c66c5a2009-07-22 17:26:344704void RenderView::OnSetActive(bool active) {
4705 if (webview())
[email protected]b4bb2502009-10-01 22:35:274706 webview()->setIsActive(active);
[email protected]d8fd6fa2010-02-01 15:54:264707
4708#if defined(OS_MACOSX)
4709 std::set<WebPluginDelegateProxy*>::iterator plugin_it;
4710 for (plugin_it = plugin_delegates_.begin();
4711 plugin_it != plugin_delegates_.end(); ++plugin_it) {
4712 (*plugin_it)->SetWindowFocus(active);
4713 }
4714#endif
[email protected]8c66c5a2009-07-22 17:26:344715}
4716
[email protected]6ce7abc52010-02-02 18:40:144717#if defined(OS_MACOSX)
4718void RenderView::OnSetWindowVisibility(bool visible) {
4719 // Inform plugins that their container has changed visibility.
4720 std::set<WebPluginDelegateProxy*>::iterator plugin_it;
4721 for (plugin_it = plugin_delegates_.begin();
4722 plugin_it != plugin_delegates_.end(); ++plugin_it) {
4723 (*plugin_it)->SetContainerVisibility(visible);
4724 }
4725}
[email protected]1e6e3c992010-02-08 15:52:134726
[email protected]4d51d5bf2010-07-26 18:48:264727void RenderView::OnWindowFrameChanged(const gfx::Rect& window_frame,
4728 const gfx::Rect& view_frame) {
[email protected]1e6e3c992010-02-08 15:52:134729 // Inform plugins that their window's frame has changed.
4730 std::set<WebPluginDelegateProxy*>::iterator plugin_it;
4731 for (plugin_it = plugin_delegates_.begin();
4732 plugin_it != plugin_delegates_.end(); ++plugin_it) {
4733 (*plugin_it)->WindowFrameChanged(window_frame, view_frame);
4734 }
4735}
[email protected]935d63d2010-10-15 23:31:554736
[email protected]b7f75862011-01-21 21:15:134737void RenderView::OnPluginImeCompositionCompleted(const string16& text,
[email protected]935d63d2010-10-15 23:31:554738 int plugin_id) {
[email protected]b7f75862011-01-21 21:15:134739 // WebPluginDelegateProxy is responsible for figuring out if this event
[email protected]935d63d2010-10-15 23:31:554740 // applies to it or not, so inform all the delegates.
4741 std::set<WebPluginDelegateProxy*>::iterator plugin_it;
4742 for (plugin_it = plugin_delegates_.begin();
4743 plugin_it != plugin_delegates_.end(); ++plugin_it) {
[email protected]b7f75862011-01-21 21:15:134744 (*plugin_it)->ImeCompositionCompleted(text, plugin_id);
[email protected]935d63d2010-10-15 23:31:554745 }
4746}
[email protected]6ce7abc52010-02-02 18:40:144747#endif // OS_MACOSX
4748
[email protected]9892b472010-09-16 00:23:424749void RenderView::postAccessibilityNotification(
4750 const WebAccessibilityObject& obj,
4751 WebAccessibilityNotification notification) {
[email protected]dea2d372010-09-25 06:41:144752 if (!accessibility_.get() && webview()) {
4753 // Load complete should be our first notification sent.
4754 // TODO(ctguil): Investigate if a different notification is a WebCore bug.
4755 if (notification != WebKit::WebAccessibilityNotificationLoadComplete)
4756 return;
4757
4758 // Create and initialize our accessibility cache
4759 accessibility_.reset(WebAccessibilityCache::create());
4760 accessibility_->initialize(webview());
4761 }
4762
[email protected]a3fa4f92010-09-30 22:19:334763 if (!accessibility_->isCached(obj)) {
4764 // The browser doesn't know about objects that are not in the cache. Send a
4765 // children change for the first accestor that actually is in the cache.
4766 WebAccessibilityObject parent = obj;
4767 while (parent.isValid() && !accessibility_->isCached(parent))
4768 parent = parent.parentObject();
4769
4770 DCHECK(parent.isValid() && accessibility_->isCached(parent));
4771 if (!parent.isValid())
4772 return;
4773 postAccessibilityNotification(
4774 parent, WebKit::WebAccessibilityNotificationChildrenChanged);
4775
4776 // The parent's children change takes care of the child's children change.
4777 if (notification == WebKit::WebAccessibilityNotificationChildrenChanged)
4778 return;
4779 }
4780
[email protected]dea2d372010-09-25 06:41:144781 // Add the accessibility object to our cache and ensure it's valid.
[email protected]54ec7f82010-10-21 22:32:514782 RendererAccessibilityNotification acc_notification;
4783 acc_notification.id = accessibility_->addOrGetId(obj);
[email protected]a527a022011-02-10 02:32:364784 acc_notification.type = notification;
[email protected]54ec7f82010-10-21 22:32:514785 if (acc_notification.id < 0)
[email protected]a3018be2010-03-09 04:28:484786 return;
4787
[email protected]fffaf972011-03-24 01:34:354788 ViewHostMsg_AccessibilityNotification_Type::Value temp;
[email protected]a527a022011-02-10 02:32:364789 if (!WebAccessibilityNotificationToViewHostMsg(notification, &temp))
[email protected]54ec7f82010-10-21 22:32:514790 return;
[email protected]54ec7f82010-10-21 22:32:514791
4792 // Discard duplicate accessibility notifications.
4793 for (uint32 i = 0; i < pending_accessibility_notifications_.size(); i++) {
4794 if (pending_accessibility_notifications_[i].id == acc_notification.id &&
4795 pending_accessibility_notifications_[i].type == acc_notification.type) {
[email protected]9892b472010-09-16 00:23:424796 return;
[email protected]54ec7f82010-10-21 22:32:514797 }
[email protected]9892b472010-09-16 00:23:424798 }
[email protected]54ec7f82010-10-21 22:32:514799 pending_accessibility_notifications_.push_back(acc_notification);
[email protected]a3018be2010-03-09 04:28:484800
[email protected]54ec7f82010-10-21 22:32:514801 if (!accessibility_ack_pending_ && accessibility_method_factory_.empty()) {
4802 // When no accessibility notifications are in-flight post a task to send
4803 // the notifications to the browser. We use PostTask so that we can queue
4804 // up additional notifications.
4805 MessageLoop::current()->PostTask(
4806 FROM_HERE,
4807 accessibility_method_factory_.NewRunnableMethod(
4808 &RenderView::SendPendingAccessibilityNotifications));
[email protected]520cb7d72010-08-31 11:54:314809 }
[email protected]520cb7d72010-08-31 11:54:314810}
4811
[email protected]446705872009-09-10 07:22:484812void RenderView::OnSetEditCommandsForNextKeyEvent(
4813 const EditCommands& edit_commands) {
4814 edit_commands_ = edit_commands;
4815}
4816
[email protected]60c42a8c72009-10-09 04:08:594817void RenderView::Close() {
4818 // We need to grab a pointer to the doomed WebView before we destroy it.
4819 WebView* doomed = webview();
4820 RenderWidget::Close();
[email protected]625332e02010-12-14 07:48:494821 g_view_map.Get().erase(doomed);
[email protected]60c42a8c72009-10-09 04:08:594822}
4823
[email protected]446705872009-09-10 07:22:484824void RenderView::DidHandleKeyEvent() {
4825 edit_commands_.clear();
4826}
4827
[email protected]6a8ddba52010-09-05 04:38:064828void RenderView::DidHandleMouseEvent(const WebKit::WebMouseEvent& event) {
[email protected]676126f72011-01-15 00:03:514829 FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidHandleMouseEvent(event));
[email protected]6a8ddba52010-09-05 04:38:064830}
4831
[email protected]941e4552010-02-01 21:23:434832void RenderView::OnWasHidden() {
4833 RenderWidget::OnWasHidden();
4834
[email protected]a6939ca42011-02-18 17:58:074835 if (webview()) {
4836 webview()->settings()->setMinimumTimerInterval(
4837 webkit_glue::kBackgroundTabTimerInterval);
4838 }
4839
4840#if defined(OS_MACOSX)
[email protected]941e4552010-02-01 21:23:434841 // Inform plugins that their container is no longer visible.
4842 std::set<WebPluginDelegateProxy*>::iterator plugin_it;
4843 for (plugin_it = plugin_delegates_.begin();
4844 plugin_it != plugin_delegates_.end(); ++plugin_it) {
4845 (*plugin_it)->SetContainerVisibility(false);
4846 }
[email protected]a6939ca42011-02-18 17:58:074847#endif // OS_MACOSX
[email protected]941e4552010-02-01 21:23:434848}
4849
4850void RenderView::OnWasRestored(bool needs_repainting) {
4851 RenderWidget::OnWasRestored(needs_repainting);
4852
[email protected]a6939ca42011-02-18 17:58:074853 if (webview()) {
4854 webview()->settings()->setMinimumTimerInterval(
4855 webkit_glue::kForegroundTabTimerInterval);
4856 }
4857
4858#if defined(OS_MACOSX)
[email protected]941e4552010-02-01 21:23:434859 // Inform plugins that their container is now visible.
4860 std::set<WebPluginDelegateProxy*>::iterator plugin_it;
4861 for (plugin_it = plugin_delegates_.begin();
4862 plugin_it != plugin_delegates_.end(); ++plugin_it) {
4863 (*plugin_it)->SetContainerVisibility(true);
4864 }
[email protected]784ea1ab2010-09-18 00:02:344865#endif // OS_MACOSX
[email protected]a6939ca42011-02-18 17:58:074866}
[email protected]1e6e3c992010-02-08 15:52:134867
4868void RenderView::OnSetFocus(bool enable) {
4869 RenderWidget::OnSetFocus(enable);
4870
[email protected]7d3c02c2010-05-05 23:10:314871 if (webview() && webview()->isActive()) {
[email protected]589621b2010-09-23 22:01:074872 // Notify all NPAPI plugins.
[email protected]1e6e3c992010-02-08 15:52:134873 std::set<WebPluginDelegateProxy*>::iterator plugin_it;
4874 for (plugin_it = plugin_delegates_.begin();
4875 plugin_it != plugin_delegates_.end(); ++plugin_it) {
[email protected]784ea1ab2010-09-18 00:02:344876#if defined(OS_MACOSX)
[email protected]7d3c02c2010-05-05 23:10:314877 // RenderWidget's call to setFocus can cause the underlying webview's
4878 // activation state to change just like a call to setIsActive.
4879 if (enable)
4880 (*plugin_it)->SetWindowFocus(true);
[email protected]784ea1ab2010-09-18 00:02:344881#endif
[email protected]7d3c02c2010-05-05 23:10:314882 (*plugin_it)->SetContentAreaFocus(enable);
[email protected]1e6e3c992010-02-08 15:52:134883 }
[email protected]589621b2010-09-23 22:01:074884
4885 // Notify all Pepper plugins.
4886 pepper_delegate_.OnSetFocus(enable);
[email protected]1e6e3c992010-02-08 15:52:134887 }
4888}
[email protected]941e4552010-02-01 21:23:434889
[email protected]43f28f832010-02-03 02:28:484890#if defined(OS_MACOSX)
[email protected]b7f75862011-01-21 21:15:134891void RenderView::PluginFocusChanged(bool focused, int plugin_id) {
4892 IPC::Message* msg = new ViewHostMsg_PluginFocusChanged(routing_id(),
4893 focused, plugin_id);
4894 Send(msg);
4895}
4896
4897void RenderView::StartPluginIme() {
4898 IPC::Message* msg = new ViewHostMsg_StartPluginIme(routing_id());
[email protected]935d63d2010-10-15 23:31:554899 // This message can be sent during event-handling, and needs to be delivered
4900 // within that context.
4901 msg->set_unblock(true);
4902 Send(msg);
4903}
4904
[email protected]ea04a4e12010-04-15 00:58:034905gfx::PluginWindowHandle RenderView::AllocateFakePluginWindowHandle(
[email protected]77e74db2010-08-04 17:46:234906 bool opaque, bool root) {
[email protected]43f28f832010-02-03 02:28:484907 gfx::PluginWindowHandle window = NULL;
4908 Send(new ViewHostMsg_AllocateFakePluginWindowHandle(
[email protected]77e74db2010-08-04 17:46:234909 routing_id(), opaque, root, &window));
[email protected]c36a9b62010-10-14 00:41:114910 if (window) {
4911 fake_plugin_window_handles_.insert(window);
4912 }
[email protected]43f28f832010-02-03 02:28:484913 return window;
4914}
4915
4916void RenderView::DestroyFakePluginWindowHandle(gfx::PluginWindowHandle window) {
[email protected]c36a9b62010-10-14 00:41:114917 if (window && fake_plugin_window_handles_.find(window) !=
4918 fake_plugin_window_handles_.end()) {
[email protected]43f28f832010-02-03 02:28:484919 Send(new ViewHostMsg_DestroyFakePluginWindowHandle(routing_id(), window));
[email protected]c36a9b62010-10-14 00:41:114920 fake_plugin_window_handles_.erase(window);
4921 }
[email protected]43f28f832010-02-03 02:28:484922}
4923
[email protected]44ce0b12010-03-12 16:45:334924void RenderView::AcceleratedSurfaceSetIOSurface(gfx::PluginWindowHandle window,
4925 int32 width,
4926 int32 height,
4927 uint64 io_surface_identifier) {
4928 Send(new ViewHostMsg_AcceleratedSurfaceSetIOSurface(
[email protected]43f28f832010-02-03 02:28:484929 routing_id(), window, width, height, io_surface_identifier));
4930}
4931
[email protected]44ce0b12010-03-12 16:45:334932void RenderView::AcceleratedSurfaceSetTransportDIB(
4933 gfx::PluginWindowHandle window,
4934 int32 width,
4935 int32 height,
4936 TransportDIB::Handle transport_dib) {
4937 Send(new ViewHostMsg_AcceleratedSurfaceSetTransportDIB(
[email protected]1aef98132010-02-23 18:00:074938 routing_id(), window, width, height, transport_dib));
4939}
4940
[email protected]44ce0b12010-03-12 16:45:334941TransportDIB::Handle RenderView::AcceleratedSurfaceAllocTransportDIB(
4942 size_t size) {
[email protected]1aef98132010-02-23 18:00:074943 TransportDIB::Handle dib_handle;
4944 // Assume this is a synchronous RPC.
[email protected]ada848b12010-04-08 22:35:384945 if (Send(new ViewHostMsg_AllocTransportDIB(size, true, &dib_handle)))
[email protected]1aef98132010-02-23 18:00:074946 return dib_handle;
4947 // Return an invalid handle if Send() fails.
4948 return TransportDIB::DefaultHandleValue();
4949}
4950
[email protected]44ce0b12010-03-12 16:45:334951void RenderView::AcceleratedSurfaceFreeTransportDIB(TransportDIB::Id dib_id) {
[email protected]1aef98132010-02-23 18:00:074952 Send(new ViewHostMsg_FreeTransportDIB(dib_id));
4953}
4954
[email protected]44ce0b12010-03-12 16:45:334955void RenderView::AcceleratedSurfaceBuffersSwapped(
[email protected]f35d6672010-10-28 21:39:144956 gfx::PluginWindowHandle window, uint64 surface_id) {
4957 Send(new ViewHostMsg_AcceleratedSurfaceBuffersSwapped(
4958 routing_id(), window, surface_id));
[email protected]43f28f832010-02-03 02:28:484959}
4960#endif
[email protected]58c321d2010-02-19 12:11:284961
[email protected]cdaf8d02010-03-30 19:52:474962bool RenderView::ScheduleFileChooser(
4963 const ViewHostMsg_RunFileChooser_Params& params,
4964 WebFileChooserCompletion* completion) {
4965 static const size_t kMaximumPendingFileChooseRequests = 4;
4966 if (file_chooser_completions_.size() > kMaximumPendingFileChooseRequests) {
4967 // This sanity check prevents too many file choose requests from getting
4968 // queued which could DoS the user. Getting these is most likely a
4969 // programming error (there are many ways to DoS the user so it's not
4970 // considered a "real" security check), either in JS requesting many file
4971 // choosers to pop up, or in a plugin.
4972 //
4973 // TODO(brettw) we might possibly want to require a user gesture to open
4974 // a file picker, which will address this issue in a better way.
4975 return false;
4976 }
4977
4978 file_chooser_completions_.push_back(linked_ptr<PendingFileChooser>(
4979 new PendingFileChooser(params, completion)));
4980 if (file_chooser_completions_.size() == 1) {
4981 // Actually show the browse dialog when this is the first request.
4982 Send(new ViewHostMsg_RunFileChooser(routing_id_, params));
4983 }
4984 return true;
4985}
4986
[email protected]290838a2010-04-27 17:37:014987void RenderView::OnPageTranslated() {
4988 WebFrame* frame = webview()->mainFrame();
4989 if (!frame)
4990 return;
4991
[email protected]676126f72011-01-15 00:03:514992 FOR_EACH_OBSERVER(RenderViewObserver, observers_, FrameTranslated(frame));
[email protected]290838a2010-04-27 17:37:014993}
4994
[email protected]0ff0ff32010-12-21 19:34:424995WebKit::WebGeolocationClient* RenderView::geolocationClient() {
[email protected]676126f72011-01-15 00:03:514996 if (!geolocation_dispatcher_)
4997 geolocation_dispatcher_ = new GeolocationDispatcher(this);
4998 return geolocation_dispatcher_;
[email protected]7e0c4702010-12-31 14:06:254999}
[email protected]61c9f032010-03-31 23:04:195000
[email protected]638694c2010-08-04 22:24:115001WebKit::WebSpeechInputController* RenderView::speechInputController(
5002 WebKit::WebSpeechInputListener* listener) {
[email protected]676126f72011-01-15 00:03:515003 if (!speech_input_dispatcher_)
5004 speech_input_dispatcher_ = new SpeechInputDispatcher(this, listener);
5005 return speech_input_dispatcher_;
[email protected]638694c2010-08-04 22:24:115006}
5007
[email protected]57ead352010-08-11 14:42:535008WebKit::WebDeviceOrientationClient* RenderView::deviceOrientationClient() {
[email protected]676126f72011-01-15 00:03:515009 if (!device_orientation_dispatcher_)
5010 device_orientation_dispatcher_ = new DeviceOrientationDispatcher(this);
5011 return device_orientation_dispatcher_;
[email protected]57ead352010-08-11 14:42:535012}
5013
[email protected]b75b8292010-10-01 07:28:255014void RenderView::zoomLimitsChanged(double minimum_level, double maximum_level) {
5015 // For now, don't remember plugin zoom values. We don't want to mix them with
5016 // normal web content (i.e. a fixed layout plugin would usually want them
5017 // different).
5018 bool remember = !webview()->mainFrame()->document().isPluginDocument();
5019
[email protected]b75b8292010-10-01 07:28:255020 int minimum_percent = static_cast<int>(
5021 WebView::zoomLevelToZoomFactor(minimum_level) * 100);
5022 int maximum_percent = static_cast<int>(
5023 WebView::zoomLevelToZoomFactor(maximum_level) * 100);
[email protected]b75b8292010-10-01 07:28:255024
5025 Send(new ViewHostMsg_UpdateZoomLimits(
5026 routing_id_, minimum_percent, maximum_percent, remember));
5027}
5028
5029void RenderView::zoomLevelChanged() {
5030 bool remember = !webview()->mainFrame()->document().isPluginDocument();
5031
[email protected]b75b8292010-10-01 07:28:255032 // Tell the browser which url got zoomed so it can update the menu and the
5033 // saved values if necessary
5034 Send(new ViewHostMsg_DidZoomURL(
[email protected]1cc58eb62010-10-01 22:38:415035 routing_id_, webview()->zoomLevel(), remember,
5036 GURL(webview()->mainFrame()->url())));
[email protected]b75b8292010-10-01 07:28:255037}
5038
[email protected]a6d36cc2011-02-23 00:39:485039void RenderView::registerProtocolHandler(const WebString& scheme,
5040 const WebString& base_url,
5041 const WebString& url,
5042 const WebString& title) {
5043 GURL base(base_url);
5044 GURL absolute_url = base.Resolve(UTF16ToUTF8(url));
5045 if (base.GetOrigin() != absolute_url.GetOrigin()) {
5046 return;
5047 }
5048 RenderThread::current()->Send(
5049 new ViewHostMsg_RegisterProtocolHandler(routing_id_,
5050 UTF16ToUTF8(scheme),
5051 absolute_url,
5052 title));
5053}
5054
[email protected]8079b362010-05-07 18:37:455055bool RenderView::IsNonLocalTopLevelNavigation(
[email protected]61c9f032010-03-31 23:04:195056 const GURL& url, WebKit::WebFrame* frame, WebKit::WebNavigationType type) {
[email protected]8079b362010-05-07 18:37:455057 // Must be a top level frame.
[email protected]61c9f032010-03-31 23:04:195058 if (frame->parent() != NULL)
5059 return false;
5060
[email protected]f0a3d0b2010-08-06 22:51:535061 // Navigations initiated within Webkit are not sent out to the external host
5062 // in the following cases.
[email protected]900eb2f12010-08-23 22:36:275063 // 1. The url scheme is not http/https
5064 // 2. There is no opener and this is not the first url being opened by this
5065 // RenderView.
5066 // 3. The origin of the url and the opener is the same in which case the
[email protected]f0a3d0b2010-08-06 22:51:535067 // opener relationship is maintained.
[email protected]f0a3d0b2010-08-06 22:51:535068 // 4. Reloads/form submits/back forward navigations
5069 if (!url.SchemeIs("http") && !url.SchemeIs("https"))
5070 return false;
5071
[email protected]2fc22d12010-12-02 23:08:165072 // Not interested in reloads/form submits/resubmits/back forward navigations.
[email protected]d0ed50d2010-06-22 01:01:325073 if (type != WebKit::WebNavigationTypeReload &&
[email protected]070c49c2010-07-13 22:22:015074 type != WebKit::WebNavigationTypeFormSubmitted &&
[email protected]2fc22d12010-12-02 23:08:165075 type != WebKit::WebNavigationTypeFormResubmitted &&
[email protected]070c49c2010-07-13 22:22:015076 type != WebKit::WebNavigationTypeBackForward) {
[email protected]d0ed50d2010-06-22 01:01:325077 // The opener relationship between the new window and the parent allows the
5078 // new window to script the parent and vice versa. This is not allowed if
5079 // the origins of the two domains are different. This can be treated as a
5080 // top level navigation and routed back to the host.
5081 WebKit::WebFrame* opener = frame->opener();
[email protected]900eb2f12010-08-23 22:36:275082 if (!opener) {
[email protected]fe9eb4f92010-08-27 23:16:475083 // Force link click navigations to always be routed to the host as they
5084 // may update session state on the server.
5085 if (type == WebKit::WebNavigationTypeLinkClicked)
5086 return true;
[email protected]900eb2f12010-08-23 22:36:275087 // If this is the first page being loaded by this RenderView instance then
5088 // it should stay here.
5089 if (page_id_ == -1) {
5090 return false;
5091 } else {
[email protected]d0ed50d2010-06-22 01:01:325092 return true;
[email protected]900eb2f12010-08-23 22:36:275093 }
[email protected]d0ed50d2010-06-22 01:01:325094 }
[email protected]900eb2f12010-08-23 22:36:275095
5096 if (url.GetOrigin() != GURL(opener->url()).GetOrigin())
5097 return true;
[email protected]d0ed50d2010-06-22 01:01:325098 }
[email protected]61c9f032010-03-31 23:04:195099 return false;
5100}
[email protected]2b06a992010-08-21 05:48:225101
[email protected]27a9ef32010-09-10 04:06:245102void RenderView::OnAsyncFileOpened(base::PlatformFileError error_code,
5103 IPC::PlatformFileForTransit file_for_transit,
5104 int message_id) {
5105 pepper_delegate_.OnAsyncFileOpened(
5106 error_code,
5107 IPC::PlatformFileForTransitToPlatformFile(file_for_transit),
5108 message_id);
5109}
[email protected]caf706f2010-10-26 17:54:085110
5111#if defined(OS_MACOSX)
5112void RenderView::OnSelectPopupMenuItem(int selected_index) {
[email protected]68dc3ba2010-12-06 21:43:155113 if (external_popup_menu_ == NULL) {
5114 // Crash reports from the field indicate that we can be notified with a
5115 // NULL external popup menu (we probably get notified twice).
5116 // If you hit this please file a bug against jcivelli and include the page
5117 // and steps to repro.
5118 NOTREACHED();
5119 return;
5120 }
[email protected]caf706f2010-10-26 17:54:085121 external_popup_menu_->DidSelectItem(selected_index);
5122 external_popup_menu_.reset();
5123}
5124#endif
[email protected]bb461532010-11-26 21:50:235125
5126void RenderView::AddErrorToRootConsole(const string16& message) {
5127 if (webview() && webview()->mainFrame()) {
5128 webview()->mainFrame()->addMessageToConsole(
5129 WebConsoleMessage(WebConsoleMessage::LevelError, message));
5130 }
5131}
[email protected]1b4209f2011-01-07 00:25:405132
5133#if defined(ENABLE_FLAPPER_HACKS)
5134void RenderView::OnConnectTcpACK(
5135 int request_id,
5136 IPC::PlatformFileForTransit socket_for_transit,
5137 const PP_Flash_NetAddress& local_addr,
5138 const PP_Flash_NetAddress& remote_addr) {
5139 pepper_delegate_.OnConnectTcpACK(
5140 request_id,
5141 IPC::PlatformFileForTransitToPlatformFile(socket_for_transit),
5142 local_addr,
5143 remote_addr);
5144}
5145#endif
[email protected]a6097f42011-01-10 08:50:515146
5147void RenderView::OnJavaScriptStressTestControl(int cmd, int param) {
5148 if (cmd == kJavaScriptStressTestSetStressRunType) {
5149 v8::Testing::SetStressRunType(static_cast<v8::Testing::StressType>(param));
5150 } else if (cmd == kJavaScriptStressTestPrepareStressRun) {
5151 v8::Testing::PrepareStressRun(param);
5152 }
5153}
[email protected]521b2482011-01-15 00:10:105154
[email protected]b29aa74b2011-01-31 21:41:085155void RenderView::OnContextMenuClosed(
5156 const webkit_glue::CustomContextMenuContext& custom_context) {
5157 if (custom_context.is_pepper_menu)
5158 pepper_delegate_.OnContextMenuClosed(custom_context);
5159 else
5160 context_menu_node_.reset();
[email protected]521b2482011-01-15 00:10:105161}
[email protected]232a5812011-03-04 22:42:085162
5163void RenderView::OnNetworkStateChanged(bool online) {
5164 WebNetworkStateNotifier::setOnLine(online);
5165}