blob: ae98ac3a93f56e3b0a089b9df0c21cc750f554e9 [file] [log] [blame]
[email protected]05d478752009-04-08 23:38:161// Copyright (c) 2009 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
5#include "chrome/renderer/render_view.h"
6
7#include <algorithm>
8#include <string>
9#include <vector>
10
[email protected]91e81ae2009-05-08 22:14:3811#include "app/gfx/color_utils.h"
[email protected]37126212009-05-06 02:23:3112#include "app/gfx/favicon_size.h"
[email protected]a92b8642009-05-05 23:38:5613#include "app/l10n_util.h"
[email protected]37126212009-05-06 02:23:3114#include "app/message_box_flags.h"
[email protected]9929da92009-05-05 02:05:1115#include "app/resource_bundle.h"
initial.commit09911bf2008-07-26 23:55:2916#include "base/command_line.h"
[email protected]bb063b72009-03-27 23:18:5017#include "base/compiler_specific.h"
[email protected]4646f292009-05-20 03:49:0518#include "base/field_trial.h"
[email protected]18bcc3c2009-01-27 21:39:1519#include "base/gfx/native_widget_types.h"
[email protected]8380c092009-06-25 17:45:5120#include "base/process_util.h"
[email protected]7b291f92009-08-14 05:43:5321#include "base/singleton.h"
initial.commit09911bf2008-07-26 23:55:2922#include "base/string_piece.h"
23#include "base/string_util.h"
[email protected]6c8afae52009-01-22 02:24:5724#include "build/build_config.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"
initial.commit09911bf2008-07-26 23:55:2927#include "chrome/common/chrome_switches.h"
[email protected]f0af6a72009-05-30 05:25:1728#include "chrome/common/chrome_constants.h"
initial.commit09911bf2008-07-26 23:55:2929#include "chrome/common/jstemplate_builder.h"
[email protected]630e26b2008-10-14 22:55:1730#include "chrome/common/page_zoom.h"
[email protected]8beff0762009-09-29 02:18:3031#include "chrome/common/plugin_messages.h"
[email protected]e09ba552009-02-05 03:26:2932#include "chrome/common/render_messages.h"
[email protected]9b6f40e2009-06-11 15:54:2633#include "chrome/common/renderer_preferences.h"
initial.commit09911bf2008-07-26 23:55:2934#include "chrome/common/thumbnail_score.h"
[email protected]6de74452009-02-25 18:04:5935#include "chrome/common/url_constants.h"
initial.commit09911bf2008-07-26 23:55:2936#include "chrome/renderer/about_handler.h"
[email protected]5fb88962009-04-16 19:03:2537#include "chrome/renderer/audio_message_filter.h"
[email protected]e4ac5df2009-03-17 15:33:1138#include "chrome/renderer/devtools_agent.h"
39#include "chrome/renderer/devtools_client.h"
[email protected]912256b32009-09-18 09:47:3540#include "chrome/renderer/extension_groups.h"
[email protected]f816c012009-06-26 21:48:3241#include "chrome/renderer/extensions/event_bindings.h"
[email protected]0f6053962009-07-09 19:26:3542#include "chrome/renderer/extensions/extension_process_bindings.h"
[email protected]7120f132009-07-20 21:05:3743#include "chrome/renderer/extensions/renderer_extension_bindings.h"
initial.commit09911bf2008-07-26 23:55:2944#include "chrome/renderer/localized_error.h"
[email protected]6f56d482009-02-20 05:02:5645#include "chrome/renderer/media/audio_renderer_impl.h"
[email protected]ed3fb032009-06-16 19:50:5646#include "chrome/renderer/navigation_state.h"
[email protected]90e908552009-10-05 01:40:1247#include "chrome/renderer/notification_provider.h"
[email protected]8beff0762009-09-29 02:18:3048#include "chrome/renderer/plugin_channel_host.h"
[email protected]d81c1e52009-06-03 22:09:5049#include "chrome/renderer/print_web_view_helper.h"
[email protected]39008c02009-02-11 23:59:2550#include "chrome/renderer/render_process.h"
[email protected]0938d3c2009-01-09 20:37:3551#include "chrome/renderer/user_script_slave.h"
initial.commit09911bf2008-07-26 23:55:2952#include "chrome/renderer/visitedlink_slave.h"
[email protected]ba4b17f2009-02-11 21:32:2953#include "chrome/renderer/webplugin_delegate_proxy.h"
[email protected]eb47a132009-03-04 00:39:5654#include "chrome/renderer/webworker_proxy.h"
[email protected]34ac8f32009-02-22 23:03:2755#include "grit/generated_resources.h"
56#include "grit/renderer_resources.h"
[email protected]f11ca0732009-04-11 00:09:3457#include "net/base/data_url.h"
initial.commit09911bf2008-07-26 23:55:2958#include "net/base/escape.h"
59#include "net/base/net_errors.h"
[email protected]c399a8a2008-11-22 19:38:0060#include "skia/ext/bitmap_platform_device.h"
[email protected]83c9e6552008-12-03 16:22:1061#include "skia/ext/image_operations.h"
[email protected]726985e22009-06-18 21:09:2862#include "webkit/api/public/WebDataSource.h"
[email protected]afdcf5c2009-05-10 20:30:4163#include "webkit/api/public/WebDragData.h"
[email protected]daa8c58e2009-06-15 17:21:1064#include "webkit/api/public/WebForm.h"
[email protected]dd7daa82009-08-10 05:46:4565#include "webkit/api/public/WebFrame.h"
[email protected]ca948a22009-06-25 19:36:1766#include "webkit/api/public/WebHistoryItem.h"
[email protected]581b87eb2009-07-23 23:06:5667#include "webkit/api/public/WebNode.h"
[email protected]afdcf5c2009-05-10 20:30:4168#include "webkit/api/public/WebPoint.h"
69#include "webkit/api/public/WebRect.h"
70#include "webkit/api/public/WebScriptSource.h"
[email protected]91733b62009-09-18 06:21:0971#include "webkit/api/public/WebSecurityOrigin.h"
[email protected]afdcf5c2009-05-10 20:30:4172#include "webkit/api/public/WebSize.h"
[email protected]a1128322009-10-06 18:38:4673#include "webkit/api/public/WebString.h"
[email protected]726985e22009-06-18 21:09:2874#include "webkit/api/public/WebURL.h"
75#include "webkit/api/public/WebURLError.h"
76#include "webkit/api/public/WebURLRequest.h"
77#include "webkit/api/public/WebURLResponse.h"
78#include "webkit/api/public/WebVector.h"
[email protected]f430b5712009-08-21 21:46:3179#include "webkit/appcache/appcache_interfaces.h"
[email protected]ba4b17f2009-02-11 21:32:2980#include "webkit/default_plugin/default_plugin_shared.h"
[email protected]ca948a22009-06-25 19:36:1781#include "webkit/glue/glue_serialize.h"
initial.commit09911bf2008-07-26 23:55:2982#include "webkit/glue/dom_operations.h"
83#include "webkit/glue/dom_serializer.h"
[email protected]f11ca0732009-04-11 00:09:3484#include "webkit/glue/image_decoder.h"
[email protected]8e296bbd2009-07-22 21:37:1785#include "webkit/glue/media/buffered_data_source.h"
[email protected]8380c092009-06-25 17:45:5186#include "webkit/glue/media/simple_data_source.h"
initial.commit09911bf2008-07-26 23:55:2987#include "webkit/glue/password_form.h"
[email protected]ba4b17f2009-02-11 21:32:2988#include "webkit/glue/plugins/plugin_list.h"
[email protected]8a3b7962009-09-04 05:53:2389#include "webkit/glue/plugins/webplugin_delegate_impl.h"
initial.commit09911bf2008-07-26 23:55:2990#include "webkit/glue/searchable_form_data.h"
[email protected]6a983b42009-03-20 20:12:2591#include "webkit/glue/webaccessibilitymanager_impl.h"
[email protected]611cad42009-03-16 18:51:3492#include "webkit/glue/webdevtoolsagent_delegate.h"
initial.commit09911bf2008-07-26 23:55:2993#include "webkit/glue/webdropdata.h"
initial.commit09911bf2008-07-26 23:55:2994#include "webkit/glue/webkit_glue.h"
[email protected]add51772009-06-11 18:25:1795#include "webkit/glue/webmediaplayer_impl.h"
[email protected]f103ab72009-09-02 17:10:5996#include "webkit/glue/webplugin_impl.h"
initial.commit09911bf2008-07-26 23:55:2997#include "webkit/glue/webview.h"
initial.commit09911bf2008-07-26 23:55:2998
[email protected]6c8afae52009-01-22 02:24:5799#if defined(OS_WIN)
100// TODO(port): these files are currently Windows only because they concern:
[email protected]6c8afae52009-01-22 02:24:57101// * theming
[email protected]86281ad2009-10-07 20:07:17102#include "app/gfx/native_theme_win.h"
[email protected]6c8afae52009-01-22 02:24:57103#endif
104
[email protected]c20210e62009-04-03 21:39:26105using base::Time;
[email protected]e1acf6f2008-10-27 20:43:33106using base::TimeDelta;
[email protected]15d79e12009-08-02 19:23:45107using webkit_glue::AltErrorPageResourceFetcher;
[email protected]daa8c58e2009-06-15 17:21:10108using webkit_glue::AutofillForm;
[email protected]b0950a72009-09-29 23:16:17109using webkit_glue::ImageResourceFetcher;
[email protected]ed3fb032009-06-16 19:50:56110using webkit_glue::PasswordForm;
[email protected]daa8c58e2009-06-15 17:21:10111using webkit_glue::PasswordFormDomManager;
112using webkit_glue::SearchableFormData;
[email protected]1c83eb42009-09-11 21:08:41113using WebKit::WebColor;
114using WebKit::WebColorName;
[email protected]0dea3ea2009-03-31 23:30:59115using WebKit::WebConsoleMessage;
[email protected]e6f546c32009-07-01 17:12:55116using WebKit::WebData;
[email protected]726985e22009-06-18 21:09:28117using WebKit::WebDataSource;
[email protected]e80c73b2009-04-07 23:24:58118using WebKit::WebDragData;
[email protected]1d9f4132009-09-08 17:29:25119using WebKit::WebDragOperation;
120using WebKit::WebDragOperationsMask;
[email protected]79dbc662009-09-04 05:42:51121using WebKit::WebEditingAction;
[email protected]daa8c58e2009-06-15 17:21:10122using WebKit::WebForm;
[email protected]dd7daa82009-08-10 05:46:45123using WebKit::WebFrame;
[email protected]ca948a22009-06-25 19:36:17124using WebKit::WebHistoryItem;
[email protected]3d9689372009-09-10 04:29:17125using WebKit::WebMediaPlayer;
[email protected]952cb702009-10-07 05:50:28126using WebKit::WebMediaPlayerAction;
[email protected]3d9689372009-09-10 04:29:17127using WebKit::WebMediaPlayerClient;
[email protected]4873c7d2009-07-16 06:36:28128using WebKit::WebNavigationPolicy;
[email protected]726985e22009-06-18 21:09:28129using WebKit::WebNavigationType;
[email protected]79dbc662009-09-04 05:42:51130using WebKit::WebNode;
[email protected]3d9689372009-09-10 04:29:17131using WebKit::WebPlugin;
132using WebKit::WebPluginParams;
[email protected]48c9cf2d2009-09-16 16:47:52133using WebKit::WebPoint;
[email protected]88efb7ec2009-07-14 16:32:59134using WebKit::WebPopupMenuInfo;
[email protected]79dbc662009-09-04 05:42:51135using WebKit::WebRange;
[email protected]b3f2b912009-04-09 16:18:52136using WebKit::WebRect;
[email protected]4f999132009-03-31 18:08:40137using WebKit::WebScriptSource;
[email protected]e3d60e5d2009-09-25 21:08:29138using WebKit::WebSecurityOrigin;
[email protected]2fab253a2009-08-17 23:00:59139using WebKit::WebSettings;
[email protected]8649fb32009-06-26 17:51:02140using WebKit::WebSize;
[email protected]726985e22009-06-18 21:09:28141using WebKit::WebString;
[email protected]79dbc662009-09-04 05:42:51142using WebKit::WebTextAffinity;
[email protected]de570ef2009-07-29 18:27:52143using WebKit::WebTextDirection;
[email protected]726985e22009-06-18 21:09:28144using WebKit::WebURL;
145using WebKit::WebURLError;
146using WebKit::WebURLRequest;
147using WebKit::WebURLResponse;
[email protected]4873c7d2009-07-16 06:36:28148using WebKit::WebVector;
149using WebKit::WebWidget;
[email protected]27ba8532009-04-24 20:22:43150using WebKit::WebWorker;
151using WebKit::WebWorkerClient;
[email protected]e1acf6f2008-10-27 20:43:33152
initial.commit09911bf2008-07-26 23:55:29153//-----------------------------------------------------------------------------
154
155// define to write the time necessary for thumbnail/DOM text retrieval,
156// respectively, into the system debug log
157// #define TIME_BITMAP_RETRIEVAL
158// #define TIME_TEXT_RETRIEVAL
159
160// maximum number of characters in the document to index, any text beyond this
161// point will be clipped
[email protected]6c8afae52009-01-22 02:24:57162static const size_t kMaxIndexChars = 65535;
initial.commit09911bf2008-07-26 23:55:29163
164// Size of the thumbnails that we'll generate
[email protected]8b4f4892009-09-04 21:52:37165static const int kThumbnailWidth = 212;
166static const int kThumbnailHeight = 132;
initial.commit09911bf2008-07-26 23:55:29167
168// Delay in milliseconds that we'll wait before capturing the page contents
169// and thumbnail.
170static const int kDelayForCaptureMs = 500;
171
172// Typically, we capture the page data once the page is loaded.
173// Sometimes, the page never finishes to load, preventing the page capture
174// To workaround this problem, we always perform a capture after the following
175// delay.
176static const int kDelayForForcedCaptureMs = 6000;
177
[email protected]81a34412009-01-05 19:17:24178// The default value for RenderView.delay_seconds_for_form_state_sync_, see
179// that variable for more.
180const int kDefaultDelaySecondsForFormStateSync = 5;
initial.commit09911bf2008-07-26 23:55:29181
182// The next available page ID to use. This ensures that the page IDs are
183// globally unique in the renderer.
184static int32 next_page_id_ = 1;
185
[email protected]0aa55312008-10-17 21:53:08186// The maximum number of popups that can be spawned from one page.
187static const int kMaximumNumberOfUnacknowledgedPopups = 25;
188
initial.commit09911bf2008-07-26 23:55:29189static const char* const kUnreachableWebDataURL =
[email protected]60e448982009-05-06 04:21:16190 "chrome://chromewebdata/";
initial.commit09911bf2008-07-26 23:55:29191
[email protected]50b691c2008-10-31 19:08:35192static const char* const kBackForwardNavigationScheme = "history";
193
[email protected]726985e22009-06-18 21:09:28194static void GetRedirectChain(WebDataSource* ds, std::vector<GURL>* result) {
195 WebVector<WebURL> urls;
196 ds->redirectChain(urls);
197 result->reserve(urls.size());
198 for (size_t i = 0; i < urls.size(); ++i)
199 result->push_back(urls[i]);
200}
201
initial.commit09911bf2008-07-26 23:55:29202///////////////////////////////////////////////////////////////////////////////
203
[email protected]2fab253a2009-08-17 23:00:59204RenderView::RenderView(RenderThreadBase* render_thread,
205 const WebPreferences& webkit_preferences)
[email protected]81a34412009-01-05 19:17:24206 : RenderWidget(render_thread, true),
[email protected]81e63782009-02-27 19:35:09207 enabled_bindings_(0),
[email protected]e75cb49e2009-01-05 23:13:21208 target_url_status_(TARGET_NONE),
[email protected]81a34412009-01-05 19:17:24209 is_loading_(false),
[email protected]e75cb49e2009-01-05 23:13:21210 navigation_gesture_(NavigationGestureUnknown),
[email protected]81a34412009-01-05 19:17:24211 page_id_(-1),
212 last_page_id_sent_to_browser_(-1),
213 last_indexed_page_id_(-1),
[email protected]81a34412009-01-05 19:17:24214 opened_by_user_gesture_(true),
[email protected]bb063b72009-03-27 23:18:50215 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
[email protected]e4ac5df2009-03-17 15:33:11216 devtools_agent_(NULL),
217 devtools_client_(NULL),
[email protected]a1128322009-10-06 18:38:46218 file_chooser_completion_(NULL),
[email protected]81a34412009-01-05 19:17:24219 history_back_list_count_(0),
220 history_forward_list_count_(0),
[email protected]81a34412009-01-05 19:17:24221 has_unload_listener_(false),
222 decrement_shared_popup_at_destruction_(false),
[email protected]81a34412009-01-05 19:17:24223 form_field_autofill_request_id_(0),
224 popup_notification_visible_(false),
[email protected]8922e1f2009-10-03 05:01:26225 spelling_panel_visible_(false),
[email protected]0666aef2009-05-13 19:48:08226 delay_seconds_for_form_state_sync_(kDefaultDelaySecondsForFormStateSync),
227 preferred_width_(0),
[email protected]5c4266922009-07-10 16:41:27228 send_preferred_width_changes_(false),
[email protected]5f450e52009-07-28 13:28:11229 determine_page_text_after_loading_stops_(false),
[email protected]7b291f92009-08-14 05:43:53230 view_type_(ViewType::INVALID),
231 browser_window_id_(-1),
[email protected]83dde542009-09-11 20:59:55232 last_top_level_navigation_page_id_(-1),
233#if defined(OS_MACOSX)
234 has_document_tag_(false),
235#endif
[email protected]98324892009-09-09 21:16:05236 document_tag_(0),
[email protected]2fab253a2009-08-17 23:00:59237 webkit_preferences_(webkit_preferences) {
[email protected]7b291f92009-08-14 05:43:53238 Singleton<RenderViewSet>()->render_view_set_.insert(this);
initial.commit09911bf2008-07-26 23:55:29239}
240
241RenderView::~RenderView() {
[email protected]7b291f92009-08-14 05:43:53242 Singleton<RenderViewSet>()->render_view_set_.erase(this);
[email protected]0aa55312008-10-17 21:53:08243 if (decrement_shared_popup_at_destruction_)
244 shared_popup_counter_->data--;
245
[email protected]b0950a72009-09-29 23:16:17246 // Dispose of un-disposed image fetchers.
247 for (ImageResourceFetcherSet::iterator i = image_fetchers_.begin();
248 i != image_fetchers_.end(); ++i) {
249 delete *i;
250 }
251
[email protected]a1128322009-10-06 18:38:46252 // If file chooser is still waiting for answer, dispatch empty answer.
253 if (file_chooser_completion_)
254 file_chooser_completion_->didChooseFile(WebVector<WebString>());
255
[email protected]83dde542009-09-11 20:59:55256#if defined(OS_MACOSX)
[email protected]98324892009-09-09 21:16:05257 // Tell the spellchecker that the document is closed.
[email protected]83dde542009-09-11 20:59:55258 if (has_document_tag_)
259 Send(new ViewHostMsg_DocumentWithTagClosed(routing_id_, document_tag_));
260#endif
[email protected]98324892009-09-09 21:16:05261
[email protected]5fb88962009-04-16 19:03:25262 render_thread_->RemoveFilter(audio_message_filter_);
[email protected]90e908552009-10-05 01:40:12263 render_thread_->RemoveFilter(notification_provider_.get());
initial.commit09911bf2008-07-26 23:55:29264}
265
266/*static*/
[email protected]0aa55312008-10-17 21:53:08267RenderView* RenderView::Create(
[email protected]81a34412009-01-05 19:17:24268 RenderThreadBase* render_thread,
[email protected]18bcc3c2009-01-27 21:39:15269 gfx::NativeViewId parent_hwnd,
[email protected]0aa55312008-10-17 21:53:08270 int32 opener_id,
[email protected]80d96fa2009-06-10 22:34:51271 const RendererPreferences& renderer_prefs,
[email protected]0aa55312008-10-17 21:53:08272 const WebPreferences& webkit_prefs,
273 SharedRenderViewCounter* counter,
274 int32 routing_id) {
initial.commit09911bf2008-07-26 23:55:29275 DCHECK(routing_id != MSG_ROUTING_NONE);
[email protected]2fab253a2009-08-17 23:00:59276 scoped_refptr<RenderView> view = new RenderView(render_thread, webkit_prefs);
initial.commit09911bf2008-07-26 23:55:29277 view->Init(parent_hwnd,
initial.commit09911bf2008-07-26 23:55:29278 opener_id,
[email protected]80d96fa2009-06-10 22:34:51279 renderer_prefs,
[email protected]0aa55312008-10-17 21:53:08280 counter,
initial.commit09911bf2008-07-26 23:55:29281 routing_id); // adds reference
282 return view;
283}
284
285/*static*/
286void RenderView::SetNextPageID(int32 next_page_id) {
287 // This method should only be called during process startup, and the given
288 // page id had better not exceed our current next page id!
[email protected]4646f292009-05-20 03:49:05289 DCHECK_EQ(next_page_id_, 1);
initial.commit09911bf2008-07-26 23:55:29290 DCHECK(next_page_id >= next_page_id_);
291 next_page_id_ = next_page_id;
292}
293
[email protected]1dbafaf72009-09-23 19:43:56294void RenderView::UserMetricsRecordAction(const std::wstring& action) {
295 Send(new ViewHostMsg_UserMetricsRecordAction(routing_id_, action));
296}
297
[email protected]fb466342009-07-15 00:43:08298void RenderView::PluginCrashed(base::ProcessId pid,
299 const FilePath& plugin_path) {
300 Send(new ViewHostMsg_CrashedPlugin(routing_id_, pid, plugin_path));
initial.commit09911bf2008-07-26 23:55:29301}
302
[email protected]18bcc3c2009-01-27 21:39:15303void RenderView::Init(gfx::NativeViewId parent_hwnd,
initial.commit09911bf2008-07-26 23:55:29304 int32 opener_id,
[email protected]80d96fa2009-06-10 22:34:51305 const RendererPreferences& renderer_prefs,
[email protected]0aa55312008-10-17 21:53:08306 SharedRenderViewCounter* counter,
initial.commit09911bf2008-07-26 23:55:29307 int32 routing_id) {
308 DCHECK(!webview());
309
310 if (opener_id != MSG_ROUTING_NONE)
311 opener_id_ = opener_id;
312
[email protected]0aa55312008-10-17 21:53:08313 if (counter) {
314 shared_popup_counter_ = counter;
315 shared_popup_counter_->data++;
316 decrement_shared_popup_at_destruction_ = true;
317 } else {
318 shared_popup_counter_ = new SharedRenderViewCounter(0);
319 decrement_shared_popup_at_destruction_ = false;
320 }
321
[email protected]58bfc6b2009-06-24 09:45:02322 devtools_agent_.reset(new DevToolsAgent(routing_id, this));
[email protected]9b9d7282009-04-08 14:13:04323
[email protected]90e908552009-10-05 01:40:12324 notification_provider_ = new NotificationProvider(this);
325
[email protected]04fc9482009-09-18 22:13:03326 webwidget_ = WebView::Create(this);
[email protected]2fab253a2009-08-17 23:00:59327 webkit_preferences_.Apply(webview());
[email protected]b4bb2502009-10-01 22:35:27328 webview()->initializeMainFrame(this);
initial.commit09911bf2008-07-26 23:55:29329
[email protected]d3ba77272009-09-03 00:06:09330 OnSetRendererPrefs(renderer_prefs);
331
initial.commit09911bf2008-07-26 23:55:29332 routing_id_ = routing_id;
[email protected]81a34412009-01-05 19:17:24333 render_thread_->AddRoute(routing_id_, this);
initial.commit09911bf2008-07-26 23:55:29334 // Take a reference on behalf of the RenderThread. This will be balanced
335 // when we receive ViewMsg_Close.
336 AddRef();
337
338 // If this is a popup, we must wait for the CreatingNew_ACK message before
339 // completing initialization. Otherwise, we can finish it now.
340 if (opener_id == MSG_ROUTING_NONE) {
341 did_show_ = true;
342 CompleteInit(parent_hwnd);
343 }
344
345 host_window_ = parent_hwnd;
initial.commit09911bf2008-07-26 23:55:29346
[email protected]58bfc6b2009-06-24 09:45:02347 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
[email protected]81e63782009-02-27 19:35:09348 if (command_line.HasSwitch(switches::kDomAutomationController))
349 enabled_bindings_ |= BindingsPolicy::DOM_AUTOMATION;
initial.commit09911bf2008-07-26 23:55:29350
[email protected]5fb88962009-04-16 19:03:25351 audio_message_filter_ = new AudioMessageFilter(routing_id_);
352 render_thread_->AddFilter(audio_message_filter_);
[email protected]90e908552009-10-05 01:40:12353 render_thread_->AddFilter(notification_provider_.get());
initial.commit09911bf2008-07-26 23:55:29354}
355
356void RenderView::OnMessageReceived(const IPC::Message& message) {
[email protected]26aa0482009-09-30 16:55:27357 WebFrame* main_frame = webview() ? webview()->mainFrame() : NULL;
[email protected]ef916272009-07-08 21:40:55358 child_process_logging::ScopedActiveURLSetter url_setter(
[email protected]dd7daa82009-08-10 05:46:45359 main_frame ? main_frame->url() : WebURL());
[email protected]f8b6b6f2009-03-10 16:48:26360
[email protected]b2abac72009-02-26 12:39:28361 // If this is developer tools renderer intercept tools messages first.
[email protected]e4ac5df2009-03-17 15:33:11362 if (devtools_client_.get() && devtools_client_->OnMessageReceived(message))
[email protected]b2abac72009-02-26 12:39:28363 return;
[email protected]b4b967e2009-04-22 11:33:05364 if (devtools_agent_.get() && devtools_agent_->OnMessageReceived(message))
365 return;
[email protected]b2abac72009-02-26 12:39:28366
initial.commit09911bf2008-07-26 23:55:29367 IPC_BEGIN_MESSAGE_MAP(RenderView, message)
initial.commit09911bf2008-07-26 23:55:29368 IPC_MESSAGE_HANDLER(ViewMsg_CaptureThumbnail, SendThumbnail)
initial.commit09911bf2008-07-26 23:55:29369 IPC_MESSAGE_HANDLER(ViewMsg_PrintPages, OnPrintPages)
[email protected]82270452009-06-19 15:58:01370 IPC_MESSAGE_HANDLER(ViewMsg_PrintingDone, OnPrintingDone)
initial.commit09911bf2008-07-26 23:55:29371 IPC_MESSAGE_HANDLER(ViewMsg_Navigate, OnNavigate)
372 IPC_MESSAGE_HANDLER(ViewMsg_Stop, OnStop)
373 IPC_MESSAGE_HANDLER(ViewMsg_LoadAlternateHTMLText, OnLoadAlternateHTMLText)
374 IPC_MESSAGE_HANDLER(ViewMsg_StopFinding, OnStopFinding)
375 IPC_MESSAGE_HANDLER(ViewMsg_Undo, OnUndo)
376 IPC_MESSAGE_HANDLER(ViewMsg_Redo, OnRedo)
377 IPC_MESSAGE_HANDLER(ViewMsg_Cut, OnCut)
378 IPC_MESSAGE_HANDLER(ViewMsg_Copy, OnCopy)
[email protected]c0cc3092009-09-12 08:27:27379#if defined(OS_MACOSX)
[email protected]a954bf72009-09-12 07:30:35380 IPC_MESSAGE_HANDLER(ViewMsg_CopyToFindPboard, OnCopyToFindPboard)
[email protected]c0cc3092009-09-12 08:27:27381#endif
initial.commit09911bf2008-07-26 23:55:29382 IPC_MESSAGE_HANDLER(ViewMsg_Paste, OnPaste)
383 IPC_MESSAGE_HANDLER(ViewMsg_Replace, OnReplace)
[email protected]98324892009-09-09 21:16:05384 IPC_MESSAGE_HANDLER(ViewMsg_ToggleSpellPanel, OnToggleSpellPanel)
385 IPC_MESSAGE_HANDLER(ViewMsg_AdvanceToNextMisspelling,
386 OnAdvanceToNextMisspelling)
[email protected]bbbd545c2008-12-15 20:18:04387 IPC_MESSAGE_HANDLER(ViewMsg_ToggleSpellCheck, OnToggleSpellCheck)
initial.commit09911bf2008-07-26 23:55:29388 IPC_MESSAGE_HANDLER(ViewMsg_Delete, OnDelete)
389 IPC_MESSAGE_HANDLER(ViewMsg_SelectAll, OnSelectAll)
390 IPC_MESSAGE_HANDLER(ViewMsg_CopyImageAt, OnCopyImageAt)
[email protected]4b59ae602009-06-23 20:58:15391 IPC_MESSAGE_HANDLER(ViewMsg_ExecuteEditCommand, OnExecuteEditCommand)
initial.commit09911bf2008-07-26 23:55:29392 IPC_MESSAGE_HANDLER(ViewMsg_Find, OnFind)
[email protected]5c4266922009-07-10 16:41:27393 IPC_MESSAGE_HANDLER(ViewMsg_DeterminePageText, OnDeterminePageText)
[email protected]630e26b2008-10-14 22:55:17394 IPC_MESSAGE_HANDLER(ViewMsg_Zoom, OnZoom)
initial.commit09911bf2008-07-26 23:55:29395 IPC_MESSAGE_HANDLER(ViewMsg_SetPageEncoding, OnSetPageEncoding)
[email protected]a697f4c2009-09-14 22:30:18396 IPC_MESSAGE_HANDLER(ViewMsg_ResetPageEncodingToDefault,
397 OnResetPageEncodingToDefault)
[email protected]b2abac72009-02-26 12:39:28398 IPC_MESSAGE_HANDLER(ViewMsg_SetupDevToolsClient, OnSetupDevToolsClient)
[email protected]bf5c2ff392009-07-08 16:24:33399 IPC_MESSAGE_HANDLER(ViewMsg_DownloadFavIcon, OnDownloadFavIcon)
initial.commit09911bf2008-07-26 23:55:29400 IPC_MESSAGE_HANDLER(ViewMsg_ScriptEvalRequest, OnScriptEvalRequest)
[email protected]1810e132009-03-24 23:35:48401 IPC_MESSAGE_HANDLER(ViewMsg_CSSInsertRequest, OnCSSInsertRequest)
initial.commit09911bf2008-07-26 23:55:29402 IPC_MESSAGE_HANDLER(ViewMsg_AddMessageToConsole, OnAddMessageToConsole)
initial.commit09911bf2008-07-26 23:55:29403 IPC_MESSAGE_HANDLER(ViewMsg_ReservePageIDRange, OnReservePageIDRange)
404 IPC_MESSAGE_HANDLER(ViewMsg_UploadFile, OnUploadFileRequest)
405 IPC_MESSAGE_HANDLER(ViewMsg_FormFill, OnFormFill)
406 IPC_MESSAGE_HANDLER(ViewMsg_FillPasswordForm, OnFillPasswordForm)
407 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragEnter, OnDragTargetDragEnter)
408 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragOver, OnDragTargetDragOver)
409 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragLeave, OnDragTargetDragLeave)
410 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDrop, OnDragTargetDrop)
[email protected]18cb2572008-08-21 20:34:45411 IPC_MESSAGE_HANDLER(ViewMsg_AllowBindings, OnAllowBindings)
initial.commit09911bf2008-07-26 23:55:29412 IPC_MESSAGE_HANDLER(ViewMsg_SetDOMUIProperty, OnSetDOMUIProperty)
[email protected]266eb6f2008-09-30 23:56:50413 IPC_MESSAGE_HANDLER(ViewMsg_DragSourceEndedOrMoved,
414 OnDragSourceEndedOrMoved)
initial.commit09911bf2008-07-26 23:55:29415 IPC_MESSAGE_HANDLER(ViewMsg_DragSourceSystemDragEnded,
416 OnDragSourceSystemDragEnded)
417 IPC_MESSAGE_HANDLER(ViewMsg_SetInitialFocus, OnSetInitialFocus)
418 IPC_MESSAGE_HANDLER(ViewMsg_FindReplyACK, OnFindReplyAck)
419 IPC_MESSAGE_HANDLER(ViewMsg_UpdateTargetURL_ACK, OnUpdateTargetURLAck)
420 IPC_MESSAGE_HANDLER(ViewMsg_UpdateWebPreferences, OnUpdateWebPreferences)
421 IPC_MESSAGE_HANDLER(ViewMsg_SetAltErrorPageURL, OnSetAltErrorPageURL)
422 IPC_MESSAGE_HANDLER(ViewMsg_InstallMissingPlugin, OnInstallMissingPlugin)
423 IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse)
424 IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode, OnEnableViewSourceMode)
425 IPC_MESSAGE_HANDLER(ViewMsg_UpdateBackForwardListCount,
426 OnUpdateBackForwardListCount)
427 IPC_MESSAGE_HANDLER(ViewMsg_GetAllSavableResourceLinksForCurrentPage,
428 OnGetAllSavableResourceLinksForCurrentPage)
[email protected]f09c7182009-03-10 12:54:04429 IPC_MESSAGE_HANDLER(
430 ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks,
431 OnGetSerializedHtmlDataForCurrentPageWithLocalLinks)
initial.commit09911bf2008-07-26 23:55:29432 IPC_MESSAGE_HANDLER(ViewMsg_GetApplicationInfo, OnGetApplicationInfo)
[email protected]266eb6f2008-09-30 23:56:50433 IPC_MESSAGE_HANDLER(ViewMsg_GetAccessibilityInfo, OnGetAccessibilityInfo)
434 IPC_MESSAGE_HANDLER(ViewMsg_ClearAccessibilityInfo,
435 OnClearAccessibilityInfo)
initial.commit09911bf2008-07-26 23:55:29436 IPC_MESSAGE_HANDLER(ViewMsg_ShouldClose, OnMsgShouldClose)
437 IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage)
438 IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged)
[email protected]18cb2572008-08-21 20:34:45439 IPC_MESSAGE_HANDLER(ViewMsg_HandleMessageFromExternalHost,
440 OnMessageFromExternalHost)
[email protected]0aa55312008-10-17 21:53:08441 IPC_MESSAGE_HANDLER(ViewMsg_DisassociateFromPopupCount,
442 OnDisassociateFromPopupCount)
[email protected]0ebf3872008-11-07 21:35:03443 IPC_MESSAGE_HANDLER(ViewMsg_AutofillSuggestions,
444 OnReceivedAutofillSuggestions)
[email protected]2c4410d2009-05-06 23:46:22445 IPC_MESSAGE_HANDLER(ViewMsg_PopupNotificationVisibilityChanged,
446 OnPopupNotificationVisibilityChanged)
[email protected]30f75e62009-02-25 22:01:00447 IPC_MESSAGE_HANDLER(ViewMsg_MoveOrResizeStarted, OnMoveOrResizeStarted)
[email protected]309d7a282009-03-24 09:18:27448 IPC_MESSAGE_HANDLER(ViewMsg_ExtensionResponse, OnExtensionResponse)
[email protected]7120f132009-07-20 21:05:37449 IPC_MESSAGE_HANDLER(ViewMsg_ExtensionMessageInvoke,
450 OnExtensionMessageInvoke)
[email protected]05d478752009-04-08 23:38:16451 IPC_MESSAGE_HANDLER(ViewMsg_ClearFocusedNode, OnClearFocusedNode)
[email protected]699ab0d2009-04-23 23:19:14452 IPC_MESSAGE_HANDLER(ViewMsg_SetBackground, OnSetBackground)
[email protected]0666aef2009-05-13 19:48:08453 IPC_MESSAGE_HANDLER(ViewMsg_EnableIntrinsicWidthChangedMode,
454 OnEnableIntrinsicWidthChangedMode)
[email protected]80d96fa2009-06-10 22:34:51455 IPC_MESSAGE_HANDLER(ViewMsg_SetRendererPrefs, OnSetRendererPrefs)
[email protected]7b291f92009-08-14 05:43:53456 IPC_MESSAGE_HANDLER(ViewMsg_UpdateBrowserWindowId,
457 OnUpdateBrowserWindowId)
458 IPC_MESSAGE_HANDLER(ViewMsg_NotifyRenderViewType,
459 OnNotifyRendererViewType)
[email protected]581b87eb2009-07-23 23:06:56460 IPC_MESSAGE_HANDLER(ViewMsg_MediaPlayerActionAt, OnMediaPlayerActionAt)
[email protected]8c66c5a2009-07-22 17:26:34461 IPC_MESSAGE_HANDLER(ViewMsg_SetActive, OnSetActive)
[email protected]446705872009-09-10 07:22:48462 IPC_MESSAGE_HANDLER(ViewMsg_SetEditCommandsForNextKeyEvent,
463 OnSetEditCommandsForNextKeyEvent);
[email protected]912256b32009-09-18 09:47:35464 IPC_MESSAGE_HANDLER(ViewMsg_ExecuteCode,
465 OnExecuteCode)
[email protected]634a6f92008-12-01 21:39:31466
initial.commit09911bf2008-07-26 23:55:29467 // Have the super handle all other messages.
468 IPC_MESSAGE_UNHANDLED(RenderWidget::OnMessageReceived(message))
469 IPC_END_MESSAGE_MAP()
470}
471
initial.commit09911bf2008-07-26 23:55:29472void RenderView::SendThumbnail() {
[email protected]26aa0482009-09-30 16:55:27473 WebFrame* main_frame = webview()->mainFrame();
initial.commit09911bf2008-07-26 23:55:29474 if (!main_frame)
475 return;
476
477 // get the URL for this page
[email protected]dd7daa82009-08-10 05:46:45478 GURL url(main_frame->url());
initial.commit09911bf2008-07-26 23:55:29479 if (url.is_empty())
480 return;
481
482 if (size_.IsEmpty())
483 return; // Don't create an empty thumbnail!
484
485 ThumbnailScore score;
486 SkBitmap thumbnail;
[email protected]8649fb32009-06-26 17:51:02487 if (!CaptureThumbnail(webview(), kThumbnailWidth, kThumbnailHeight,
[email protected]b6e4bec2008-11-12 01:17:15488 &thumbnail, &score))
489 return;
490
initial.commit09911bf2008-07-26 23:55:29491 // send the thumbnail message to the browser process
[email protected]674741932009-02-04 23:44:46492 Send(new ViewHostMsg_Thumbnail(routing_id_, url, score, thumbnail));
initial.commit09911bf2008-07-26 23:55:29493}
494
[email protected]068637222009-01-29 16:58:07495void RenderView::OnPrintPages() {
initial.commit09911bf2008-07-26 23:55:29496 DCHECK(webview());
[email protected]aa82249f2009-07-16 17:23:58497 if (webview()) {
498 // If the user has selected text in the currently focused frame we print
499 // only that frame (this makes print selection work for multiple frames).
[email protected]26aa0482009-09-30 16:55:27500 if (webview()->focusedFrame()->hasSelection())
501 Print(webview()->focusedFrame(), false);
[email protected]aa82249f2009-07-16 17:23:58502 else
[email protected]26aa0482009-09-30 16:55:27503 Print(webview()->mainFrame(), false);
[email protected]aa82249f2009-07-16 17:23:58504 }
initial.commit09911bf2008-07-26 23:55:29505}
506
[email protected]82270452009-06-19 15:58:01507void RenderView::OnPrintingDone(int document_cookie, bool success) {
508 // Ignoring document cookie here since only one print job can be outstanding
509 // per renderer and document_cookie is 0 when printing is successful.
510 DCHECK(print_helper_.get());
511 if (print_helper_.get() != NULL) {
512 print_helper_->DidFinishPrinting(success);
513 }
514}
515
initial.commit09911bf2008-07-26 23:55:29516void RenderView::CapturePageInfo(int load_id, bool preliminary_capture) {
517 if (load_id != page_id_)
518 return; // this capture call is no longer relevant due to navigation
519 if (load_id == last_indexed_page_id_)
520 return; // we already indexed this page
521
522 if (!webview())
523 return;
524
[email protected]26aa0482009-09-30 16:55:27525 WebFrame* main_frame = webview()->mainFrame();
initial.commit09911bf2008-07-26 23:55:29526 if (!main_frame)
527 return;
528
529 // Don't index/capture pages that are in view source mode.
[email protected]dd7daa82009-08-10 05:46:45530 if (main_frame->isViewSourceModeEnabled())
initial.commit09911bf2008-07-26 23:55:29531 return;
532
533 // Don't index/capture pages that failed to load. This only checks the top
534 // level frame so the thumbnail may contain a frame that failed to load.
[email protected]dd7daa82009-08-10 05:46:45535 WebDataSource* ds = main_frame->dataSource();
[email protected]726985e22009-06-18 21:09:28536 if (ds && ds->hasUnreachableURL())
initial.commit09911bf2008-07-26 23:55:29537 return;
538
539 if (!preliminary_capture)
540 last_indexed_page_id_ = load_id;
541
542 // get the URL for this page
[email protected]dd7daa82009-08-10 05:46:45543 GURL url(main_frame->url());
initial.commit09911bf2008-07-26 23:55:29544 if (url.is_empty())
545 return;
546
547 // full text
548 std::wstring contents;
549 CaptureText(main_frame, &contents);
550 if (contents.size()) {
551 // Send the text to the browser for indexing.
552 Send(new ViewHostMsg_PageContents(url, load_id, contents));
553 }
554
[email protected]5c4266922009-07-10 16:41:27555 // Send over text content of this page to the browser.
556 if (determine_page_text_after_loading_stops_) {
557 determine_page_text_after_loading_stops_ = false;
558 Send(new ViewMsg_DeterminePageText_Reply(routing_id_, contents));
559 }
560
initial.commit09911bf2008-07-26 23:55:29561 // thumbnail
562 SendThumbnail();
563}
564
565void RenderView::CaptureText(WebFrame* frame, std::wstring* contents) {
566 contents->clear();
567 if (!frame)
568 return;
569
[email protected]0faf0bd92008-09-09 20:53:27570 // Don't index any https pages. People generally don't want their bank
571 // accounts, etc. indexed on their computer, especially since some of these
572 // things are not marked cachable.
573 // TODO(brettw) we may want to consider more elaborate heuristics such as
574 // the cachability of the page. We may also want to consider subframes (this
575 // test will still index subframes if the subframe is SSL).
[email protected]dd7daa82009-08-10 05:46:45576 if (GURL(frame->url()).SchemeIsSecure())
[email protected]0faf0bd92008-09-09 20:53:27577 return;
578
initial.commit09911bf2008-07-26 23:55:29579#ifdef TIME_TEXT_RETRIEVAL
580 double begin = time_util::GetHighResolutionTimeNow();
581#endif
582
583 // get the contents of the frame
[email protected]dd7daa82009-08-10 05:46:45584 *contents = UTF16ToWideHack(frame->contentAsText(kMaxIndexChars));
initial.commit09911bf2008-07-26 23:55:29585
586#ifdef TIME_TEXT_RETRIEVAL
587 double end = time_util::GetHighResolutionTimeNow();
588 char buf[128];
589 sprintf_s(buf, "%d chars retrieved for indexing in %gms\n",
590 contents.size(), (end - begin)*1000);
591 OutputDebugStringA(buf);
592#endif
593
594 // When the contents are clipped to the maximum, we don't want to have a
595 // partial word indexed at the end that might have been clipped. Therefore,
596 // terminate the string at the last space to ensure no words are clipped.
597 if (contents->size() == kMaxIndexChars) {
598 size_t last_space_index = contents->find_last_of(kWhitespaceWide);
599 if (last_space_index == std::wstring::npos)
600 return; // don't index if we got a huge block of text with no spaces
601 contents->resize(last_space_index);
602 }
603}
604
[email protected]8649fb32009-06-26 17:51:02605bool RenderView::CaptureThumbnail(WebView* view,
initial.commit09911bf2008-07-26 23:55:29606 int w,
607 int h,
608 SkBitmap* thumbnail,
609 ThumbnailScore* score) {
610#ifdef TIME_BITMAP_RETRIEVAL
611 double begin = time_util::GetHighResolutionTimeNow();
612#endif
613
[email protected]4873c7d2009-07-16 06:36:28614 view->layout();
615 const WebSize& size = view->size();
[email protected]b6e4bec2008-11-12 01:17:15616
[email protected]8649fb32009-06-26 17:51:02617 skia::PlatformCanvas canvas;
618 if (!canvas.initialize(size.width, size.height, true))
619 return false;
[email protected]8c89e7792009-08-19 21:18:34620 view->paint(webkit_glue::ToWebCanvas(&canvas),
621 WebRect(0, 0, size.width, size.height));
[email protected]8649fb32009-06-26 17:51:02622
623 skia::BitmapPlatformDevice& device =
624 static_cast<skia::BitmapPlatformDevice&>(canvas.getTopPlatformDevice());
625
626 const SkBitmap& src_bmp = device.accessBitmap(false);
initial.commit09911bf2008-07-26 23:55:29627
[email protected]cab34d6a2009-09-24 01:14:52628 SkRect dest_rect = { 0, 0, SkIntToScalar(w), SkIntToScalar(h) };
initial.commit09911bf2008-07-26 23:55:29629 float dest_aspect = dest_rect.width() / dest_rect.height();
630
631 // Get the src rect so that we can preserve the aspect ratio while filling
632 // the destination.
633 SkIRect src_rect;
634 if (src_bmp.width() < dest_rect.width() ||
635 src_bmp.height() < dest_rect.height()) {
636 // Source image is smaller: we clip the part of source image within the
637 // dest rect, and then stretch it to fill the dest rect. We don't respect
638 // the aspect ratio in this case.
639 src_rect.set(0, 0, static_cast<S16CPU>(dest_rect.width()),
640 static_cast<S16CPU>(dest_rect.height()));
641 score->good_clipping = false;
642 } else {
643 float src_aspect = static_cast<float>(src_bmp.width()) / src_bmp.height();
644 if (src_aspect > dest_aspect) {
645 // Wider than tall, clip horizontally: we center the smaller thumbnail in
646 // the wider screen.
647 S16CPU new_width = static_cast<S16CPU>(src_bmp.height() * dest_aspect);
648 S16CPU x_offset = (src_bmp.width() - new_width) / 2;
649 src_rect.set(x_offset, 0, new_width + x_offset, src_bmp.height());
650 score->good_clipping = false;
651 } else {
652 src_rect.set(0, 0, src_bmp.width(),
653 static_cast<S16CPU>(src_bmp.width() / dest_aspect));
654 score->good_clipping = true;
655 }
656 }
657
[email protected]26aa0482009-09-30 16:55:27658 score->at_top = (view->mainFrame()->scrollOffset().height == 0);
initial.commit09911bf2008-07-26 23:55:29659
660 SkBitmap subset;
[email protected]8649fb32009-06-26 17:51:02661 device.accessBitmap(false).extractSubset(&subset, src_rect);
initial.commit09911bf2008-07-26 23:55:29662
663 // Resample the subset that we want to get it the right size.
[email protected]465b34b72008-12-12 20:19:14664 *thumbnail = skia::ImageOperations::Resize(
665 subset, skia::ImageOperations::RESIZE_LANCZOS3, w, h);
initial.commit09911bf2008-07-26 23:55:29666
667 score->boring_score = CalculateBoringScore(thumbnail);
668
669#ifdef TIME_BITMAP_RETRIEVAL
670 double end = time_util::GetHighResolutionTimeNow();
671 char buf[128];
672 sprintf_s(buf, "thumbnail in %gms\n", (end - begin) * 1000);
673 OutputDebugStringA(buf);
674#endif
[email protected]b6e4bec2008-11-12 01:17:15675 return true;
initial.commit09911bf2008-07-26 23:55:29676}
677
678double RenderView::CalculateBoringScore(SkBitmap* bitmap) {
679 int histogram[256] = {0};
680 color_utils::BuildLumaHistogram(bitmap, histogram);
681
682 int color_count = *std::max_element(histogram, histogram + 256);
683 int pixel_count = bitmap->width() * bitmap->height();
684 return static_cast<double>(color_count) / pixel_count;
685}
686
687void RenderView::OnNavigate(const ViewMsg_Navigate_Params& params) {
688 if (!webview())
689 return;
690
[email protected]8c785c62009-07-13 14:20:15691 if (devtools_agent_.get())
692 devtools_agent_->OnNavigate();
693
[email protected]ef916272009-07-08 21:40:55694 child_process_logging::ScopedActiveURLSetter url_setter(params.url);
[email protected]f8b6b6f2009-03-10 16:48:26695
initial.commit09911bf2008-07-26 23:55:29696 AboutHandler::MaybeHandle(params.url);
697
698 bool is_reload = params.reload;
699
[email protected]26aa0482009-09-30 16:55:27700 WebFrame* main_frame = webview()->mainFrame();
[email protected]dd7daa82009-08-10 05:46:45701 if (is_reload && main_frame->currentHistoryItem().isNull()) {
initial.commit09911bf2008-07-26 23:55:29702 // We cannot reload if we do not have any history state. This happens, for
703 // example, when recovering from a crash. Our workaround here is a bit of
704 // a hack since it means that reload after a crashed tab does not cause an
705 // end-to-end cache validation.
706 is_reload = false;
707 }
708
[email protected]77f17a82009-05-21 04:42:54709 // A navigation resulting from loading a javascript URL should not be treated
710 // as a browser initiated event. Instead, we want it to look as if the page
711 // initiated any load resulting from JS execution.
712 if (!params.url.SchemeIs(chrome::kJavaScriptScheme)) {
[email protected]daa8c58e2009-06-15 17:21:10713 pending_navigation_state_.reset(NavigationState::CreateBrowserInitiated(
[email protected]77f17a82009-05-21 04:42:54714 params.page_id, params.transition, params.request_time));
715 }
initial.commit09911bf2008-07-26 23:55:29716
[email protected]04d3c6e2009-05-22 17:00:13717 // If we are reloading, then WebKit will use the history state of the current
718 // page, so we should just ignore any given history state. Otherwise, if we
719 // have history state, then we need to navigate to it, which corresponds to a
720 // back/forward navigation event.
[email protected]e6f546c32009-07-01 17:12:55721 if (is_reload) {
[email protected]dd7daa82009-08-10 05:46:45722 main_frame->reload();
[email protected]e6f546c32009-07-01 17:12:55723 } else if (!params.state.empty()) {
[email protected]04d3c6e2009-05-22 17:00:13724 // We must know the page ID of the page we are navigating back to.
[email protected]f929f2f22009-06-12 16:56:58725 DCHECK_NE(params.page_id, -1);
[email protected]dd7daa82009-08-10 05:46:45726 main_frame->loadHistoryItem(
[email protected]ca948a22009-06-25 19:36:17727 webkit_glue::HistoryItemFromString(params.state));
[email protected]04d3c6e2009-05-22 17:00:13728 } else {
729 // Navigate to the given URL.
[email protected]726985e22009-06-18 21:09:28730 WebURLRequest request(params.url);
initial.commit09911bf2008-07-26 23:55:29731
[email protected]e6f546c32009-07-01 17:12:55732 // A session history navigation should have been accompanied by state.
733 DCHECK_EQ(params.page_id, -1);
[email protected]04d3c6e2009-05-22 17:00:13734
[email protected]dd7daa82009-08-10 05:46:45735 if (main_frame->isViewSourceModeEnabled())
[email protected]e6f546c32009-07-01 17:12:55736 request.setCachePolicy(WebURLRequest::ReturnCacheDataElseLoad);
[email protected]04d3c6e2009-05-22 17:00:13737
[email protected]726985e22009-06-18 21:09:28738 if (params.referrer.is_valid()) {
739 request.setHTTPHeaderField(WebString::fromUTF8("Referer"),
740 WebString::fromUTF8(params.referrer.spec()));
741 }
[email protected]04d3c6e2009-05-22 17:00:13742
[email protected]dd7daa82009-08-10 05:46:45743 main_frame->loadRequest(request);
[email protected]c0588052008-10-27 23:01:50744 }
745
[email protected]77f17a82009-05-21 04:42:54746 // In case LoadRequest failed before DidCreateDataSource was called.
747 pending_navigation_state_.reset();
initial.commit09911bf2008-07-26 23:55:29748}
749
750// Stop loading the current page
751void RenderView::OnStop() {
752 if (webview())
[email protected]b4bb2502009-10-01 22:35:27753 webview()->mainFrame()->stopLoading();
initial.commit09911bf2008-07-26 23:55:29754}
755
[email protected]e6f546c32009-07-01 17:12:55756void RenderView::OnLoadAlternateHTMLText(const std::string& html,
initial.commit09911bf2008-07-26 23:55:29757 bool new_navigation,
758 const GURL& display_url,
759 const std::string& security_info) {
760 if (!webview())
761 return;
762
[email protected]e6f546c32009-07-01 17:12:55763 pending_navigation_state_.reset(NavigationState::CreateBrowserInitiated(
764 new_navigation ? -1 : page_id_, PageTransition::LINK, Time::Now()));
765 pending_navigation_state_->set_security_info(security_info);
initial.commit09911bf2008-07-26 23:55:29766
[email protected]26aa0482009-09-30 16:55:27767 webview()->mainFrame()->loadHTMLString(
768 html, GURL(kUnreachableWebDataURL), display_url, !new_navigation);
[email protected]e6f546c32009-07-01 17:12:55769
770 pending_navigation_state_.reset();
initial.commit09911bf2008-07-26 23:55:29771}
772
773void RenderView::OnCopyImageAt(int x, int y) {
[email protected]26aa0482009-09-30 16:55:27774 webview()->copyImageAt(WebPoint(x, y));
initial.commit09911bf2008-07-26 23:55:29775}
776
[email protected]68b1e922009-06-23 16:00:25777void RenderView::OnExecuteEditCommand(const std::string& name,
778 const std::string& value) {
[email protected]26aa0482009-09-30 16:55:27779 if (!webview() || !webview()->focusedFrame())
[email protected]68b1e922009-06-23 16:00:25780 return;
781
[email protected]26aa0482009-09-30 16:55:27782 webview()->focusedFrame()->executeCommand(
[email protected]dd7daa82009-08-10 05:46:45783 WebString::fromUTF8(name), WebString::fromUTF8(value));
[email protected]68b1e922009-06-23 16:00:25784}
785
[email protected]b2abac72009-02-26 12:39:28786void RenderView::OnSetupDevToolsClient() {
[email protected]e4ac5df2009-03-17 15:33:11787 DCHECK(!devtools_client_.get());
788 devtools_client_.reset(new DevToolsClient(this));
[email protected]b2abac72009-02-26 12:39:28789}
790
initial.commit09911bf2008-07-26 23:55:29791void RenderView::OnStopFinding(bool clear_selection) {
792 WebView* view = webview();
793 if (!view)
794 return;
795
796 if (clear_selection)
[email protected]26aa0482009-09-30 16:55:27797 view->focusedFrame()->executeCommand(WebString::fromUTF8("Unselect"));
initial.commit09911bf2008-07-26 23:55:29798
[email protected]26aa0482009-09-30 16:55:27799 WebFrame* frame = view->mainFrame();
initial.commit09911bf2008-07-26 23:55:29800 while (frame) {
[email protected]dd7daa82009-08-10 05:46:45801 frame->stopFinding(clear_selection);
[email protected]b4bb2502009-10-01 22:35:27802 frame = frame->traverseNext(false);
initial.commit09911bf2008-07-26 23:55:29803 }
804}
805
806void RenderView::OnFindReplyAck() {
807 // Check if there is any queued up request waiting to be sent.
808 if (queued_find_reply_message_.get()) {
809 // Send the search result over to the browser process.
810 Send(queued_find_reply_message_.get());
811 queued_find_reply_message_.release();
812 }
813}
814
815void RenderView::OnUpdateTargetURLAck() {
816 // Check if there is a targeturl waiting to be sent.
817 if (target_url_status_ == TARGET_PENDING) {
818 Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_,
819 pending_target_url_));
820 }
821
822 target_url_status_ = TARGET_NONE;
823}
824
825void RenderView::OnUndo() {
826 if (!webview())
827 return;
828
[email protected]26aa0482009-09-30 16:55:27829 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Undo"));
[email protected]dd7daa82009-08-10 05:46:45830 UserMetricsRecordAction(L"Undo");
initial.commit09911bf2008-07-26 23:55:29831}
832
833void RenderView::OnRedo() {
834 if (!webview())
835 return;
836
[email protected]26aa0482009-09-30 16:55:27837 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Redo"));
[email protected]dd7daa82009-08-10 05:46:45838 UserMetricsRecordAction(L"Redo");
initial.commit09911bf2008-07-26 23:55:29839}
840
841void RenderView::OnCut() {
842 if (!webview())
843 return;
844
[email protected]26aa0482009-09-30 16:55:27845 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Cut"));
[email protected]dd7daa82009-08-10 05:46:45846 UserMetricsRecordAction(L"Cut");
initial.commit09911bf2008-07-26 23:55:29847}
848
849void RenderView::OnCopy() {
850 if (!webview())
851 return;
852
[email protected]26aa0482009-09-30 16:55:27853 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Copy"));
[email protected]dd7daa82009-08-10 05:46:45854 UserMetricsRecordAction(L"Copy");
initial.commit09911bf2008-07-26 23:55:29855}
856
[email protected]c0cc3092009-09-12 08:27:27857#if defined(OS_MACOSX)
[email protected]a954bf72009-09-12 07:30:35858void RenderView::OnCopyToFindPboard() {
859 if (!webview())
860 return;
861
862 // Since the find pasteboard supports only plain text, this can be simpler
863 // than the |OnCopy()| case.
[email protected]26aa0482009-09-30 16:55:27864 WebFrame* frame = webview()->focusedFrame();
[email protected]a954bf72009-09-12 07:30:35865 if (frame->hasSelection()) {
866 string16 selection = frame->selectionAsText();
867 RenderThread::current()->Send(
868 new ViewHostMsg_ClipboardFindPboardWriteStringAsync(selection));
869 }
870
871 UserMetricsRecordAction(L"CopyToFindPboard");
872}
[email protected]c0cc3092009-09-12 08:27:27873#endif
[email protected]a954bf72009-09-12 07:30:35874
initial.commit09911bf2008-07-26 23:55:29875void RenderView::OnPaste() {
876 if (!webview())
877 return;
878
[email protected]26aa0482009-09-30 16:55:27879 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Paste"));
[email protected]dd7daa82009-08-10 05:46:45880 UserMetricsRecordAction(L"Paste");
initial.commit09911bf2008-07-26 23:55:29881}
882
883void RenderView::OnReplace(const std::wstring& text) {
884 if (!webview())
885 return;
886
[email protected]26aa0482009-09-30 16:55:27887 webview()->focusedFrame()->replaceSelection(WideToUTF16Hack(text));
initial.commit09911bf2008-07-26 23:55:29888}
889
[email protected]98324892009-09-09 21:16:05890void RenderView::OnAdvanceToNextMisspelling() {
891 if (!webview())
892 return;
[email protected]26aa0482009-09-30 16:55:27893 webview()->focusedFrame()->executeCommand(
[email protected]98324892009-09-09 21:16:05894 WebString::fromUTF8("AdvanceToNextMisspelling"));
895}
896
897void RenderView::OnToggleSpellPanel(bool is_currently_visible) {
898 if (!webview())
899 return;
900 // We need to tell the webView whether the spelling panel is visible or not so
901 // that it won't need to make ipc calls later.
[email protected]8922e1f2009-10-03 05:01:26902 spelling_panel_visible_ = is_currently_visible;
[email protected]26aa0482009-09-30 16:55:27903 webview()->focusedFrame()->executeCommand(
[email protected]98324892009-09-09 21:16:05904 WebString::fromUTF8("ToggleSpellPanel"));
905}
906
[email protected]bbbd545c2008-12-15 20:18:04907void RenderView::OnToggleSpellCheck() {
908 if (!webview())
909 return;
910
[email protected]26aa0482009-09-30 16:55:27911 WebFrame* frame = webview()->focusedFrame();
[email protected]dd7daa82009-08-10 05:46:45912 frame->enableContinuousSpellChecking(
913 !frame->isContinuousSpellCheckingEnabled());
[email protected]bbbd545c2008-12-15 20:18:04914}
915
initial.commit09911bf2008-07-26 23:55:29916void RenderView::OnDelete() {
917 if (!webview())
918 return;
919
[email protected]26aa0482009-09-30 16:55:27920 webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Delete"));
[email protected]dd7daa82009-08-10 05:46:45921 UserMetricsRecordAction(L"DeleteSelection");
initial.commit09911bf2008-07-26 23:55:29922}
923
924void RenderView::OnSelectAll() {
925 if (!webview())
926 return;
927
[email protected]26aa0482009-09-30 16:55:27928 webview()->focusedFrame()->executeCommand(
[email protected]a100d76bb2009-08-14 17:50:22929 WebString::fromUTF8("SelectAll"));
930 UserMetricsRecordAction(L"SelectAll");
initial.commit09911bf2008-07-26 23:55:29931}
932
933void RenderView::OnSetInitialFocus(bool reverse) {
934 if (!webview())
935 return;
[email protected]26aa0482009-09-30 16:55:27936 webview()->setInitialFocus(reverse);
initial.commit09911bf2008-07-26 23:55:29937}
938
939///////////////////////////////////////////////////////////////////////////////
940
941// Tell the embedding application that the URL of the active page has changed
942void RenderView::UpdateURL(WebFrame* frame) {
[email protected]dd7daa82009-08-10 05:46:45943 WebDataSource* ds = frame->dataSource();
initial.commit09911bf2008-07-26 23:55:29944 DCHECK(ds);
945
[email protected]726985e22009-06-18 21:09:28946 const WebURLRequest& request = ds->request();
947 const WebURLRequest& original_request = ds->originalRequest();
948 const WebURLResponse& response = ds->response();
initial.commit09911bf2008-07-26 23:55:29949
[email protected]daa8c58e2009-06-15 17:21:10950 NavigationState* navigation_state = NavigationState::FromDataSource(ds);
951 DCHECK(navigation_state);
initial.commit09911bf2008-07-26 23:55:29952
953 ViewHostMsg_FrameNavigate_Params params;
[email protected]726985e22009-06-18 21:09:28954 params.http_status_code = response.httpStatusCode();
initial.commit09911bf2008-07-26 23:55:29955 params.is_post = false;
956 params.page_id = page_id_;
[email protected]726985e22009-06-18 21:09:28957 params.is_content_filtered = response.isContentFiltered();
[email protected]e6f546c32009-07-01 17:12:55958 if (!navigation_state->security_info().empty()) {
initial.commit09911bf2008-07-26 23:55:29959 // SSL state specified in the request takes precedence over the one in the
960 // response.
961 // So far this is only intended for error pages that are not expected to be
962 // over ssl, so we should not get any clash.
[email protected]726985e22009-06-18 21:09:28963 DCHECK(response.securityInfo().isEmpty());
[email protected]e6f546c32009-07-01 17:12:55964 params.security_info = navigation_state->security_info();
initial.commit09911bf2008-07-26 23:55:29965 } else {
[email protected]726985e22009-06-18 21:09:28966 params.security_info = response.securityInfo();
initial.commit09911bf2008-07-26 23:55:29967 }
968
969 // Set the URL to be displayed in the browser UI to the user.
[email protected]726985e22009-06-18 21:09:28970 if (ds->hasUnreachableURL()) {
971 params.url = ds->unreachableURL();
initial.commit09911bf2008-07-26 23:55:29972 } else {
[email protected]726985e22009-06-18 21:09:28973 params.url = request.url();
initial.commit09911bf2008-07-26 23:55:29974 }
975
[email protected]726985e22009-06-18 21:09:28976 GetRedirectChain(ds, &params.redirects);
977 params.should_update_history = !ds->hasUnreachableURL();
initial.commit09911bf2008-07-26 23:55:29978
979 const SearchableFormData* searchable_form_data =
[email protected]daa8c58e2009-06-15 17:21:10980 navigation_state->searchable_form_data();
initial.commit09911bf2008-07-26 23:55:29981 if (searchable_form_data) {
982 params.searchable_form_url = searchable_form_data->url();
983 params.searchable_form_element_name = searchable_form_data->element_name();
984 params.searchable_form_encoding = searchable_form_data->encoding();
985 }
986
987 const PasswordForm* password_form_data =
[email protected]daa8c58e2009-06-15 17:21:10988 navigation_state->password_form_data();
initial.commit09911bf2008-07-26 23:55:29989 if (password_form_data)
990 params.password_form = *password_form_data;
991
992 params.gesture = navigation_gesture_;
993 navigation_gesture_ = NavigationGestureUnknown;
994
[email protected]dd7daa82009-08-10 05:46:45995 if (!frame->parent()) {
initial.commit09911bf2008-07-26 23:55:29996 // Top-level navigation.
997
998 // Update contents MIME type for main frame.
[email protected]9c5645b2009-08-11 03:37:55999 params.contents_mime_type = ds->response().mimeType().utf8();
initial.commit09911bf2008-07-26 23:55:291000
[email protected]daa8c58e2009-06-15 17:21:101001 params.transition = navigation_state->transition_type();
initial.commit09911bf2008-07-26 23:55:291002 if (!PageTransition::IsMainFrame(params.transition)) {
1003 // If the main frame does a load, it should not be reported as a subframe
1004 // navigation. This can occur in the following case:
1005 // 1. You're on a site with frames.
1006 // 2. You do a subframe navigation. This is stored with transition type
1007 // MANUAL_SUBFRAME.
1008 // 3. You navigate to some non-frame site, say, google.com.
1009 // 4. You navigate back to the page from step 2. Since it was initially
1010 // MANUAL_SUBFRAME, it will be that same transition type here.
1011 // We don't want that, because any navigation that changes the toplevel
1012 // frame should be tracked as a toplevel navigation (this allows us to
1013 // update the URL bar, etc).
1014 params.transition = PageTransition::LINK;
1015 }
1016
initial.commit09911bf2008-07-26 23:55:291017 // If we have a valid consumed client redirect source,
1018 // the page contained a client redirect (meta refresh, document.loc...),
1019 // so we set the referrer and transition to match.
1020 if (completed_client_redirect_src_.is_valid()) {
[email protected]77e09a92008-08-01 18:11:041021 DCHECK(completed_client_redirect_src_ == params.redirects[0]);
initial.commit09911bf2008-07-26 23:55:291022 params.referrer = completed_client_redirect_src_;
1023 params.transition = static_cast<PageTransition::Type>(
1024 params.transition | PageTransition::CLIENT_REDIRECT);
1025 } else {
1026 // Bug 654101: the referrer will be empty on https->http transitions. It
1027 // would be nice if we could get the real referrer from somewhere.
[email protected]726985e22009-06-18 21:09:281028 params.referrer = GURL(
1029 original_request.httpHeaderField(WebString::fromUTF8("Referer")));
initial.commit09911bf2008-07-26 23:55:291030 }
1031
[email protected]726985e22009-06-18 21:09:281032 string16 method = request.httpMethod();
1033 if (EqualsASCII(method, "POST"))
initial.commit09911bf2008-07-26 23:55:291034 params.is_post = true;
1035
[email protected]c2a797d2009-09-21 16:46:321036 // Save some histogram data so we can compute the average memory used per
1037 // page load of the glyphs.
1038 UMA_HISTOGRAM_COUNTS_10000("Memory.GlyphPagesPerLoad",
1039 webkit_glue::GetGlyphPageCount());
1040
initial.commit09911bf2008-07-26 23:55:291041 Send(new ViewHostMsg_FrameNavigate(routing_id_, params));
1042 } else {
1043 // Subframe navigation: the type depends on whether this navigation
1044 // generated a new session history entry. When they do generate a session
1045 // history entry, it means the user initiated the navigation and we should
1046 // mark it as such. This test checks if this is the first time UpdateURL
1047 // has been called since WillNavigateToURL was called to initiate the load.
1048 if (page_id_ > last_page_id_sent_to_browser_)
1049 params.transition = PageTransition::MANUAL_SUBFRAME;
1050 else
1051 params.transition = PageTransition::AUTO_SUBFRAME;
1052
initial.commit09911bf2008-07-26 23:55:291053 Send(new ViewHostMsg_FrameNavigate(routing_id_, params));
1054 }
1055
1056 last_page_id_sent_to_browser_ =
1057 std::max(last_page_id_sent_to_browser_, page_id_);
1058
1059 // If we end up reusing this WebRequest (for example, due to a #ref click),
[email protected]daa8c58e2009-06-15 17:21:101060 // we don't want the transition type to persist. Just clear it.
1061 navigation_state->set_transition_type(PageTransition::LINK);
[email protected]266eb6f2008-09-30 23:56:501062
[email protected]6c8afae52009-01-22 02:24:571063#if defined(OS_WIN)
[email protected]6a983b42009-03-20 20:12:251064 if (web_accessibility_manager_.get()) {
[email protected]be645db2009-02-06 20:36:331065 // Clear accessibility info cache.
[email protected]6a983b42009-03-20 20:12:251066 web_accessibility_manager_->ClearAccObjMap(-1, true);
[email protected]266eb6f2008-09-30 23:56:501067 }
[email protected]6c8afae52009-01-22 02:24:571068#else
[email protected]7d926f92009-03-03 14:26:541069 // TODO(port): accessibility not yet implemented. See http://crbug.com/8288.
[email protected]6c8afae52009-01-22 02:24:571070#endif
initial.commit09911bf2008-07-26 23:55:291071}
1072
1073// Tell the embedding application that the title of the active page has changed
[email protected]3d9689372009-09-10 04:29:171074void RenderView::UpdateTitle(WebFrame* frame, const string16& title) {
initial.commit09911bf2008-07-26 23:55:291075 // Ignore all but top level navigations...
[email protected]3d9689372009-09-10 04:29:171076 if (!frame->parent()) {
[email protected]f0af6a72009-05-30 05:25:171077 Send(new ViewHostMsg_UpdateTitle(
[email protected]3d9689372009-09-10 04:29:171078 routing_id_,
1079 page_id_,
1080 UTF16ToWideHack(title.length() > chrome::kMaxTitleChars ?
1081 title.substr(0, chrome::kMaxTitleChars) : title)));
[email protected]f0af6a72009-05-30 05:25:171082 }
initial.commit09911bf2008-07-26 23:55:291083}
1084
1085void RenderView::UpdateEncoding(WebFrame* frame,
[email protected]41fc0322009-09-04 22:23:401086 const std::string& encoding_name) {
initial.commit09911bf2008-07-26 23:55:291087 // Only update main frame's encoding_name.
[email protected]26aa0482009-09-30 16:55:271088 if (webview()->mainFrame() == frame &&
initial.commit09911bf2008-07-26 23:55:291089 last_encoding_name_ != encoding_name) {
[email protected]e38f40152008-09-12 23:08:301090 // Save the encoding name for later comparing.
initial.commit09911bf2008-07-26 23:55:291091 last_encoding_name_ = encoding_name;
1092
[email protected]e38f40152008-09-12 23:08:301093 Send(new ViewHostMsg_UpdateEncoding(routing_id_, last_encoding_name_));
initial.commit09911bf2008-07-26 23:55:291094 }
1095}
1096
[email protected]f4d34b52008-11-24 23:05:011097// Sends the previous session history state to the browser so it will be saved
1098// before we navigate to a new page. This must be called *before* the page ID
1099// has been updated so we know what it was.
initial.commit09911bf2008-07-26 23:55:291100void RenderView::UpdateSessionHistory(WebFrame* frame) {
1101 // If we have a valid page ID at this point, then it corresponds to the page
1102 // we are navigating away from. Otherwise, this is the first navigation, so
1103 // there is no past session history to record.
1104 if (page_id_ == -1)
1105 return;
1106
[email protected]ca948a22009-06-25 19:36:171107 const WebHistoryItem& item =
[email protected]26aa0482009-09-30 16:55:271108 webview()->mainFrame()->previousHistoryItem();
[email protected]ca948a22009-06-25 19:36:171109 if (item.isNull())
initial.commit09911bf2008-07-26 23:55:291110 return;
[email protected]ca948a22009-06-25 19:36:171111
1112 Send(new ViewHostMsg_UpdateState(
1113 routing_id_, page_id_, webkit_glue::HistoryItemToString(item)));
initial.commit09911bf2008-07-26 23:55:291114}
1115
[email protected]3d9689372009-09-10 04:29:171116void RenderView::OpenURL(
1117 const GURL& url, const GURL& referrer, WebNavigationPolicy policy) {
1118 Send(new ViewHostMsg_OpenURL(
1119 routing_id_, url, referrer, NavigationPolicyToDisposition(policy)));
1120}
1121
[email protected]79dbc662009-09-04 05:42:511122// WebViewDelegate ------------------------------------------------------------
initial.commit09911bf2008-07-26 23:55:291123
[email protected]a2f6bc112009-06-27 16:27:251124void RenderView::DidPaint() {
[email protected]26aa0482009-09-30 16:55:271125 WebFrame* main_frame = webview()->mainFrame();
[email protected]a2f6bc112009-06-27 16:27:251126
[email protected]dd7daa82009-08-10 05:46:451127 if (main_frame->provisionalDataSource()) {
[email protected]a2f6bc112009-06-27 16:27:251128 // If we have a provisional frame we are between the start
1129 // and commit stages of loading...ignore this paint.
1130 return;
1131 }
1132
[email protected]dd7daa82009-08-10 05:46:451133 WebDataSource* ds = main_frame->dataSource();
[email protected]a2f6bc112009-06-27 16:27:251134 NavigationState* navigation_state = NavigationState::FromDataSource(ds);
[email protected]78a3a6f2009-07-02 16:15:011135 DCHECK(navigation_state);
1136
1137 Time now = Time::Now();
1138 if (navigation_state->first_paint_time().is_null()) {
1139 navigation_state->set_first_paint_time(now);
1140 }
1141 if (navigation_state->first_paint_after_load_time().is_null() &&
1142 !navigation_state->finish_load_time().is_null()) {
1143 navigation_state->set_first_paint_after_load_time(now);
[email protected]a2f6bc112009-06-27 16:27:251144 }
1145}
1146
initial.commit09911bf2008-07-26 23:55:291147void RenderView::LoadNavigationErrorPage(WebFrame* frame,
[email protected]726985e22009-06-18 21:09:281148 const WebURLRequest& failed_request,
1149 const WebURLError& error,
initial.commit09911bf2008-07-26 23:55:291150 const std::string& html,
1151 bool replace) {
[email protected]726985e22009-06-18 21:09:281152 GURL failed_url = error.unreachableURL;
initial.commit09911bf2008-07-26 23:55:291153
1154 std::string alt_html;
1155 if (html.empty()) {
1156 // Use a local error page.
1157 int resource_id;
1158 DictionaryValue error_strings;
[email protected]726985e22009-06-18 21:09:281159 if (error.reason == net::ERR_CACHE_MISS &&
1160 EqualsASCII(failed_request.httpMethod(), "POST")) {
initial.commit09911bf2008-07-26 23:55:291161 GetFormRepostErrorValues(failed_url, &error_strings);
1162 resource_id = IDR_ERROR_NO_DETAILS_HTML;
1163 } else {
1164 GetLocalizedErrorValues(error, &error_strings);
1165 resource_id = IDR_NET_ERROR_HTML;
1166 }
[email protected]8e50b602009-03-03 22:59:431167 error_strings.SetString(L"textdirection",
1168 (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) ?
1169 L"rtl" : L"ltr");
initial.commit09911bf2008-07-26 23:55:291170
1171 alt_html = GetAltHTMLForTemplate(error_strings, resource_id);
1172 } else {
1173 alt_html = html;
1174 }
1175
[email protected]dd7daa82009-08-10 05:46:451176 frame->loadHTMLString(alt_html,
[email protected]e6f546c32009-07-01 17:12:551177 GURL(kUnreachableWebDataURL),
1178 failed_url,
1179 replace);
initial.commit09911bf2008-07-26 23:55:291180}
1181
[email protected]7ccddb8c2009-08-04 17:36:551182void RenderView::BindDOMAutomationController(WebFrame* frame) {
initial.commit09911bf2008-07-26 23:55:291183 dom_automation_controller_.set_message_sender(this);
1184 dom_automation_controller_.set_routing_id(routing_id_);
[email protected]7ccddb8c2009-08-04 17:36:551185 dom_automation_controller_.BindToJavascript(frame,
initial.commit09911bf2008-07-26 23:55:291186 L"domAutomationController");
1187}
1188
initial.commit09911bf2008-07-26 23:55:291189bool RenderView::RunJavaScriptMessage(int type,
1190 const std::wstring& message,
1191 const std::wstring& default_value,
[email protected]a455d3812009-03-05 20:18:071192 const GURL& frame_url,
initial.commit09911bf2008-07-26 23:55:291193 std::wstring* result) {
1194 bool success = false;
1195 std::wstring result_temp;
1196 if (!result)
1197 result = &result_temp;
initial.commit09911bf2008-07-26 23:55:291198
[email protected]12636df2009-09-28 22:32:211199 SendAndRunNestedMessageLoop(new ViewHostMsg_RunJavaScriptMessage(
1200 routing_id_, message, default_value, frame_url, type, &success, result));
initial.commit09911bf2008-07-26 23:55:291201 return success;
1202}
1203
1204void RenderView::AddGURLSearchProvider(const GURL& osd_url, bool autodetected) {
1205 if (!osd_url.is_empty())
1206 Send(new ViewHostMsg_PageHasOSDD(routing_id_, page_id_, osd_url,
1207 autodetected));
1208}
1209
[email protected]0ebf3872008-11-07 21:35:031210void RenderView::QueryFormFieldAutofill(const std::wstring& field_name,
1211 const std::wstring& text,
1212 int64 node_id) {
1213 static int message_id_counter = 0;
1214 form_field_autofill_request_id_ = message_id_counter++;
1215 Send(new ViewHostMsg_QueryFormFieldAutofill(routing_id_,
1216 field_name, text,
1217 node_id,
1218 form_field_autofill_request_id_));
1219}
1220
[email protected]4d2b6fb2009-03-20 22:28:171221void RenderView::RemoveStoredAutofillEntry(const std::wstring& name,
1222 const std::wstring& value) {
1223 Send(new ViewHostMsg_RemoveAutofillEntry(routing_id_, name, value));
1224}
1225
[email protected]0ebf3872008-11-07 21:35:031226void RenderView::OnReceivedAutofillSuggestions(
1227 int64 node_id,
1228 int request_id,
[email protected]8d0f15c2008-11-11 01:01:091229 const std::vector<std::wstring>& suggestions,
[email protected]0ebf3872008-11-07 21:35:031230 int default_suggestion_index) {
1231 if (!webview() || request_id != form_field_autofill_request_id_)
1232 return;
1233
1234 webview()->AutofillSuggestionsForNode(node_id, suggestions,
1235 default_suggestion_index);
1236}
1237
[email protected]2c4410d2009-05-06 23:46:221238void RenderView::OnPopupNotificationVisibilityChanged(bool visible) {
[email protected]634a6f92008-12-01 21:39:311239 popup_notification_visible_ = visible;
1240}
1241
initial.commit09911bf2008-07-26 23:55:291242uint32 RenderView::GetCPBrowsingContext() {
1243 uint32 context = 0;
1244 Send(new ViewHostMsg_GetCPBrowsingContext(&context));
1245 return context;
1246}
1247
initial.commit09911bf2008-07-26 23:55:291248void RenderView::AddSearchProvider(const std::string& url) {
1249 AddGURLSearchProvider(GURL(url),
1250 false); // not autodetected
1251}
1252
[email protected]f103ab72009-09-02 17:10:591253void RenderView::OnMissingPluginStatus(
1254 WebPluginDelegateProxy* delegate,
1255 int status) {
[email protected]6c8afae52009-01-22 02:24:571256#if defined(OS_WIN)
[email protected]f103ab72009-09-02 17:10:591257 if (!first_default_plugin_) {
initial.commit09911bf2008-07-26 23:55:291258 // Show the InfoBar for the first available plugin.
1259 if (status == default_plugin::MISSING_PLUGIN_AVAILABLE) {
[email protected]f103ab72009-09-02 17:10:591260 first_default_plugin_ = delegate->AsWeakPtr();
initial.commit09911bf2008-07-26 23:55:291261 Send(new ViewHostMsg_MissingPluginStatus(routing_id_, status));
1262 }
1263 } else {
1264 // Closes the InfoBar if user clicks on the plugin (instead of the InfoBar)
1265 // to start the download/install.
1266 if (status == default_plugin::MISSING_PLUGIN_USER_STARTED_DOWNLOAD) {
1267 Send(new ViewHostMsg_MissingPluginStatus(routing_id_, status));
1268 }
1269 }
[email protected]6c8afae52009-01-22 02:24:571270#else
1271 // TODO(port): plugins current not supported
1272 NOTIMPLEMENTED();
1273#endif
initial.commit09911bf2008-07-26 23:55:291274}
1275
[email protected]48c9cf2d2009-09-16 16:47:521276// WebKit::WebViewClient ------------------------------------------------------
1277
1278WebView* RenderView::createView(WebFrame* creator) {
1279 // Check to make sure we aren't overloading on popups.
1280 if (shared_popup_counter_->data > kMaximumNumberOfUnacknowledgedPopups)
1281 return NULL;
1282
1283 // This window can't be closed from a window.close() call until we receive a
1284 // message from the Browser process explicitly allowing it.
1285 popup_notification_visible_ = true;
1286
1287 int32 routing_id = MSG_ROUTING_NONE;
1288 bool user_gesture = creator->isProcessingUserGesture();
1289
[email protected]48c9cf2d2009-09-16 16:47:521290 render_thread_->Send(
[email protected]12636df2009-09-28 22:32:211291 new ViewHostMsg_CreateWindow(routing_id_, user_gesture, &routing_id));
1292 if (routing_id == MSG_ROUTING_NONE)
[email protected]48c9cf2d2009-09-16 16:47:521293 return NULL;
[email protected]48c9cf2d2009-09-16 16:47:521294
[email protected]48c9cf2d2009-09-16 16:47:521295 RenderView* view = RenderView::Create(render_thread_,
[email protected]12636df2009-09-28 22:32:211296 NULL,
1297 routing_id_,
[email protected]48c9cf2d2009-09-16 16:47:521298 renderer_preferences_,
1299 webkit_preferences_,
[email protected]12636df2009-09-28 22:32:211300 shared_popup_counter_,
1301 routing_id);
[email protected]48c9cf2d2009-09-16 16:47:521302 view->opened_by_user_gesture_ = user_gesture;
1303
1304 // Record the security origin of the creator.
[email protected]91733b62009-09-18 06:21:091305 GURL creator_url(creator->securityOrigin().toString().utf8());
[email protected]48c9cf2d2009-09-16 16:47:521306 if (!creator_url.is_valid() || !creator_url.IsStandard())
1307 creator_url = GURL();
1308 view->creator_url_ = creator_url;
1309
1310 // Copy over the alternate error page URL so we can have alt error pages in
1311 // the new render view (we don't need the browser to send the URL back down).
1312 view->alternate_error_page_url_ = alternate_error_page_url_;
1313
1314 return view->webview();
1315}
1316
1317WebWidget* RenderView::createPopupMenu(bool activatable) {
1318 RenderWidget* widget = RenderWidget::Create(routing_id_,
1319 render_thread_,
1320 activatable);
1321 return widget->webwidget();
1322}
1323
1324WebWidget* RenderView::createPopupMenu(const WebPopupMenuInfo& info) {
1325 RenderWidget* widget = RenderWidget::Create(routing_id_,
1326 render_thread_,
1327 true);
1328 widget->ConfigureAsExternalPopupMenu(info);
1329 return widget->webwidget();
1330}
1331
1332void RenderView::didAddMessageToConsole(
1333 const WebConsoleMessage& message, const WebString& source_name,
1334 unsigned source_line) {
1335 Send(new ViewHostMsg_AddMessageToConsole(routing_id_,
1336 UTF16ToWideHack(message.text),
1337 static_cast<int32>(source_line),
1338 UTF16ToWideHack(source_name)));
1339}
1340
1341void RenderView::printPage(WebFrame* frame) {
[email protected]71a14262009-09-22 20:02:581342 DCHECK(frame);
1343 Print(frame, true);
[email protected]48c9cf2d2009-09-16 16:47:521344}
1345
1346void RenderView::didStartLoading() {
1347 if (is_loading_) {
1348 DLOG(WARNING) << "didStartLoading called while loading";
1349 return;
1350 }
1351
1352 is_loading_ = true;
1353 // Clear the pointer so that we can assign it only when there is an unknown
1354 // plugin on a page.
1355 first_default_plugin_.reset();
1356
1357 Send(new ViewHostMsg_DidStartLoading(routing_id_));
1358}
1359
1360void RenderView::didStopLoading() {
1361 if (!is_loading_) {
1362 DLOG(WARNING) << "DidStopLoading called while not loading";
1363 return;
1364 }
1365
1366 is_loading_ = false;
1367
1368 // NOTE: For now we're doing the safest thing, and sending out notification
1369 // when done loading. This currently isn't an issue as the favicon is only
1370 // displayed when done loading. Ideally we would send notification when
1371 // finished parsing the head, but webkit doesn't support that yet.
1372 // The feed discovery code would also benefit from access to the head.
[email protected]26aa0482009-09-30 16:55:271373 GURL favicon_url(webview()->mainFrame()->favIconURL());
[email protected]48c9cf2d2009-09-16 16:47:521374 if (!favicon_url.is_empty())
1375 Send(new ViewHostMsg_UpdateFavIconURL(routing_id_, page_id_, favicon_url));
1376
[email protected]26aa0482009-09-30 16:55:271377 AddGURLSearchProvider(webview()->mainFrame()->openSearchDescriptionURL(),
[email protected]48c9cf2d2009-09-16 16:47:521378 true); // autodetected
1379
1380 Send(new ViewHostMsg_DidStopLoading(routing_id_));
1381
1382 MessageLoop::current()->PostDelayedTask(FROM_HERE,
1383 method_factory_.NewRunnableMethod(&RenderView::CapturePageInfo, page_id_,
1384 false),
1385 kDelayForCaptureMs);
1386
1387 // The page is loaded. Try to process the file we need to upload if any.
1388 ProcessPendingUpload();
1389
1390 // Since the page is done loading, we are sure we don't need to try
1391 // again.
1392 ResetPendingUpload();
1393}
1394
[email protected]04fc9482009-09-18 22:13:031395bool RenderView::shouldBeginEditing(const WebRange& range) {
1396 return true;
1397}
1398
1399bool RenderView::shouldEndEditing(const WebRange& range) {
1400 return true;
1401}
1402
1403bool RenderView::shouldInsertNode(const WebNode& node, const WebRange& range,
1404 WebEditingAction action) {
1405 return true;
1406}
1407
1408bool RenderView::shouldInsertText(const WebString& text, const WebRange& range,
1409 WebEditingAction action) {
1410 return true;
1411}
1412
1413bool RenderView::shouldChangeSelectedRange(const WebRange& from_range,
1414 const WebRange& to_range,
1415 WebTextAffinity affinity,
1416 bool still_selecting) {
1417 return true;
1418}
1419
1420bool RenderView::shouldDeleteRange(const WebRange& range) {
1421 return true;
1422}
1423
1424bool RenderView::shouldApplyStyle(const WebString& style,
1425 const WebRange& range) {
1426 return true;
1427}
1428
1429bool RenderView::isSmartInsertDeleteEnabled() {
1430 return true;
1431}
1432
1433bool RenderView::isSelectTrailingWhitespaceEnabled() {
1434#if defined(OS_WIN)
1435 return true;
1436#else
1437 return false;
1438#endif
1439}
1440
1441void RenderView::setInputMethodEnabled(bool enabled) {
1442 // Save the updated IME status and mark the input focus has been updated.
1443 // The IME status is to be sent to a browser process next time when
1444 // the input caret is rendered.
1445 if (!ime_control_busy_) {
1446 ime_control_updated_ = true;
1447 ime_control_new_state_ = enabled;
1448 }
1449}
1450
1451void RenderView::didChangeSelection(bool is_empty_selection) {
1452#if defined(OS_LINUX)
1453 if (!handling_input_event_)
1454 return;
1455 // TODO(estade): investigate incremental updates to the selection so that we
1456 // don't send the entire selection over IPC every time.
1457 if (!is_empty_selection) {
1458 // Sometimes we get repeated didChangeSelection calls from webkit when
1459 // the selection hasn't actually changed. We don't want to report these
1460 // because it will cause us to continually claim the X clipboard.
1461 const std::string& this_selection =
[email protected]26aa0482009-09-30 16:55:271462 webview()->focusedFrame()->selectionAsText().utf8();
[email protected]04fc9482009-09-18 22:13:031463 if (this_selection == last_selection_)
1464 return;
1465
1466 Send(new ViewHostMsg_SelectionChanged(routing_id_,
1467 this_selection));
1468 last_selection_ = this_selection;
1469 } else {
1470 last_selection_.clear();
1471 }
1472#endif
1473}
1474
1475void RenderView::didExecuteCommand(const WebString& command_name) {
1476 const std::wstring& name = UTF16ToWideHack(command_name);
1477 if (StartsWith(name, L"Move", true) ||
1478 StartsWith(name, L"Insert", true) ||
1479 StartsWith(name, L"Delete", true))
1480 return;
1481 UserMetricsRecordAction(name);
1482}
1483
[email protected]b2528b72009-09-24 06:57:101484bool RenderView::handleCurrentKeyboardEvent() {
1485 if (edit_commands_.empty())
1486 return false;
1487
[email protected]26aa0482009-09-30 16:55:271488 WebFrame* frame = webview()->focusedFrame();
[email protected]b2528b72009-09-24 06:57:101489 if (!frame)
1490 return false;
1491
1492 EditCommands::iterator it = edit_commands_.begin();
1493 EditCommands::iterator end = edit_commands_.end();
1494
[email protected]507b33ea2009-09-29 03:56:511495 bool did_execute_command = false;
[email protected]b2528b72009-09-24 06:57:101496 for (; it != end; ++it) {
[email protected]e6e15012009-09-30 14:59:331497 // In gtk and cocoa, it's possible to bind multiple edit commands to one
1498 // key (but it's the exception). Once one edit command is not executed, it
1499 // seems safest to not execute the rest.
[email protected]b2528b72009-09-24 06:57:101500 if (!frame->executeCommand(WebString::fromUTF8(it->name),
1501 WebString::fromUTF8(it->value)))
1502 break;
[email protected]507b33ea2009-09-29 03:56:511503 did_execute_command = true;
[email protected]b2528b72009-09-24 06:57:101504 }
1505
[email protected]507b33ea2009-09-29 03:56:511506 return did_execute_command;
[email protected]b2528b72009-09-24 06:57:101507}
1508
[email protected]1dbafaf72009-09-23 19:43:561509void RenderView::spellCheck(
1510 const WebString& text, int& misspelled_offset, int& misspelled_length) {
1511 EnsureDocumentTag();
1512 Send(new ViewHostMsg_SpellCheck(
1513 routing_id_, UTF16ToWideHack(text), document_tag_,
1514 &misspelled_offset, &misspelled_length));
1515}
1516
1517WebString RenderView::autoCorrectWord(const WebKit::WebString& word) {
1518 std::wstring autocorrect_word;
1519 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
[email protected]b86c8c12009-10-05 22:01:261520 if (command_line.HasSwitch(switches::kExperimentalSpellcheckerFeatures)) {
[email protected]1dbafaf72009-09-23 19:43:561521 EnsureDocumentTag();
1522 Send(new ViewHostMsg_GetAutoCorrectWord(
1523 routing_id_, UTF16ToWideHack(word), document_tag_, &autocorrect_word));
1524 }
1525 return WideToUTF16Hack(autocorrect_word);
1526}
1527
[email protected]c49085c72009-10-02 16:28:561528void RenderView::showSpellingUI(bool show) {
1529 Send(new ViewHostMsg_ShowSpellingPanel(routing_id_, show));
1530}
1531
[email protected]8922e1f2009-10-03 05:01:261532bool RenderView::isShowingSpellingUI() {
1533 return spelling_panel_visible_;
1534}
1535
[email protected]1dbafaf72009-09-23 19:43:561536void RenderView::updateSpellingUIWithMisspelledWord(const WebString& word) {
1537 Send(new ViewHostMsg_UpdateSpellingPanelWithMisspelledWord(
1538 routing_id_, UTF16ToWideHack(word)));
1539}
1540
[email protected]a1128322009-10-06 18:38:461541bool RenderView::runFileChooser(
1542 bool multi_select,
1543 const WebKit::WebString& title,
1544 const WebKit::WebString& initial_value,
1545 WebKit::WebFileChooserCompletion* chooser_completion) {
1546 if (file_chooser_completion_) {
1547 // TODO(brettw): bug 1235154: This should be a synchronous message to deal
1548 // with the fact that web pages can programatically trigger this. With the
1549 // asnychronous messages, we can get an additional call when one is pending,
1550 // which this test is for. For now, we just ignore the additional file
1551 // chooser request. WebKit doesn't do anything to expect the callback, so
1552 // we can just ignore calling it.
1553 return false;
1554 }
1555 file_chooser_completion_ = chooser_completion;
1556 Send(new ViewHostMsg_RunFileChooser(
1557 routing_id_, multi_select, title,
1558 webkit_glue::WebStringToFilePath(initial_value)));
1559 return true;
1560}
1561
[email protected]48c9cf2d2009-09-16 16:47:521562void RenderView::runModalAlertDialog(
1563 WebFrame* frame, const WebString& message) {
1564 RunJavaScriptMessage(MessageBoxFlags::kIsJavascriptAlert,
1565 UTF16ToWideHack(message),
1566 std::wstring(),
1567 frame->url(),
1568 NULL);
1569}
1570
1571bool RenderView::runModalConfirmDialog(
1572 WebFrame* frame, const WebString& message) {
1573 return RunJavaScriptMessage(MessageBoxFlags::kIsJavascriptConfirm,
1574 UTF16ToWideHack(message),
1575 std::wstring(),
1576 frame->url(),
1577 NULL);
1578}
1579
1580bool RenderView::runModalPromptDialog(
1581 WebFrame* frame, const WebString& message, const WebString& default_value,
1582 WebString* actual_value) {
1583 std::wstring result;
1584 bool ok = RunJavaScriptMessage(MessageBoxFlags::kIsJavascriptPrompt,
1585 UTF16ToWideHack(message),
1586 UTF16ToWideHack(default_value),
1587 frame->url(),
1588 &result);
1589 if (ok)
1590 actual_value->assign(WideToUTF16Hack(result));
1591 return ok;
1592}
1593
1594bool RenderView::runModalBeforeUnloadDialog(
1595 WebFrame* frame, const WebString& message) {
1596 bool success = false;
1597 // This is an ignored return value, but is included so we can accept the same
1598 // response as RunJavaScriptMessage.
1599 std::wstring ignored_result;
[email protected]12636df2009-09-28 22:32:211600 SendAndRunNestedMessageLoop(new ViewHostMsg_RunBeforeUnloadConfirm(
[email protected]48c9cf2d2009-09-16 16:47:521601 routing_id_, frame->url(), UTF16ToWideHack(message), &success,
[email protected]12636df2009-09-28 22:32:211602 &ignored_result));
[email protected]48c9cf2d2009-09-16 16:47:521603 return success;
1604}
1605
1606void RenderView::setStatusText(const WebString& text) {
1607}
1608
1609void RenderView::setMouseOverURL(const WebURL& url) {
[email protected]8d32b9832009-09-17 06:21:011610 GURL latest_url(url);
[email protected]48c9cf2d2009-09-16 16:47:521611 if (latest_url == target_url_)
1612 return;
1613 // Tell the browser to display a destination link.
1614 if (target_url_status_ == TARGET_INFLIGHT ||
1615 target_url_status_ == TARGET_PENDING) {
1616 // If we have a request in-flight, save the URL to be sent when we
1617 // receive an ACK to the in-flight request. We can happily overwrite
1618 // any existing pending sends.
1619 pending_target_url_ = latest_url;
1620 target_url_status_ = TARGET_PENDING;
1621 } else {
1622 Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_, latest_url));
1623 target_url_ = latest_url;
1624 target_url_status_ = TARGET_INFLIGHT;
1625 }
1626}
1627
1628void RenderView::setToolTipText(const WebString& text, WebTextDirection hint) {
1629 Send(new ViewHostMsg_SetTooltipText(routing_id_, UTF16ToWideHack(text),
1630 hint));
1631}
1632
1633void RenderView::startDragging(const WebPoint& from, const WebDragData& data,
1634 WebDragOperationsMask allowed_ops) {
1635 Send(new ViewHostMsg_StartDragging(routing_id_,
1636 WebDropData(data),
1637 allowed_ops));
1638}
1639
[email protected]28b92df2009-09-25 17:35:451640bool RenderView::acceptsLoadDrops() {
1641 return renderer_preferences_.can_accept_load_drops;
1642}
1643
[email protected]48c9cf2d2009-09-16 16:47:521644void RenderView::focusNext() {
1645 Send(new ViewHostMsg_TakeFocus(routing_id_, false));
1646}
1647
1648void RenderView::focusPrevious() {
1649 Send(new ViewHostMsg_TakeFocus(routing_id_, true));
1650}
1651
1652void RenderView::navigateBackForwardSoon(int offset) {
1653 history_back_list_count_ += offset;
1654 history_forward_list_count_ -= offset;
1655
1656 Send(new ViewHostMsg_GoToEntryAtOffset(routing_id_, offset));
1657}
1658
1659int RenderView::historyBackListCount() {
1660 return history_back_list_count_;
1661}
1662
1663int RenderView::historyForwardListCount() {
1664 return history_forward_list_count_;
1665}
1666
1667void RenderView::didAddHistoryItem() {
1668 // We don't want to update the history length for the start page
1669 // navigation.
[email protected]26aa0482009-09-30 16:55:271670 WebFrame* main_frame = webview()->mainFrame();
[email protected]48c9cf2d2009-09-16 16:47:521671 DCHECK(main_frame != NULL);
1672
1673 WebDataSource* ds = main_frame->dataSource();
1674 DCHECK(ds != NULL);
1675
1676 NavigationState* navigation_state = NavigationState::FromDataSource(ds);
1677 DCHECK(navigation_state);
1678 if (navigation_state->transition_type() == PageTransition::START_PAGE)
1679 return;
1680
1681 history_back_list_count_++;
1682 history_forward_list_count_ = 0;
1683}
1684
[email protected]8922e1f2009-10-03 05:01:261685void RenderView::didUpdateInspectorSettings() {
1686 Send(new ViewHostMsg_UpdateInspectorSettings(
1687 routing_id_, webview()->inspectorSettings().utf8()));
1688}
1689
[email protected]79dbc662009-09-04 05:42:511690// WebKit::WebWidgetClient ----------------------------------------------------
1691
initial.commit09911bf2008-07-26 23:55:291692// We are supposed to get a single call to Show for a newly created RenderView
1693// that was created via RenderView::CreateWebView. So, we wait until this
1694// point to dispatch the ShowView message.
1695//
1696// This method provides us with the information about how to display the newly
1697// created RenderView (i.e., as a constrained popup or as a new tab).
1698//
[email protected]4873c7d2009-07-16 06:36:281699void RenderView::show(WebNavigationPolicy policy) {
initial.commit09911bf2008-07-26 23:55:291700 DCHECK(!did_show_) << "received extraneous Show call";
1701 DCHECK(opener_id_ != MSG_ROUTING_NONE);
1702
1703 if (did_show_)
1704 return;
1705 did_show_ = true;
1706
1707 // NOTE: initial_pos_ may still have its default values at this point, but
1708 // that's okay. It'll be ignored if disposition is not NEW_POPUP, or the
1709 // browser process will impose a default position otherwise.
[email protected]4873c7d2009-07-16 06:36:281710 Send(new ViewHostMsg_ShowView(opener_id_, routing_id_,
1711 NavigationPolicyToDisposition(policy), initial_pos_,
1712 opened_by_user_gesture_, creator_url_));
[email protected]2533ce12009-05-09 00:02:241713 SetPendingWindowRect(initial_pos_);
initial.commit09911bf2008-07-26 23:55:291714}
1715
[email protected]4873c7d2009-07-16 06:36:281716void RenderView::closeWidgetSoon() {
[email protected]2c4410d2009-05-06 23:46:221717 if (!popup_notification_visible_)
[email protected]4873c7d2009-07-16 06:36:281718 RenderWidget::closeWidgetSoon();
[email protected]634a6f92008-12-01 21:39:311719}
1720
[email protected]4873c7d2009-07-16 06:36:281721void RenderView::runModal() {
initial.commit09911bf2008-07-26 23:55:291722 DCHECK(did_show_) << "should already have shown the view";
1723
[email protected]12636df2009-09-28 22:32:211724 SendAndRunNestedMessageLoop(new ViewHostMsg_RunModal(routing_id_));
initial.commit09911bf2008-07-26 23:55:291725}
1726
[email protected]3d9689372009-09-10 04:29:171727// WebKit::WebFrameClient -----------------------------------------------------
1728
1729WebPlugin* RenderView::createPlugin(
1730 WebFrame* frame, const WebPluginParams& params) {
1731 return new webkit_glue::WebPluginImpl(frame, params, AsWeakPtr());
1732}
1733
1734WebWorker* RenderView::createWorker(WebFrame* frame, WebWorkerClient* client) {
1735 return new WebWorkerProxy(client, RenderThread::current(), routing_id_);
1736}
1737
1738WebMediaPlayer* RenderView::createMediaPlayer(
1739 WebFrame* frame, WebMediaPlayerClient* client) {
1740 scoped_refptr<media::FilterFactoryCollection> factory =
1741 new media::FilterFactoryCollection();
1742 // Add in any custom filter factories first.
1743 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
1744 if (!cmd_line->HasSwitch(switches::kDisableAudio)) {
1745 // Add the chrome specific audio renderer.
1746 factory->AddFactory(
1747 AudioRendererImpl::CreateFactory(audio_message_filter()));
1748 }
1749
1750 // TODO(hclam): obtain the following parameters from |client|.
1751 webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory =
1752 new webkit_glue::MediaResourceLoaderBridgeFactory(
1753 GURL::EmptyGURL(), // referrer
1754 "null", // frame origin
1755 "null", // main_frame_origin
1756 base::GetCurrentProcId(),
1757 appcache::kNoHostId,
1758 routing_id());
1759
1760 if (!cmd_line->HasSwitch(switches::kSimpleDataSource)) {
1761 // Add the chrome specific media data source.
1762 factory->AddFactory(
1763 webkit_glue::BufferedDataSource::CreateFactory(MessageLoop::current(),
1764 bridge_factory));
1765 } else {
1766 factory->AddFactory(
1767 webkit_glue::SimpleDataSource::CreateFactory(MessageLoop::current(),
1768 bridge_factory));
1769 }
1770 return new webkit_glue::WebMediaPlayerImpl(client, factory);
1771}
1772
1773void RenderView::willClose(WebFrame* frame) {
1774 if (!frame->parent()) {
1775 const GURL& url = frame->url();
1776 if (url.SchemeIs("http") || url.SchemeIs("https"))
1777 DumpLoadHistograms();
1778 }
1779}
1780
1781void RenderView::loadURLExternally(
1782 WebFrame* frame, const WebURLRequest& request,
1783 WebNavigationPolicy policy) {
[email protected]efce17b2009-09-11 18:04:591784 GURL referrer(request.httpHeaderField(WebString::fromUTF8("Referer")));
1785 if (policy == WebKit::WebNavigationPolicyDownload) {
1786 Send(new ViewHostMsg_DownloadUrl(routing_id_, request.url(), referrer));
1787 } else {
1788 OpenURL(request.url(), referrer, policy);
1789 }
[email protected]3d9689372009-09-10 04:29:171790}
1791
1792WebNavigationPolicy RenderView::decidePolicyForNavigation(
1793 WebFrame* frame, const WebURLRequest& request, WebNavigationType type,
1794 WebNavigationPolicy default_policy, bool is_redirect) {
1795 // Webkit is asking whether to navigate to a new URL.
1796 // This is fine normally, except if we're showing UI from one security
1797 // context and they're trying to navigate to a different context.
1798 const GURL& url = request.url();
1799
1800 // If the browser is interested, then give it a chance to look at top level
1801 // navigations
1802 if (renderer_preferences_.browser_handles_top_level_requests &&
1803 // Only send once.
1804 last_top_level_navigation_page_id_ != page_id_ &&
1805 // Not interested in reloads.
1806 type != WebKit::WebNavigationTypeReload &&
1807 type != WebKit::WebNavigationTypeFormSubmitted &&
1808 // Must be a top level frame.
1809 frame->parent() == NULL) {
1810 // Skip if navigation is on the same page (using '#').
1811 GURL frame_origin = GURL(frame->url()).GetOrigin();
1812 if (url.GetOrigin() != frame_origin || url.ref().empty()) {
1813 last_top_level_navigation_page_id_ = page_id_;
1814 OpenURL(url, GURL(), default_policy);
1815 return WebKit::WebNavigationPolicyIgnore; // Suppress the load here.
1816 }
1817 }
1818
1819 // A content initiated navigation may have originated from a link-click,
1820 // script, drag-n-drop operation, etc.
1821 bool is_content_initiated =
1822 NavigationState::FromDataSource(frame->provisionalDataSource())->
1823 is_content_initiated();
1824
1825 // We only care about navigations that are within the current tab (as opposed
1826 // to, for example, opening a new window).
1827 // But we sometimes navigate to about:blank to clear a tab, and we want to
1828 // still allow that.
1829 if (default_policy == WebKit::WebNavigationPolicyCurrentTab &&
1830 is_content_initiated && frame->parent() == NULL &&
1831 !url.SchemeIs(chrome::kAboutScheme)) {
1832 // When we received such unsolicited navigations, we sometimes want to
1833 // punt them up to the browser to handle.
1834 if (BindingsPolicy::is_dom_ui_enabled(enabled_bindings_) ||
1835 BindingsPolicy::is_extension_enabled(enabled_bindings_) ||
1836 frame->isViewSourceModeEnabled() ||
1837 url.SchemeIs(chrome::kViewSourceScheme) ||
1838 url.SchemeIs(chrome::kPrintScheme)) {
1839 OpenURL(url, GURL(), default_policy);
1840 return WebKit::WebNavigationPolicyIgnore; // Suppress the load here.
1841 }
1842 }
1843
1844 // Detect when a page is "forking" a new tab that can be safely rendered in
1845 // its own process. This is done by sites like Gmail that try to open links
1846 // in new windows without script connections back to the original page. We
1847 // treat such cases as browser navigations (in which we will create a new
1848 // renderer for a cross-site navigation), rather than WebKit navigations.
1849 //
1850 // We use the following heuristic to decide whether to fork a new page in its
1851 // own process:
1852 // The parent page must open a new tab to about:blank, set the new tab's
1853 // window.opener to null, and then redirect the tab to a cross-site URL using
1854 // JavaScript.
1855 bool is_fork =
1856 // Must start from a tab showing about:blank, which is later redirected.
[email protected]e0d481582009-09-15 21:06:251857 GURL(frame->url()) == GURL(chrome::kAboutBlankURL) &&
[email protected]3d9689372009-09-10 04:29:171858 // Must be the first real navigation of the tab.
[email protected]48c9cf2d2009-09-16 16:47:521859 historyBackListCount() < 1 &&
1860 historyForwardListCount() < 1 &&
[email protected]3d9689372009-09-10 04:29:171861 // The parent page must have set the child's window.opener to null before
1862 // redirecting to the desired URL.
1863 frame->opener() == NULL &&
1864 // Must be a top-level frame.
1865 frame->parent() == NULL &&
1866 // Must not have issued the request from this page.
1867 is_content_initiated &&
1868 // Must be targeted at the current tab.
1869 default_policy == WebKit::WebNavigationPolicyCurrentTab &&
1870 // Must be a JavaScript navigation, which appears as "other".
1871 type == WebKit::WebNavigationTypeOther;
1872 if (is_fork) {
1873 // Open the URL via the browser, not via WebKit.
1874 OpenURL(url, GURL(), default_policy);
1875 return WebKit::WebNavigationPolicyIgnore;
1876 }
1877
1878 return default_policy;
1879}
1880
1881void RenderView::willSubmitForm(WebFrame* frame, const WebForm& form) {
1882 NavigationState* navigation_state =
1883 NavigationState::FromDataSource(frame->provisionalDataSource());
1884
1885 if (navigation_state->transition_type() == PageTransition::LINK)
1886 navigation_state->set_transition_type(PageTransition::FORM_SUBMIT);
1887
1888 // Save these to be processed when the ensuing navigation is committed.
1889 navigation_state->set_searchable_form_data(
1890 SearchableFormData::Create(form));
1891 navigation_state->set_password_form_data(
1892 PasswordFormDomManager::CreatePasswordForm(form));
1893
1894 if (form.isAutoCompleteEnabled()) {
1895 scoped_ptr<AutofillForm> autofill_form(AutofillForm::Create(form));
1896 if (autofill_form.get())
1897 Send(new ViewHostMsg_AutofillFormSubmitted(routing_id_, *autofill_form));
1898 }
1899}
1900
1901void RenderView::willPerformClientRedirect(
1902 WebFrame* frame, const WebURL& from, const WebURL& to, double interval,
1903 double fire_time) {
1904 // Ignore
1905}
1906
1907void RenderView::didCancelClientRedirect(WebFrame* frame) {
1908 // Ignore
1909}
1910
1911void RenderView::didCompleteClientRedirect(
1912 WebFrame* frame, const WebURL& from) {
1913 if (!frame->parent())
1914 completed_client_redirect_src_ = from;
1915}
1916
1917void RenderView::didCreateDataSource(WebFrame* frame, WebDataSource* ds) {
1918 // The rest of RenderView assumes that a WebDataSource will always have a
1919 // non-null NavigationState.
1920 if (pending_navigation_state_.get()) {
1921 ds->setExtraData(pending_navigation_state_.release());
1922 } else {
1923 ds->setExtraData(NavigationState::CreateContentInitiated());
1924 }
1925}
1926
1927void RenderView::didStartProvisionalLoad(WebFrame* frame) {
1928 WebDataSource* ds = frame->provisionalDataSource();
1929 NavigationState* navigation_state = NavigationState::FromDataSource(ds);
1930
1931 navigation_state->set_start_load_time(Time::Now());
1932
1933 // Update the request time if WebKit has better knowledge of it.
1934 if (navigation_state->request_time().is_null()) {
1935 double event_time = ds->triggeringEventTime();
1936 if (event_time != 0.0)
1937 navigation_state->set_request_time(Time::FromDoubleT(event_time));
1938 }
1939
1940 bool is_top_most = !frame->parent();
1941 if (is_top_most) {
1942 navigation_gesture_ = frame->isProcessingUserGesture() ?
1943 NavigationGestureUnknown : NavigationGestureAuto;
1944
1945 // Make sure redirect tracking state is clear for the new load.
1946 completed_client_redirect_src_ = GURL();
1947 } else if (frame->parent()->isLoading()) {
1948 // Take note of AUTO_SUBFRAME loads here, so that we can know how to
1949 // load an error page. See DidFailProvisionalLoadWithError.
1950 navigation_state->set_transition_type(PageTransition::AUTO_SUBFRAME);
1951 }
1952
1953 Send(new ViewHostMsg_DidStartProvisionalLoadForFrame(
1954 routing_id_, is_top_most, ds->request().url()));
1955}
1956
1957void RenderView::didReceiveServerRedirectForProvisionalLoad(WebFrame* frame) {
1958 if (frame->parent())
1959 return;
1960 // Received a redirect on the main frame.
1961 WebDataSource* data_source = frame->provisionalDataSource();
1962 if (!data_source) {
1963 // Should only be invoked when we have a data source.
1964 NOTREACHED();
1965 return;
1966 }
1967 std::vector<GURL> redirects;
1968 GetRedirectChain(data_source, &redirects);
1969 if (redirects.size() >= 2) {
1970 Send(new ViewHostMsg_DidRedirectProvisionalLoad(
1971 routing_id_, page_id_, redirects[redirects.size() - 2],
1972 redirects[redirects.size() - 1]));
1973 }
1974}
1975
1976void RenderView::didFailProvisionalLoad(
1977 WebFrame* frame, const WebURLError& error) {
1978 // Notify the browser that we failed a provisional load with an error.
1979 //
1980 // Note: It is important this notification occur before DidStopLoading so the
1981 // SSL manager can react to the provisional load failure before being
1982 // notified the load stopped.
1983 //
1984 WebDataSource* ds = frame->provisionalDataSource();
1985 DCHECK(ds);
1986
1987 const WebURLRequest& failed_request = ds->request();
1988
1989 bool show_repost_interstitial =
1990 (error.reason == net::ERR_CACHE_MISS &&
1991 EqualsASCII(failed_request.httpMethod(), "POST"));
1992 Send(new ViewHostMsg_DidFailProvisionalLoadWithError(
1993 routing_id_, !frame->parent(), error.reason, error.unreachableURL,
1994 show_repost_interstitial));
1995
1996 // Don't display an error page if this is simply a cancelled load. Aside
1997 // from being dumb, WebCore doesn't expect it and it will cause a crash.
1998 if (error.reason == net::ERR_ABORTED)
1999 return;
2000
2001 // Make sure we never show errors in view source mode.
2002 frame->enableViewSourceMode(false);
2003
2004 NavigationState* navigation_state = NavigationState::FromDataSource(ds);
2005
2006 // If this is a failed back/forward/reload navigation, then we need to do a
2007 // 'replace' load. This is necessary to avoid messing up session history.
2008 // Otherwise, we do a normal load, which simulates a 'go' navigation as far
2009 // as session history is concerned.
2010 //
2011 // AUTO_SUBFRAME loads should always be treated as loads that do not advance
2012 // the page id.
2013 //
2014 bool replace =
2015 navigation_state->pending_page_id() != -1 ||
2016 navigation_state->transition_type() == PageTransition::AUTO_SUBFRAME;
2017
2018 // If we failed on a browser initiated request, then make sure that our error
2019 // page load is regarded as the same browser initiated request.
2020 if (!navigation_state->is_content_initiated()) {
2021 pending_navigation_state_.reset(NavigationState::CreateBrowserInitiated(
2022 navigation_state->pending_page_id(),
2023 navigation_state->transition_type(),
2024 navigation_state->request_time()));
2025 }
2026
2027 // Provide the user with a more helpful error page?
2028 if (MaybeLoadAlternateErrorPage(frame, error, replace))
2029 return;
2030
2031 // Fallback to a local error page.
2032 LoadNavigationErrorPage(frame, failed_request, error, std::string(),
2033 replace);
2034}
2035
2036void RenderView::didReceiveDocumentData(
2037 WebFrame* frame, const char* data, size_t data_len,
2038 bool& prevent_default) {
2039 NavigationState* navigation_state =
2040 NavigationState::FromDataSource(frame->dataSource());
2041 if (!navigation_state->postpone_loading_data())
2042 return;
2043
2044 // We're going to call commitDocumentData ourselves...
2045 prevent_default = true;
2046
2047 // Continue buffering the response data for the original 404 page. If it
2048 // grows too large, then we'll just let it through.
2049 navigation_state->append_postponed_data(data, data_len);
2050 if (navigation_state->postponed_data().size() >= 512) {
2051 navigation_state->set_postpone_loading_data(false);
2052 frame->commitDocumentData(navigation_state->postponed_data().data(),
2053 navigation_state->postponed_data().size());
2054 navigation_state->clear_postponed_data();
2055 }
2056}
2057
2058void RenderView::didCommitProvisionalLoad(
2059 WebFrame* frame, bool is_new_navigation) {
2060 NavigationState* navigation_state =
2061 NavigationState::FromDataSource(frame->dataSource());
2062
2063 navigation_state->set_commit_load_time(Time::Now());
2064 if (is_new_navigation) {
2065 // When we perform a new navigation, we need to update the previous session
2066 // history entry with state for the page we are leaving.
2067 UpdateSessionHistory(frame);
2068
2069 // We bump our Page ID to correspond with the new session history entry.
2070 page_id_ = next_page_id_++;
2071
2072 MessageLoop::current()->PostDelayedTask(FROM_HERE,
2073 method_factory_.NewRunnableMethod(&RenderView::CapturePageInfo,
2074 page_id_, true),
2075 kDelayForForcedCaptureMs);
2076 } else {
2077 // Inspect the navigation_state on this frame to see if the navigation
2078 // corresponds to a session history navigation... Note: |frame| may or
2079 // may not be the toplevel frame, but for the case of capturing session
2080 // history, the first committed frame suffices. We keep track of whether
2081 // we've seen this commit before so that only capture session history once
2082 // per navigation.
2083 //
2084 // Note that we need to check if the page ID changed. In the case of a
2085 // reload, the page ID doesn't change, and UpdateSessionHistory gets the
2086 // previous URL and the current page ID, which would be wrong.
2087 if (navigation_state->pending_page_id() != -1 &&
2088 navigation_state->pending_page_id() != page_id_ &&
2089 !navigation_state->request_committed()) {
2090 // This is a successful session history navigation!
2091 UpdateSessionHistory(frame);
2092 page_id_ = navigation_state->pending_page_id();
2093 }
2094 }
2095
2096 // Remember that we've already processed this request, so we don't update
2097 // the session history again. We do this regardless of whether this is
2098 // a session history navigation, because if we attempted a session history
2099 // navigation without valid HistoryItem state, WebCore will think it is a
2100 // new navigation.
2101 navigation_state->set_request_committed(true);
2102
2103 UpdateURL(frame);
2104
2105 // If this committed load was initiated by a client redirect, we're
2106 // at the last stop now, so clear it.
2107 completed_client_redirect_src_ = GURL();
2108
2109 // Check whether we have new encoding name.
[email protected]26aa0482009-09-30 16:55:272110 UpdateEncoding(frame, frame->view()->pageEncoding().utf8());
[email protected]3d9689372009-09-10 04:29:172111}
2112
2113void RenderView::didClearWindowObject(WebFrame* frame) {
2114 if (BindingsPolicy::is_dom_automation_enabled(enabled_bindings_))
2115 BindDOMAutomationController(frame);
2116 if (BindingsPolicy::is_dom_ui_enabled(enabled_bindings_)) {
2117 dom_ui_bindings_.set_message_sender(this);
2118 dom_ui_bindings_.set_routing_id(routing_id_);
2119 dom_ui_bindings_.BindToJavascript(frame, L"chrome");
2120 }
2121 if (BindingsPolicy::is_external_host_enabled(enabled_bindings_)) {
2122 external_host_bindings_.set_message_sender(this);
2123 external_host_bindings_.set_routing_id(routing_id_);
2124 external_host_bindings_.BindToJavascript(frame, L"externalHost");
2125 }
2126}
2127
2128void RenderView::didCreateDocumentElement(WebFrame* frame) {
2129 if (RenderThread::current()) { // Will be NULL during unit tests.
2130 RenderThread::current()->user_script_slave()->InjectScripts(
2131 frame, UserScript::DOCUMENT_START);
2132 }
[email protected]078b34612009-09-19 19:31:512133 if (view_type_ == ViewType::EXTENSION_TOOLSTRIP ||
2134 view_type_ == ViewType::EXTENSION_MOLE) {
2135 InjectToolstripCSS();
2136 ExtensionProcessBindings::SetViewType(webview(), view_type_);
2137 }
[email protected]3d9689372009-09-10 04:29:172138
[email protected]912256b32009-09-18 09:47:352139 while (!pending_code_execution_queue_.empty()) {
2140 scoped_refptr<CodeExecutionInfo> info =
2141 pending_code_execution_queue_.front();
2142 OnExecuteCode(info->request_id, info->extension_id, info->is_js_code,
2143 info->code_string);
2144 pending_code_execution_queue_.pop();
2145 }
2146
[email protected]3d9689372009-09-10 04:29:172147 // Notify the browser about non-blank documents loading in the top frame.
2148 GURL url = frame->url();
[email protected]e0d481582009-09-15 21:06:252149 if (url.is_valid() && url.spec() != chrome::kAboutBlankURL) {
[email protected]26aa0482009-09-30 16:55:272150 if (frame == webview()->mainFrame())
[email protected]3d9689372009-09-10 04:29:172151 Send(new ViewHostMsg_DocumentAvailableInMainFrame(routing_id_));
2152 }
2153}
2154
2155void RenderView::didReceiveTitle(WebFrame* frame, const WebString& title) {
2156 UpdateTitle(frame, title);
2157
2158 // Also check whether we have new encoding name.
[email protected]26aa0482009-09-30 16:55:272159 UpdateEncoding(frame, frame->view()->pageEncoding().utf8());
[email protected]3d9689372009-09-10 04:29:172160}
2161
2162void RenderView::didFinishDocumentLoad(WebFrame* frame) {
2163 WebDataSource* ds = frame->dataSource();
2164 NavigationState* navigation_state = NavigationState::FromDataSource(ds);
2165 DCHECK(navigation_state);
2166 navigation_state->set_finish_document_load_time(Time::Now());
2167
2168 Send(new ViewHostMsg_DocumentLoadedInFrame(routing_id_));
2169
2170 // The document has now been fully loaded. Scan for password forms to be
2171 // sent up to the browser.
2172 SendPasswordForms(frame);
2173
2174 // Check whether we have new encoding name.
[email protected]26aa0482009-09-30 16:55:272175 UpdateEncoding(frame, frame->view()->pageEncoding().utf8());
[email protected]3d9689372009-09-10 04:29:172176
2177 if (RenderThread::current()) { // Will be NULL during unit tests.
2178 RenderThread::current()->user_script_slave()->InjectScripts(
2179 frame, UserScript::DOCUMENT_END);
2180 }
2181}
2182
2183void RenderView::didHandleOnloadEvents(WebFrame* frame) {
2184 // Ignore
2185}
2186
2187void RenderView::didFailLoad(WebFrame* frame, const WebURLError& error) {
2188 // Ignore
2189}
2190
2191void RenderView::didFinishLoad(WebFrame* frame) {
2192 WebDataSource* ds = frame->dataSource();
2193 NavigationState* navigation_state = NavigationState::FromDataSource(ds);
2194 DCHECK(navigation_state);
2195 navigation_state->set_finish_load_time(Time::Now());
2196}
2197
2198void RenderView::didChangeLocationWithinPage(
2199 WebFrame* frame, bool is_new_navigation) {
2200 // If this was a reference fragment navigation that we initiated, then we
2201 // could end up having a non-null pending navigation state. We just need to
2202 // update the ExtraData on the datasource so that others who read the
2203 // ExtraData will get the new NavigationState. Similarly, if we did not
2204 // initiate this navigation, then we need to take care to reset any pre-
2205 // existing navigation state to a content-initiated navigation state.
2206 // DidCreateDataSource conveniently takes care of this for us.
2207 didCreateDataSource(frame, frame->dataSource());
2208
2209 didCommitProvisionalLoad(frame, is_new_navigation);
2210
[email protected]26aa0482009-09-30 16:55:272211 UpdateTitle(frame, frame->view()->mainFrame()->dataSource()->pageTitle());
[email protected]3d9689372009-09-10 04:29:172212}
2213
[email protected]476b6f82009-09-10 21:00:592214void RenderView::didUpdateCurrentHistoryItem(WebFrame* frame) {
2215 if (!nav_state_sync_timer_.IsRunning()) {
2216 nav_state_sync_timer_.Start(
2217 TimeDelta::FromSeconds(delay_seconds_for_form_state_sync_), this,
2218 &RenderView::SyncNavigationState);
2219 }
2220}
2221
[email protected]3d9689372009-09-10 04:29:172222void RenderView::assignIdentifierToRequest(
2223 WebFrame* frame, unsigned identifier, const WebURLRequest& request) {
2224 // Ignore
2225}
2226
2227void RenderView::willSendRequest(
2228 WebFrame* frame, unsigned identifier, WebURLRequest& request,
2229 const WebURLResponse& redirect_response) {
2230 request.setRequestorID(routing_id_);
2231}
2232
2233void RenderView::didReceiveResponse(
2234 WebFrame* frame, unsigned identifier, const WebURLResponse& response) {
2235 // Consider loading an alternate error page for 404 responses.
2236 if (response.httpStatusCode() != 404)
2237 return;
2238
2239 // Only do this for responses that correspond to a provisional data source
2240 // of the top-most frame. If we have a provisional data source, then we
2241 // can't have any sub-resources yet, so we know that this response must
2242 // correspond to a frame load.
2243 if (!frame->provisionalDataSource() || frame->parent())
2244 return;
2245
2246 // If we are in view source mode, then just let the user see the source of
2247 // the server's 404 error page.
2248 if (frame->isViewSourceModeEnabled())
2249 return;
2250
2251 // Can we even load an alternate error page for this URL?
2252 if (!GetAlternateErrorPageURL(response.url(), HTTP_404).is_valid())
2253 return;
2254
2255 NavigationState* navigation_state =
2256 NavigationState::FromDataSource(frame->provisionalDataSource());
2257 navigation_state->set_postpone_loading_data(true);
2258 navigation_state->clear_postponed_data();
2259}
2260
2261void RenderView::didFinishResourceLoad(
2262 WebFrame* frame, unsigned identifier) {
2263 NavigationState* navigation_state =
2264 NavigationState::FromDataSource(frame->dataSource());
2265 if (!navigation_state->postpone_loading_data())
2266 return;
2267
2268 // The server returned a 404 and the content was < 512 bytes (which we
2269 // suppressed). Go ahead and fetch the alternate page content.
2270
2271 const GURL& frame_url = frame->url();
2272
2273 const GURL& error_page_url = GetAlternateErrorPageURL(frame_url, HTTP_404);
2274 DCHECK(error_page_url.is_valid());
2275
2276 WebURLError original_error;
2277 original_error.unreachableURL = frame_url;
2278
2279 navigation_state->set_alt_error_page_fetcher(
2280 new AltErrorPageResourceFetcher(
2281 error_page_url, frame, original_error,
2282 NewCallback(this, &RenderView::AltErrorPageFinished)));
2283}
2284
2285void RenderView::didFailResourceLoad(
2286 WebFrame* frame, unsigned identifier, const WebURLError& error) {
2287 // Ignore
2288}
2289
2290void RenderView::didLoadResourceFromMemoryCache(
2291 WebFrame* frame, const WebURLRequest& request,
2292 const WebURLResponse& response) {
2293 // Let the browser know we loaded a resource from the memory cache. This
2294 // message is needed to display the correct SSL indicators.
2295 Send(new ViewHostMsg_DidLoadResourceFromMemoryCache(
2296 routing_id_,
2297 request.url(),
[email protected]91733b62009-09-18 06:21:092298 frame->securityOrigin().toString().utf8(),
2299 frame->top()->securityOrigin().toString().utf8(),
[email protected]3d9689372009-09-10 04:29:172300 response.securityInfo()));
2301}
2302
[email protected]e3d60e5d2009-09-25 21:08:292303void RenderView::didDisplayInsecureContent(WebKit::WebFrame* frame) {
2304 Send(new ViewHostMsg_DidDisplayInsecureContent(routing_id_));
2305}
2306
2307void RenderView::didRunInsecureContent(
2308 WebFrame* frame, const WebSecurityOrigin& origin) {
2309 Send(new ViewHostMsg_DidRunInsecureContent(
2310 routing_id_,
2311 origin.toString().utf8()));
2312}
2313
[email protected]3d9689372009-09-10 04:29:172314void RenderView::didExhaustMemoryAvailableForScript(WebFrame* frame) {
2315 Send(new ViewHostMsg_JSOutOfMemory(routing_id_));
2316}
2317
[email protected]0c882b282009-10-07 17:01:282318void RenderView::didCreateScriptContext(WebFrame* frame) {
2319 EventBindings::HandleContextCreated(frame, false);
2320}
2321
2322void RenderView::didDestroyScriptContext(WebFrame* frame) {
2323 EventBindings::HandleContextDestroyed(frame);
2324}
2325
2326void RenderView::didCreateIsolatedScriptContext(WebFrame* frame) {
2327 EventBindings::HandleContextCreated(frame, true);
2328}
2329
[email protected]3d9689372009-09-10 04:29:172330void RenderView::didChangeContentsSize(WebFrame* frame, const WebSize& size) {
2331 // We don't always want to send the change messages over IPC, only if we've
2332 // be put in that mode by getting a |ViewMsg_EnableIntrinsicWidthChangedMode|
2333 // message.
[email protected]f87eee052009-09-10 21:39:092334 if (send_preferred_width_changes_) {
[email protected]3d9689372009-09-10 04:29:172335 // WebCore likes to tell us things have changed even when they haven't, so
2336 // cache the width and only send the IPC message when we're sure the
2337 // width is different.
[email protected]26aa0482009-09-30 16:55:272338 int width = webview()->mainFrame()->contentsPreferredWidth();
[email protected]3d9689372009-09-10 04:29:172339 if (width != preferred_width_) {
2340 Send(new ViewHostMsg_DidContentsPreferredWidthChange(routing_id_, width));
2341 preferred_width_ = width;
2342 }
2343 }
2344}
2345
[email protected]8922e1f2009-10-03 05:01:262346void RenderView::reportFindInPageMatchCount(int request_id, int count,
2347 bool final_update) {
2348 // If we have a message that has been queued up, then we should just replace
2349 // it. The ACK from the browser will make sure it gets sent when the browser
2350 // wants it.
2351 if (queued_find_reply_message_.get()) {
2352 IPC::Message* msg = new ViewHostMsg_Find_Reply(
2353 routing_id_,
2354 request_id,
2355 count,
2356 gfx::Rect(),
2357 -1, // Don't update active match ordinal.
2358 final_update);
2359 queued_find_reply_message_.reset(msg);
2360 } else {
2361 // Send the search result over to the browser process.
2362 Send(new ViewHostMsg_Find_Reply(
2363 routing_id_,
2364 request_id,
2365 count,
2366 gfx::Rect(),
2367 -1, // // Don't update active match ordinal.
2368 final_update));
2369 }
2370}
2371
2372void RenderView::reportFindInPageSelection(int request_id,
2373 int active_match_ordinal,
2374 const WebRect& selection_rect) {
2375 // Send the search result over to the browser process.
2376 Send(new ViewHostMsg_Find_Reply(routing_id_,
2377 request_id,
2378 -1,
2379 selection_rect,
2380 active_match_ordinal,
2381 false));
2382}
2383
[email protected]79dbc662009-09-04 05:42:512384// webkit_glue::WebPluginPageDelegate -----------------------------------------
2385
[email protected]f103ab72009-09-02 17:10:592386webkit_glue::WebPluginDelegate* RenderView::CreatePluginDelegate(
2387 const GURL& url,
2388 const std::string& mime_type,
[email protected]f103ab72009-09-02 17:10:592389 std::string* actual_mime_type) {
2390 if (!PluginChannelHost::IsListening())
2391 return NULL;
2392
2393 GURL policy_url;
[email protected]26aa0482009-09-30 16:55:272394 WebFrame* main_frame = webview()->mainFrame();
[email protected]f103ab72009-09-02 17:10:592395 if (main_frame)
2396 policy_url = main_frame->url();
2397
2398 FilePath path;
[email protected]610c0892009-09-08 19:46:182399 render_thread_->Send(new ViewHostMsg_GetPluginPath(
2400 url, policy_url, mime_type, &path, actual_mime_type));
[email protected]f103ab72009-09-02 17:10:592401 if (path.value().empty())
2402 return NULL;
2403
2404 const std::string* mime_type_to_use;
2405 if (!actual_mime_type->empty())
2406 mime_type_to_use = actual_mime_type;
2407 else
2408 mime_type_to_use = &mime_type;
2409
[email protected]d032f492009-09-29 00:33:462410 bool in_process_plugin = RenderProcess::current()->in_process_plugins();
2411 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kInternalNaCl)) {
2412 if (mime_type == "application/x-nacl-srpc") {
2413 in_process_plugin = true;
2414 }
2415 }
2416 if (in_process_plugin) {
[email protected]f103ab72009-09-02 17:10:592417#if defined(OS_WIN) // In-proc plugins aren't supported on Linux or Mac.
[email protected]8a3b7962009-09-04 05:53:232418 return WebPluginDelegateImpl::Create(
[email protected]f103ab72009-09-02 17:10:592419 path, *mime_type_to_use, gfx::NativeViewFromId(host_window_));
2420#else
2421 NOTIMPLEMENTED();
2422 return NULL;
2423#endif
2424 }
2425
[email protected]610c0892009-09-08 19:46:182426 return new WebPluginDelegateProxy(*mime_type_to_use, AsWeakPtr());
[email protected]f103ab72009-09-02 17:10:592427}
2428
2429void RenderView::CreatedPluginWindow(gfx::PluginWindowHandle window) {
2430#if defined(OS_LINUX)
2431 RenderThread::current()->Send(new ViewHostMsg_CreatePluginContainer(
2432 routing_id(), window));
2433#endif
2434}
2435
2436void RenderView::WillDestroyPluginWindow(gfx::PluginWindowHandle window) {
2437#if defined(OS_LINUX)
2438 RenderThread::current()->Send(new ViewHostMsg_DestroyPluginContainer(
2439 routing_id(), window));
2440#endif
2441 CleanupWindowInPluginMoves(window);
2442}
2443
2444void RenderView::DidMovePlugin(const webkit_glue::WebPluginGeometry& move) {
2445 SchedulePluginMove(move);
2446}
2447
2448void RenderView::DidStartLoadingForPlugin() {
2449 // TODO(darin): Make is_loading_ be a counter!
[email protected]48c9cf2d2009-09-16 16:47:522450 didStartLoading();
[email protected]f103ab72009-09-02 17:10:592451}
2452
2453void RenderView::DidStopLoadingForPlugin() {
2454 // TODO(darin): Make is_loading_ be a counter!
[email protected]48c9cf2d2009-09-16 16:47:522455 didStopLoading();
[email protected]f103ab72009-09-02 17:10:592456}
2457
2458void RenderView::ShowModalHTMLDialogForPlugin(
2459 const GURL& url,
2460 const gfx::Size& size,
2461 const std::string& json_arguments,
2462 std::string* json_retval) {
[email protected]12636df2009-09-28 22:32:212463 SendAndRunNestedMessageLoop(new ViewHostMsg_ShowModalHTMLDialog(
[email protected]f103ab72009-09-02 17:10:592464 routing_id_, url, size.width(), size.height(), json_arguments,
[email protected]12636df2009-09-28 22:32:212465 json_retval));
[email protected]f103ab72009-09-02 17:10:592466}
2467
initial.commit09911bf2008-07-26 23:55:292468void RenderView::SyncNavigationState() {
2469 if (!webview())
2470 return;
2471
[email protected]26aa0482009-09-30 16:55:272472 const WebHistoryItem& item = webview()->mainFrame()->currentHistoryItem();
[email protected]ca948a22009-06-25 19:36:172473 if (item.isNull())
initial.commit09911bf2008-07-26 23:55:292474 return;
[email protected]ca948a22009-06-25 19:36:172475
2476 Send(new ViewHostMsg_UpdateState(
2477 routing_id_, page_id_, webkit_glue::HistoryItemToString(item)));
initial.commit09911bf2008-07-26 23:55:292478}
2479
2480void RenderView::ShowContextMenu(WebView* webview,
[email protected]581b87eb2009-07-23 23:06:562481 ContextNodeType node_type,
initial.commit09911bf2008-07-26 23:55:292482 int x,
2483 int y,
2484 const GURL& link_url,
[email protected]574a1d62009-07-17 03:23:462485 const GURL& src_url,
initial.commit09911bf2008-07-26 23:55:292486 const GURL& page_url,
2487 const GURL& frame_url,
[email protected]574a1d62009-07-17 03:23:462488 const ContextMenuMediaParams& media_params,
initial.commit09911bf2008-07-26 23:55:292489 const std::wstring& selection_text,
2490 const std::wstring& misspelled_word,
[email protected]6aa376b2008-09-23 18:49:522491 int edit_flags,
[email protected]c9825a42009-05-01 22:51:502492 const std::string& security_info,
2493 const std::string& frame_charset) {
[email protected]e09ba552009-02-05 03:26:292494 ContextMenuParams params;
[email protected]581b87eb2009-07-23 23:06:562495 params.node_type = node_type;
initial.commit09911bf2008-07-26 23:55:292496 params.x = x;
2497 params.y = y;
[email protected]574a1d62009-07-17 03:23:462498 params.src_url = src_url;
initial.commit09911bf2008-07-26 23:55:292499 params.link_url = link_url;
[email protected]e6c79812009-04-22 22:31:422500 params.unfiltered_link_url = link_url;
initial.commit09911bf2008-07-26 23:55:292501 params.page_url = page_url;
2502 params.frame_url = frame_url;
[email protected]574a1d62009-07-17 03:23:462503 params.media_params = media_params;
initial.commit09911bf2008-07-26 23:55:292504 params.selection_text = selection_text;
2505 params.misspelled_word = misspelled_word;
[email protected]be645db2009-02-06 20:36:332506 params.spellcheck_enabled =
[email protected]26aa0482009-09-30 16:55:272507 webview->focusedFrame()->isContinuousSpellCheckingEnabled();
initial.commit09911bf2008-07-26 23:55:292508 params.edit_flags = edit_flags;
[email protected]6aa376b2008-09-23 18:49:522509 params.security_info = security_info;
[email protected]c9825a42009-05-01 22:51:502510 params.frame_charset = frame_charset;
initial.commit09911bf2008-07-26 23:55:292511 Send(new ViewHostMsg_ContextMenu(routing_id_, params));
2512}
2513
[email protected]b0950a72009-09-29 23:16:172514bool RenderView::DownloadImage(int id, const GURL& image_url, int image_size) {
2515 // Make sure webview was not shut down.
2516 if (!webview())
2517 return false;
2518 // Create an image resource fetcher and assign it with a call back object.
2519 image_fetchers_.insert(new ImageResourceFetcher(
[email protected]26aa0482009-09-30 16:55:272520 image_url, webview()->mainFrame(), id, image_size,
[email protected]b0950a72009-09-29 23:16:172521 NewCallback(this, &RenderView::DidDownloadImage)));
2522 return true;
2523}
2524
2525void RenderView::DidDownloadImage(ImageResourceFetcher* fetcher,
initial.commit09911bf2008-07-26 23:55:292526 const SkBitmap& image) {
[email protected]b0950a72009-09-29 23:16:172527 // Notify requester of image download status.
2528 Send(new ViewHostMsg_DidDownloadFavIcon(routing_id_,
2529 fetcher->id(),
2530 fetcher->image_url(),
2531 image.isNull(),
2532 image));
2533 // Dispose of the image fetcher.
2534 DCHECK(image_fetchers_.find(fetcher) != image_fetchers_.end());
2535 image_fetchers_.erase(fetcher);
2536 // We're in the callback from the ImageResourceFetcher, best to delay
2537 // deletion.
2538 MessageLoop::current()->DeleteSoon(FROM_HERE, fetcher);
initial.commit09911bf2008-07-26 23:55:292539}
2540
[email protected]bf5c2ff392009-07-08 16:24:332541void RenderView::OnDownloadFavIcon(int id,
2542 const GURL& image_url,
2543 int image_size) {
[email protected]f11ca0732009-04-11 00:09:342544 bool data_image_failed = false;
2545 if (image_url.SchemeIs("data")) {
2546 SkBitmap data_image = ImageFromDataUrl(image_url);
2547 data_image_failed = data_image.empty();
2548 if (!data_image_failed) {
[email protected]bf5c2ff392009-07-08 16:24:332549 Send(new ViewHostMsg_DidDownloadFavIcon(routing_id_, id, image_url, false,
2550 data_image));
[email protected]f11ca0732009-04-11 00:09:342551 }
2552 }
2553
[email protected]bf5c2ff392009-07-08 16:24:332554 if (data_image_failed ||
[email protected]b0950a72009-09-29 23:16:172555 !DownloadImage(id, image_url, image_size)) {
[email protected]bf5c2ff392009-07-08 16:24:332556 Send(new ViewHostMsg_DidDownloadFavIcon(routing_id_, id, image_url, true,
2557 SkBitmap()));
2558 }
initial.commit09911bf2008-07-26 23:55:292559}
2560
[email protected]f11ca0732009-04-11 00:09:342561SkBitmap RenderView::ImageFromDataUrl(const GURL& url) const {
2562 std::string mime_type, char_set, data;
2563 if (net::DataURL::Parse(url, &mime_type, &char_set, &data) && !data.empty()) {
2564 // Decode the favicon using WebKit's image decoder.
2565 webkit_glue::ImageDecoder decoder(gfx::Size(kFavIconSize, kFavIconSize));
2566 const unsigned char* src_data =
2567 reinterpret_cast<const unsigned char*>(&data[0]);
2568
2569 return decoder.Decode(src_data, data.size());
2570 }
2571 return SkBitmap();
2572}
2573
initial.commit09911bf2008-07-26 23:55:292574void RenderView::OnGetApplicationInfo(int page_id) {
2575 webkit_glue::WebApplicationInfo app_info;
2576 if (page_id == page_id_)
2577 webkit_glue::GetApplicationInfo(webview(), &app_info);
2578
2579 // Prune out any data URLs in the set of icons. The browser process expects
2580 // any icon with a data URL to have originated from a favicon. We don't want
2581 // to decode arbitrary data URLs in the browser process. See
2582 // http://b/issue?id=1162972
2583 for (size_t i = 0; i < app_info.icons.size(); ++i) {
[email protected]6de74452009-02-25 18:04:592584 if (app_info.icons[i].url.SchemeIs(chrome::kDataScheme)) {
initial.commit09911bf2008-07-26 23:55:292585 app_info.icons.erase(app_info.icons.begin() + i);
2586 --i;
2587 }
2588 }
2589
2590 Send(new ViewHostMsg_DidGetApplicationInfo(routing_id_, page_id, app_info));
2591}
2592
[email protected]7ccddb8c2009-08-04 17:36:552593GURL RenderView::GetAlternateErrorPageURL(const GURL& failed_url,
initial.commit09911bf2008-07-26 23:55:292594 ErrorPageType error_type) {
[email protected]7ccddb8c2009-08-04 17:36:552595 if (failed_url.SchemeIsSecure()) {
initial.commit09911bf2008-07-26 23:55:292596 // If the URL that failed was secure, then the embedding web page was not
2597 // expecting a network attacker to be able to manipulate its contents. As
2598 // we fetch alternate error pages over HTTP, we would be allowing a network
2599 // attacker to manipulate the contents of the response if we tried to use
2600 // the link doctor here.
2601 return GURL::EmptyGURL();
2602 }
2603
2604 // Grab the base URL from the browser process.
2605 if (!alternate_error_page_url_.is_valid())
2606 return GURL::EmptyGURL();
2607
2608 // Strip query params from the failed URL.
2609 GURL::Replacements remove_params;
2610 remove_params.ClearUsername();
2611 remove_params.ClearPassword();
2612 remove_params.ClearQuery();
2613 remove_params.ClearRef();
[email protected]7ccddb8c2009-08-04 17:36:552614 const GURL url_to_send = failed_url.ReplaceComponents(remove_params);
initial.commit09911bf2008-07-26 23:55:292615
2616 // Construct the query params to send to link doctor.
2617 std::string params(alternate_error_page_url_.query());
2618 params.append("&url=");
2619 params.append(EscapeQueryParamValue(url_to_send.spec()));
2620 params.append("&sourceid=chrome");
2621 params.append("&error=");
2622 switch (error_type) {
2623 case DNS_ERROR:
2624 params.append("dnserror");
2625 break;
2626
2627 case HTTP_404:
2628 params.append("http404");
2629 break;
2630
[email protected]5df266ac2008-10-15 19:50:132631 case CONNECTION_ERROR:
[email protected]e1f934b2009-01-26 20:41:332632 params.append("connectionfailure");
[email protected]5df266ac2008-10-15 19:50:132633 break;
2634
initial.commit09911bf2008-07-26 23:55:292635 default:
2636 NOTREACHED() << "unknown ErrorPageType";
2637 }
2638
2639 // OK, build the final url to return.
2640 GURL::Replacements link_doctor_params;
2641 link_doctor_params.SetQueryStr(params);
2642 GURL url = alternate_error_page_url_.ReplaceComponents(link_doctor_params);
2643 return url;
2644}
2645
[email protected]7ea066a2009-04-06 20:21:592646void RenderView::OnFind(int request_id,
2647 const string16& search_text,
2648 const WebKit::WebFindOptions& options) {
[email protected]26aa0482009-09-30 16:55:272649 WebFrame* main_frame = webview()->mainFrame();
[email protected]b4bb2502009-10-01 22:35:272650 WebFrame* frame_after_main = main_frame->traverseNext(true);
[email protected]26aa0482009-09-30 16:55:272651 WebFrame* focused_frame = webview()->focusedFrame();
initial.commit09911bf2008-07-26 23:55:292652 WebFrame* search_frame = focused_frame; // start searching focused frame.
2653
2654 bool multi_frame = (frame_after_main != main_frame);
2655
2656 // If we have multiple frames, we don't want to wrap the search within the
2657 // frame, so we check here if we only have main_frame in the chain.
2658 bool wrap_within_frame = !multi_frame;
2659
[email protected]b3f2b912009-04-09 16:18:522660 WebRect selection_rect;
initial.commit09911bf2008-07-26 23:55:292661 bool result = false;
2662
2663 do {
[email protected]dd7daa82009-08-10 05:46:452664 result = search_frame->find(
[email protected]7ea066a2009-04-06 20:21:592665 request_id, search_text, options, wrap_within_frame, &selection_rect);
initial.commit09911bf2008-07-26 23:55:292666
2667 if (!result) {
2668 // don't leave text selected as you move to the next frame.
[email protected]a100d76bb2009-08-14 17:50:222669 search_frame->executeCommand(WebString::fromUTF8("Unselect"));
initial.commit09911bf2008-07-26 23:55:292670
2671 // Find the next frame, but skip the invisible ones.
2672 do {
2673 // What is the next frame to search? (we might be going backwards). Note
2674 // that we specify wrap=true so that search_frame never becomes NULL.
[email protected]7ea066a2009-04-06 20:21:592675 search_frame = options.forward ?
[email protected]b4bb2502009-10-01 22:35:272676 search_frame->traverseNext(true) :
2677 search_frame->traversePrevious(true);
[email protected]dd7daa82009-08-10 05:46:452678 } while (!search_frame->hasVisibleContent() &&
2679 search_frame != focused_frame);
initial.commit09911bf2008-07-26 23:55:292680
[email protected]884db412008-11-24 23:46:502681 // Make sure selection doesn't affect the search operation in new frame.
[email protected]a100d76bb2009-08-14 17:50:222682 search_frame->executeCommand(WebString::fromUTF8("Unselect"));
initial.commit09911bf2008-07-26 23:55:292683
2684 // If we have multiple frames and we have wrapped back around to the
2685 // focused frame, we need to search it once more allowing wrap within
2686 // the frame, otherwise it will report 'no match' if the focused frame has
2687 // reported matches, but no frames after the focused_frame contain a
2688 // match for the search word(s).
2689 if (multi_frame && search_frame == focused_frame) {
[email protected]dd7daa82009-08-10 05:46:452690 result = search_frame->find(
[email protected]7ea066a2009-04-06 20:21:592691 request_id, search_text, options, true, // Force wrapping.
2692 &selection_rect);
initial.commit09911bf2008-07-26 23:55:292693 }
2694 }
2695
[email protected]26aa0482009-09-30 16:55:272696 webview()->setFocusedFrame(search_frame);
initial.commit09911bf2008-07-26 23:55:292697 } while (!result && search_frame != focused_frame);
2698
[email protected]7ea066a2009-04-06 20:21:592699 if (options.findNext) {
[email protected]4f3dc372009-02-24 00:10:292700 // Force the main_frame to report the actual count.
[email protected]dd7daa82009-08-10 05:46:452701 main_frame->increaseMatchCount(0, request_id);
[email protected]4f3dc372009-02-24 00:10:292702 } else {
2703 // If nothing is found, set result to "0 of 0", otherwise, set it to
2704 // "-1 of 1" to indicate that we found at least one item, but we don't know
2705 // yet what is active.
2706 int ordinal = result ? -1 : 0; // -1 here means, we might know more later.
2707 int match_count = result ? 1 : 0; // 1 here means possibly more coming.
initial.commit09911bf2008-07-26 23:55:292708
[email protected]4f3dc372009-02-24 00:10:292709 // If we find no matches then this will be our last status update.
2710 // Otherwise the scoping effort will send more results.
2711 bool final_status_update = !result;
initial.commit09911bf2008-07-26 23:55:292712
[email protected]4f3dc372009-02-24 00:10:292713 // Send the search result over to the browser process.
[email protected]4f999132009-03-31 18:08:402714 Send(new ViewHostMsg_Find_Reply(routing_id_,
[email protected]7ea066a2009-04-06 20:21:592715 request_id,
[email protected]4f3dc372009-02-24 00:10:292716 match_count,
2717 selection_rect,
2718 ordinal,
2719 final_status_update));
initial.commit09911bf2008-07-26 23:55:292720
initial.commit09911bf2008-07-26 23:55:292721 // Scoping effort begins, starting with the mainframe.
2722 search_frame = main_frame;
2723
[email protected]dd7daa82009-08-10 05:46:452724 main_frame->resetMatchCount();
initial.commit09911bf2008-07-26 23:55:292725
2726 do {
2727 // Cancel all old scoping requests before starting a new one.
[email protected]dd7daa82009-08-10 05:46:452728 search_frame->cancelPendingScopingEffort();
initial.commit09911bf2008-07-26 23:55:292729
2730 // We don't start another scoping effort unless at least one match has
2731 // been found.
2732 if (result) {
2733 // Start new scoping request. If the scoping function determines that it
2734 // needs to scope, it will defer until later.
[email protected]dd7daa82009-08-10 05:46:452735 search_frame->scopeStringMatches(request_id,
[email protected]7ea066a2009-04-06 20:21:592736 search_text,
2737 options,
initial.commit09911bf2008-07-26 23:55:292738 true); // reset the tickmarks
2739 }
2740
2741 // Iterate to the next frame. The frame will not necessarily scope, for
2742 // example if it is not visible.
[email protected]b4bb2502009-10-01 22:35:272743 search_frame = search_frame->traverseNext(true);
initial.commit09911bf2008-07-26 23:55:292744 } while (search_frame != main_frame);
2745 }
2746}
2747
[email protected]5c4266922009-07-10 16:41:272748void RenderView::OnDeterminePageText() {
2749 if (!is_loading_) {
2750 if (!webview())
2751 return;
[email protected]26aa0482009-09-30 16:55:272752 WebFrame* main_frame = webview()->mainFrame();
[email protected]5c4266922009-07-10 16:41:272753 std::wstring contents;
2754 CaptureText(main_frame, &contents);
2755 Send(new ViewMsg_DeterminePageText_Reply(routing_id_, contents));
2756 determine_page_text_after_loading_stops_ = false;
2757 return;
2758 }
2759
2760 // We set |determine_page_text_after_loading_stops_| true here so that,
2761 // after page has been loaded completely, the text in the page is captured.
2762 determine_page_text_after_loading_stops_ = true;
2763}
2764
[email protected]ed4bf2d2009-05-05 00:10:062765bool RenderView::WasOpenedByUserGesture() const {
initial.commit09911bf2008-07-26 23:55:292766 return opened_by_user_gesture_;
2767}
2768
initial.commit09911bf2008-07-26 23:55:292769void RenderView::DnsPrefetch(const std::vector<std::string>& host_names) {
2770 Send(new ViewHostMsg_DnsPrefetch(host_names));
2771}
2772
[email protected]630e26b2008-10-14 22:55:172773void RenderView::OnZoom(int function) {
2774 static const bool kZoomIsTextOnly = false;
2775 switch (function) {
2776 case PageZoom::SMALLER:
[email protected]26aa0482009-09-30 16:55:272777 webview()->zoomOut(kZoomIsTextOnly);
initial.commit09911bf2008-07-26 23:55:292778 break;
[email protected]630e26b2008-10-14 22:55:172779 case PageZoom::STANDARD:
[email protected]26aa0482009-09-30 16:55:272780 webview()->zoomDefault();
initial.commit09911bf2008-07-26 23:55:292781 break;
[email protected]630e26b2008-10-14 22:55:172782 case PageZoom::LARGER:
[email protected]26aa0482009-09-30 16:55:272783 webview()->zoomIn(kZoomIsTextOnly);
initial.commit09911bf2008-07-26 23:55:292784 break;
2785 default:
2786 NOTREACHED();
2787 }
2788}
2789
[email protected]41fc0322009-09-04 22:23:402790void RenderView::OnSetPageEncoding(const std::string& encoding_name) {
[email protected]26aa0482009-09-30 16:55:272791 webview()->setPageEncoding(WebString::fromUTF8(encoding_name));
initial.commit09911bf2008-07-26 23:55:292792}
2793
[email protected]a697f4c2009-09-14 22:30:182794void RenderView::OnResetPageEncodingToDefault() {
[email protected]26aa0482009-09-30 16:55:272795 WebString no_encoding;
2796 webview()->setPageEncoding(no_encoding);
[email protected]a697f4c2009-09-14 22:30:182797}
2798
[email protected]611cad42009-03-16 18:51:342799WebDevToolsAgentDelegate* RenderView::GetWebDevToolsAgentDelegate() {
[email protected]b75b7d072009-04-06 13:47:002800 return devtools_agent_.get();
[email protected]611cad42009-03-16 18:51:342801}
2802
[email protected]dd7daa82009-08-10 05:46:452803WebFrame* RenderView::GetChildFrame(const std::wstring& xpath) const {
2804 if (xpath.empty())
[email protected]26aa0482009-09-30 16:55:272805 return webview()->mainFrame();
[email protected]dd7daa82009-08-10 05:46:452806
2807 // xpath string can represent a frame deep down the tree (across multiple
2808 // frame DOMs).
2809 // Example, /html/body/table/tbody/tr/td/iframe\n/frameset/frame[0]
2810 // should break into 2 xpaths
2811 // /html/body/table/tbody/tr/td/iframe & /frameset/frame[0]
2812
[email protected]26aa0482009-09-30 16:55:272813 WebFrame* frame = webview()->mainFrame();
[email protected]dd7daa82009-08-10 05:46:452814
2815 std::wstring xpath_remaining = xpath;
2816 while (!xpath_remaining.empty()) {
2817 std::wstring::size_type delim_pos = xpath_remaining.find_first_of(L'\n');
2818 std::wstring xpath_child;
2819 if (delim_pos != std::wstring::npos) {
2820 xpath_child = xpath_remaining.substr(0, delim_pos);
2821 xpath_remaining.erase(0, delim_pos + 1);
2822 } else {
2823 xpath_remaining.swap(xpath_child);
2824 }
2825 frame = frame->findChildByExpression(WideToUTF16Hack(xpath_child));
initial.commit09911bf2008-07-26 23:55:292826 }
2827
[email protected]dd7daa82009-08-10 05:46:452828 return frame;
initial.commit09911bf2008-07-26 23:55:292829}
2830
[email protected]f29acf52008-11-03 20:08:332831void RenderView::EvaluateScript(const std::wstring& frame_xpath,
2832 const std::wstring& script) {
initial.commit09911bf2008-07-26 23:55:292833 WebFrame* web_frame = GetChildFrame(frame_xpath);
2834 if (!web_frame)
2835 return;
2836
[email protected]dd7daa82009-08-10 05:46:452837 web_frame->executeScript(WebScriptSource(WideToUTF16Hack(script)));
initial.commit09911bf2008-07-26 23:55:292838}
2839
[email protected]1810e132009-03-24 23:35:482840void RenderView::InsertCSS(const std::wstring& frame_xpath,
[email protected]ffaef0c2009-09-15 17:08:082841 const std::string& css,
2842 const std::string& id) {
[email protected]1810e132009-03-24 23:35:482843 WebFrame* web_frame = GetChildFrame(frame_xpath);
2844 if (!web_frame)
2845 return;
2846
[email protected]ffaef0c2009-09-15 17:08:082847 web_frame->insertStyleText(WebString::fromUTF8(css), WebString::fromUTF8(id));
[email protected]1810e132009-03-24 23:35:482848}
2849
initial.commit09911bf2008-07-26 23:55:292850void RenderView::OnScriptEvalRequest(const std::wstring& frame_xpath,
2851 const std::wstring& jscript) {
[email protected]f29acf52008-11-03 20:08:332852 EvaluateScript(frame_xpath, jscript);
initial.commit09911bf2008-07-26 23:55:292853}
2854
[email protected]1810e132009-03-24 23:35:482855void RenderView::OnCSSInsertRequest(const std::wstring& frame_xpath,
[email protected]ffaef0c2009-09-15 17:08:082856 const std::string& css,
2857 const std::string& id) {
2858 InsertCSS(frame_xpath, css, id);
[email protected]ae461542009-06-19 19:03:412859
2860 // Notify RenderViewHost that css has been inserted into the frame.
2861 Send(new ViewHostMsg_OnCSSInserted(routing_id_));
[email protected]1810e132009-03-24 23:35:482862}
2863
[email protected]7ea066a2009-04-06 20:21:592864void RenderView::OnAddMessageToConsole(
2865 const string16& frame_xpath,
2866 const string16& message,
2867 const WebConsoleMessage::Level& level) {
2868 WebFrame* web_frame = GetChildFrame(UTF16ToWideHack(frame_xpath));
[email protected]0dea3ea2009-03-31 23:30:592869 if (web_frame)
[email protected]dd7daa82009-08-10 05:46:452870 web_frame->addMessageToConsole(WebConsoleMessage(level, message));
initial.commit09911bf2008-07-26 23:55:292871}
2872
[email protected]81e63782009-02-27 19:35:092873void RenderView::OnAllowBindings(int enabled_bindings_flags) {
2874 enabled_bindings_ |= enabled_bindings_flags;
initial.commit09911bf2008-07-26 23:55:292875}
2876
2877void RenderView::OnSetDOMUIProperty(const std::string& name,
2878 const std::string& value) {
[email protected]81e63782009-02-27 19:35:092879 DCHECK(BindingsPolicy::is_dom_ui_enabled(enabled_bindings_));
initial.commit09911bf2008-07-26 23:55:292880 dom_ui_bindings_.SetProperty(name, value);
2881}
2882
2883void RenderView::OnReservePageIDRange(int size_of_range) {
2884 next_page_id_ += size_of_range + 1;
2885}
2886
[email protected]e80c73b2009-04-07 23:24:582887void RenderView::OnDragSourceEndedOrMoved(const gfx::Point& client_point,
2888 const gfx::Point& screen_point,
[email protected]1d9f4132009-09-08 17:29:252889 bool ended,
2890 WebDragOperation op) {
[email protected]5f9ae6c2009-07-08 02:38:032891 if (ended) {
[email protected]26aa0482009-09-30 16:55:272892 webview()->dragSourceEndedAt(client_point, screen_point, op);
[email protected]5f9ae6c2009-07-08 02:38:032893 } else {
[email protected]26aa0482009-09-30 16:55:272894 webview()->dragSourceMovedTo(client_point, screen_point);
[email protected]5f9ae6c2009-07-08 02:38:032895 }
initial.commit09911bf2008-07-26 23:55:292896}
2897
2898void RenderView::OnDragSourceSystemDragEnded() {
[email protected]26aa0482009-09-30 16:55:272899 webview()->dragSourceSystemDragEnded();
initial.commit09911bf2008-07-26 23:55:292900}
2901
2902void RenderView::OnUploadFileRequest(const ViewMsg_UploadFile_Params& p) {
2903 webkit_glue::FileUploadData* f = new webkit_glue::FileUploadData;
2904 f->file_path = p.file_path;
2905 f->form_name = p.form;
2906 f->file_name = p.file;
2907 f->submit_name = p.submit;
2908
2909 // Build the other form values map.
2910 if (!p.other_values.empty()) {
2911 std::vector<std::wstring> e;
2912 std::vector<std::wstring> kvp;
2913 std::vector<std::wstring>::iterator i;
2914
2915 SplitString(p.other_values, L'\n', &e);
2916 for (i = e.begin(); i != e.end(); ++i) {
2917 SplitString(*i, L'=', &kvp);
2918 if (kvp.size() == 2)
2919 f->other_form_values[kvp[0]] = kvp[1];
2920 kvp.clear();
2921 }
2922 }
2923
2924 pending_upload_data_.reset(f);
2925 ProcessPendingUpload();
2926}
2927
2928void RenderView::ProcessPendingUpload() {
2929 webkit_glue::FileUploadData* f = pending_upload_data_.get();
2930 if (f && webview() && webkit_glue::FillFormToUploadFile(webview(), *f))
2931 ResetPendingUpload();
2932}
2933
2934void RenderView::ResetPendingUpload() {
2935 pending_upload_data_.reset();
2936}
2937
2938void RenderView::OnFormFill(const FormData& form) {
2939 webkit_glue::FillForm(this->webview(), form);
2940}
2941
2942void RenderView::OnFillPasswordForm(
[email protected]daa8c58e2009-06-15 17:21:102943 const webkit_glue::PasswordFormDomManager::FillData& form_data) {
initial.commit09911bf2008-07-26 23:55:292944 webkit_glue::FillPasswordForm(this->webview(), form_data);
2945}
2946
2947void RenderView::OnDragTargetDragEnter(const WebDropData& drop_data,
[email protected]e80c73b2009-04-07 23:24:582948 const gfx::Point& client_point,
[email protected]1d9f4132009-09-08 17:29:252949 const gfx::Point& screen_point,
2950 WebDragOperationsMask ops) {
[email protected]26aa0482009-09-30 16:55:272951 WebDragOperation operation = webview()->dragTargetDragEnter(
[email protected]e80c73b2009-04-07 23:24:582952 drop_data.ToDragData(),
2953 drop_data.identity,
2954 client_point,
[email protected]1d9f4132009-09-08 17:29:252955 screen_point,
2956 ops);
initial.commit09911bf2008-07-26 23:55:292957
[email protected]1d9f4132009-09-08 17:29:252958 Send(new ViewHostMsg_UpdateDragCursor(routing_id_, operation));
initial.commit09911bf2008-07-26 23:55:292959}
2960
[email protected]e80c73b2009-04-07 23:24:582961void RenderView::OnDragTargetDragOver(const gfx::Point& client_point,
[email protected]1d9f4132009-09-08 17:29:252962 const gfx::Point& screen_point,
2963 WebDragOperationsMask ops) {
[email protected]26aa0482009-09-30 16:55:272964 WebDragOperation operation = webview()->dragTargetDragOver(
[email protected]1d9f4132009-09-08 17:29:252965 client_point,
2966 screen_point,
2967 ops);
initial.commit09911bf2008-07-26 23:55:292968
[email protected]1d9f4132009-09-08 17:29:252969 Send(new ViewHostMsg_UpdateDragCursor(routing_id_, operation));
initial.commit09911bf2008-07-26 23:55:292970}
2971
2972void RenderView::OnDragTargetDragLeave() {
[email protected]26aa0482009-09-30 16:55:272973 webview()->dragTargetDragLeave();
initial.commit09911bf2008-07-26 23:55:292974}
2975
[email protected]e80c73b2009-04-07 23:24:582976void RenderView::OnDragTargetDrop(const gfx::Point& client_point,
2977 const gfx::Point& screen_point) {
[email protected]26aa0482009-09-30 16:55:272978 webview()->dragTargetDrop(client_point, screen_point);
initial.commit09911bf2008-07-26 23:55:292979}
2980
2981void RenderView::OnUpdateWebPreferences(const WebPreferences& prefs) {
[email protected]2fab253a2009-08-17 23:00:592982 webkit_preferences_ = prefs;
2983 webkit_preferences_.Apply(webview());
initial.commit09911bf2008-07-26 23:55:292984}
2985
2986void RenderView::OnSetAltErrorPageURL(const GURL& url) {
2987 alternate_error_page_url_ = url;
2988}
2989
initial.commit09911bf2008-07-26 23:55:292990void RenderView::OnInstallMissingPlugin() {
2991 // This could happen when the first default plugin is deleted.
[email protected]f103ab72009-09-02 17:10:592992 if (first_default_plugin_)
2993 first_default_plugin_->InstallMissingPlugin();
initial.commit09911bf2008-07-26 23:55:292994}
2995
[email protected]b62d1a8c2009-01-13 23:54:572996void RenderView::OnFileChooserResponse(
[email protected]561abe62009-04-06 18:08:342997 const std::vector<FilePath>& file_names) {
[email protected]8029f5672009-03-20 22:33:362998 // This could happen if we navigated to a different page before the user
2999 // closed the chooser.
[email protected]a1128322009-10-06 18:38:463000 if (!file_chooser_completion_)
[email protected]8029f5672009-03-20 22:33:363001 return;
3002
[email protected]a1128322009-10-06 18:38:463003 WebKit::WebVector<WebKit::WebString> ws_file_names(file_names.size());
3004 for (size_t i = 0; i < file_names.size(); ++i) {
3005 ws_file_names[i] = webkit_glue::FilePathToWebString(file_names[i]);
3006 }
3007
3008 file_chooser_completion_->didChooseFile(ws_file_names);
3009 // Reset the chooser pointer
3010 file_chooser_completion_ = NULL;
initial.commit09911bf2008-07-26 23:55:293011}
3012
3013void RenderView::OnEnableViewSourceMode() {
3014 if (!webview())
3015 return;
[email protected]26aa0482009-09-30 16:55:273016 WebFrame* main_frame = webview()->mainFrame();
initial.commit09911bf2008-07-26 23:55:293017 if (!main_frame)
3018 return;
3019
[email protected]dd7daa82009-08-10 05:46:453020 main_frame->enableViewSourceMode(true);
initial.commit09911bf2008-07-26 23:55:293021}
3022
[email protected]0666aef2009-05-13 19:48:083023void RenderView::OnEnableIntrinsicWidthChangedMode() {
3024 send_preferred_width_changes_ = true;
3025}
3026
[email protected]80d96fa2009-06-10 22:34:513027void RenderView::OnSetRendererPrefs(const RendererPreferences& renderer_prefs) {
3028 renderer_preferences_ = renderer_prefs;
[email protected]6e282c92009-07-24 01:19:373029 UpdateFontRenderingFromRendererPrefs();
[email protected]7a74e102009-09-03 00:16:563030#if defined(OS_LINUX)
[email protected]1c83eb42009-09-11 21:08:413031 WebColorName name = WebKit::WebColorWebkitFocusRingColor;
3032 WebKit::setNamedColors(&name, &renderer_prefs.focus_ring_color, 1);
[email protected]7a74e102009-09-03 00:16:563033#endif
[email protected]80d96fa2009-06-10 22:34:513034}
3035
[email protected]952cb702009-10-07 05:50:283036void RenderView::OnMediaPlayerActionAt(const gfx::Point& location,
3037 const WebMediaPlayerAction& action) {
3038 if (webview())
3039 webview()->performMediaPlayerAction(action, location);
[email protected]581b87eb2009-07-23 23:06:563040}
3041
[email protected]7b291f92009-08-14 05:43:533042void RenderView::OnNotifyRendererViewType(ViewType::Type type) {
[email protected]078b34612009-09-19 19:31:513043 // When this is first set, the bindings aren't fully loaded. We only need
3044 // to call through this API after the page has already been loaded. It's
3045 // also called in didCreateDocumentElement to bootstrap.
3046 if (view_type_ != ViewType::INVALID) {
3047 if (type == ViewType::EXTENSION_MOLE ||
3048 type == ViewType::EXTENSION_TOOLSTRIP) {
3049 ExtensionProcessBindings::SetViewType(webview(), type);
3050 }
3051 }
[email protected]7b291f92009-08-14 05:43:533052 view_type_ = type;
3053}
3054
3055void RenderView::OnUpdateBrowserWindowId(int window_id) {
3056 browser_window_id_ = window_id;
3057}
3058
initial.commit09911bf2008-07-26 23:55:293059void RenderView::OnUpdateBackForwardListCount(int back_list_count,
3060 int forward_list_count) {
3061 history_back_list_count_ = back_list_count;
3062 history_forward_list_count_ = forward_list_count;
3063}
3064
[email protected]266eb6f2008-09-30 23:56:503065void RenderView::OnGetAccessibilityInfo(
[email protected]6a983b42009-03-20 20:12:253066 const webkit_glue::WebAccessibility::InParams& in_params,
3067 webkit_glue::WebAccessibility::OutParams* out_params) {
[email protected]6c8afae52009-01-22 02:24:573068#if defined(OS_WIN)
[email protected]6a983b42009-03-20 20:12:253069 if (!web_accessibility_manager_.get()) {
3070 web_accessibility_manager_.reset(
3071 webkit_glue::WebAccessibilityManager::Create());
3072 }
[email protected]266eb6f2008-09-30 23:56:503073
[email protected]6a983b42009-03-20 20:12:253074 if (!web_accessibility_manager_->GetAccObjInfo(webview(), in_params,
3075 out_params)) {
[email protected]266eb6f2008-09-30 23:56:503076 return;
3077 }
[email protected]6c8afae52009-01-22 02:24:573078#else // defined(OS_WIN)
3079 // TODO(port): accessibility not yet implemented
3080 NOTIMPLEMENTED();
3081#endif
[email protected]266eb6f2008-09-30 23:56:503082}
3083
[email protected]6a983b42009-03-20 20:12:253084void RenderView::OnClearAccessibilityInfo(int acc_obj_id, bool clear_all) {
[email protected]6c8afae52009-01-22 02:24:573085#if defined(OS_WIN)
[email protected]6a983b42009-03-20 20:12:253086 if (!web_accessibility_manager_.get()) {
[email protected]266eb6f2008-09-30 23:56:503087 // If accessibility is not activated, ignore clearing message.
3088 return;
3089 }
[email protected]e846d0d2009-05-20 00:53:063090
[email protected]6a983b42009-03-20 20:12:253091 if (!web_accessibility_manager_->ClearAccObjMap(acc_obj_id, clear_all))
[email protected]266eb6f2008-09-30 23:56:503092 return;
[email protected]e846d0d2009-05-20 00:53:063093
[email protected]6c8afae52009-01-22 02:24:573094#else // defined(OS_WIN)
3095 // TODO(port): accessibility not yet implemented
3096 NOTIMPLEMENTED();
3097#endif
[email protected]266eb6f2008-09-30 23:56:503098}
3099
initial.commit09911bf2008-07-26 23:55:293100void RenderView::OnGetAllSavableResourceLinksForCurrentPage(
3101 const GURL& page_url) {
3102 // Prepare list to storage all savable resource links.
3103 std::vector<GURL> resources_list;
3104 std::vector<GURL> referrers_list;
3105 std::vector<GURL> frames_list;
3106 webkit_glue::SavableResourcesResult result(&resources_list,
3107 &referrers_list,
3108 &frames_list);
3109
3110 if (!webkit_glue::GetAllSavableResourceLinksForCurrentPage(webview(),
3111 page_url,
3112 &result)) {
3113 // If something is wrong when collecting all savable resource links,
3114 // send empty list to embedder(browser) to tell it failed.
3115 referrers_list.clear();
3116 resources_list.clear();
3117 frames_list.clear();
3118 }
3119
3120 // Send result of all savable resource links to embedder.
3121 Send(new ViewHostMsg_SendCurrentPageAllSavableResourceLinks(routing_id_,
3122 resources_list,
3123 referrers_list,
3124 frames_list));
3125}
3126
3127void RenderView::OnGetSerializedHtmlDataForCurrentPageWithLocalLinks(
[email protected]f6b48532009-02-12 01:56:323128 const std::vector<GURL>& links,
[email protected]fde6714d12009-02-18 22:39:313129 const std::vector<FilePath>& local_paths,
3130 const FilePath& local_directory_name) {
[email protected]26aa0482009-09-30 16:55:273131 webkit_glue::DomSerializer dom_serializer(webview()->mainFrame(),
initial.commit09911bf2008-07-26 23:55:293132 true,
3133 this,
3134 links,
3135 local_paths,
3136 local_directory_name);
3137 dom_serializer.SerializeDom();
3138}
3139
3140void RenderView::DidSerializeDataForFrame(const GURL& frame_url,
3141 const std::string& data, PageSavingSerializationStatus status) {
3142 Send(new ViewHostMsg_SendSerializedHtmlData(routing_id_,
3143 frame_url, data, static_cast<int32>(status)));
3144}
3145
[email protected]04b4a6c2008-08-02 00:44:473146void RenderView::OnMsgShouldClose() {
[email protected]26aa0482009-09-30 16:55:273147 bool should_close = webview()->dispatchBeforeUnloadEvent();
[email protected]04b4a6c2008-08-02 00:44:473148 Send(new ViewHostMsg_ShouldClose_ACK(routing_id_, should_close));
initial.commit09911bf2008-07-26 23:55:293149}
3150
[email protected]eb6b87a2009-07-24 15:57:393151void RenderView::OnClosePage(const ViewMsg_ClosePage_Params& params) {
initial.commit09911bf2008-07-26 23:55:293152 // TODO(creis): We'd rather use webview()->Close() here, but that currently
3153 // sets the WebView's delegate_ to NULL, preventing any JavaScript dialogs
3154 // in the onunload handler from appearing. For now, we're bypassing that and
3155 // calling the FrameLoader's CloseURL method directly. This should be
3156 // revisited to avoid having two ways to close a page. Having a single way
3157 // to close that can run onunload is also useful for fixing
3158 // http://b/issue?id=753080.
[email protected]26aa0482009-09-30 16:55:273159 WebFrame* main_frame = webview()->mainFrame();
[email protected]7a9b51f2009-06-29 21:28:293160 if (main_frame) {
[email protected]dd7daa82009-08-10 05:46:453161 const GURL& url = main_frame->url();
[email protected]3d9689372009-09-10 04:29:173162 // TODO(davemoore) this code should be removed once willClose() gets
[email protected]7a9b51f2009-06-29 21:28:293163 // called when a page is destroyed. DumpLoadHistograms() is safe to call
3164 // multiple times for the same frame, but it will simplify things.
[email protected]dd7daa82009-08-10 05:46:453165 if (url.SchemeIs(chrome::kHttpScheme) ||
3166 url.SchemeIs(chrome::kHttpsScheme))
[email protected]7a9b51f2009-06-29 21:28:293167 DumpLoadHistograms();
[email protected]7a9b51f2009-06-29 21:28:293168 }
[email protected]26aa0482009-09-30 16:55:273169 webview()->dispatchUnloadEvent();
initial.commit09911bf2008-07-26 23:55:293170
[email protected]eb6b87a2009-07-24 15:57:393171 // Just echo back the params in the ACK.
3172 Send(new ViewHostMsg_ClosePage_ACK(routing_id_, params));
initial.commit09911bf2008-07-26 23:55:293173}
3174
3175void RenderView::OnThemeChanged() {
[email protected]6c8afae52009-01-22 02:24:573176#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:293177 gfx::NativeTheme::instance()->CloseHandles();
3178 gfx::Rect view_rect(0, 0, size_.width(), size_.height());
[email protected]4873c7d2009-07-16 06:36:283179 didInvalidateRect(view_rect);
[email protected]6c8afae52009-01-22 02:24:573180#else // defined(OS_WIN)
3181 // TODO(port): we don't support theming on non-Windows platforms yet
3182 NOTIMPLEMENTED();
3183#endif
initial.commit09911bf2008-07-26 23:55:293184}
3185
[email protected]28790922009-03-09 19:48:373186void RenderView::OnMessageFromExternalHost(const std::string& message,
3187 const std::string& origin,
3188 const std::string& target) {
[email protected]3ac14a052008-08-15 21:22:153189 if (message.empty())
3190 return;
3191
[email protected]28790922009-03-09 19:48:373192 external_host_bindings_.ForwardMessageFromExternalHost(message, origin,
3193 target);
[email protected]3ac14a052008-08-15 21:22:153194}
3195
[email protected]0aa55312008-10-17 21:53:083196void RenderView::OnDisassociateFromPopupCount() {
3197 if (decrement_shared_popup_at_destruction_)
3198 shared_popup_counter_->data--;
3199 shared_popup_counter_ = new SharedRenderViewCounter(0);
3200 decrement_shared_popup_at_destruction_ = false;
3201}
3202
[email protected]15d79e12009-08-02 19:23:453203bool RenderView::MaybeLoadAlternateErrorPage(WebFrame* frame,
3204 const WebURLError& error,
3205 bool replace) {
3206 // We only show alternate error pages in the main frame. They are
3207 // intended to assist the user when navigating, so there is not much
3208 // value in showing them for failed subframes. Ideally, we would be
3209 // able to use the TYPED transition type for this, but that flag is
3210 // not preserved across page reloads.
[email protected]dd7daa82009-08-10 05:46:453211 if (frame->parent())
[email protected]15d79e12009-08-02 19:23:453212 return false;
3213
3214 // Use the alternate error page service if this is a DNS failure or
[email protected]c53976d52009-08-07 18:58:373215 // connection failure.
[email protected]15d79e12009-08-02 19:23:453216 int ec = error.reason;
3217 if (ec != net::ERR_NAME_NOT_RESOLVED &&
3218 ec != net::ERR_CONNECTION_FAILED &&
3219 ec != net::ERR_CONNECTION_REFUSED &&
3220 ec != net::ERR_ADDRESS_UNREACHABLE &&
[email protected]c53976d52009-08-07 18:58:373221 ec != net::ERR_CONNECTION_TIMED_OUT)
[email protected]15d79e12009-08-02 19:23:453222 return false;
3223
3224 const GURL& error_page_url = GetAlternateErrorPageURL(error.unreachableURL,
[email protected]7ccddb8c2009-08-04 17:36:553225 ec == net::ERR_NAME_NOT_RESOLVED ? DNS_ERROR : CONNECTION_ERROR);
[email protected]15d79e12009-08-02 19:23:453226 if (!error_page_url.is_valid())
3227 return false;
3228
3229 // Load an empty page first so there is an immediate response to the error,
3230 // and then kick off a request for the alternate error page.
[email protected]dd7daa82009-08-10 05:46:453231 frame->loadHTMLString(std::string(),
[email protected]15d79e12009-08-02 19:23:453232 GURL(kUnreachableWebDataURL),
3233 error.unreachableURL,
3234 replace);
3235
3236 // Now, create a fetcher for the error page and associate it with the data
3237 // source we just created via the LoadHTMLString call. That way if another
3238 // navigation occurs, the fetcher will get destroyed.
3239 NavigationState* navigation_state =
[email protected]dd7daa82009-08-10 05:46:453240 NavigationState::FromDataSource(frame->provisionalDataSource());
[email protected]15d79e12009-08-02 19:23:453241 navigation_state->set_alt_error_page_fetcher(
3242 new AltErrorPageResourceFetcher(
3243 error_page_url, frame, error,
3244 NewCallback(this, &RenderView::AltErrorPageFinished)));
3245 return true;
3246}
3247
initial.commit09911bf2008-07-26 23:55:293248std::string RenderView::GetAltHTMLForTemplate(
3249 const DictionaryValue& error_strings, int template_resource_id) const {
[email protected]8a16266e2009-09-10 21:08:393250 const base::StringPiece template_html(
initial.commit09911bf2008-07-26 23:55:293251 ResourceBundle::GetSharedInstance().GetRawDataResource(
3252 template_resource_id));
3253
3254 if (template_html.empty()) {
3255 NOTREACHED() << "unable to load template. ID: " << template_resource_id;
3256 return "";
3257 }
[email protected]7cd22a52009-07-14 00:40:253258
initial.commit09911bf2008-07-26 23:55:293259 // "t" is the id of the templates root node.
[email protected]7cd22a52009-07-14 00:40:253260 return jstemplate_builder::GetTemplatesHtml(
initial.commit09911bf2008-07-26 23:55:293261 template_html, &error_strings, "t");
3262}
[email protected]0e79b9e2009-02-13 04:20:483263
[email protected]15d79e12009-08-02 19:23:453264void RenderView::AltErrorPageFinished(WebFrame* frame,
3265 const WebURLError& original_error,
3266 const std::string& html) {
3267 // Here, we replace the blank page we loaded previously.
[email protected]7ccddb8c2009-08-04 17:36:553268
3269 // If we failed to download the alternate error page, fall back to the
3270 // original error page if present. Otherwise, LoadNavigationErrorPage
3271 // will simply display a default error page.
3272 const std::string* html_to_load = &html;
3273 if (html.empty()) {
3274 NavigationState* navigation_state =
[email protected]dd7daa82009-08-10 05:46:453275 NavigationState::FromDataSource(frame->dataSource());
[email protected]7ccddb8c2009-08-04 17:36:553276 html_to_load = &navigation_state->postponed_data();
3277 }
3278 LoadNavigationErrorPage(
3279 frame, WebURLRequest(), original_error, *html_to_load, true);
[email protected]15d79e12009-08-02 19:23:453280}
3281
[email protected]30f75e62009-02-25 22:01:003282void RenderView::OnMoveOrResizeStarted() {
3283 if (webview())
3284 webview()->HideAutofillPopup();
3285}
3286
[email protected]30f75e62009-02-25 22:01:003287void RenderView::OnResize(const gfx::Size& new_size,
3288 const gfx::Rect& resizer_rect) {
3289 if (webview())
3290 webview()->HideAutofillPopup();
3291 RenderWidget::OnResize(new_size, resizer_rect);
3292}
[email protected]0aa477bd2009-03-23 22:21:433293
[email protected]05d478752009-04-08 23:38:163294void RenderView::OnClearFocusedNode() {
3295 if (webview())
[email protected]26aa0482009-09-30 16:55:273296 webview()->clearFocusedNode();
[email protected]05d478752009-04-08 23:38:163297}
3298
[email protected]699ab0d2009-04-23 23:19:143299void RenderView::OnSetBackground(const SkBitmap& background) {
3300 if (webview())
[email protected]b4bb2502009-10-01 22:35:273301 webview()->setIsTransparent(!background.empty());
[email protected]699ab0d2009-04-23 23:19:143302
3303 SetBackground(background);
3304}
3305
[email protected]8c66c5a2009-07-22 17:26:343306void RenderView::OnSetActive(bool active) {
3307 if (webview())
[email protected]b4bb2502009-10-01 22:35:273308 webview()->setIsActive(active);
[email protected]8c66c5a2009-07-22 17:26:343309}
3310
[email protected]309d7a282009-03-24 09:18:273311void RenderView::SendExtensionRequest(const std::string& name,
[email protected]e4dad9fb2009-10-06 18:15:583312 const ListValue& args,
[email protected]c6619182009-05-12 14:59:323313 int request_id,
[email protected]2f25d7b92009-06-10 00:06:473314 bool has_callback) {
[email protected]c6619182009-05-12 14:59:323315 Send(new ViewHostMsg_ExtensionRequest(routing_id_, name, args, request_id,
[email protected]2f25d7b92009-06-10 00:06:473316 has_callback));
[email protected]309d7a282009-03-24 09:18:273317}
3318
[email protected]c6619182009-05-12 14:59:323319void RenderView::OnExtensionResponse(int request_id,
3320 bool success,
3321 const std::string& response,
3322 const std::string& error) {
[email protected]0f6053962009-07-09 19:26:353323 ExtensionProcessBindings::HandleResponse(
3324 request_id, success, response, error);
[email protected]309d7a282009-03-24 09:18:273325}
[email protected]c20210e62009-04-03 21:39:263326
[email protected]078b34612009-09-19 19:31:513327void RenderView::InjectToolstripCSS() {
3328 if (view_type_ != ViewType::EXTENSION_TOOLSTRIP)
3329 return;
3330
3331 static const base::StringPiece toolstrip_css(
3332 ResourceBundle::GetSharedInstance().GetRawDataResource(
3333 IDR_EXTENSION_TOOLSTRIP_CSS));
3334 std::string css = toolstrip_css.as_string();
3335 InsertCSS(L"", css, "ToolstripDefaultCSS");
3336}
3337
[email protected]7120f132009-07-20 21:05:373338void RenderView::OnExtensionMessageInvoke(const std::string& function_name,
3339 const ListValue& args) {
3340 RendererExtensionBindings::Invoke(function_name, args, this);
3341}
3342
[email protected]e7e4f3c2009-04-21 15:24:083343// Dump all load time histograms.
[email protected]c20210e62009-04-03 21:39:263344//
[email protected]7a9b51f2009-06-29 21:28:293345// There are 13 histograms measuring various times.
[email protected]c20210e62009-04-03 21:39:263346// The time points we keep are
3347// request: time document was requested by user
3348// start: time load of document started
[email protected]a2f6bc112009-06-27 16:27:253349// commit: time load of document started
[email protected]7a9b51f2009-06-29 21:28:293350// finish_document: main document loaded, before onload()
[email protected]c20210e62009-04-03 21:39:263351// finish: after onload() and all resources are loaded
[email protected]7a9b51f2009-06-29 21:28:293352// first_paint: first paint performed
3353// first_paint_after_load: first paint performed after load is finished
3354// begin: request if it was user requested, start otherwise
3355//
[email protected]c20210e62009-04-03 21:39:263356// The times that we histogram are
[email protected]a2f6bc112009-06-27 16:27:253357// request->start,
[email protected]7a9b51f2009-06-29 21:28:293358// start->commit,
3359// commit->finish_document,
3360// finish_document->finish,
3361// begin->commit,
3362// begin->finishDoc,
3363// begin->finish,
3364// begin->first_paint,
3365// begin->first_paint_after_load
3366// commit->finishDoc,
3367// commit->first_paint,
3368// commit->first_paint_after_load,
3369// finish->first_paint_after_load,
[email protected]c20210e62009-04-03 21:39:263370//
[email protected]e7e4f3c2009-04-21 15:24:083371// It's possible for the request time not to be set, if a client
3372// redirect had been done (the user never requested the page)
3373// Also, it's possible to load a page without ever laying it out
[email protected]7a9b51f2009-06-29 21:28:293374// so first_paint and first_paint_after_load can be 0.
[email protected]c20210e62009-04-03 21:39:263375void RenderView::DumpLoadHistograms() const {
[email protected]26aa0482009-09-30 16:55:273376 WebFrame* main_frame = webview()->mainFrame();
[email protected]ed3fb032009-06-16 19:50:563377 NavigationState* navigation_state =
[email protected]dd7daa82009-08-10 05:46:453378 NavigationState::FromDataSource(main_frame->dataSource());
[email protected]7a9b51f2009-06-29 21:28:293379 Time finish = navigation_state->finish_load_time();
[email protected]ed3fb032009-06-16 19:50:563380
[email protected]7a9b51f2009-06-29 21:28:293381 // If we've already dumped or we haven't finished loading, do nothing.
3382 if (navigation_state->load_histograms_recorded() || finish.is_null())
3383 return;
[email protected]ed3fb032009-06-16 19:50:563384
[email protected]7a9b51f2009-06-29 21:28:293385 Time request = navigation_state->request_time();
3386 Time start = navigation_state->start_load_time();
3387 Time commit = navigation_state->commit_load_time();
3388 Time finish_doc = navigation_state->finish_document_load_time();
3389 Time first_paint = navigation_state->first_paint_time();
3390 Time first_paint_after_load =
3391 navigation_state->first_paint_after_load_time();
[email protected]c20210e62009-04-03 21:39:263392
[email protected]7a9b51f2009-06-29 21:28:293393 Time begin;
3394 // Client side redirects will have no request time.
3395 if (request.is_null()) {
3396 begin = start;
3397 } else {
3398 begin = request;
3399 UMA_HISTOGRAM_MEDIUM_TIMES("Renderer4.RequestToStart", start - request);
[email protected]e7e4f3c2009-04-21 15:24:083400 }
[email protected]7a9b51f2009-06-29 21:28:293401 UMA_HISTOGRAM_MEDIUM_TIMES("Renderer4.StartToCommit", commit - start);
3402 UMA_HISTOGRAM_MEDIUM_TIMES(
3403 "Renderer4.CommitToFinishDoc", finish_doc - commit);
3404 UMA_HISTOGRAM_MEDIUM_TIMES(
3405 "Renderer4.FinishDocToFinish", finish - finish_doc);
3406
3407 UMA_HISTOGRAM_MEDIUM_TIMES("Renderer4.BeginToCommit", commit - begin);
3408 UMA_HISTOGRAM_MEDIUM_TIMES("Renderer4.BeginToFinishDoc", finish_doc - begin);
[email protected]e695fbd62009-06-30 16:31:543409
3410 static const TimeDelta kBeginToFinishMin(TimeDelta::FromMilliseconds(10));
3411 static const TimeDelta kBeginToFinishMax(TimeDelta::FromMinutes(10));
3412 static const size_t kBeginToFinishBucketCount(100);
3413
3414 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer4.BeginToFinish",
3415 finish - begin, kBeginToFinishMin,
3416 kBeginToFinishMax, kBeginToFinishBucketCount);
[email protected]0a32257a2009-07-09 18:10:413417 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer4.StartToFinish",
3418 finish - start, kBeginToFinishMin,
3419 kBeginToFinishMax, kBeginToFinishBucketCount);
3420 if (!request.is_null())
3421 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer4.RequestToFinish",
3422 finish - request, kBeginToFinishMin,
3423 kBeginToFinishMax, kBeginToFinishBucketCount);
[email protected]e695fbd62009-06-30 16:31:543424
[email protected]36285b52009-06-30 19:10:003425 static bool use_dns_histogram(FieldTrialList::Find("DnsImpact") &&
3426 !FieldTrialList::Find("DnsImpact")->group_name().empty());
[email protected]0a32257a2009-07-09 18:10:413427 if (use_dns_histogram) {
[email protected]36285b52009-06-30 19:10:003428 UMA_HISTOGRAM_CUSTOM_TIMES(
3429 FieldTrial::MakeName("Renderer4.BeginToFinish", "DnsImpact").data(),
3430 finish - begin, kBeginToFinishMin,
3431 kBeginToFinishMax, kBeginToFinishBucketCount);
[email protected]0a32257a2009-07-09 18:10:413432 UMA_HISTOGRAM_CUSTOM_TIMES(
3433 FieldTrial::MakeName("Renderer4.StartToFinish", "DnsImpact").data(),
3434 finish - start, kBeginToFinishMin,
3435 kBeginToFinishMax, kBeginToFinishBucketCount);
3436 if (!request.is_null())
3437 UMA_HISTOGRAM_CUSTOM_TIMES(
3438 FieldTrial::MakeName("Renderer4.RequestToFinish", "DnsImpact").data(),
3439 finish - request, kBeginToFinishMin,
3440 kBeginToFinishMax, kBeginToFinishBucketCount);
3441 }
[email protected]e695fbd62009-06-30 16:31:543442
[email protected]36285b52009-06-30 19:10:003443 static bool use_sdch_histogram(FieldTrialList::Find("GlobalSdch") &&
3444 !FieldTrialList::Find("GlobalSdch")->group_name().empty());
[email protected]0a32257a2009-07-09 18:10:413445 if (use_sdch_histogram) {
[email protected]36285b52009-06-30 19:10:003446 UMA_HISTOGRAM_CUSTOM_TIMES(
3447 FieldTrial::MakeName("Renderer4.BeginToFinish", "GlobalSdch").data(),
3448 finish - begin, kBeginToFinishMin,
3449 kBeginToFinishMax, kBeginToFinishBucketCount);
[email protected]0a32257a2009-07-09 18:10:413450 UMA_HISTOGRAM_CUSTOM_TIMES(
3451 FieldTrial::MakeName("Renderer4.StartToFinish", "GlobalSdch").data(),
3452 finish - start, kBeginToFinishMin,
3453 kBeginToFinishMax, kBeginToFinishBucketCount);
3454 if (!request.is_null())
3455 UMA_HISTOGRAM_CUSTOM_TIMES(
3456 FieldTrial::MakeName("Renderer4.RequestToFinish",
3457 "GlobalSdch").data(),
3458 finish - request, kBeginToFinishMin,
3459 kBeginToFinishMax, kBeginToFinishBucketCount);
3460 }
[email protected]7a9b51f2009-06-29 21:28:293461
[email protected]5fff93f2009-08-02 04:27:343462 static bool use_socket_late_binding_histogram =
3463 FieldTrialList::Find("SocketLateBinding") &&
3464 !FieldTrialList::Find("SocketLateBinding")->group_name().empty();
3465 if (use_socket_late_binding_histogram) {
3466 UMA_HISTOGRAM_CUSTOM_TIMES(
3467 FieldTrial::MakeName("Renderer4.BeginToFinish",
3468 "SocketLateBinding").data(),
3469 finish - begin, kBeginToFinishMin,
3470 kBeginToFinishMax, kBeginToFinishBucketCount);
3471 UMA_HISTOGRAM_CUSTOM_TIMES(
3472 FieldTrial::MakeName("Renderer4.StartToFinish",
3473 "SocketLateBinding").data(),
3474 finish - start, kBeginToFinishMin,
3475 kBeginToFinishMax, kBeginToFinishBucketCount);
3476 if (!request.is_null())
3477 UMA_HISTOGRAM_CUSTOM_TIMES(
3478 FieldTrial::MakeName("Renderer4.RequestToFinish",
3479 "SocketLateBinding").data(),
3480 finish - request, kBeginToFinishMin,
3481 kBeginToFinishMax, kBeginToFinishBucketCount);
3482 }
3483
[email protected]7e05f6c42009-07-11 01:50:483484 static bool use_cache_histogram1(FieldTrialList::Find("CacheSize") &&
3485 !FieldTrialList::Find("CacheSize")->group_name().empty());
3486 if (use_cache_histogram1)
3487 UMA_HISTOGRAM_CUSTOM_TIMES(
3488 FieldTrial::MakeName("Renderer4.StartToFinish", "CacheSize").data(),
3489 finish - start, kBeginToFinishMin,
3490 kBeginToFinishMax, kBeginToFinishBucketCount);
3491
3492 static bool use_cache_histogram2(FieldTrialList::Find("NewEviction") &&
3493 !FieldTrialList::Find("NewEviction")->group_name().empty());
3494 if (use_cache_histogram2)
3495 UMA_HISTOGRAM_CUSTOM_TIMES(
3496 FieldTrial::MakeName("Renderer4.StartToFinish", "NewEviction").data(),
3497 finish - start, kBeginToFinishMin,
3498 kBeginToFinishMax, kBeginToFinishBucketCount);
3499
[email protected]ab0729e2009-09-30 04:42:463500 static bool use_async_tcp(FieldTrialList::Find("AsyncSlowStart") &&
3501 !FieldTrialList::Find("AsyncSlowStart")->group_name().empty());
3502 if (use_async_tcp) {
3503 UMA_HISTOGRAM_CUSTOM_TIMES(
3504 FieldTrial::MakeName("Renderer4.StartToFinish",
3505 "AsyncSlowStart").data(),
3506 finish - start, kBeginToFinishMin,
3507 kBeginToFinishMax, kBeginToFinishBucketCount);
3508 }
3509
[email protected]7a9b51f2009-06-29 21:28:293510 UMA_HISTOGRAM_MEDIUM_TIMES("Renderer4.CommitToFinish", finish - commit);
3511
3512 if (!first_paint.is_null()) {
3513 UMA_HISTOGRAM_MEDIUM_TIMES(
3514 "Renderer4.BeginToFirstPaint", first_paint - begin);
3515 UMA_HISTOGRAM_MEDIUM_TIMES(
3516 "Renderer4.CommitToFirstPaint", first_paint - commit);
[email protected]c20210e62009-04-03 21:39:263517 }
[email protected]7a9b51f2009-06-29 21:28:293518
3519 if (!first_paint_after_load.is_null()) {
3520 UMA_HISTOGRAM_MEDIUM_TIMES(
3521 "Renderer4.BeginToFirstPaintAfterLoad", first_paint_after_load - begin);
3522 UMA_HISTOGRAM_MEDIUM_TIMES(
3523 "Renderer4.CommitToFirstPaintAfterLoad",
3524 first_paint_after_load - commit);
3525 UMA_HISTOGRAM_MEDIUM_TIMES(
3526 "Renderer4.FinishToFirstPaintAfterLoad",
3527 first_paint_after_load - finish);
3528 }
3529
3530 navigation_state->set_load_histograms_recorded(true);
[email protected]c20210e62009-04-03 21:39:263531}
[email protected]e846d0d2009-05-20 00:53:063532
3533void RenderView::FocusAccessibilityObject(
3534 WebCore::AccessibilityObject* acc_obj) {
3535#if defined(OS_WIN)
3536 if (!web_accessibility_manager_.get()) {
3537 web_accessibility_manager_.reset(
3538 webkit_glue::WebAccessibilityManager::Create());
3539 }
3540
3541 // Retrieve the accessibility object id of the AccessibilityObject.
3542 int acc_obj_id = web_accessibility_manager_->FocusAccObj(acc_obj);
3543
3544 // If id is valid, alert the browser side that an accessibility focus change
3545 // occurred.
3546 if (acc_obj_id >= 0)
3547 Send(new ViewHostMsg_AccessibilityFocusChange(routing_id_, acc_obj_id));
3548
3549#else // defined(OS_WIN)
3550 // TODO(port): accessibility not yet implemented
3551 NOTIMPLEMENTED();
3552#endif
3553}
[email protected]daa8c58e2009-06-15 17:21:103554
3555void RenderView::SendPasswordForms(WebFrame* frame) {
[email protected]dd7daa82009-08-10 05:46:453556 WebVector<WebForm> forms;
3557 frame->forms(forms);
[email protected]daa8c58e2009-06-15 17:21:103558
3559 std::vector<PasswordForm> password_forms;
3560 for (size_t i = 0; i < forms.size(); ++i) {
3561 const WebForm& form = forms[i];
3562
3563 // Respect autocomplete=off.
3564 if (form.isAutoCompleteEnabled()) {
3565 scoped_ptr<PasswordForm> password_form(
3566 PasswordFormDomManager::CreatePasswordForm(form));
3567 if (password_form.get())
3568 password_forms.push_back(*password_form);
3569 }
3570 }
3571
3572 if (!password_forms.empty())
3573 Send(new ViewHostMsg_PasswordFormsSeen(routing_id_, password_forms));
3574}
[email protected]0fda7272009-06-26 15:49:333575
3576void RenderView::Print(WebFrame* frame, bool script_initiated) {
3577 DCHECK(frame);
3578 if (print_helper_.get() == NULL) {
3579 print_helper_.reset(new PrintWebViewHelper(this));
3580 }
3581 print_helper_->Print(frame, script_initiated);
3582}
[email protected]446705872009-09-10 07:22:483583
3584void RenderView::OnSetEditCommandsForNextKeyEvent(
3585 const EditCommands& edit_commands) {
3586 edit_commands_ = edit_commands;
3587}
3588
[email protected]912256b32009-09-18 09:47:353589void RenderView::OnExecuteCode(int request_id, const std::string& extension_id,
3590 bool is_js_code,
3591 const std::string& code_string) {
3592 if (is_loading_) {
3593 scoped_refptr<CodeExecutionInfo> info = new CodeExecutionInfo(
3594 request_id, extension_id, is_js_code, code_string);
3595 pending_code_execution_queue_.push(info);
3596 return;
3597 }
[email protected]26aa0482009-09-30 16:55:273598 WebFrame* main_frame = webview() ? webview()->mainFrame() : NULL;
[email protected]912256b32009-09-18 09:47:353599 if (!main_frame) {
3600 Send(new ViewMsg_ExecuteCodeFinished(routing_id_, request_id, false));
3601 return;
3602 }
3603
3604 if (is_js_code) {
3605 std::vector<WebScriptSource> sources;
3606 sources.push_back(
3607 WebScriptSource(WebString::fromUTF8(code_string)));
3608 UserScriptSlave::InsertInitExtensionCode(&sources, extension_id);
3609 main_frame->executeScriptInNewWorld(&sources.front(), sources.size(),
3610 EXTENSION_GROUP_CONTENT_SCRIPTS);
3611 } else {
3612 main_frame->insertStyleText(WebString::fromUTF8(code_string), WebString());
3613 }
3614
3615 Send(new ViewMsg_ExecuteCodeFinished(routing_id_, request_id, true));
3616}
3617
[email protected]446705872009-09-10 07:22:483618void RenderView::DidHandleKeyEvent() {
3619 edit_commands_.clear();
3620}
3621
[email protected]83dde542009-09-11 20:59:553622void RenderView::EnsureDocumentTag() {
3623 // TODO(darin): There's actually no reason for this to be here. We should
3624 // have the browser side manage the document tag.
3625#if defined(OS_MACOSX)
3626 if (!has_document_tag_) {
3627 // Make the call to get the tag.
3628 Send(new ViewHostMsg_GetDocumentTag(routing_id_, &document_tag_));
3629 has_document_tag_ = true;
3630 }
3631#endif
3632}
[email protected]12636df2009-09-28 22:32:213633
3634bool RenderView::SendAndRunNestedMessageLoop(IPC::SyncMessage* message) {
[email protected]8beff0762009-09-29 02:18:303635 PluginChannelHost::Broadcast(
3636 new PluginMsg_SignalModalDialogEvent(host_window_));
[email protected]12636df2009-09-28 22:32:213637
3638 message->EnableMessagePumping(); // Runs a nested message loop.
3639 bool rv = Send(message);
3640
[email protected]8beff0762009-09-29 02:18:303641 PluginChannelHost::Broadcast(
3642 new PluginMsg_ResetModalDialogEvent(host_window_));
[email protected]12636df2009-09-28 22:32:213643
3644 return rv;
3645}