blob: 5000ec10c540012e66b9baf98edd67f267541573 [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"
initial.commit09911bf2008-07-26 23:55:2919#include "base/gfx/png_encoder.h"
[email protected]18bcc3c2009-01-27 21:39:1520#include "base/gfx/native_widget_types.h"
[email protected]8380c092009-06-25 17:45:5121#include "base/process_util.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]e09ba552009-02-05 03:26:2931#include "chrome/common/render_messages.h"
[email protected]9b6f40e2009-06-11 15:54:2632#include "chrome/common/renderer_preferences.h"
initial.commit09911bf2008-07-26 23:55:2933#include "chrome/common/thumbnail_score.h"
[email protected]6de74452009-02-25 18:04:5934#include "chrome/common/url_constants.h"
initial.commit09911bf2008-07-26 23:55:2935#include "chrome/renderer/about_handler.h"
[email protected]5fb88962009-04-16 19:03:2536#include "chrome/renderer/audio_message_filter.h"
[email protected]e4ac5df2009-03-17 15:33:1137#include "chrome/renderer/devtools_agent.h"
38#include "chrome/renderer/devtools_client.h"
[email protected]f816c012009-06-26 21:48:3239#include "chrome/renderer/extensions/event_bindings.h"
[email protected]0f6053962009-07-09 19:26:3540#include "chrome/renderer/extensions/extension_process_bindings.h"
initial.commit09911bf2008-07-26 23:55:2941#include "chrome/renderer/localized_error.h"
[email protected]6f56d482009-02-20 05:02:5642#include "chrome/renderer/media/audio_renderer_impl.h"
[email protected]add51772009-06-11 18:25:1743#include "chrome/renderer/media/buffered_data_source.h"
[email protected]ed3fb032009-06-16 19:50:5644#include "chrome/renderer/navigation_state.h"
[email protected]d81c1e52009-06-03 22:09:5045#include "chrome/renderer/print_web_view_helper.h"
[email protected]39008c02009-02-11 23:59:2546#include "chrome/renderer/render_process.h"
[email protected]0938d3c2009-01-09 20:37:3547#include "chrome/renderer/user_script_slave.h"
initial.commit09911bf2008-07-26 23:55:2948#include "chrome/renderer/visitedlink_slave.h"
[email protected]ba4b17f2009-02-11 21:32:2949#include "chrome/renderer/webplugin_delegate_proxy.h"
[email protected]eb47a132009-03-04 00:39:5650#include "chrome/renderer/webworker_proxy.h"
[email protected]34ac8f32009-02-22 23:03:2751#include "grit/generated_resources.h"
52#include "grit/renderer_resources.h"
[email protected]f11ca0732009-04-11 00:09:3453#include "net/base/data_url.h"
initial.commit09911bf2008-07-26 23:55:2954#include "net/base/escape.h"
55#include "net/base/net_errors.h"
[email protected]c399a8a2008-11-22 19:38:0056#include "skia/ext/bitmap_platform_device.h"
[email protected]83c9e6552008-12-03 16:22:1057#include "skia/ext/image_operations.h"
[email protected]726985e22009-06-18 21:09:2858#include "webkit/api/public/WebDataSource.h"
[email protected]afdcf5c2009-05-10 20:30:4159#include "webkit/api/public/WebDragData.h"
[email protected]daa8c58e2009-06-15 17:21:1060#include "webkit/api/public/WebForm.h"
[email protected]ca948a22009-06-25 19:36:1761#include "webkit/api/public/WebHistoryItem.h"
[email protected]afdcf5c2009-05-10 20:30:4162#include "webkit/api/public/WebPoint.h"
63#include "webkit/api/public/WebRect.h"
64#include "webkit/api/public/WebScriptSource.h"
65#include "webkit/api/public/WebSize.h"
[email protected]726985e22009-06-18 21:09:2866#include "webkit/api/public/WebURL.h"
67#include "webkit/api/public/WebURLError.h"
68#include "webkit/api/public/WebURLRequest.h"
69#include "webkit/api/public/WebURLResponse.h"
70#include "webkit/api/public/WebVector.h"
[email protected]ba4b17f2009-02-11 21:32:2971#include "webkit/default_plugin/default_plugin_shared.h"
[email protected]ca948a22009-06-25 19:36:1772#include "webkit/glue/glue_serialize.h"
initial.commit09911bf2008-07-26 23:55:2973#include "webkit/glue/dom_operations.h"
74#include "webkit/glue/dom_serializer.h"
[email protected]f11ca0732009-04-11 00:09:3475#include "webkit/glue/image_decoder.h"
[email protected]8380c092009-06-25 17:45:5176#include "webkit/glue/media/simple_data_source.h"
initial.commit09911bf2008-07-26 23:55:2977#include "webkit/glue/password_form.h"
[email protected]ba4b17f2009-02-11 21:32:2978#include "webkit/glue/plugins/plugin_list.h"
initial.commit09911bf2008-07-26 23:55:2979#include "webkit/glue/searchable_form_data.h"
[email protected]6a983b42009-03-20 20:12:2580#include "webkit/glue/webaccessibilitymanager_impl.h"
[email protected]611cad42009-03-16 18:51:3481#include "webkit/glue/webdevtoolsagent_delegate.h"
initial.commit09911bf2008-07-26 23:55:2982#include "webkit/glue/webdropdata.h"
initial.commit09911bf2008-07-26 23:55:2983#include "webkit/glue/webframe.h"
initial.commit09911bf2008-07-26 23:55:2984#include "webkit/glue/webkit_glue.h"
[email protected]add51772009-06-11 18:25:1785#include "webkit/glue/webmediaplayer_impl.h"
initial.commit09911bf2008-07-26 23:55:2986#include "webkit/glue/webpreferences.h"
[email protected]b94d3322009-02-12 19:49:0487#include "webkit/glue/webplugin_delegate.h"
[email protected]00d7e622009-04-21 23:06:0588#include "webkit/glue/webtextinput.h"
initial.commit09911bf2008-07-26 23:55:2989#include "webkit/glue/webview.h"
initial.commit09911bf2008-07-26 23:55:2990
[email protected]6c8afae52009-01-22 02:24:5791#if defined(OS_WIN)
92// TODO(port): these files are currently Windows only because they concern:
[email protected]6c8afae52009-01-22 02:24:5793// * theming
[email protected]6c8afae52009-01-22 02:24:5794#include "base/gfx/native_theme.h"
[email protected]6c8afae52009-01-22 02:24:5795#endif
96
[email protected]c20210e62009-04-03 21:39:2697using base::Time;
[email protected]e1acf6f2008-10-27 20:43:3398using base::TimeDelta;
[email protected]daa8c58e2009-06-15 17:21:1099using webkit_glue::AutofillForm;
[email protected]ed3fb032009-06-16 19:50:56100using webkit_glue::PasswordForm;
[email protected]daa8c58e2009-06-15 17:21:10101using webkit_glue::PasswordFormDomManager;
102using webkit_glue::SearchableFormData;
[email protected]0dea3ea2009-03-31 23:30:59103using WebKit::WebConsoleMessage;
[email protected]e6f546c32009-07-01 17:12:55104using WebKit::WebData;
[email protected]726985e22009-06-18 21:09:28105using WebKit::WebDataSource;
[email protected]e80c73b2009-04-07 23:24:58106using WebKit::WebDragData;
[email protected]daa8c58e2009-06-15 17:21:10107using WebKit::WebForm;
[email protected]ca948a22009-06-25 19:36:17108using WebKit::WebHistoryItem;
[email protected]726985e22009-06-18 21:09:28109using WebKit::WebNavigationType;
[email protected]b3f2b912009-04-09 16:18:52110using WebKit::WebRect;
[email protected]4f999132009-03-31 18:08:40111using WebKit::WebScriptSource;
[email protected]8649fb32009-06-26 17:51:02112using WebKit::WebSize;
[email protected]726985e22009-06-18 21:09:28113using WebKit::WebString;
114using WebKit::WebURL;
115using WebKit::WebURLError;
116using WebKit::WebURLRequest;
117using WebKit::WebURLResponse;
[email protected]27ba8532009-04-24 20:22:43118using WebKit::WebWorker;
119using WebKit::WebWorkerClient;
[email protected]726985e22009-06-18 21:09:28120using WebKit::WebVector;
[email protected]e1acf6f2008-10-27 20:43:33121
initial.commit09911bf2008-07-26 23:55:29122//-----------------------------------------------------------------------------
123
124// define to write the time necessary for thumbnail/DOM text retrieval,
125// respectively, into the system debug log
126// #define TIME_BITMAP_RETRIEVAL
127// #define TIME_TEXT_RETRIEVAL
128
129// maximum number of characters in the document to index, any text beyond this
130// point will be clipped
[email protected]6c8afae52009-01-22 02:24:57131static const size_t kMaxIndexChars = 65535;
initial.commit09911bf2008-07-26 23:55:29132
133// Size of the thumbnails that we'll generate
134static const int kThumbnailWidth = 196;
135static const int kThumbnailHeight = 136;
136
137// Delay in milliseconds that we'll wait before capturing the page contents
138// and thumbnail.
139static const int kDelayForCaptureMs = 500;
140
141// Typically, we capture the page data once the page is loaded.
142// Sometimes, the page never finishes to load, preventing the page capture
143// To workaround this problem, we always perform a capture after the following
144// delay.
145static const int kDelayForForcedCaptureMs = 6000;
146
[email protected]81a34412009-01-05 19:17:24147// The default value for RenderView.delay_seconds_for_form_state_sync_, see
148// that variable for more.
149const int kDefaultDelaySecondsForFormStateSync = 5;
initial.commit09911bf2008-07-26 23:55:29150
151// The next available page ID to use. This ensures that the page IDs are
152// globally unique in the renderer.
153static int32 next_page_id_ = 1;
154
[email protected]0aa55312008-10-17 21:53:08155// The maximum number of popups that can be spawned from one page.
156static const int kMaximumNumberOfUnacknowledgedPopups = 25;
157
initial.commit09911bf2008-07-26 23:55:29158static const char* const kUnreachableWebDataURL =
[email protected]60e448982009-05-06 04:21:16159 "chrome://chromewebdata/";
initial.commit09911bf2008-07-26 23:55:29160
[email protected]50b691c2008-10-31 19:08:35161static const char* const kBackForwardNavigationScheme = "history";
162
[email protected]726985e22009-06-18 21:09:28163static void GetRedirectChain(WebDataSource* ds, std::vector<GURL>* result) {
164 WebVector<WebURL> urls;
165 ds->redirectChain(urls);
166 result->reserve(urls.size());
167 for (size_t i = 0; i < urls.size(); ++i)
168 result->push_back(urls[i]);
169}
170
initial.commit09911bf2008-07-26 23:55:29171///////////////////////////////////////////////////////////////////////////////
172
[email protected]81a34412009-01-05 19:17:24173RenderView::RenderView(RenderThreadBase* render_thread)
174 : RenderWidget(render_thread, true),
[email protected]81e63782009-02-27 19:35:09175 enabled_bindings_(0),
[email protected]e75cb49e2009-01-05 23:13:21176 target_url_status_(TARGET_NONE),
[email protected]81a34412009-01-05 19:17:24177 is_loading_(false),
[email protected]e75cb49e2009-01-05 23:13:21178 navigation_gesture_(NavigationGestureUnknown),
[email protected]81a34412009-01-05 19:17:24179 page_id_(-1),
180 last_page_id_sent_to_browser_(-1),
181 last_indexed_page_id_(-1),
[email protected]81a34412009-01-05 19:17:24182 opened_by_user_gesture_(true),
[email protected]bb063b72009-03-27 23:18:50183 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
[email protected]81a34412009-01-05 19:17:24184 first_default_plugin_(NULL),
[email protected]e4ac5df2009-03-17 15:33:11185 devtools_agent_(NULL),
186 devtools_client_(NULL),
[email protected]81a34412009-01-05 19:17:24187 history_back_list_count_(0),
188 history_forward_list_count_(0),
[email protected]81a34412009-01-05 19:17:24189 has_unload_listener_(false),
190 decrement_shared_popup_at_destruction_(false),
[email protected]81a34412009-01-05 19:17:24191 form_field_autofill_request_id_(0),
192 popup_notification_visible_(false),
[email protected]0666aef2009-05-13 19:48:08193 delay_seconds_for_form_state_sync_(kDefaultDelaySecondsForFormStateSync),
194 preferred_width_(0),
[email protected]5c4266922009-07-10 16:41:27195 send_preferred_width_changes_(false),
196 determine_page_text_after_loading_stops_(false) {
initial.commit09911bf2008-07-26 23:55:29197}
198
199RenderView::~RenderView() {
[email protected]0aa55312008-10-17 21:53:08200 if (decrement_shared_popup_at_destruction_)
201 shared_popup_counter_->data--;
202
initial.commit09911bf2008-07-26 23:55:29203 // Clear any back-pointers that might still be held by plugins.
204 PluginDelegateList::iterator it = plugin_delegates_.begin();
205 while (it != plugin_delegates_.end()) {
206 (*it)->DropRenderView();
207 it = plugin_delegates_.erase(it);
208 }
209
[email protected]5fb88962009-04-16 19:03:25210 render_thread_->RemoveFilter(audio_message_filter_);
initial.commit09911bf2008-07-26 23:55:29211}
212
213/*static*/
[email protected]0aa55312008-10-17 21:53:08214RenderView* RenderView::Create(
[email protected]81a34412009-01-05 19:17:24215 RenderThreadBase* render_thread,
[email protected]18bcc3c2009-01-27 21:39:15216 gfx::NativeViewId parent_hwnd,
[email protected]1c4947f2009-01-15 22:25:11217 base::WaitableEvent* modal_dialog_event,
[email protected]0aa55312008-10-17 21:53:08218 int32 opener_id,
[email protected]80d96fa2009-06-10 22:34:51219 const RendererPreferences& renderer_prefs,
[email protected]0aa55312008-10-17 21:53:08220 const WebPreferences& webkit_prefs,
221 SharedRenderViewCounter* counter,
222 int32 routing_id) {
initial.commit09911bf2008-07-26 23:55:29223 DCHECK(routing_id != MSG_ROUTING_NONE);
[email protected]81a34412009-01-05 19:17:24224 scoped_refptr<RenderView> view = new RenderView(render_thread);
initial.commit09911bf2008-07-26 23:55:29225 view->Init(parent_hwnd,
226 modal_dialog_event,
227 opener_id,
[email protected]80d96fa2009-06-10 22:34:51228 renderer_prefs,
initial.commit09911bf2008-07-26 23:55:29229 webkit_prefs,
[email protected]0aa55312008-10-17 21:53:08230 counter,
initial.commit09911bf2008-07-26 23:55:29231 routing_id); // adds reference
232 return view;
233}
234
235/*static*/
236void RenderView::SetNextPageID(int32 next_page_id) {
237 // This method should only be called during process startup, and the given
238 // page id had better not exceed our current next page id!
[email protected]4646f292009-05-20 03:49:05239 DCHECK_EQ(next_page_id_, 1);
initial.commit09911bf2008-07-26 23:55:29240 DCHECK(next_page_id >= next_page_id_);
241 next_page_id_ = next_page_id;
242}
243
244void RenderView::PluginDestroyed(WebPluginDelegateProxy* proxy) {
245 PluginDelegateList::iterator it =
246 std::find(plugin_delegates_.begin(), plugin_delegates_.end(), proxy);
247 DCHECK(it != plugin_delegates_.end());
248 plugin_delegates_.erase(it);
249 // If the plugin is deleted, we need to clear our reference in case user
250 // clicks the info bar to install. Unfortunately we are getting
251 // PluginDestroyed in single process mode. However, that is not a huge
252 // concern.
253 if (proxy == first_default_plugin_)
254 first_default_plugin_ = NULL;
255}
256
[email protected]690a99c2009-01-06 16:48:45257void RenderView::PluginCrashed(const FilePath& plugin_path) {
initial.commit09911bf2008-07-26 23:55:29258 Send(new ViewHostMsg_CrashedPlugin(routing_id_, plugin_path));
259}
260
261
262void RenderView::JSOutOfMemory() {
263 Send(new ViewHostMsg_JSOutOfMemory(routing_id_));
264}
265
[email protected]18bcc3c2009-01-27 21:39:15266void RenderView::Init(gfx::NativeViewId parent_hwnd,
[email protected]1c4947f2009-01-15 22:25:11267 base::WaitableEvent* modal_dialog_event,
initial.commit09911bf2008-07-26 23:55:29268 int32 opener_id,
[email protected]80d96fa2009-06-10 22:34:51269 const RendererPreferences& renderer_prefs,
initial.commit09911bf2008-07-26 23:55:29270 const WebPreferences& webkit_prefs,
[email protected]0aa55312008-10-17 21:53:08271 SharedRenderViewCounter* counter,
initial.commit09911bf2008-07-26 23:55:29272 int32 routing_id) {
273 DCHECK(!webview());
274
275 if (opener_id != MSG_ROUTING_NONE)
276 opener_id_ = opener_id;
277
[email protected]0aa55312008-10-17 21:53:08278 if (counter) {
279 shared_popup_counter_ = counter;
280 shared_popup_counter_->data++;
281 decrement_shared_popup_at_destruction_ = true;
282 } else {
283 shared_popup_counter_ = new SharedRenderViewCounter(0);
284 decrement_shared_popup_at_destruction_ = false;
285 }
286
[email protected]80d96fa2009-06-10 22:34:51287 OnSetRendererPrefs(renderer_prefs);
288
[email protected]58bfc6b2009-06-24 09:45:02289 devtools_agent_.reset(new DevToolsAgent(routing_id, this));
[email protected]9b9d7282009-04-08 14:13:04290
[email protected]c5b3b5e2009-02-13 06:41:11291 webwidget_ = WebView::Create(this, webkit_prefs);
initial.commit09911bf2008-07-26 23:55:29292
[email protected]2e417c82009-04-02 22:30:26293#if defined(OS_LINUX)
294 // We have to enable ourselves as the editor delegate on linux so we can copy
295 // text selections to the X clipboard.
296 webview()->SetUseEditorDelegate(true);
297#endif
298
initial.commit09911bf2008-07-26 23:55:29299 // Don't let WebCore keep a B/F list - we have our own.
300 // We let it keep 1 entry because FrameLoader::goToItem expects an item in the
301 // backForwardList, which is used only in ASSERTs.
302 webview()->SetBackForwardListSize(1);
303
304 routing_id_ = routing_id;
[email protected]81a34412009-01-05 19:17:24305 render_thread_->AddRoute(routing_id_, this);
initial.commit09911bf2008-07-26 23:55:29306 // Take a reference on behalf of the RenderThread. This will be balanced
307 // when we receive ViewMsg_Close.
308 AddRef();
309
310 // If this is a popup, we must wait for the CreatingNew_ACK message before
311 // completing initialization. Otherwise, we can finish it now.
312 if (opener_id == MSG_ROUTING_NONE) {
313 did_show_ = true;
314 CompleteInit(parent_hwnd);
315 }
316
317 host_window_ = parent_hwnd;
[email protected]1c4947f2009-01-15 22:25:11318 modal_dialog_event_.reset(modal_dialog_event);
initial.commit09911bf2008-07-26 23:55:29319
[email protected]58bfc6b2009-06-24 09:45:02320 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
[email protected]81e63782009-02-27 19:35:09321 if (command_line.HasSwitch(switches::kDomAutomationController))
322 enabled_bindings_ |= BindingsPolicy::DOM_AUTOMATION;
initial.commit09911bf2008-07-26 23:55:29323
[email protected]5fb88962009-04-16 19:03:25324 audio_message_filter_ = new AudioMessageFilter(routing_id_);
325 render_thread_->AddFilter(audio_message_filter_);
initial.commit09911bf2008-07-26 23:55:29326}
327
328void RenderView::OnMessageReceived(const IPC::Message& message) {
[email protected]f8b6b6f2009-03-10 16:48:26329 WebFrame* main_frame = webview() ? webview()->GetMainFrame() : NULL;
[email protected]ef916272009-07-08 21:40:55330 child_process_logging::ScopedActiveURLSetter url_setter(
[email protected]f8b6b6f2009-03-10 16:48:26331 main_frame ? main_frame->GetURL() : GURL());
[email protected]f8b6b6f2009-03-10 16:48:26332
[email protected]b2abac72009-02-26 12:39:28333 // If this is developer tools renderer intercept tools messages first.
[email protected]e4ac5df2009-03-17 15:33:11334 if (devtools_client_.get() && devtools_client_->OnMessageReceived(message))
[email protected]b2abac72009-02-26 12:39:28335 return;
[email protected]b4b967e2009-04-22 11:33:05336 if (devtools_agent_.get() && devtools_agent_->OnMessageReceived(message))
337 return;
[email protected]b2abac72009-02-26 12:39:28338
initial.commit09911bf2008-07-26 23:55:29339 IPC_BEGIN_MESSAGE_MAP(RenderView, message)
initial.commit09911bf2008-07-26 23:55:29340 IPC_MESSAGE_HANDLER(ViewMsg_CaptureThumbnail, SendThumbnail)
initial.commit09911bf2008-07-26 23:55:29341 IPC_MESSAGE_HANDLER(ViewMsg_PrintPages, OnPrintPages)
[email protected]82270452009-06-19 15:58:01342 IPC_MESSAGE_HANDLER(ViewMsg_PrintingDone, OnPrintingDone)
initial.commit09911bf2008-07-26 23:55:29343 IPC_MESSAGE_HANDLER(ViewMsg_Navigate, OnNavigate)
344 IPC_MESSAGE_HANDLER(ViewMsg_Stop, OnStop)
345 IPC_MESSAGE_HANDLER(ViewMsg_LoadAlternateHTMLText, OnLoadAlternateHTMLText)
346 IPC_MESSAGE_HANDLER(ViewMsg_StopFinding, OnStopFinding)
347 IPC_MESSAGE_HANDLER(ViewMsg_Undo, OnUndo)
348 IPC_MESSAGE_HANDLER(ViewMsg_Redo, OnRedo)
349 IPC_MESSAGE_HANDLER(ViewMsg_Cut, OnCut)
350 IPC_MESSAGE_HANDLER(ViewMsg_Copy, OnCopy)
351 IPC_MESSAGE_HANDLER(ViewMsg_Paste, OnPaste)
352 IPC_MESSAGE_HANDLER(ViewMsg_Replace, OnReplace)
[email protected]bbbd545c2008-12-15 20:18:04353 IPC_MESSAGE_HANDLER(ViewMsg_ToggleSpellCheck, OnToggleSpellCheck)
initial.commit09911bf2008-07-26 23:55:29354 IPC_MESSAGE_HANDLER(ViewMsg_Delete, OnDelete)
355 IPC_MESSAGE_HANDLER(ViewMsg_SelectAll, OnSelectAll)
356 IPC_MESSAGE_HANDLER(ViewMsg_CopyImageAt, OnCopyImageAt)
[email protected]4b59ae602009-06-23 20:58:15357 IPC_MESSAGE_HANDLER(ViewMsg_ExecuteEditCommand, OnExecuteEditCommand)
initial.commit09911bf2008-07-26 23:55:29358 IPC_MESSAGE_HANDLER(ViewMsg_Find, OnFind)
[email protected]5c4266922009-07-10 16:41:27359 IPC_MESSAGE_HANDLER(ViewMsg_DeterminePageText, OnDeterminePageText)
[email protected]630e26b2008-10-14 22:55:17360 IPC_MESSAGE_HANDLER(ViewMsg_Zoom, OnZoom)
[email protected]ea8c7452009-04-02 20:47:06361 IPC_MESSAGE_HANDLER(ViewMsg_InsertText, OnInsertText)
initial.commit09911bf2008-07-26 23:55:29362 IPC_MESSAGE_HANDLER(ViewMsg_SetPageEncoding, OnSetPageEncoding)
[email protected]b2abac72009-02-26 12:39:28363 IPC_MESSAGE_HANDLER(ViewMsg_SetupDevToolsClient, OnSetupDevToolsClient)
[email protected]bf5c2ff392009-07-08 16:24:33364 IPC_MESSAGE_HANDLER(ViewMsg_DownloadFavIcon, OnDownloadFavIcon)
initial.commit09911bf2008-07-26 23:55:29365 IPC_MESSAGE_HANDLER(ViewMsg_ScriptEvalRequest, OnScriptEvalRequest)
[email protected]1810e132009-03-24 23:35:48366 IPC_MESSAGE_HANDLER(ViewMsg_CSSInsertRequest, OnCSSInsertRequest)
initial.commit09911bf2008-07-26 23:55:29367 IPC_MESSAGE_HANDLER(ViewMsg_AddMessageToConsole, OnAddMessageToConsole)
initial.commit09911bf2008-07-26 23:55:29368 IPC_MESSAGE_HANDLER(ViewMsg_ReservePageIDRange, OnReservePageIDRange)
369 IPC_MESSAGE_HANDLER(ViewMsg_UploadFile, OnUploadFileRequest)
370 IPC_MESSAGE_HANDLER(ViewMsg_FormFill, OnFormFill)
371 IPC_MESSAGE_HANDLER(ViewMsg_FillPasswordForm, OnFillPasswordForm)
372 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragEnter, OnDragTargetDragEnter)
373 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragOver, OnDragTargetDragOver)
374 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragLeave, OnDragTargetDragLeave)
375 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDrop, OnDragTargetDrop)
[email protected]18cb2572008-08-21 20:34:45376 IPC_MESSAGE_HANDLER(ViewMsg_AllowBindings, OnAllowBindings)
initial.commit09911bf2008-07-26 23:55:29377 IPC_MESSAGE_HANDLER(ViewMsg_SetDOMUIProperty, OnSetDOMUIProperty)
[email protected]266eb6f2008-09-30 23:56:50378 IPC_MESSAGE_HANDLER(ViewMsg_DragSourceEndedOrMoved,
379 OnDragSourceEndedOrMoved)
initial.commit09911bf2008-07-26 23:55:29380 IPC_MESSAGE_HANDLER(ViewMsg_DragSourceSystemDragEnded,
381 OnDragSourceSystemDragEnded)
382 IPC_MESSAGE_HANDLER(ViewMsg_SetInitialFocus, OnSetInitialFocus)
383 IPC_MESSAGE_HANDLER(ViewMsg_FindReplyACK, OnFindReplyAck)
384 IPC_MESSAGE_HANDLER(ViewMsg_UpdateTargetURL_ACK, OnUpdateTargetURLAck)
385 IPC_MESSAGE_HANDLER(ViewMsg_UpdateWebPreferences, OnUpdateWebPreferences)
386 IPC_MESSAGE_HANDLER(ViewMsg_SetAltErrorPageURL, OnSetAltErrorPageURL)
387 IPC_MESSAGE_HANDLER(ViewMsg_InstallMissingPlugin, OnInstallMissingPlugin)
388 IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse)
389 IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode, OnEnableViewSourceMode)
390 IPC_MESSAGE_HANDLER(ViewMsg_UpdateBackForwardListCount,
391 OnUpdateBackForwardListCount)
392 IPC_MESSAGE_HANDLER(ViewMsg_GetAllSavableResourceLinksForCurrentPage,
393 OnGetAllSavableResourceLinksForCurrentPage)
[email protected]f09c7182009-03-10 12:54:04394 IPC_MESSAGE_HANDLER(
395 ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks,
396 OnGetSerializedHtmlDataForCurrentPageWithLocalLinks)
initial.commit09911bf2008-07-26 23:55:29397 IPC_MESSAGE_HANDLER(ViewMsg_GetApplicationInfo, OnGetApplicationInfo)
[email protected]266eb6f2008-09-30 23:56:50398 IPC_MESSAGE_HANDLER(ViewMsg_GetAccessibilityInfo, OnGetAccessibilityInfo)
399 IPC_MESSAGE_HANDLER(ViewMsg_ClearAccessibilityInfo,
400 OnClearAccessibilityInfo)
initial.commit09911bf2008-07-26 23:55:29401 IPC_MESSAGE_HANDLER(ViewMsg_ShouldClose, OnMsgShouldClose)
402 IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage)
403 IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged)
[email protected]18cb2572008-08-21 20:34:45404 IPC_MESSAGE_HANDLER(ViewMsg_HandleMessageFromExternalHost,
405 OnMessageFromExternalHost)
[email protected]0aa55312008-10-17 21:53:08406 IPC_MESSAGE_HANDLER(ViewMsg_DisassociateFromPopupCount,
407 OnDisassociateFromPopupCount)
[email protected]0ebf3872008-11-07 21:35:03408 IPC_MESSAGE_HANDLER(ViewMsg_AutofillSuggestions,
409 OnReceivedAutofillSuggestions)
[email protected]2c4410d2009-05-06 23:46:22410 IPC_MESSAGE_HANDLER(ViewMsg_PopupNotificationVisibilityChanged,
411 OnPopupNotificationVisibilityChanged)
[email protected]30f75e62009-02-25 22:01:00412 IPC_MESSAGE_HANDLER(ViewMsg_MoveOrResizeStarted, OnMoveOrResizeStarted)
[email protected]309d7a282009-03-24 09:18:27413 IPC_MESSAGE_HANDLER(ViewMsg_ExtensionResponse, OnExtensionResponse)
[email protected]05d478752009-04-08 23:38:16414 IPC_MESSAGE_HANDLER(ViewMsg_ClearFocusedNode, OnClearFocusedNode)
[email protected]699ab0d2009-04-23 23:19:14415 IPC_MESSAGE_HANDLER(ViewMsg_SetBackground, OnSetBackground)
[email protected]0666aef2009-05-13 19:48:08416 IPC_MESSAGE_HANDLER(ViewMsg_EnableIntrinsicWidthChangedMode,
417 OnEnableIntrinsicWidthChangedMode)
[email protected]80d96fa2009-06-10 22:34:51418 IPC_MESSAGE_HANDLER(ViewMsg_SetRendererPrefs, OnSetRendererPrefs)
[email protected]634a6f92008-12-01 21:39:31419
initial.commit09911bf2008-07-26 23:55:29420 // Have the super handle all other messages.
421 IPC_MESSAGE_UNHANDLED(RenderWidget::OnMessageReceived(message))
422 IPC_END_MESSAGE_MAP()
423}
424
initial.commit09911bf2008-07-26 23:55:29425void RenderView::SendThumbnail() {
426 WebFrame* main_frame = webview()->GetMainFrame();
427 if (!main_frame)
428 return;
429
430 // get the URL for this page
431 GURL url(main_frame->GetURL());
432 if (url.is_empty())
433 return;
434
435 if (size_.IsEmpty())
436 return; // Don't create an empty thumbnail!
437
438 ThumbnailScore score;
439 SkBitmap thumbnail;
[email protected]8649fb32009-06-26 17:51:02440 if (!CaptureThumbnail(webview(), kThumbnailWidth, kThumbnailHeight,
[email protected]b6e4bec2008-11-12 01:17:15441 &thumbnail, &score))
442 return;
443
initial.commit09911bf2008-07-26 23:55:29444 // send the thumbnail message to the browser process
[email protected]674741932009-02-04 23:44:46445 Send(new ViewHostMsg_Thumbnail(routing_id_, url, score, thumbnail));
initial.commit09911bf2008-07-26 23:55:29446}
447
[email protected]068637222009-01-29 16:58:07448void RenderView::OnPrintPages() {
initial.commit09911bf2008-07-26 23:55:29449 DCHECK(webview());
[email protected]0fda7272009-06-26 15:49:33450 if (webview())
451 Print(webview()->GetMainFrame(), false);
initial.commit09911bf2008-07-26 23:55:29452}
453
[email protected]82270452009-06-19 15:58:01454void RenderView::OnPrintingDone(int document_cookie, bool success) {
455 // Ignoring document cookie here since only one print job can be outstanding
456 // per renderer and document_cookie is 0 when printing is successful.
457 DCHECK(print_helper_.get());
458 if (print_helper_.get() != NULL) {
459 print_helper_->DidFinishPrinting(success);
460 }
461}
462
initial.commit09911bf2008-07-26 23:55:29463void RenderView::CapturePageInfo(int load_id, bool preliminary_capture) {
464 if (load_id != page_id_)
465 return; // this capture call is no longer relevant due to navigation
466 if (load_id == last_indexed_page_id_)
467 return; // we already indexed this page
468
469 if (!webview())
470 return;
471
472 WebFrame* main_frame = webview()->GetMainFrame();
473 if (!main_frame)
474 return;
475
476 // Don't index/capture pages that are in view source mode.
477 if (main_frame->GetInViewSourceMode())
478 return;
479
480 // Don't index/capture pages that failed to load. This only checks the top
481 // level frame so the thumbnail may contain a frame that failed to load.
482 WebDataSource* ds = main_frame->GetDataSource();
[email protected]726985e22009-06-18 21:09:28483 if (ds && ds->hasUnreachableURL())
initial.commit09911bf2008-07-26 23:55:29484 return;
485
486 if (!preliminary_capture)
487 last_indexed_page_id_ = load_id;
488
489 // get the URL for this page
490 GURL url(main_frame->GetURL());
491 if (url.is_empty())
492 return;
493
494 // full text
495 std::wstring contents;
496 CaptureText(main_frame, &contents);
497 if (contents.size()) {
498 // Send the text to the browser for indexing.
499 Send(new ViewHostMsg_PageContents(url, load_id, contents));
500 }
501
[email protected]5c4266922009-07-10 16:41:27502 // Send over text content of this page to the browser.
503 if (determine_page_text_after_loading_stops_) {
504 determine_page_text_after_loading_stops_ = false;
505 Send(new ViewMsg_DeterminePageText_Reply(routing_id_, contents));
506 }
507
initial.commit09911bf2008-07-26 23:55:29508 // thumbnail
509 SendThumbnail();
510}
511
512void RenderView::CaptureText(WebFrame* frame, std::wstring* contents) {
513 contents->clear();
514 if (!frame)
515 return;
516
[email protected]0faf0bd92008-09-09 20:53:27517 // Don't index any https pages. People generally don't want their bank
518 // accounts, etc. indexed on their computer, especially since some of these
519 // things are not marked cachable.
520 // TODO(brettw) we may want to consider more elaborate heuristics such as
521 // the cachability of the page. We may also want to consider subframes (this
522 // test will still index subframes if the subframe is SSL).
523 if (frame->GetURL().SchemeIsSecure())
524 return;
525
initial.commit09911bf2008-07-26 23:55:29526#ifdef TIME_TEXT_RETRIEVAL
527 double begin = time_util::GetHighResolutionTimeNow();
528#endif
529
530 // get the contents of the frame
531 frame->GetContentAsPlainText(kMaxIndexChars, contents);
532
533#ifdef TIME_TEXT_RETRIEVAL
534 double end = time_util::GetHighResolutionTimeNow();
535 char buf[128];
536 sprintf_s(buf, "%d chars retrieved for indexing in %gms\n",
537 contents.size(), (end - begin)*1000);
538 OutputDebugStringA(buf);
539#endif
540
541 // When the contents are clipped to the maximum, we don't want to have a
542 // partial word indexed at the end that might have been clipped. Therefore,
543 // terminate the string at the last space to ensure no words are clipped.
544 if (contents->size() == kMaxIndexChars) {
545 size_t last_space_index = contents->find_last_of(kWhitespaceWide);
546 if (last_space_index == std::wstring::npos)
547 return; // don't index if we got a huge block of text with no spaces
548 contents->resize(last_space_index);
549 }
550}
551
[email protected]8649fb32009-06-26 17:51:02552bool RenderView::CaptureThumbnail(WebView* view,
initial.commit09911bf2008-07-26 23:55:29553 int w,
554 int h,
555 SkBitmap* thumbnail,
556 ThumbnailScore* score) {
557#ifdef TIME_BITMAP_RETRIEVAL
558 double begin = time_util::GetHighResolutionTimeNow();
559#endif
560
[email protected]8649fb32009-06-26 17:51:02561 view->Layout();
562 const WebSize& size = view->GetSize();
[email protected]b6e4bec2008-11-12 01:17:15563
[email protected]8649fb32009-06-26 17:51:02564 skia::PlatformCanvas canvas;
565 if (!canvas.initialize(size.width, size.height, true))
566 return false;
567 view->Paint(&canvas, WebRect(0, 0, size.width, size.height));
568
569 skia::BitmapPlatformDevice& device =
570 static_cast<skia::BitmapPlatformDevice&>(canvas.getTopPlatformDevice());
571
572 const SkBitmap& src_bmp = device.accessBitmap(false);
initial.commit09911bf2008-07-26 23:55:29573
574 SkRect dest_rect;
575 dest_rect.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
576 float dest_aspect = dest_rect.width() / dest_rect.height();
577
578 // Get the src rect so that we can preserve the aspect ratio while filling
579 // the destination.
580 SkIRect src_rect;
581 if (src_bmp.width() < dest_rect.width() ||
582 src_bmp.height() < dest_rect.height()) {
583 // Source image is smaller: we clip the part of source image within the
584 // dest rect, and then stretch it to fill the dest rect. We don't respect
585 // the aspect ratio in this case.
586 src_rect.set(0, 0, static_cast<S16CPU>(dest_rect.width()),
587 static_cast<S16CPU>(dest_rect.height()));
588 score->good_clipping = false;
589 } else {
590 float src_aspect = static_cast<float>(src_bmp.width()) / src_bmp.height();
591 if (src_aspect > dest_aspect) {
592 // Wider than tall, clip horizontally: we center the smaller thumbnail in
593 // the wider screen.
594 S16CPU new_width = static_cast<S16CPU>(src_bmp.height() * dest_aspect);
595 S16CPU x_offset = (src_bmp.width() - new_width) / 2;
596 src_rect.set(x_offset, 0, new_width + x_offset, src_bmp.height());
597 score->good_clipping = false;
598 } else {
599 src_rect.set(0, 0, src_bmp.width(),
600 static_cast<S16CPU>(src_bmp.width() / dest_aspect));
601 score->good_clipping = true;
602 }
603 }
604
[email protected]8649fb32009-06-26 17:51:02605 score->at_top = (view->GetMainFrame()->ScrollOffset().height == 0);
initial.commit09911bf2008-07-26 23:55:29606
607 SkBitmap subset;
[email protected]8649fb32009-06-26 17:51:02608 device.accessBitmap(false).extractSubset(&subset, src_rect);
initial.commit09911bf2008-07-26 23:55:29609
610 // Resample the subset that we want to get it the right size.
[email protected]465b34b72008-12-12 20:19:14611 *thumbnail = skia::ImageOperations::Resize(
612 subset, skia::ImageOperations::RESIZE_LANCZOS3, w, h);
initial.commit09911bf2008-07-26 23:55:29613
614 score->boring_score = CalculateBoringScore(thumbnail);
615
616#ifdef TIME_BITMAP_RETRIEVAL
617 double end = time_util::GetHighResolutionTimeNow();
618 char buf[128];
619 sprintf_s(buf, "thumbnail in %gms\n", (end - begin) * 1000);
620 OutputDebugStringA(buf);
621#endif
[email protected]b6e4bec2008-11-12 01:17:15622 return true;
initial.commit09911bf2008-07-26 23:55:29623}
624
625double RenderView::CalculateBoringScore(SkBitmap* bitmap) {
626 int histogram[256] = {0};
627 color_utils::BuildLumaHistogram(bitmap, histogram);
628
629 int color_count = *std::max_element(histogram, histogram + 256);
630 int pixel_count = bitmap->width() * bitmap->height();
631 return static_cast<double>(color_count) / pixel_count;
632}
633
634void RenderView::OnNavigate(const ViewMsg_Navigate_Params& params) {
635 if (!webview())
636 return;
637
[email protected]ef916272009-07-08 21:40:55638 child_process_logging::ScopedActiveURLSetter url_setter(params.url);
[email protected]f8b6b6f2009-03-10 16:48:26639
initial.commit09911bf2008-07-26 23:55:29640 AboutHandler::MaybeHandle(params.url);
641
642 bool is_reload = params.reload;
643
644 WebFrame* main_frame = webview()->GetMainFrame();
[email protected]ca948a22009-06-25 19:36:17645 if (is_reload && main_frame->GetCurrentHistoryItem().isNull()) {
initial.commit09911bf2008-07-26 23:55:29646 // We cannot reload if we do not have any history state. This happens, for
647 // example, when recovering from a crash. Our workaround here is a bit of
648 // a hack since it means that reload after a crashed tab does not cause an
649 // end-to-end cache validation.
650 is_reload = false;
651 }
652
[email protected]77f17a82009-05-21 04:42:54653 // A navigation resulting from loading a javascript URL should not be treated
654 // as a browser initiated event. Instead, we want it to look as if the page
655 // initiated any load resulting from JS execution.
656 if (!params.url.SchemeIs(chrome::kJavaScriptScheme)) {
[email protected]daa8c58e2009-06-15 17:21:10657 pending_navigation_state_.reset(NavigationState::CreateBrowserInitiated(
[email protected]77f17a82009-05-21 04:42:54658 params.page_id, params.transition, params.request_time));
659 }
initial.commit09911bf2008-07-26 23:55:29660
[email protected]04d3c6e2009-05-22 17:00:13661 // If we are reloading, then WebKit will use the history state of the current
662 // page, so we should just ignore any given history state. Otherwise, if we
663 // have history state, then we need to navigate to it, which corresponds to a
664 // back/forward navigation event.
[email protected]e6f546c32009-07-01 17:12:55665 if (is_reload) {
666 main_frame->Reload();
667 } else if (!params.state.empty()) {
[email protected]04d3c6e2009-05-22 17:00:13668 // We must know the page ID of the page we are navigating back to.
[email protected]f929f2f22009-06-12 16:56:58669 DCHECK_NE(params.page_id, -1);
[email protected]ca948a22009-06-25 19:36:17670 main_frame->LoadHistoryItem(
671 webkit_glue::HistoryItemFromString(params.state));
[email protected]04d3c6e2009-05-22 17:00:13672 } else {
673 // Navigate to the given URL.
[email protected]726985e22009-06-18 21:09:28674 WebURLRequest request(params.url);
initial.commit09911bf2008-07-26 23:55:29675
[email protected]e6f546c32009-07-01 17:12:55676 // A session history navigation should have been accompanied by state.
677 DCHECK_EQ(params.page_id, -1);
[email protected]04d3c6e2009-05-22 17:00:13678
[email protected]e6f546c32009-07-01 17:12:55679 if (main_frame->GetInViewSourceMode())
680 request.setCachePolicy(WebURLRequest::ReturnCacheDataElseLoad);
[email protected]04d3c6e2009-05-22 17:00:13681
[email protected]726985e22009-06-18 21:09:28682 if (params.referrer.is_valid()) {
683 request.setHTTPHeaderField(WebString::fromUTF8("Referer"),
684 WebString::fromUTF8(params.referrer.spec()));
685 }
[email protected]04d3c6e2009-05-22 17:00:13686
[email protected]726985e22009-06-18 21:09:28687 main_frame->LoadRequest(request);
[email protected]c0588052008-10-27 23:01:50688 }
689
[email protected]77f17a82009-05-21 04:42:54690 // In case LoadRequest failed before DidCreateDataSource was called.
691 pending_navigation_state_.reset();
initial.commit09911bf2008-07-26 23:55:29692}
693
694// Stop loading the current page
695void RenderView::OnStop() {
696 if (webview())
697 webview()->StopLoading();
698}
699
[email protected]e6f546c32009-07-01 17:12:55700void RenderView::OnLoadAlternateHTMLText(const std::string& html,
initial.commit09911bf2008-07-26 23:55:29701 bool new_navigation,
702 const GURL& display_url,
703 const std::string& security_info) {
704 if (!webview())
705 return;
706
[email protected]e6f546c32009-07-01 17:12:55707 pending_navigation_state_.reset(NavigationState::CreateBrowserInitiated(
708 new_navigation ? -1 : page_id_, PageTransition::LINK, Time::Now()));
709 pending_navigation_state_->set_security_info(security_info);
initial.commit09911bf2008-07-26 23:55:29710
[email protected]e6f546c32009-07-01 17:12:55711 webview()->GetMainFrame()->LoadHTMLString(html,
712 GURL(kUnreachableWebDataURL),
713 display_url,
714 !new_navigation);
715
716 pending_navigation_state_.reset();
initial.commit09911bf2008-07-26 23:55:29717}
718
719void RenderView::OnCopyImageAt(int x, int y) {
720 webview()->CopyImageAt(x, y);
721}
722
[email protected]68b1e922009-06-23 16:00:25723void RenderView::OnExecuteEditCommand(const std::string& name,
724 const std::string& value) {
725 if (!webview() || !webview()->GetFocusedFrame())
726 return;
727
[email protected]4b59ae602009-06-23 20:58:15728 webview()->GetFocusedFrame()->ExecuteEditCommandByName(name, value);
[email protected]68b1e922009-06-23 16:00:25729}
730
[email protected]b2abac72009-02-26 12:39:28731void RenderView::OnSetupDevToolsClient() {
[email protected]e4ac5df2009-03-17 15:33:11732 DCHECK(!devtools_client_.get());
733 devtools_client_.reset(new DevToolsClient(this));
[email protected]b2abac72009-02-26 12:39:28734}
735
initial.commit09911bf2008-07-26 23:55:29736void RenderView::OnStopFinding(bool clear_selection) {
737 WebView* view = webview();
738 if (!view)
739 return;
740
741 if (clear_selection)
742 view->GetFocusedFrame()->ClearSelection();
743
744 WebFrame* frame = view->GetMainFrame();
745 while (frame) {
[email protected]65134c432008-09-26 21:47:20746 frame->StopFinding(clear_selection);
initial.commit09911bf2008-07-26 23:55:29747 frame = view->GetNextFrameAfter(frame, false);
748 }
749}
750
751void RenderView::OnFindReplyAck() {
752 // Check if there is any queued up request waiting to be sent.
753 if (queued_find_reply_message_.get()) {
754 // Send the search result over to the browser process.
755 Send(queued_find_reply_message_.get());
756 queued_find_reply_message_.release();
757 }
758}
759
760void RenderView::OnUpdateTargetURLAck() {
761 // Check if there is a targeturl waiting to be sent.
762 if (target_url_status_ == TARGET_PENDING) {
763 Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_,
764 pending_target_url_));
765 }
766
767 target_url_status_ = TARGET_NONE;
768}
769
770void RenderView::OnUndo() {
771 if (!webview())
772 return;
773
774 webview()->GetFocusedFrame()->Undo();
775}
776
777void RenderView::OnRedo() {
778 if (!webview())
779 return;
780
781 webview()->GetFocusedFrame()->Redo();
782}
783
784void RenderView::OnCut() {
785 if (!webview())
786 return;
787
788 webview()->GetFocusedFrame()->Cut();
789}
790
791void RenderView::OnCopy() {
792 if (!webview())
793 return;
794
795 webview()->GetFocusedFrame()->Copy();
796}
797
798void RenderView::OnPaste() {
799 if (!webview())
800 return;
801
802 webview()->GetFocusedFrame()->Paste();
803}
804
805void RenderView::OnReplace(const std::wstring& text) {
806 if (!webview())
807 return;
808
809 webview()->GetFocusedFrame()->Replace(text);
810}
811
[email protected]bbbd545c2008-12-15 20:18:04812void RenderView::OnToggleSpellCheck() {
813 if (!webview())
814 return;
815
816 webview()->GetFocusedFrame()->ToggleSpellCheck();
817}
818
initial.commit09911bf2008-07-26 23:55:29819void RenderView::OnDelete() {
820 if (!webview())
821 return;
822
823 webview()->GetFocusedFrame()->Delete();
824}
825
826void RenderView::OnSelectAll() {
827 if (!webview())
828 return;
829
830 webview()->GetFocusedFrame()->SelectAll();
831}
832
833void RenderView::OnSetInitialFocus(bool reverse) {
834 if (!webview())
835 return;
836 webview()->SetInitialFocus(reverse);
837}
838
839///////////////////////////////////////////////////////////////////////////////
840
841// Tell the embedding application that the URL of the active page has changed
842void RenderView::UpdateURL(WebFrame* frame) {
843 WebDataSource* ds = frame->GetDataSource();
844 DCHECK(ds);
845
[email protected]726985e22009-06-18 21:09:28846 const WebURLRequest& request = ds->request();
847 const WebURLRequest& original_request = ds->originalRequest();
848 const WebURLResponse& response = ds->response();
initial.commit09911bf2008-07-26 23:55:29849
[email protected]daa8c58e2009-06-15 17:21:10850 NavigationState* navigation_state = NavigationState::FromDataSource(ds);
851 DCHECK(navigation_state);
initial.commit09911bf2008-07-26 23:55:29852
853 ViewHostMsg_FrameNavigate_Params params;
[email protected]726985e22009-06-18 21:09:28854 params.http_status_code = response.httpStatusCode();
initial.commit09911bf2008-07-26 23:55:29855 params.is_post = false;
856 params.page_id = page_id_;
[email protected]726985e22009-06-18 21:09:28857 params.is_content_filtered = response.isContentFiltered();
[email protected]e6f546c32009-07-01 17:12:55858 if (!navigation_state->security_info().empty()) {
initial.commit09911bf2008-07-26 23:55:29859 // SSL state specified in the request takes precedence over the one in the
860 // response.
861 // So far this is only intended for error pages that are not expected to be
862 // over ssl, so we should not get any clash.
[email protected]726985e22009-06-18 21:09:28863 DCHECK(response.securityInfo().isEmpty());
[email protected]e6f546c32009-07-01 17:12:55864 params.security_info = navigation_state->security_info();
initial.commit09911bf2008-07-26 23:55:29865 } else {
[email protected]726985e22009-06-18 21:09:28866 params.security_info = response.securityInfo();
initial.commit09911bf2008-07-26 23:55:29867 }
868
869 // Set the URL to be displayed in the browser UI to the user.
[email protected]726985e22009-06-18 21:09:28870 if (ds->hasUnreachableURL()) {
871 params.url = ds->unreachableURL();
initial.commit09911bf2008-07-26 23:55:29872 } else {
[email protected]726985e22009-06-18 21:09:28873 params.url = request.url();
initial.commit09911bf2008-07-26 23:55:29874 }
875
[email protected]726985e22009-06-18 21:09:28876 GetRedirectChain(ds, &params.redirects);
877 params.should_update_history = !ds->hasUnreachableURL();
initial.commit09911bf2008-07-26 23:55:29878
879 const SearchableFormData* searchable_form_data =
[email protected]daa8c58e2009-06-15 17:21:10880 navigation_state->searchable_form_data();
initial.commit09911bf2008-07-26 23:55:29881 if (searchable_form_data) {
882 params.searchable_form_url = searchable_form_data->url();
883 params.searchable_form_element_name = searchable_form_data->element_name();
884 params.searchable_form_encoding = searchable_form_data->encoding();
885 }
886
887 const PasswordForm* password_form_data =
[email protected]daa8c58e2009-06-15 17:21:10888 navigation_state->password_form_data();
initial.commit09911bf2008-07-26 23:55:29889 if (password_form_data)
890 params.password_form = *password_form_data;
891
892 params.gesture = navigation_gesture_;
893 navigation_gesture_ = NavigationGestureUnknown;
894
[email protected]77f17a82009-05-21 04:42:54895 if (!frame->GetParent()) {
initial.commit09911bf2008-07-26 23:55:29896 // Top-level navigation.
897
898 // Update contents MIME type for main frame.
[email protected]726985e22009-06-18 21:09:28899 params.contents_mime_type = UTF16ToUTF8(ds->response().mimeType());
initial.commit09911bf2008-07-26 23:55:29900
[email protected]daa8c58e2009-06-15 17:21:10901 params.transition = navigation_state->transition_type();
initial.commit09911bf2008-07-26 23:55:29902 if (!PageTransition::IsMainFrame(params.transition)) {
903 // If the main frame does a load, it should not be reported as a subframe
904 // navigation. This can occur in the following case:
905 // 1. You're on a site with frames.
906 // 2. You do a subframe navigation. This is stored with transition type
907 // MANUAL_SUBFRAME.
908 // 3. You navigate to some non-frame site, say, google.com.
909 // 4. You navigate back to the page from step 2. Since it was initially
910 // MANUAL_SUBFRAME, it will be that same transition type here.
911 // We don't want that, because any navigation that changes the toplevel
912 // frame should be tracked as a toplevel navigation (this allows us to
913 // update the URL bar, etc).
914 params.transition = PageTransition::LINK;
915 }
916
initial.commit09911bf2008-07-26 23:55:29917 // If we have a valid consumed client redirect source,
918 // the page contained a client redirect (meta refresh, document.loc...),
919 // so we set the referrer and transition to match.
920 if (completed_client_redirect_src_.is_valid()) {
[email protected]77e09a92008-08-01 18:11:04921 DCHECK(completed_client_redirect_src_ == params.redirects[0]);
initial.commit09911bf2008-07-26 23:55:29922 params.referrer = completed_client_redirect_src_;
923 params.transition = static_cast<PageTransition::Type>(
924 params.transition | PageTransition::CLIENT_REDIRECT);
925 } else {
926 // Bug 654101: the referrer will be empty on https->http transitions. It
927 // would be nice if we could get the real referrer from somewhere.
[email protected]726985e22009-06-18 21:09:28928 params.referrer = GURL(
929 original_request.httpHeaderField(WebString::fromUTF8("Referer")));
initial.commit09911bf2008-07-26 23:55:29930 }
931
[email protected]726985e22009-06-18 21:09:28932 string16 method = request.httpMethod();
933 if (EqualsASCII(method, "POST"))
initial.commit09911bf2008-07-26 23:55:29934 params.is_post = true;
935
936 Send(new ViewHostMsg_FrameNavigate(routing_id_, params));
937 } else {
938 // Subframe navigation: the type depends on whether this navigation
939 // generated a new session history entry. When they do generate a session
940 // history entry, it means the user initiated the navigation and we should
941 // mark it as such. This test checks if this is the first time UpdateURL
942 // has been called since WillNavigateToURL was called to initiate the load.
943 if (page_id_ > last_page_id_sent_to_browser_)
944 params.transition = PageTransition::MANUAL_SUBFRAME;
945 else
946 params.transition = PageTransition::AUTO_SUBFRAME;
947
initial.commit09911bf2008-07-26 23:55:29948 Send(new ViewHostMsg_FrameNavigate(routing_id_, params));
949 }
950
951 last_page_id_sent_to_browser_ =
952 std::max(last_page_id_sent_to_browser_, page_id_);
953
954 // If we end up reusing this WebRequest (for example, due to a #ref click),
[email protected]daa8c58e2009-06-15 17:21:10955 // we don't want the transition type to persist. Just clear it.
956 navigation_state->set_transition_type(PageTransition::LINK);
[email protected]266eb6f2008-09-30 23:56:50957
[email protected]6c8afae52009-01-22 02:24:57958#if defined(OS_WIN)
[email protected]6a983b42009-03-20 20:12:25959 if (web_accessibility_manager_.get()) {
[email protected]be645db2009-02-06 20:36:33960 // Clear accessibility info cache.
[email protected]6a983b42009-03-20 20:12:25961 web_accessibility_manager_->ClearAccObjMap(-1, true);
[email protected]266eb6f2008-09-30 23:56:50962 }
[email protected]6c8afae52009-01-22 02:24:57963#else
[email protected]7d926f92009-03-03 14:26:54964 // TODO(port): accessibility not yet implemented. See http://crbug.com/8288.
[email protected]6c8afae52009-01-22 02:24:57965#endif
initial.commit09911bf2008-07-26 23:55:29966}
967
968// Tell the embedding application that the title of the active page has changed
969void RenderView::UpdateTitle(WebFrame* frame, const std::wstring& title) {
970 // Ignore all but top level navigations...
[email protected]f0af6a72009-05-30 05:25:17971 if (webview()->GetMainFrame() == frame) {
972 Send(new ViewHostMsg_UpdateTitle(
973 routing_id_,
974 page_id_,
975 title.length() > chrome::kMaxTitleChars ?
976 title.substr(0, chrome::kMaxTitleChars) : title));
977 }
initial.commit09911bf2008-07-26 23:55:29978}
979
980void RenderView::UpdateEncoding(WebFrame* frame,
[email protected]e38f40152008-09-12 23:08:30981 const std::wstring& encoding_name) {
initial.commit09911bf2008-07-26 23:55:29982 // Only update main frame's encoding_name.
983 if (webview()->GetMainFrame() == frame &&
984 last_encoding_name_ != encoding_name) {
[email protected]e38f40152008-09-12 23:08:30985 // Save the encoding name for later comparing.
initial.commit09911bf2008-07-26 23:55:29986 last_encoding_name_ = encoding_name;
987
[email protected]e38f40152008-09-12 23:08:30988 Send(new ViewHostMsg_UpdateEncoding(routing_id_, last_encoding_name_));
initial.commit09911bf2008-07-26 23:55:29989 }
990}
991
[email protected]f4d34b52008-11-24 23:05:01992// Sends the previous session history state to the browser so it will be saved
993// before we navigate to a new page. This must be called *before* the page ID
994// has been updated so we know what it was.
initial.commit09911bf2008-07-26 23:55:29995void RenderView::UpdateSessionHistory(WebFrame* frame) {
996 // If we have a valid page ID at this point, then it corresponds to the page
997 // we are navigating away from. Otherwise, this is the first navigation, so
998 // there is no past session history to record.
999 if (page_id_ == -1)
1000 return;
1001
[email protected]ca948a22009-06-25 19:36:171002 const WebHistoryItem& item =
1003 webview()->GetMainFrame()->GetPreviousHistoryItem();
1004 if (item.isNull())
initial.commit09911bf2008-07-26 23:55:291005 return;
[email protected]ca948a22009-06-25 19:36:171006
1007 Send(new ViewHostMsg_UpdateState(
1008 routing_id_, page_id_, webkit_glue::HistoryItemToString(item)));
initial.commit09911bf2008-07-26 23:55:291009}
1010
1011///////////////////////////////////////////////////////////////////////////////
1012// WebViewDelegate
1013
[email protected]80d96fa2009-06-10 22:34:511014bool RenderView::CanAcceptLoadDrops() const {
1015 return renderer_preferences_.can_accept_load_drops;
1016}
1017
initial.commit09911bf2008-07-26 23:55:291018void RenderView::DidStartLoading(WebView* webview) {
1019 if (is_loading_) {
1020 DLOG(WARNING) << "DidStartLoading called while loading";
1021 return;
1022 }
1023
1024 is_loading_ = true;
1025 // Clear the pointer so that we can assign it only when there is an unknown
1026 // plugin on a page.
1027 first_default_plugin_ = NULL;
1028
[email protected]329581b2009-04-28 06:52:351029 Send(new ViewHostMsg_DidStartLoading(routing_id_));
initial.commit09911bf2008-07-26 23:55:291030}
1031
1032void RenderView::DidStopLoading(WebView* webview) {
1033 if (!is_loading_) {
1034 DLOG(WARNING) << "DidStopLoading called while not loading";
1035 return;
1036 }
1037
1038 is_loading_ = false;
1039
1040 // NOTE: For now we're doing the safest thing, and sending out notification
1041 // when done loading. This currently isn't an issue as the favicon is only
1042 // displayed when done loading. Ideally we would send notification when
1043 // finished parsing the head, but webkit doesn't support that yet.
1044 // The feed discovery code would also benefit from access to the head.
1045 GURL favicon_url(webview->GetMainFrame()->GetFavIconURL());
1046 if (!favicon_url.is_empty())
1047 Send(new ViewHostMsg_UpdateFavIconURL(routing_id_, page_id_, favicon_url));
1048
1049 AddGURLSearchProvider(webview->GetMainFrame()->GetOSDDURL(),
1050 true); // autodetected
1051
[email protected]329581b2009-04-28 06:52:351052 Send(new ViewHostMsg_DidStopLoading(routing_id_));
initial.commit09911bf2008-07-26 23:55:291053
1054 MessageLoop::current()->PostDelayedTask(FROM_HERE,
1055 method_factory_.NewRunnableMethod(&RenderView::CapturePageInfo, page_id_,
1056 false),
1057 kDelayForCaptureMs);
1058
1059 // The page is loaded. Try to process the file we need to upload if any.
1060 ProcessPendingUpload();
1061
1062 // Since the page is done loading, we are sure we don't need to try
1063 // again.
1064 ResetPendingUpload();
1065}
1066
[email protected]77f17a82009-05-21 04:42:541067void RenderView::DidCreateDataSource(WebFrame* frame, WebDataSource* ds) {
[email protected]daa8c58e2009-06-15 17:21:101068 // The rest of RenderView assumes that a WebDataSource will always have a
1069 // non-null NavigationState.
1070 if (pending_navigation_state_.get()) {
[email protected]726985e22009-06-18 21:09:281071 ds->setExtraData(pending_navigation_state_.release());
[email protected]daa8c58e2009-06-15 17:21:101072 } else {
[email protected]726985e22009-06-18 21:09:281073 ds->setExtraData(NavigationState::CreateContentInitiated());
[email protected]daa8c58e2009-06-15 17:21:101074 }
[email protected]77f17a82009-05-21 04:42:541075}
1076
[email protected]a2f6bc112009-06-27 16:27:251077void RenderView::DidPaint() {
1078 WebFrame* main_frame = webview()->GetMainFrame();
1079
1080 if (main_frame->GetProvisionalDataSource()) {
1081 // If we have a provisional frame we are between the start
1082 // and commit stages of loading...ignore this paint.
1083 return;
1084 }
1085
1086 WebDataSource* ds = main_frame->GetDataSource();
1087 NavigationState* navigation_state = NavigationState::FromDataSource(ds);
[email protected]78a3a6f2009-07-02 16:15:011088 DCHECK(navigation_state);
1089
1090 Time now = Time::Now();
1091 if (navigation_state->first_paint_time().is_null()) {
1092 navigation_state->set_first_paint_time(now);
1093 }
1094 if (navigation_state->first_paint_after_load_time().is_null() &&
1095 !navigation_state->finish_load_time().is_null()) {
1096 navigation_state->set_first_paint_after_load_time(now);
[email protected]a2f6bc112009-06-27 16:27:251097 }
1098}
1099
initial.commit09911bf2008-07-26 23:55:291100void RenderView::DidStartProvisionalLoadForFrame(
1101 WebView* webview,
1102 WebFrame* frame,
1103 NavigationGesture gesture) {
[email protected]ed3fb032009-06-16 19:50:561104 WebDataSource* ds = frame->GetProvisionalDataSource();
1105 NavigationState* navigation_state = NavigationState::FromDataSource(ds);
1106
1107 navigation_state->set_start_load_time(Time::Now());
1108
1109 // Update the request time if WebKit has better knowledge of it.
1110 if (navigation_state->request_time().is_null()) {
[email protected]726985e22009-06-18 21:09:281111 double event_time = ds->triggeringEventTime();
[email protected]ed3fb032009-06-16 19:50:561112 if (event_time != 0.0)
1113 navigation_state->set_request_time(Time::FromDoubleT(event_time));
1114 }
1115
1116 bool is_top_most = !frame->GetParent();
1117 if (is_top_most) {
initial.commit09911bf2008-07-26 23:55:291118 navigation_gesture_ = gesture;
[email protected]266eb6f2008-09-30 23:56:501119
[email protected]77e09a92008-08-01 18:11:041120 // Make sure redirect tracking state is clear for the new load.
1121 completed_client_redirect_src_ = GURL();
1122 }
initial.commit09911bf2008-07-26 23:55:291123
1124 Send(new ViewHostMsg_DidStartProvisionalLoadForFrame(
[email protected]726985e22009-06-18 21:09:281125 routing_id_, is_top_most, ds->request().url()));
initial.commit09911bf2008-07-26 23:55:291126}
1127
1128bool RenderView::DidLoadResourceFromMemoryCache(WebView* webview,
[email protected]726985e22009-06-18 21:09:281129 const WebURLRequest& request,
1130 const WebURLResponse& response,
initial.commit09911bf2008-07-26 23:55:291131 WebFrame* frame) {
1132 // Let the browser know we loaded a resource from the memory cache. This
1133 // message is needed to display the correct SSL indicators.
1134 Send(new ViewHostMsg_DidLoadResourceFromMemoryCache(routing_id_,
[email protected]726985e22009-06-18 21:09:281135 request.url(), frame->GetSecurityOrigin(),
[email protected]ffc45862009-03-17 06:11:081136 frame->GetTop()->GetSecurityOrigin(),
[email protected]726985e22009-06-18 21:09:281137 response.securityInfo()));
initial.commit09911bf2008-07-26 23:55:291138
1139 return false;
1140}
1141
1142void RenderView::DidReceiveProvisionalLoadServerRedirect(WebView* webview,
1143 WebFrame* frame) {
1144 if (frame == webview->GetMainFrame()) {
1145 // Received a redirect on the main frame.
1146 WebDataSource* data_source =
1147 webview->GetMainFrame()->GetProvisionalDataSource();
1148 if (!data_source) {
1149 // Should only be invoked when we have a data source.
1150 NOTREACHED();
1151 return;
1152 }
[email protected]726985e22009-06-18 21:09:281153 std::vector<GURL> redirects;
1154 GetRedirectChain(data_source, &redirects);
initial.commit09911bf2008-07-26 23:55:291155 if (redirects.size() >= 2) {
1156 Send(new ViewHostMsg_DidRedirectProvisionalLoad(
1157 routing_id_, page_id_, redirects[redirects.size() - 2],
1158 redirects[redirects.size() - 1]));
1159 }
1160 }
1161}
1162
1163void RenderView::DidFailProvisionalLoadWithError(WebView* webview,
[email protected]726985e22009-06-18 21:09:281164 const WebURLError& error,
initial.commit09911bf2008-07-26 23:55:291165 WebFrame* frame) {
1166 // Notify the browser that we failed a provisional load with an error.
1167 //
1168 // Note: It is important this notification occur before DidStopLoading so the
1169 // SSL manager can react to the provisional load failure before being
1170 // notified the load stopped.
1171 //
1172 WebDataSource* ds = frame->GetProvisionalDataSource();
1173 DCHECK(ds);
1174
[email protected]726985e22009-06-18 21:09:281175 const WebURLRequest& failed_request = ds->request();
initial.commit09911bf2008-07-26 23:55:291176
1177 bool show_repost_interstitial =
[email protected]726985e22009-06-18 21:09:281178 (error.reason == net::ERR_CACHE_MISS &&
1179 EqualsASCII(failed_request.httpMethod(), "POST"));
initial.commit09911bf2008-07-26 23:55:291180 Send(new ViewHostMsg_DidFailProvisionalLoadWithError(
[email protected]726985e22009-06-18 21:09:281181 routing_id_, !frame->GetParent(),
1182 error.reason, error.unreachableURL,
initial.commit09911bf2008-07-26 23:55:291183 show_repost_interstitial));
1184
initial.commit09911bf2008-07-26 23:55:291185 // Don't display an error page if this is simply a cancelled load. Aside
1186 // from being dumb, WebCore doesn't expect it and it will cause a crash.
[email protected]726985e22009-06-18 21:09:281187 if (error.reason == net::ERR_ABORTED)
initial.commit09911bf2008-07-26 23:55:291188 return;
1189
[email protected]546ddd172009-06-25 00:25:011190 // Make sure we never show errors in view source mode.
1191 frame->SetInViewSourceMode(false);
1192
initial.commit09911bf2008-07-26 23:55:291193 // If this is a failed back/forward/reload navigation, then we need to do a
1194 // 'replace' load. This is necessary to avoid messing up session history.
1195 // Otherwise, we do a normal load, which simulates a 'go' navigation as far
1196 // as session history is concerned.
[email protected]daa8c58e2009-06-15 17:21:101197 bool replace = !NavigationState::FromDataSource(ds)->is_new_navigation();
initial.commit09911bf2008-07-26 23:55:291198
[email protected]5df266ac2008-10-15 19:50:131199 // Use the alternate error page service if this is a DNS failure or
1200 // connection failure. ERR_CONNECTION_FAILED can be dropped once we no longer
1201 // use winhttp.
[email protected]726985e22009-06-18 21:09:281202 int ec = error.reason;
[email protected]5df266ac2008-10-15 19:50:131203 if (ec == net::ERR_NAME_NOT_RESOLVED ||
1204 ec == net::ERR_CONNECTION_FAILED ||
1205 ec == net::ERR_CONNECTION_REFUSED ||
1206 ec == net::ERR_ADDRESS_UNREACHABLE ||
1207 ec == net::ERR_TIMED_OUT) {
[email protected]726985e22009-06-18 21:09:281208 const GURL& failed_url = error.unreachableURL;
[email protected]5df266ac2008-10-15 19:50:131209 const GURL& error_page_url = GetAlternateErrorPageURL(failed_url,
1210 ec == net::ERR_NAME_NOT_RESOLVED ? WebViewDelegate::DNS_ERROR
1211 : WebViewDelegate::CONNECTION_ERROR);
1212 if (error_page_url.is_valid()) {
1213 // Ask the WebFrame to fetch the alternate error page for us.
[email protected]726985e22009-06-18 21:09:281214 frame->LoadAlternateHTMLErrorPage(failed_request, error, error_page_url,
[email protected]5df266ac2008-10-15 19:50:131215 replace, GURL(kUnreachableWebDataURL));
1216 return;
1217 }
initial.commit09911bf2008-07-26 23:55:291218 }
[email protected]5df266ac2008-10-15 19:50:131219
[email protected]be645db2009-02-06 20:36:331220 // Fallback to a local error page.
[email protected]726985e22009-06-18 21:09:281221 LoadNavigationErrorPage(frame, failed_request, error, std::string(),
[email protected]5df266ac2008-10-15 19:50:131222 replace);
initial.commit09911bf2008-07-26 23:55:291223}
1224
1225void RenderView::LoadNavigationErrorPage(WebFrame* frame,
[email protected]726985e22009-06-18 21:09:281226 const WebURLRequest& failed_request,
1227 const WebURLError& error,
initial.commit09911bf2008-07-26 23:55:291228 const std::string& html,
1229 bool replace) {
[email protected]726985e22009-06-18 21:09:281230 GURL failed_url = error.unreachableURL;
initial.commit09911bf2008-07-26 23:55:291231
1232 std::string alt_html;
1233 if (html.empty()) {
1234 // Use a local error page.
1235 int resource_id;
1236 DictionaryValue error_strings;
[email protected]726985e22009-06-18 21:09:281237 if (error.reason == net::ERR_CACHE_MISS &&
1238 EqualsASCII(failed_request.httpMethod(), "POST")) {
initial.commit09911bf2008-07-26 23:55:291239 GetFormRepostErrorValues(failed_url, &error_strings);
1240 resource_id = IDR_ERROR_NO_DETAILS_HTML;
1241 } else {
1242 GetLocalizedErrorValues(error, &error_strings);
1243 resource_id = IDR_NET_ERROR_HTML;
1244 }
[email protected]8e50b602009-03-03 22:59:431245 error_strings.SetString(L"textdirection",
1246 (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) ?
1247 L"rtl" : L"ltr");
initial.commit09911bf2008-07-26 23:55:291248
1249 alt_html = GetAltHTMLForTemplate(error_strings, resource_id);
1250 } else {
1251 alt_html = html;
1252 }
1253
[email protected]e6f546c32009-07-01 17:12:551254 frame->LoadHTMLString(alt_html,
1255 GURL(kUnreachableWebDataURL),
1256 failed_url,
1257 replace);
initial.commit09911bf2008-07-26 23:55:291258}
1259
1260void RenderView::DidCommitLoadForFrame(WebView *webview, WebFrame* frame,
1261 bool is_new_navigation) {
[email protected]daa8c58e2009-06-15 17:21:101262 NavigationState* navigation_state =
1263 NavigationState::FromDataSource(frame->GetDataSource());
initial.commit09911bf2008-07-26 23:55:291264
[email protected]a2f6bc112009-06-27 16:27:251265 navigation_state->set_commit_load_time(Time::Now());
initial.commit09911bf2008-07-26 23:55:291266 if (is_new_navigation) {
1267 // When we perform a new navigation, we need to update the previous session
1268 // history entry with state for the page we are leaving.
1269 UpdateSessionHistory(frame);
1270
1271 // We bump our Page ID to correspond with the new session history entry.
1272 page_id_ = next_page_id_++;
1273
1274 MessageLoop::current()->PostDelayedTask(FROM_HERE,
1275 method_factory_.NewRunnableMethod(&RenderView::CapturePageInfo,
1276 page_id_, true),
1277 kDelayForForcedCaptureMs);
1278 } else {
[email protected]77f17a82009-05-21 04:42:541279 // Inspect the navigation_state on the main frame (set in our Navigate
1280 // method) to see if the navigation corresponds to a session history
1281 // navigation... Note: |frame| may or may not be the toplevel frame, but
1282 // for the case of capturing session history, the first committed frame
1283 // suffices. We keep track of whether we've seen this commit before so
1284 // that only capture session history once per navigation.
[email protected]f4d34b52008-11-24 23:05:011285 //
1286 // Note that we need to check if the page ID changed. In the case of a
1287 // reload, the page ID doesn't change, and UpdateSessionHistory gets the
1288 // previous URL and the current page ID, which would be wrong.
[email protected]daa8c58e2009-06-15 17:21:101289 if (!navigation_state->is_new_navigation() &&
1290 !navigation_state->request_committed() &&
[email protected]77f17a82009-05-21 04:42:541291 page_id_ != navigation_state->pending_page_id()) {
initial.commit09911bf2008-07-26 23:55:291292 // This is a successful session history navigation!
1293 UpdateSessionHistory(frame);
[email protected]77f17a82009-05-21 04:42:541294 page_id_ = navigation_state->pending_page_id();
initial.commit09911bf2008-07-26 23:55:291295 }
1296 }
1297
1298 // Remember that we've already processed this request, so we don't update
1299 // the session history again. We do this regardless of whether this is
1300 // a session history navigation, because if we attempted a session history
1301 // navigation without valid HistoryItem state, WebCore will think it is a
1302 // new navigation.
[email protected]daa8c58e2009-06-15 17:21:101303 navigation_state->set_request_committed(true);
initial.commit09911bf2008-07-26 23:55:291304
1305 UpdateURL(frame);
1306
1307 // If this committed load was initiated by a client redirect, we're
1308 // at the last stop now, so clear it.
1309 completed_client_redirect_src_ = GURL();
1310
1311 // Check whether we have new encoding name.
1312 UpdateEncoding(frame, webview->GetMainFrameEncodingName());
1313}
1314
1315void RenderView::DidReceiveTitle(WebView* webview,
1316 const std::wstring& title,
1317 WebFrame* frame) {
1318 UpdateTitle(frame, title);
1319
1320 // Also check whether we have new encoding name.
1321 UpdateEncoding(frame, webview->GetMainFrameEncodingName());
1322}
1323
1324void RenderView::DidFinishLoadForFrame(WebView* webview, WebFrame* frame) {
[email protected]a2f6bc112009-06-27 16:27:251325 WebDataSource* ds = frame->GetDataSource();
1326 NavigationState* navigation_state = NavigationState::FromDataSource(ds);
[email protected]78a3a6f2009-07-02 16:15:011327 DCHECK(navigation_state);
1328 navigation_state->set_finish_load_time(Time::Now());
initial.commit09911bf2008-07-26 23:55:291329}
1330
1331void RenderView::DidFailLoadWithError(WebView* webview,
[email protected]726985e22009-06-18 21:09:281332 const WebURLError& error,
initial.commit09911bf2008-07-26 23:55:291333 WebFrame* frame) {
[email protected]546ddd172009-06-25 00:25:011334 // Currently this function is empty. When you implement something here and it
1335 // will display any error messages in HTML, please make sure to call
1336 // frame->SetInViewSourceMode(false) not to show them in view source mode.
initial.commit09911bf2008-07-26 23:55:291337}
1338
1339void RenderView::DidFinishDocumentLoadForFrame(WebView* webview,
1340 WebFrame* frame) {
[email protected]a2f6bc112009-06-27 16:27:251341 WebDataSource* ds = frame->GetDataSource();
1342 NavigationState* navigation_state = NavigationState::FromDataSource(ds);
[email protected]78a3a6f2009-07-02 16:15:011343 DCHECK(navigation_state);
1344 navigation_state->set_finish_document_load_time(Time::Now());
[email protected]a2f6bc112009-06-27 16:27:251345
[email protected]09b8f82f2009-06-16 20:22:111346 Send(new ViewHostMsg_DocumentLoadedInFrame(routing_id_));
1347
[email protected]daa8c58e2009-06-15 17:21:101348 // The document has now been fully loaded. Scan for password forms to be
1349 // sent up to the browser.
1350 SendPasswordForms(frame);
1351
initial.commit09911bf2008-07-26 23:55:291352 // Check whether we have new encoding name.
1353 UpdateEncoding(frame, webview->GetMainFrameEncodingName());
[email protected]1e0f70402008-10-16 23:57:471354
[email protected]8930d472009-02-21 08:05:281355 if (RenderThread::current()) // Will be NULL during unit tests.
1356 RenderThread::current()->user_script_slave()->InjectScripts(
[email protected]0afe8272009-02-14 04:15:161357 frame, UserScript::DOCUMENT_END);
initial.commit09911bf2008-07-26 23:55:291358}
1359
1360void RenderView::DidHandleOnloadEventsForFrame(WebView* webview,
1361 WebFrame* frame) {
1362}
1363
1364void RenderView::DidChangeLocationWithinPageForFrame(WebView* webview,
1365 WebFrame* frame,
1366 bool is_new_navigation) {
[email protected]77f17a82009-05-21 04:42:541367 // If this was a reference fragment navigation that we initiated, then we
1368 // could end up having a non-null pending navigation state. We just need to
1369 // update the ExtraData on the datasource so that others who read the
1370 // ExtraData will get the new NavigationState. Similarly, if we did not
[email protected]daa8c58e2009-06-15 17:21:101371 // initiate this navigation, then we need to take care to reset any pre-
1372 // existing navigation state to a content-initiated navigation state.
1373 // DidCreateDataSource conveniently takes care of this for us.
1374 DidCreateDataSource(frame, frame->GetDataSource());
[email protected]77f17a82009-05-21 04:42:541375
initial.commit09911bf2008-07-26 23:55:291376 DidCommitLoadForFrame(webview, frame, is_new_navigation);
[email protected]77f17a82009-05-21 04:42:541377
[email protected]9d806f52009-03-12 22:50:541378 const string16& title =
[email protected]726985e22009-06-18 21:09:281379 webview->GetMainFrame()->GetDataSource()->pageTitle();
[email protected]9d806f52009-03-12 22:50:541380 UpdateTitle(frame, UTF16ToWideHack(title));
initial.commit09911bf2008-07-26 23:55:291381}
1382
initial.commit09911bf2008-07-26 23:55:291383void RenderView::DidCompleteClientRedirect(WebView* webview,
1384 WebFrame* frame,
1385 const GURL& source) {
1386 if (webview->GetMainFrame() == frame)
1387 completed_client_redirect_src_ = source;
1388}
1389
[email protected]7a9b51f2009-06-29 21:28:291390void RenderView::WillCloseFrame(WebView* webview, WebFrame* frame) {
1391 if (!frame->GetParent()) {
1392 const GURL& url = frame->GetURL();
1393 if (url.SchemeIs("http") || url.SchemeIs("https"))
1394 DumpLoadHistograms();
1395 }
1396}
1397
[email protected]daa8c58e2009-06-15 17:21:101398void RenderView::WillSubmitForm(WebView* webview, WebFrame* frame,
1399 const WebForm& form) {
1400 NavigationState* navigation_state =
1401 NavigationState::FromDataSource(frame->GetProvisionalDataSource());
1402
1403 if (navigation_state->transition_type() == PageTransition::LINK)
1404 navigation_state->set_transition_type(PageTransition::FORM_SUBMIT);
1405
1406 // Save these to be processed when the ensuing navigation is committed.
1407 navigation_state->set_searchable_form_data(
1408 SearchableFormData::Create(form));
1409 navigation_state->set_password_form_data(
1410 PasswordFormDomManager::CreatePasswordForm(form));
1411
1412 if (form.isAutoCompleteEnabled()) {
1413 scoped_ptr<AutofillForm> autofill_form(AutofillForm::Create(form));
1414 if (autofill_form.get())
1415 Send(new ViewHostMsg_AutofillFormSubmitted(routing_id_, *autofill_form));
1416 }
1417}
1418
[email protected]5b35a6b2009-03-16 19:58:081419void RenderView::WillSendRequest(WebView* webview,
1420 uint32 identifier,
[email protected]726985e22009-06-18 21:09:281421 WebURLRequest* request) {
1422 request->setRequestorID(routing_id_);
[email protected]5b35a6b2009-03-16 19:58:081423}
1424
initial.commit09911bf2008-07-26 23:55:291425void RenderView::BindDOMAutomationController(WebFrame* webframe) {
1426 dom_automation_controller_.set_message_sender(this);
1427 dom_automation_controller_.set_routing_id(routing_id_);
1428 dom_automation_controller_.BindToJavascript(webframe,
1429 L"domAutomationController");
1430}
1431
1432void RenderView::WindowObjectCleared(WebFrame* webframe) {
[email protected]81e63782009-02-27 19:35:091433 if (BindingsPolicy::is_dom_automation_enabled(enabled_bindings_))
initial.commit09911bf2008-07-26 23:55:291434 BindDOMAutomationController(webframe);
[email protected]81e63782009-02-27 19:35:091435 if (BindingsPolicy::is_dom_ui_enabled(enabled_bindings_)) {
initial.commit09911bf2008-07-26 23:55:291436 dom_ui_bindings_.set_message_sender(this);
1437 dom_ui_bindings_.set_routing_id(routing_id_);
1438 dom_ui_bindings_.BindToJavascript(webframe, L"chrome");
1439 }
[email protected]81e63782009-02-27 19:35:091440 if (BindingsPolicy::is_external_host_enabled(enabled_bindings_)) {
[email protected]18cb2572008-08-21 20:34:451441 external_host_bindings_.set_message_sender(this);
1442 external_host_bindings_.set_routing_id(routing_id_);
1443 external_host_bindings_.BindToJavascript(webframe, L"externalHost");
1444 }
initial.commit09911bf2008-07-26 23:55:291445}
1446
[email protected]0afe8272009-02-14 04:15:161447void RenderView::DocumentElementAvailable(WebFrame* frame) {
[email protected]4b8323b2009-04-17 18:45:441448 // TODO(mpcomplete): remove this before Chrome extensions ship.
1449 // HACK. This is a temporary workaround to allow cross-origin XHR for Chrome
1450 // extensions. It grants full access to every origin, when we really want
1451 // to be able to restrict them more specifically.
[email protected]d959ce22009-04-15 21:03:421452 if (frame->GetURL().SchemeIs(chrome::kExtensionScheme))
[email protected]4b8323b2009-04-17 18:45:441453 frame->GrantUniversalAccess();
[email protected]d959ce22009-04-15 21:03:421454
[email protected]8930d472009-02-21 08:05:281455 if (RenderThread::current()) // Will be NULL during unit tests.
1456 RenderThread::current()->user_script_slave()->InjectScripts(
[email protected]0afe8272009-02-14 04:15:161457 frame, UserScript::DOCUMENT_START);
1458}
1459
[email protected]f816c012009-06-26 21:48:321460void RenderView::DidCreateScriptContext(WebFrame* webframe) {
1461 EventBindings::HandleContextCreated(webframe);
1462}
1463
1464void RenderView::DidDestroyScriptContext(WebFrame* webframe) {
1465 EventBindings::HandleContextDestroyed(webframe);
1466}
1467
initial.commit09911bf2008-07-26 23:55:291468WindowOpenDisposition RenderView::DispositionForNavigationAction(
1469 WebView* webview,
1470 WebFrame* frame,
[email protected]726985e22009-06-18 21:09:281471 const WebURLRequest& request,
initial.commit09911bf2008-07-26 23:55:291472 WebNavigationType type,
1473 WindowOpenDisposition disposition,
1474 bool is_redirect) {
[email protected]daa8c58e2009-06-15 17:21:101475 // A content initiated navigation may have originated from a link-click,
1476 // script, drag-n-drop operation, etc.
[email protected]77f17a82009-05-21 04:42:541477 bool is_content_initiated =
[email protected]daa8c58e2009-06-15 17:21:101478 NavigationState::FromDataSource(frame->GetProvisionalDataSource())->
1479 is_content_initiated();
[email protected]77f17a82009-05-21 04:42:541480
initial.commit09911bf2008-07-26 23:55:291481 // Webkit is asking whether to navigate to a new URL.
1482 // This is fine normally, except if we're showing UI from one security
1483 // context and they're trying to navigate to a different context.
[email protected]726985e22009-06-18 21:09:281484 const GURL& url = request.url();
[email protected]77f17a82009-05-21 04:42:541485
initial.commit09911bf2008-07-26 23:55:291486 // We only care about navigations that are within the current tab (as opposed
1487 // to, for example, opening a new window).
1488 // But we sometimes navigate to about:blank to clear a tab, and we want to
1489 // still allow that.
[email protected]77f17a82009-05-21 04:42:541490 if (disposition == CURRENT_TAB && is_content_initiated &&
1491 frame->GetParent() == NULL && !url.SchemeIs(chrome::kAboutScheme)) {
1492 // When we received such unsolicited navigations, we sometimes want to
1493 // punt them up to the browser to handle.
1494 if (BindingsPolicy::is_dom_ui_enabled(enabled_bindings_) ||
[email protected]1e5f53a2009-06-15 23:48:041495 BindingsPolicy::is_extension_enabled(enabled_bindings_) ||
[email protected]77f17a82009-05-21 04:42:541496 frame->GetInViewSourceMode() ||
[email protected]a2176742009-07-03 12:13:481497 url.SchemeIs(chrome::kViewSourceScheme) ||
1498 url.SchemeIs(chrome::kPrintScheme)) {
[email protected]77f17a82009-05-21 04:42:541499 OpenURL(webview, url, GURL(), disposition);
1500 return IGNORE_ACTION; // Suppress the load here.
initial.commit09911bf2008-07-26 23:55:291501 }
1502 }
1503
1504 // Detect when a page is "forking" a new tab that can be safely rendered in
1505 // its own process. This is done by sites like Gmail that try to open links
1506 // in new windows without script connections back to the original page. We
1507 // treat such cases as browser navigations (in which we will create a new
1508 // renderer for a cross-site navigation), rather than WebKit navigations.
1509 //
1510 // We use the following heuristic to decide whether to fork a new page in its
1511 // own process:
1512 // The parent page must open a new tab to about:blank, set the new tab's
1513 // window.opener to null, and then redirect the tab to a cross-site URL using
1514 // JavaScript.
1515 bool is_fork =
1516 // Must start from a tab showing about:blank, which is later redirected.
[email protected]6aad4bd2009-02-26 22:55:171517 frame->GetURL() == GURL("about:blank") &&
initial.commit09911bf2008-07-26 23:55:291518 // Must be the first real navigation of the tab.
1519 GetHistoryBackListCount() < 1 &&
1520 GetHistoryForwardListCount() < 1 &&
1521 // The parent page must have set the child's window.opener to null before
1522 // redirecting to the desired URL.
1523 frame->GetOpener() == NULL &&
1524 // Must be a top-level frame.
1525 frame->GetParent() == NULL &&
[email protected]77f17a82009-05-21 04:42:541526 // Must not have issued the request from this page.
1527 is_content_initiated &&
initial.commit09911bf2008-07-26 23:55:291528 // Must be targeted at the current tab.
1529 disposition == CURRENT_TAB &&
1530 // Must be a JavaScript navigation, which appears as "other".
[email protected]726985e22009-06-18 21:09:281531 type == WebKit::WebNavigationTypeOther;
initial.commit09911bf2008-07-26 23:55:291532 if (is_fork) {
1533 // Open the URL via the browser, not via WebKit.
[email protected]c0588052008-10-27 23:01:501534 OpenURL(webview, url, GURL(), disposition);
initial.commit09911bf2008-07-26 23:55:291535 return IGNORE_ACTION;
1536 }
1537
1538 return disposition;
1539}
1540
[email protected]a455d3812009-03-05 20:18:071541void RenderView::RunJavaScriptAlert(WebFrame* webframe,
initial.commit09911bf2008-07-26 23:55:291542 const std::wstring& message) {
[email protected]478ff2ed2009-04-21 23:49:181543 RunJavaScriptMessage(MessageBoxFlags::kIsJavascriptAlert,
initial.commit09911bf2008-07-26 23:55:291544 message,
1545 std::wstring(),
[email protected]a455d3812009-03-05 20:18:071546 webframe->GetURL(),
initial.commit09911bf2008-07-26 23:55:291547 NULL);
1548}
1549
[email protected]a455d3812009-03-05 20:18:071550bool RenderView::RunJavaScriptConfirm(WebFrame* webframe,
initial.commit09911bf2008-07-26 23:55:291551 const std::wstring& message) {
[email protected]478ff2ed2009-04-21 23:49:181552 return RunJavaScriptMessage(MessageBoxFlags::kIsJavascriptConfirm,
initial.commit09911bf2008-07-26 23:55:291553 message,
1554 std::wstring(),
[email protected]a455d3812009-03-05 20:18:071555 webframe->GetURL(),
initial.commit09911bf2008-07-26 23:55:291556 NULL);
1557}
1558
[email protected]a455d3812009-03-05 20:18:071559bool RenderView::RunJavaScriptPrompt(WebFrame* webframe,
initial.commit09911bf2008-07-26 23:55:291560 const std::wstring& message,
1561 const std::wstring& default_value,
1562 std::wstring* result) {
[email protected]478ff2ed2009-04-21 23:49:181563 return RunJavaScriptMessage(MessageBoxFlags::kIsJavascriptPrompt,
initial.commit09911bf2008-07-26 23:55:291564 message,
1565 default_value,
[email protected]a455d3812009-03-05 20:18:071566 webframe->GetURL(),
initial.commit09911bf2008-07-26 23:55:291567 result);
1568}
1569
1570bool RenderView::RunJavaScriptMessage(int type,
1571 const std::wstring& message,
1572 const std::wstring& default_value,
[email protected]a455d3812009-03-05 20:18:071573 const GURL& frame_url,
initial.commit09911bf2008-07-26 23:55:291574 std::wstring* result) {
1575 bool success = false;
1576 std::wstring result_temp;
1577 if (!result)
1578 result = &result_temp;
1579 IPC::SyncMessage* msg = new ViewHostMsg_RunJavaScriptMessage(
[email protected]a455d3812009-03-05 20:18:071580 routing_id_, message, default_value, frame_url, type, &success, result);
initial.commit09911bf2008-07-26 23:55:291581
[email protected]1c4947f2009-01-15 22:25:111582 msg->set_pump_messages_event(modal_dialog_event_.get());
initial.commit09911bf2008-07-26 23:55:291583 Send(msg);
1584
1585 return success;
1586}
1587
1588void RenderView::AddGURLSearchProvider(const GURL& osd_url, bool autodetected) {
1589 if (!osd_url.is_empty())
1590 Send(new ViewHostMsg_PageHasOSDD(routing_id_, page_id_, osd_url,
1591 autodetected));
1592}
1593
[email protected]a455d3812009-03-05 20:18:071594bool RenderView::RunBeforeUnloadConfirm(WebFrame* webframe,
initial.commit09911bf2008-07-26 23:55:291595 const std::wstring& 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;
1600 IPC::SyncMessage* msg = new ViewHostMsg_RunBeforeUnloadConfirm(
[email protected]a455d3812009-03-05 20:18:071601 routing_id_, webframe->GetURL(), message, &success, &ignored_result);
initial.commit09911bf2008-07-26 23:55:291602
[email protected]1c4947f2009-01-15 22:25:111603 msg->set_pump_messages_event(modal_dialog_event_.get());
initial.commit09911bf2008-07-26 23:55:291604 Send(msg);
1605
1606 return success;
1607}
1608
[email protected]0ebf3872008-11-07 21:35:031609void RenderView::QueryFormFieldAutofill(const std::wstring& field_name,
1610 const std::wstring& text,
1611 int64 node_id) {
1612 static int message_id_counter = 0;
1613 form_field_autofill_request_id_ = message_id_counter++;
1614 Send(new ViewHostMsg_QueryFormFieldAutofill(routing_id_,
1615 field_name, text,
1616 node_id,
1617 form_field_autofill_request_id_));
1618}
1619
[email protected]4d2b6fb2009-03-20 22:28:171620void RenderView::RemoveStoredAutofillEntry(const std::wstring& name,
1621 const std::wstring& value) {
1622 Send(new ViewHostMsg_RemoveAutofillEntry(routing_id_, name, value));
1623}
1624
[email protected]0ebf3872008-11-07 21:35:031625void RenderView::OnReceivedAutofillSuggestions(
1626 int64 node_id,
1627 int request_id,
[email protected]8d0f15c2008-11-11 01:01:091628 const std::vector<std::wstring>& suggestions,
[email protected]0ebf3872008-11-07 21:35:031629 int default_suggestion_index) {
1630 if (!webview() || request_id != form_field_autofill_request_id_)
1631 return;
1632
1633 webview()->AutofillSuggestionsForNode(node_id, suggestions,
1634 default_suggestion_index);
1635}
1636
[email protected]2c4410d2009-05-06 23:46:221637void RenderView::OnPopupNotificationVisibilityChanged(bool visible) {
[email protected]634a6f92008-12-01 21:39:311638 popup_notification_visible_ = visible;
1639}
1640
initial.commit09911bf2008-07-26 23:55:291641void RenderView::ShowModalHTMLDialog(const GURL& url, int width, int height,
1642 const std::string& json_arguments,
1643 std::string* json_retval) {
1644 IPC::SyncMessage* msg = new ViewHostMsg_ShowModalHTMLDialog(
1645 routing_id_, url, width, height, json_arguments, json_retval);
1646
[email protected]1c4947f2009-01-15 22:25:111647 msg->set_pump_messages_event(modal_dialog_event_.get());
initial.commit09911bf2008-07-26 23:55:291648 Send(msg);
1649}
1650
1651uint32 RenderView::GetCPBrowsingContext() {
1652 uint32 context = 0;
1653 Send(new ViewHostMsg_GetCPBrowsingContext(&context));
1654 return context;
1655}
1656
1657// Tell the browser to display a destination link.
1658void RenderView::UpdateTargetURL(WebView* webview, const GURL& url) {
1659 if (url != target_url_) {
1660 if (target_url_status_ == TARGET_INFLIGHT ||
1661 target_url_status_ == TARGET_PENDING) {
1662 // If we have a request in-flight, save the URL to be sent when we
1663 // receive an ACK to the in-flight request. We can happily overwrite
1664 // any existing pending sends.
1665 pending_target_url_ = url;
1666 target_url_status_ = TARGET_PENDING;
1667 } else {
1668 Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_, url));
1669 target_url_ = url;
1670 target_url_status_ = TARGET_INFLIGHT;
1671 }
1672 }
1673}
1674
[email protected]b62d1a8c2009-01-13 23:54:571675void RenderView::RunFileChooser(bool multi_select,
[email protected]b949f1112009-04-12 20:03:081676 const string16& title,
1677 const FilePath& default_filename,
initial.commit09911bf2008-07-26 23:55:291678 WebFileChooserCallback* file_chooser) {
1679 if (file_chooser_.get()) {
1680 // TODO(brettw): bug 1235154: This should be a synchronous message to deal
1681 // with the fact that web pages can programatically trigger this. With the
1682 // asnychronous messages, we can get an additional call when one is pending,
1683 // which this test is for. For now, we just ignore the additional file
1684 // chooser request. WebKit doesn't do anything to expect the callback, so
1685 // we can just ignore calling it.
1686 delete file_chooser;
1687 return;
1688 }
1689 file_chooser_.reset(file_chooser);
[email protected]b62d1a8c2009-01-13 23:54:571690 Send(new ViewHostMsg_RunFileChooser(routing_id_, multi_select, title,
[email protected]b949f1112009-04-12 20:03:081691 default_filename));
initial.commit09911bf2008-07-26 23:55:291692}
1693
1694void RenderView::AddMessageToConsole(WebView* webview,
1695 const std::wstring& message,
1696 unsigned int line_no,
1697 const std::wstring& source_id) {
1698 Send(new ViewHostMsg_AddMessageToConsole(routing_id_, message,
1699 static_cast<int32>(line_no),
1700 source_id));
1701}
1702
1703void RenderView::AddSearchProvider(const std::string& url) {
1704 AddGURLSearchProvider(GURL(url),
1705 false); // not autodetected
1706}
1707
[email protected]c88a70fe2009-05-05 20:00:221708WebView* RenderView::CreateWebView(WebView* webview,
1709 bool user_gesture,
1710 const GURL& creator_url) {
[email protected]0aa55312008-10-17 21:53:081711 // Check to make sure we aren't overloading on popups.
1712 if (shared_popup_counter_->data > kMaximumNumberOfUnacknowledgedPopups)
1713 return NULL;
1714
[email protected]634a6f92008-12-01 21:39:311715 // This window can't be closed from a window.close() call until we receive a
1716 // message from the Browser process explicitly allowing it.
1717 popup_notification_visible_ = true;
1718
initial.commit09911bf2008-07-26 23:55:291719 int32 routing_id = MSG_ROUTING_NONE;
[email protected]6c8afae52009-01-22 02:24:571720
[email protected]18bcc3c2009-01-27 21:39:151721 ModalDialogEvent modal_dialog_event;
[email protected]6c8afae52009-01-22 02:24:571722 render_thread_->Send(
[email protected]15787f8f2008-10-17 15:29:031723 new ViewHostMsg_CreateWindow(routing_id_, user_gesture, &routing_id,
1724 &modal_dialog_event));
initial.commit09911bf2008-07-26 23:55:291725 if (routing_id == MSG_ROUTING_NONE) {
initial.commit09911bf2008-07-26 23:55:291726 return NULL;
1727 }
1728
1729 // The WebView holds a reference to this new RenderView
[email protected]80d96fa2009-06-10 22:34:511730 const WebPreferences& web_prefs = webview->GetPreferences();
[email protected]6c8afae52009-01-22 02:24:571731 base::WaitableEvent* waitable_event = new base::WaitableEvent
1732#if defined(OS_WIN)
[email protected]18bcc3c2009-01-27 21:39:151733 (modal_dialog_event.event);
[email protected]6c8afae52009-01-22 02:24:571734#else
1735 (true, false);
1736#endif
[email protected]81a34412009-01-05 19:17:241737 RenderView* view = RenderView::Create(render_thread_,
[email protected]1c4947f2009-01-15 22:25:111738 NULL, waitable_event, routing_id_,
[email protected]80d96fa2009-06-10 22:34:511739 renderer_preferences_, web_prefs,
1740 shared_popup_counter_, routing_id);
[email protected]ed4bf2d2009-05-05 00:10:061741 view->opened_by_user_gesture_ = user_gesture;
[email protected]c88a70fe2009-05-05 20:00:221742 view->creator_url_ = creator_url;
initial.commit09911bf2008-07-26 23:55:291743
1744 // Copy over the alternate error page URL so we can have alt error pages in
1745 // the new render view (we don't need the browser to send the URL back down).
1746 view->alternate_error_page_url_ = alternate_error_page_url_;
1747
1748 return view->webview();
1749}
1750
[email protected]0ebf3872008-11-07 21:35:031751WebWidget* RenderView::CreatePopupWidget(WebView* webview,
[email protected]cfd727f2009-01-09 20:21:111752 bool activatable) {
[email protected]8085dbc82008-09-26 22:53:441753 RenderWidget* widget = RenderWidget::Create(routing_id_,
[email protected]81a34412009-01-05 19:17:241754 render_thread_,
[email protected]cfd727f2009-01-09 20:21:111755 activatable);
initial.commit09911bf2008-07-26 23:55:291756 return widget->webwidget();
1757}
1758
1759WebPluginDelegate* RenderView::CreatePluginDelegate(
1760 WebView* webview,
1761 const GURL& url,
1762 const std::string& mime_type,
1763 const std::string& clsid,
1764 std::string* actual_mime_type) {
[email protected]ffeba6d2009-04-27 20:43:261765#if defined(OS_WIN) || defined(OS_LINUX)
[email protected]6273e2e72009-04-17 00:13:551766 if (!PluginChannelHost::IsListening())
1767 return NULL;
1768
[email protected]9dd9e8382009-06-05 18:23:211769 GURL policy_url;
1770 if (webview->GetMainFrame())
1771 policy_url = webview->GetMainFrame()->GetURL();
1772
[email protected]f5cdaff2009-05-19 21:01:471773 FilePath path;
1774 render_thread_->Send(
[email protected]9dd9e8382009-06-05 18:23:211775 new ViewHostMsg_GetPluginPath(url, policy_url, mime_type, clsid, &path,
[email protected]f5cdaff2009-05-19 21:01:471776 actual_mime_type));
1777 if (path.value().empty())
1778 return NULL;
1779
1780 std::string mime_type_to_use;
1781 if (!actual_mime_type->empty())
1782 mime_type_to_use = *actual_mime_type;
1783 else
1784 mime_type_to_use = mime_type;
1785
[email protected]ffeba6d2009-04-27 20:43:261786#if !defined(OS_LINUX) // In-proc plugins aren't supported on Linux.
[email protected]88a1fb47a2009-03-13 00:18:061787 if (RenderProcess::current()->in_process_plugins()) {
[email protected]b94d3322009-02-12 19:49:041788 return WebPluginDelegate::Create(path,
1789 mime_type_to_use,
1790 gfx::NativeViewFromId(host_window_));
initial.commit09911bf2008-07-26 23:55:291791 }
[email protected]ffeba6d2009-04-27 20:43:261792#endif
initial.commit09911bf2008-07-26 23:55:291793
1794 WebPluginDelegateProxy* proxy =
[email protected]f5cdaff2009-05-19 21:01:471795 WebPluginDelegateProxy::Create(url, mime_type_to_use, clsid, this);
initial.commit09911bf2008-07-26 23:55:291796 if (!proxy)
1797 return NULL;
1798
initial.commit09911bf2008-07-26 23:55:291799 plugin_delegates_.push_back(proxy);
1800
1801 return proxy;
[email protected]6c8afae52009-01-22 02:24:571802#else
[email protected]157e5d22009-04-23 18:43:351803 // TODO(port): Plugins currently not supported
1804 NOTIMPLEMENTED();
1805 return NULL;
[email protected]6c8afae52009-01-22 02:24:571806#endif
initial.commit09911bf2008-07-26 23:55:291807}
1808
[email protected]4e6be3f2009-05-07 02:24:441809WebKit::WebMediaPlayer* RenderView::CreateWebMediaPlayer(
1810 WebKit::WebMediaPlayerClient* client) {
[email protected]add51772009-06-11 18:25:171811 scoped_refptr<media::FilterFactoryCollection> factory =
1812 new media::FilterFactoryCollection();
1813 // Add in any custom filter factories first.
1814 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
1815 if (!cmd_line->HasSwitch(switches::kDisableAudio)) {
1816 // Add the chrome specific audio renderer.
1817 factory->AddFactory(
1818 AudioRendererImpl::CreateFactory(audio_message_filter()));
1819 }
[email protected]8380c092009-06-25 17:45:511820
1821 // TODO(hclam): obtain the following parameters from |client|.
1822 webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory =
1823 new webkit_glue::MediaResourceLoaderBridgeFactory(
1824 GURL::EmptyGURL(), // referrer
1825 "null", // frame origin
1826 "null", // main_frame_origin
1827 base::GetCurrentProcId(),
1828 WebAppCacheContext::kNoAppCacheContextId,
1829 routing_id());
1830
[email protected]add51772009-06-11 18:25:171831 if (!cmd_line->HasSwitch(switches::kSimpleDataSource)) {
1832 // Add the chrome specific media data source.
[email protected]70ab61c92009-06-16 19:29:391833 factory->AddFactory(
1834 BufferedDataSource::CreateFactory(MessageLoop::current(),
[email protected]8380c092009-06-25 17:45:511835 bridge_factory));
1836 } else {
1837 factory->AddFactory(
1838 webkit_glue::SimpleDataSource::CreateFactory(MessageLoop::current(),
1839 bridge_factory));
[email protected]add51772009-06-11 18:25:171840 }
1841 return new webkit_glue::WebMediaPlayerImpl(client, factory);
[email protected]ec9212f2008-12-18 21:40:361842}
1843
initial.commit09911bf2008-07-26 23:55:291844void RenderView::OnMissingPluginStatus(WebPluginDelegate* delegate,
1845 int status) {
[email protected]6c8afae52009-01-22 02:24:571846#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:291847 if (first_default_plugin_ == NULL) {
1848 // Show the InfoBar for the first available plugin.
1849 if (status == default_plugin::MISSING_PLUGIN_AVAILABLE) {
1850 first_default_plugin_ = delegate;
1851 Send(new ViewHostMsg_MissingPluginStatus(routing_id_, status));
1852 }
1853 } else {
1854 // Closes the InfoBar if user clicks on the plugin (instead of the InfoBar)
1855 // to start the download/install.
1856 if (status == default_plugin::MISSING_PLUGIN_USER_STARTED_DOWNLOAD) {
1857 Send(new ViewHostMsg_MissingPluginStatus(routing_id_, status));
1858 }
1859 }
[email protected]6c8afae52009-01-22 02:24:571860#else
1861 // TODO(port): plugins current not supported
1862 NOTIMPLEMENTED();
1863#endif
initial.commit09911bf2008-07-26 23:55:291864}
1865
[email protected]eb47a132009-03-04 00:39:561866WebWorker* RenderView::CreateWebWorker(WebWorkerClient* client) {
1867#if defined(OS_WIN)
[email protected]ec775ef2009-05-01 21:20:471868 return new WebWorkerProxy(client, RenderThread::current(), routing_id_);
[email protected]eb47a132009-03-04 00:39:561869#else
1870 // TODO(port): out of process workers
1871 NOTIMPLEMENTED();
1872 return NULL;
1873#endif
1874}
1875
initial.commit09911bf2008-07-26 23:55:291876void RenderView::OpenURL(WebView* webview, const GURL& url,
[email protected]c0588052008-10-27 23:01:501877 const GURL& referrer,
initial.commit09911bf2008-07-26 23:55:291878 WindowOpenDisposition disposition) {
[email protected]c0588052008-10-27 23:01:501879 Send(new ViewHostMsg_OpenURL(routing_id_, url, referrer, disposition));
initial.commit09911bf2008-07-26 23:55:291880}
1881
[email protected]1d522202009-04-04 01:56:421882void RenderView::DidContentsSizeChange(WebWidget* webwidget,
1883 int new_width,
1884 int new_height) {
[email protected]0666aef2009-05-13 19:48:081885 // We don't always want to send the change messages over IPC, only if we've
1886 // be put in that mode by getting a |ViewMsg_EnableIntrinsicWidthChangedMode|
1887 // message.
1888 // TODO(rafaelw): Figure out where the best place to set this for extensions
1889 // is. It isn't clean to test for ExtensionView by examining the
1890 // enabled_bindings. This needs to be generalized as it becomes clear what
1891 // extension toolbars need.
1892 if (BindingsPolicy::is_extension_enabled(enabled_bindings_) ||
1893 send_preferred_width_changes_) {
1894 // WebCore likes to tell us things have changed even when they haven't, so
1895 // cache the width and only send the IPC message when we're sure the
1896 // width is different.
[email protected]1d522202009-04-04 01:56:421897 int width = webview()->GetMainFrame()->GetContentsPreferredWidth();
[email protected]0666aef2009-05-13 19:48:081898 if (width != preferred_width_) {
1899 Send(new ViewHostMsg_DidContentsPreferredWidthChange(routing_id_, width));
1900 preferred_width_ = width;
1901 }
[email protected]1d522202009-04-04 01:56:421902 }
1903}
1904
initial.commit09911bf2008-07-26 23:55:291905// We are supposed to get a single call to Show for a newly created RenderView
1906// that was created via RenderView::CreateWebView. So, we wait until this
1907// point to dispatch the ShowView message.
1908//
1909// This method provides us with the information about how to display the newly
1910// created RenderView (i.e., as a constrained popup or as a new tab).
1911//
1912void RenderView::Show(WebWidget* webwidget, WindowOpenDisposition disposition) {
1913 DCHECK(!did_show_) << "received extraneous Show call";
1914 DCHECK(opener_id_ != MSG_ROUTING_NONE);
1915
1916 if (did_show_)
1917 return;
1918 did_show_ = true;
1919
1920 // NOTE: initial_pos_ may still have its default values at this point, but
1921 // that's okay. It'll be ignored if disposition is not NEW_POPUP, or the
1922 // browser process will impose a default position otherwise.
[email protected]35f7d212009-04-29 21:19:271923 Send(new ViewHostMsg_ShowView(opener_id_, routing_id_, disposition,
[email protected]c88a70fe2009-05-05 20:00:221924 initial_pos_, opened_by_user_gesture_, creator_url_));
[email protected]2533ce12009-05-09 00:02:241925 SetPendingWindowRect(initial_pos_);
initial.commit09911bf2008-07-26 23:55:291926}
1927
[email protected]634a6f92008-12-01 21:39:311928void RenderView::CloseWidgetSoon(WebWidget* webwidget) {
[email protected]2c4410d2009-05-06 23:46:221929 if (!popup_notification_visible_)
[email protected]634a6f92008-12-01 21:39:311930 RenderWidget::CloseWidgetSoon(webwidget);
1931}
1932
initial.commit09911bf2008-07-26 23:55:291933void RenderView::RunModal(WebWidget* webwidget) {
1934 DCHECK(did_show_) << "should already have shown the view";
1935
1936 IPC::SyncMessage* msg = new ViewHostMsg_RunModal(routing_id_);
1937
[email protected]1c4947f2009-01-15 22:25:111938 msg->set_pump_messages_event(modal_dialog_event_.get());
initial.commit09911bf2008-07-26 23:55:291939 Send(msg);
1940}
1941
1942void RenderView::SyncNavigationState() {
1943 if (!webview())
1944 return;
1945
[email protected]ca948a22009-06-25 19:36:171946 const WebHistoryItem& item =
1947 webview()->GetMainFrame()->GetCurrentHistoryItem();
1948 if (item.isNull())
initial.commit09911bf2008-07-26 23:55:291949 return;
[email protected]ca948a22009-06-25 19:36:171950
1951 Send(new ViewHostMsg_UpdateState(
1952 routing_id_, page_id_, webkit_glue::HistoryItemToString(item)));
initial.commit09911bf2008-07-26 23:55:291953}
1954
1955void RenderView::ShowContextMenu(WebView* webview,
[email protected]124646932009-01-28 18:39:021956 ContextNode node,
initial.commit09911bf2008-07-26 23:55:291957 int x,
1958 int y,
1959 const GURL& link_url,
1960 const GURL& image_url,
1961 const GURL& page_url,
1962 const GURL& frame_url,
1963 const std::wstring& selection_text,
1964 const std::wstring& misspelled_word,
[email protected]6aa376b2008-09-23 18:49:521965 int edit_flags,
[email protected]c9825a42009-05-01 22:51:501966 const std::string& security_info,
1967 const std::string& frame_charset) {
[email protected]e09ba552009-02-05 03:26:291968 ContextMenuParams params;
[email protected]124646932009-01-28 18:39:021969 params.node = node;
initial.commit09911bf2008-07-26 23:55:291970 params.x = x;
1971 params.y = y;
1972 params.image_url = image_url;
1973 params.link_url = link_url;
[email protected]e6c79812009-04-22 22:31:421974 params.unfiltered_link_url = link_url;
initial.commit09911bf2008-07-26 23:55:291975 params.page_url = page_url;
1976 params.frame_url = frame_url;
1977 params.selection_text = selection_text;
1978 params.misspelled_word = misspelled_word;
[email protected]be645db2009-02-06 20:36:331979 params.spellcheck_enabled =
[email protected]bbbd545c2008-12-15 20:18:041980 webview->GetFocusedFrame()->SpellCheckEnabled();
initial.commit09911bf2008-07-26 23:55:291981 params.edit_flags = edit_flags;
[email protected]6aa376b2008-09-23 18:49:521982 params.security_info = security_info;
[email protected]c9825a42009-05-01 22:51:501983 params.frame_charset = frame_charset;
initial.commit09911bf2008-07-26 23:55:291984 Send(new ViewHostMsg_ContextMenu(routing_id_, params));
1985}
1986
[email protected]e80c73b2009-04-07 23:24:581987void RenderView::StartDragging(WebView* webview,
1988 const WebDragData& drag_data) {
1989 Send(new ViewHostMsg_StartDragging(routing_id_, WebDropData(drag_data)));
initial.commit09911bf2008-07-26 23:55:291990}
1991
1992void RenderView::TakeFocus(WebView* webview, bool reverse) {
1993 Send(new ViewHostMsg_TakeFocus(routing_id_, reverse));
1994}
1995
1996void RenderView::DidDownloadImage(int id,
1997 const GURL& image_url,
1998 bool errored,
1999 const SkBitmap& image) {
[email protected]bf5c2ff392009-07-08 16:24:332000 Send(new ViewHostMsg_DidDownloadFavIcon(routing_id_, id, image_url, errored,
2001 image));
initial.commit09911bf2008-07-26 23:55:292002}
2003
[email protected]bf5c2ff392009-07-08 16:24:332004void RenderView::OnDownloadFavIcon(int id,
2005 const GURL& image_url,
2006 int image_size) {
[email protected]f11ca0732009-04-11 00:09:342007 bool data_image_failed = false;
2008 if (image_url.SchemeIs("data")) {
2009 SkBitmap data_image = ImageFromDataUrl(image_url);
2010 data_image_failed = data_image.empty();
2011 if (!data_image_failed) {
[email protected]bf5c2ff392009-07-08 16:24:332012 Send(new ViewHostMsg_DidDownloadFavIcon(routing_id_, id, image_url, false,
2013 data_image));
[email protected]f11ca0732009-04-11 00:09:342014 }
2015 }
2016
[email protected]bf5c2ff392009-07-08 16:24:332017 if (data_image_failed ||
2018 !webview()->DownloadImage(id, image_url, image_size)) {
2019 Send(new ViewHostMsg_DidDownloadFavIcon(routing_id_, id, image_url, true,
2020 SkBitmap()));
2021 }
initial.commit09911bf2008-07-26 23:55:292022}
2023
[email protected]f11ca0732009-04-11 00:09:342024SkBitmap RenderView::ImageFromDataUrl(const GURL& url) const {
2025 std::string mime_type, char_set, data;
2026 if (net::DataURL::Parse(url, &mime_type, &char_set, &data) && !data.empty()) {
2027 // Decode the favicon using WebKit's image decoder.
2028 webkit_glue::ImageDecoder decoder(gfx::Size(kFavIconSize, kFavIconSize));
2029 const unsigned char* src_data =
2030 reinterpret_cast<const unsigned char*>(&data[0]);
2031
2032 return decoder.Decode(src_data, data.size());
2033 }
2034 return SkBitmap();
2035}
2036
initial.commit09911bf2008-07-26 23:55:292037void RenderView::OnGetApplicationInfo(int page_id) {
2038 webkit_glue::WebApplicationInfo app_info;
2039 if (page_id == page_id_)
2040 webkit_glue::GetApplicationInfo(webview(), &app_info);
2041
2042 // Prune out any data URLs in the set of icons. The browser process expects
2043 // any icon with a data URL to have originated from a favicon. We don't want
2044 // to decode arbitrary data URLs in the browser process. See
2045 // http://b/issue?id=1162972
2046 for (size_t i = 0; i < app_info.icons.size(); ++i) {
[email protected]6de74452009-02-25 18:04:592047 if (app_info.icons[i].url.SchemeIs(chrome::kDataScheme)) {
initial.commit09911bf2008-07-26 23:55:292048 app_info.icons.erase(app_info.icons.begin() + i);
2049 --i;
2050 }
2051 }
2052
2053 Send(new ViewHostMsg_DidGetApplicationInfo(routing_id_, page_id, app_info));
2054}
2055
2056GURL RenderView::GetAlternateErrorPageURL(const GURL& failedURL,
2057 ErrorPageType error_type) {
2058 if (failedURL.SchemeIsSecure()) {
2059 // If the URL that failed was secure, then the embedding web page was not
2060 // expecting a network attacker to be able to manipulate its contents. As
2061 // we fetch alternate error pages over HTTP, we would be allowing a network
2062 // attacker to manipulate the contents of the response if we tried to use
2063 // the link doctor here.
2064 return GURL::EmptyGURL();
2065 }
2066
2067 // Grab the base URL from the browser process.
2068 if (!alternate_error_page_url_.is_valid())
2069 return GURL::EmptyGURL();
2070
2071 // Strip query params from the failed URL.
2072 GURL::Replacements remove_params;
2073 remove_params.ClearUsername();
2074 remove_params.ClearPassword();
2075 remove_params.ClearQuery();
2076 remove_params.ClearRef();
2077 const GURL url_to_send = failedURL.ReplaceComponents(remove_params);
2078
2079 // Construct the query params to send to link doctor.
2080 std::string params(alternate_error_page_url_.query());
2081 params.append("&url=");
2082 params.append(EscapeQueryParamValue(url_to_send.spec()));
2083 params.append("&sourceid=chrome");
2084 params.append("&error=");
2085 switch (error_type) {
2086 case DNS_ERROR:
2087 params.append("dnserror");
2088 break;
2089
2090 case HTTP_404:
2091 params.append("http404");
2092 break;
2093
[email protected]5df266ac2008-10-15 19:50:132094 case CONNECTION_ERROR:
[email protected]e1f934b2009-01-26 20:41:332095 params.append("connectionfailure");
[email protected]5df266ac2008-10-15 19:50:132096 break;
2097
initial.commit09911bf2008-07-26 23:55:292098 default:
2099 NOTREACHED() << "unknown ErrorPageType";
2100 }
2101
2102 // OK, build the final url to return.
2103 GURL::Replacements link_doctor_params;
2104 link_doctor_params.SetQueryStr(params);
2105 GURL url = alternate_error_page_url_.ReplaceComponents(link_doctor_params);
2106 return url;
2107}
2108
[email protected]7ea066a2009-04-06 20:21:592109void RenderView::OnFind(int request_id,
2110 const string16& search_text,
2111 const WebKit::WebFindOptions& options) {
initial.commit09911bf2008-07-26 23:55:292112 WebFrame* main_frame = webview()->GetMainFrame();
2113 WebFrame* frame_after_main = webview()->GetNextFrameAfter(main_frame, true);
2114 WebFrame* focused_frame = webview()->GetFocusedFrame();
2115 WebFrame* search_frame = focused_frame; // start searching focused frame.
2116
2117 bool multi_frame = (frame_after_main != main_frame);
2118
2119 // If we have multiple frames, we don't want to wrap the search within the
2120 // frame, so we check here if we only have main_frame in the chain.
2121 bool wrap_within_frame = !multi_frame;
2122
[email protected]b3f2b912009-04-09 16:18:522123 WebRect selection_rect;
initial.commit09911bf2008-07-26 23:55:292124 bool result = false;
2125
2126 do {
[email protected]7ea066a2009-04-06 20:21:592127 result = search_frame->Find(
2128 request_id, search_text, options, wrap_within_frame, &selection_rect);
initial.commit09911bf2008-07-26 23:55:292129
2130 if (!result) {
2131 // don't leave text selected as you move to the next frame.
2132 search_frame->ClearSelection();
2133
2134 // Find the next frame, but skip the invisible ones.
2135 do {
2136 // What is the next frame to search? (we might be going backwards). Note
2137 // that we specify wrap=true so that search_frame never becomes NULL.
[email protected]7ea066a2009-04-06 20:21:592138 search_frame = options.forward ?
initial.commit09911bf2008-07-26 23:55:292139 webview()->GetNextFrameAfter(search_frame, true) :
2140 webview()->GetPreviousFrameBefore(search_frame, true);
2141 } while (!search_frame->Visible() && search_frame != focused_frame);
2142
[email protected]884db412008-11-24 23:46:502143 // Make sure selection doesn't affect the search operation in new frame.
initial.commit09911bf2008-07-26 23:55:292144 search_frame->ClearSelection();
2145
2146 // If we have multiple frames and we have wrapped back around to the
2147 // focused frame, we need to search it once more allowing wrap within
2148 // the frame, otherwise it will report 'no match' if the focused frame has
2149 // reported matches, but no frames after the focused_frame contain a
2150 // match for the search word(s).
2151 if (multi_frame && search_frame == focused_frame) {
[email protected]7ea066a2009-04-06 20:21:592152 result = search_frame->Find(
2153 request_id, search_text, options, true, // Force wrapping.
2154 &selection_rect);
initial.commit09911bf2008-07-26 23:55:292155 }
2156 }
2157
initial.commit09911bf2008-07-26 23:55:292158 webview()->SetFocusedFrame(search_frame);
2159 } while (!result && search_frame != focused_frame);
2160
[email protected]7ea066a2009-04-06 20:21:592161 if (options.findNext) {
[email protected]4f3dc372009-02-24 00:10:292162 // Force the main_frame to report the actual count.
[email protected]7ea066a2009-04-06 20:21:592163 main_frame->IncreaseMatchCount(0, request_id);
[email protected]4f3dc372009-02-24 00:10:292164 } else {
2165 // If nothing is found, set result to "0 of 0", otherwise, set it to
2166 // "-1 of 1" to indicate that we found at least one item, but we don't know
2167 // yet what is active.
2168 int ordinal = result ? -1 : 0; // -1 here means, we might know more later.
2169 int match_count = result ? 1 : 0; // 1 here means possibly more coming.
initial.commit09911bf2008-07-26 23:55:292170
[email protected]4f3dc372009-02-24 00:10:292171 // If we find no matches then this will be our last status update.
2172 // Otherwise the scoping effort will send more results.
2173 bool final_status_update = !result;
initial.commit09911bf2008-07-26 23:55:292174
[email protected]4f3dc372009-02-24 00:10:292175 // Send the search result over to the browser process.
[email protected]4f999132009-03-31 18:08:402176 Send(new ViewHostMsg_Find_Reply(routing_id_,
[email protected]7ea066a2009-04-06 20:21:592177 request_id,
[email protected]4f3dc372009-02-24 00:10:292178 match_count,
2179 selection_rect,
2180 ordinal,
2181 final_status_update));
initial.commit09911bf2008-07-26 23:55:292182
initial.commit09911bf2008-07-26 23:55:292183 // Scoping effort begins, starting with the mainframe.
2184 search_frame = main_frame;
2185
2186 main_frame->ResetMatchCount();
2187
2188 do {
2189 // Cancel all old scoping requests before starting a new one.
2190 search_frame->CancelPendingScopingEffort();
2191
2192 // We don't start another scoping effort unless at least one match has
2193 // been found.
2194 if (result) {
2195 // Start new scoping request. If the scoping function determines that it
2196 // needs to scope, it will defer until later.
[email protected]7ea066a2009-04-06 20:21:592197 search_frame->ScopeStringMatches(request_id,
2198 search_text,
2199 options,
initial.commit09911bf2008-07-26 23:55:292200 true); // reset the tickmarks
2201 }
2202
2203 // Iterate to the next frame. The frame will not necessarily scope, for
2204 // example if it is not visible.
2205 search_frame = webview()->GetNextFrameAfter(search_frame, true);
2206 } while (search_frame != main_frame);
2207 }
2208}
2209
[email protected]5c4266922009-07-10 16:41:272210void RenderView::OnDeterminePageText() {
2211 if (!is_loading_) {
2212 if (!webview())
2213 return;
2214 WebFrame* main_frame = webview()->GetMainFrame();
2215 std::wstring contents;
2216 CaptureText(main_frame, &contents);
2217 Send(new ViewMsg_DeterminePageText_Reply(routing_id_, contents));
2218 determine_page_text_after_loading_stops_ = false;
2219 return;
2220 }
2221
2222 // We set |determine_page_text_after_loading_stops_| true here so that,
2223 // after page has been loaded completely, the text in the page is captured.
2224 determine_page_text_after_loading_stops_ = true;
2225}
2226
initial.commit09911bf2008-07-26 23:55:292227void RenderView::ReportFindInPageMatchCount(int count, int request_id,
2228 bool final_update) {
2229 // If we have a message that has been queued up, then we should just replace
2230 // it. The ACK from the browser will make sure it gets sent when the browser
2231 // wants it.
2232 if (queued_find_reply_message_.get()) {
2233 IPC::Message* msg = new ViewHostMsg_Find_Reply(
2234 routing_id_,
2235 request_id,
2236 count,
[email protected]b3f2b912009-04-09 16:18:522237 gfx::Rect(),
initial.commit09911bf2008-07-26 23:55:292238 -1, // Don't update active match ordinal.
2239 final_update);
2240 queued_find_reply_message_.reset(msg);
2241 } else {
2242 // Send the search result over to the browser process.
2243 Send(new ViewHostMsg_Find_Reply(
2244 routing_id_,
2245 request_id,
2246 count,
[email protected]b3f2b912009-04-09 16:18:522247 gfx::Rect(),
initial.commit09911bf2008-07-26 23:55:292248 -1, // // Don't update active match ordinal.
2249 final_update));
2250 }
2251}
2252
2253void RenderView::ReportFindInPageSelection(int request_id,
2254 int active_match_ordinal,
[email protected]b3f2b912009-04-09 16:18:522255 const WebRect& selection_rect) {
initial.commit09911bf2008-07-26 23:55:292256 // Send the search result over to the browser process.
2257 Send(new ViewHostMsg_Find_Reply(routing_id_,
2258 request_id,
2259 -1,
2260 selection_rect,
2261 active_match_ordinal,
2262 false));
2263}
2264
[email protected]ed4bf2d2009-05-05 00:10:062265bool RenderView::WasOpenedByUserGesture() const {
initial.commit09911bf2008-07-26 23:55:292266 return opened_by_user_gesture_;
2267}
2268
[email protected]7f40fc5b2009-06-12 19:23:082269void RenderView::SpellCheck(const std::wstring& word, int* misspell_location,
2270 int* misspell_length) {
2271 Send(new ViewHostMsg_SpellCheck(routing_id_, word, misspell_location,
2272 misspell_length));
initial.commit09911bf2008-07-26 23:55:292273}
2274
[email protected]26ea6c42009-06-10 22:32:212275std::wstring RenderView::GetAutoCorrectWord(
2276 const std::wstring& misspelled_word) {
2277 std::wstring autocorrect_word;
[email protected]eda2b5a2009-05-12 19:30:212278 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
2279 if (command_line.HasSwitch(switches::kAutoSpellCorrect)) {
2280 Send(new ViewHostMsg_GetAutoCorrectWord(routing_id_, misspelled_word,
2281 &autocorrect_word));
2282 }
[email protected]26ea6c42009-06-10 22:32:212283
2284 return autocorrect_word;
[email protected]eda2b5a2009-05-12 19:30:212285}
2286
initial.commit09911bf2008-07-26 23:55:292287void RenderView::SetInputMethodState(bool enabled) {
2288 // Save the updated IME status and mark the input focus has been updated.
2289 // The IME status is to be sent to a browser process next time when
2290 // the input caret is rendered.
[email protected]9f23f592008-11-17 08:36:342291 if (!ime_control_busy_) {
2292 ime_control_updated_ = true;
2293 ime_control_new_state_ = enabled;
2294 }
initial.commit09911bf2008-07-26 23:55:292295}
2296
2297void RenderView::ScriptedPrint(WebFrame* frame) {
[email protected]0fda7272009-06-26 15:49:332298 Print(frame, true);
initial.commit09911bf2008-07-26 23:55:292299}
2300
initial.commit09911bf2008-07-26 23:55:292301void RenderView::UserMetricsRecordAction(const std::wstring& action) {
2302 Send(new ViewHostMsg_UserMetricsRecordAction(routing_id_, action));
2303}
2304
2305void RenderView::DnsPrefetch(const std::vector<std::string>& host_names) {
2306 Send(new ViewHostMsg_DnsPrefetch(host_names));
2307}
2308
[email protected]630e26b2008-10-14 22:55:172309void RenderView::OnZoom(int function) {
2310 static const bool kZoomIsTextOnly = false;
2311 switch (function) {
2312 case PageZoom::SMALLER:
2313 webview()->ZoomOut(kZoomIsTextOnly);
initial.commit09911bf2008-07-26 23:55:292314 break;
[email protected]630e26b2008-10-14 22:55:172315 case PageZoom::STANDARD:
2316 webview()->ResetZoom();
initial.commit09911bf2008-07-26 23:55:292317 break;
[email protected]630e26b2008-10-14 22:55:172318 case PageZoom::LARGER:
2319 webview()->ZoomIn(kZoomIsTextOnly);
initial.commit09911bf2008-07-26 23:55:292320 break;
2321 default:
2322 NOTREACHED();
2323 }
2324}
2325
[email protected]ea8c7452009-04-02 20:47:062326void RenderView::OnInsertText(const string16& text) {
[email protected]5f9e0b82009-05-08 22:13:392327 WebFrame* frame = webview()->GetFocusedFrame();
2328 if (!frame)
2329 return;
2330 WebTextInput* text_input = frame->GetTextInput();
[email protected]00d7e622009-04-21 23:06:052331 if (text_input)
[email protected]7be0e172009-05-14 01:05:272332 text_input->InsertText(text);
[email protected]ea8c7452009-04-02 20:47:062333}
2334
[email protected]e38f40152008-09-12 23:08:302335void RenderView::OnSetPageEncoding(const std::wstring& encoding_name) {
initial.commit09911bf2008-07-26 23:55:292336 webview()->SetPageEncoding(encoding_name);
2337}
2338
[email protected]f6e59a62009-05-13 21:12:032339void RenderView::NavigateBackForwardSoon(int offset) {
[email protected]f46aff62008-10-16 07:58:052340 history_back_list_count_ += offset;
2341 history_forward_list_count_ -= offset;
2342
initial.commit09911bf2008-07-26 23:55:292343 Send(new ViewHostMsg_GoToEntryAtOffset(routing_id_, offset));
2344}
2345
2346int RenderView::GetHistoryBackListCount() {
2347 return history_back_list_count_;
2348}
2349
2350int RenderView::GetHistoryForwardListCount() {
2351 return history_forward_list_count_;
2352}
2353
2354void RenderView::OnNavStateChanged(WebView* webview) {
[email protected]81a34412009-01-05 19:17:242355 if (!nav_state_sync_timer_.IsRunning()) {
2356 nav_state_sync_timer_.Start(
2357 TimeDelta::FromSeconds(delay_seconds_for_form_state_sync_), this,
2358 &RenderView::SyncNavigationState);
2359 }
initial.commit09911bf2008-07-26 23:55:292360}
2361
2362void RenderView::SetTooltipText(WebView* webview,
2363 const std::wstring& tooltip_text) {
2364 Send(new ViewHostMsg_SetTooltipText(routing_id_, tooltip_text));
2365}
2366
[email protected]2e417c82009-04-02 22:30:262367void RenderView::DidChangeSelection(bool is_empty_selection) {
2368#if defined(OS_LINUX)
[email protected]d5d7b8002009-05-18 21:20:542369 // TODO(estade): investigate incremental updates to the selection so that we
2370 // don't send the entire selection over IPC every time.
[email protected]2e417c82009-04-02 22:30:262371 if (!is_empty_selection) {
[email protected]d5d7b8002009-05-18 21:20:542372 // Sometimes we get repeated DidChangeSelection calls from webkit when
2373 // the selection hasn't actually changed. We don't want to report these
2374 // because it will cause us to continually claim the X clipboard.
2375 const std::string& this_selection =
2376 webview()->GetFocusedFrame()->GetSelection(false);
2377 if (this_selection == last_selection_)
2378 return;
2379
[email protected]dbadbcc2009-04-09 00:57:102380 Send(new ViewHostMsg_SelectionChanged(routing_id_,
[email protected]d5d7b8002009-05-18 21:20:542381 this_selection));
2382 last_selection_ = this_selection;
[email protected]4f61a022009-06-25 23:49:012383 } else {
2384 last_selection_.clear();
[email protected]2e417c82009-04-02 22:30:262385 }
2386#endif
2387}
2388
initial.commit09911bf2008-07-26 23:55:292389void RenderView::DownloadUrl(const GURL& url, const GURL& referrer) {
2390 Send(new ViewHostMsg_DownloadUrl(routing_id_, url, referrer));
2391}
2392
[email protected]0df30122009-06-03 12:13:082393void RenderView::UpdateInspectorSettings(const std::wstring& raw_settings) {
2394 Send(new ViewHostMsg_UpdateInspectorSettings(routing_id_, raw_settings));
2395}
2396
[email protected]611cad42009-03-16 18:51:342397WebDevToolsAgentDelegate* RenderView::GetWebDevToolsAgentDelegate() {
[email protected]b75b7d072009-04-06 13:47:002398 return devtools_agent_.get();
[email protected]611cad42009-03-16 18:51:342399}
2400
[email protected]ea8c7452009-04-02 20:47:062401void RenderView::PasteFromSelectionClipboard() {
2402 Send(new ViewHostMsg_PasteFromSelectionClipboard(routing_id_));
2403}
2404
initial.commit09911bf2008-07-26 23:55:292405WebFrame* RenderView::GetChildFrame(const std::wstring& frame_xpath) const {
2406 WebFrame* web_frame;
2407 if (frame_xpath.empty()) {
2408 web_frame = webview()->GetMainFrame();
2409 } else {
2410 web_frame = webview()->GetMainFrame()->GetChildFrame(frame_xpath);
2411 }
2412
2413 return web_frame;
2414}
2415
[email protected]f29acf52008-11-03 20:08:332416void RenderView::EvaluateScript(const std::wstring& frame_xpath,
2417 const std::wstring& script) {
initial.commit09911bf2008-07-26 23:55:292418 WebFrame* web_frame = GetChildFrame(frame_xpath);
2419 if (!web_frame)
2420 return;
2421
[email protected]4f999132009-03-31 18:08:402422 web_frame->ExecuteScript(WebScriptSource(WideToUTF16Hack(script)));
initial.commit09911bf2008-07-26 23:55:292423}
2424
[email protected]1810e132009-03-24 23:35:482425void RenderView::InsertCSS(const std::wstring& frame_xpath,
2426 const std::string& css) {
2427 WebFrame* web_frame = GetChildFrame(frame_xpath);
2428 if (!web_frame)
2429 return;
2430
2431 web_frame->InsertCSSStyles(css);
2432}
2433
initial.commit09911bf2008-07-26 23:55:292434void RenderView::OnScriptEvalRequest(const std::wstring& frame_xpath,
2435 const std::wstring& jscript) {
[email protected]f29acf52008-11-03 20:08:332436 EvaluateScript(frame_xpath, jscript);
initial.commit09911bf2008-07-26 23:55:292437}
2438
[email protected]1810e132009-03-24 23:35:482439void RenderView::OnCSSInsertRequest(const std::wstring& frame_xpath,
2440 const std::string& css) {
2441 InsertCSS(frame_xpath, css);
[email protected]ae461542009-06-19 19:03:412442
2443 // Notify RenderViewHost that css has been inserted into the frame.
2444 Send(new ViewHostMsg_OnCSSInserted(routing_id_));
[email protected]1810e132009-03-24 23:35:482445}
2446
[email protected]7ea066a2009-04-06 20:21:592447void RenderView::OnAddMessageToConsole(
2448 const string16& frame_xpath,
2449 const string16& message,
2450 const WebConsoleMessage::Level& level) {
2451 WebFrame* web_frame = GetChildFrame(UTF16ToWideHack(frame_xpath));
[email protected]0dea3ea2009-03-31 23:30:592452 if (web_frame)
[email protected]7ea066a2009-04-06 20:21:592453 web_frame->AddMessageToConsole(WebConsoleMessage(level, message));
initial.commit09911bf2008-07-26 23:55:292454}
2455
[email protected]81e63782009-02-27 19:35:092456void RenderView::OnAllowBindings(int enabled_bindings_flags) {
2457 enabled_bindings_ |= enabled_bindings_flags;
initial.commit09911bf2008-07-26 23:55:292458}
2459
2460void RenderView::OnSetDOMUIProperty(const std::string& name,
2461 const std::string& value) {
[email protected]81e63782009-02-27 19:35:092462 DCHECK(BindingsPolicy::is_dom_ui_enabled(enabled_bindings_));
initial.commit09911bf2008-07-26 23:55:292463 dom_ui_bindings_.SetProperty(name, value);
2464}
2465
2466void RenderView::OnReservePageIDRange(int size_of_range) {
2467 next_page_id_ += size_of_range + 1;
2468}
2469
[email protected]e80c73b2009-04-07 23:24:582470void RenderView::OnDragSourceEndedOrMoved(const gfx::Point& client_point,
2471 const gfx::Point& screen_point,
[email protected]5f9ae6c2009-07-08 02:38:032472 bool ended, bool cancelled) {
2473 if (ended) {
2474 if (cancelled)
2475 webview()->DragSourceCancelledAt(client_point, screen_point);
2476 else
2477 webview()->DragSourceEndedAt(client_point, screen_point);
2478 } else {
[email protected]e80c73b2009-04-07 23:24:582479 webview()->DragSourceMovedTo(client_point, screen_point);
[email protected]5f9ae6c2009-07-08 02:38:032480 }
initial.commit09911bf2008-07-26 23:55:292481}
2482
2483void RenderView::OnDragSourceSystemDragEnded() {
2484 webview()->DragSourceSystemDragEnded();
2485}
2486
2487void RenderView::OnUploadFileRequest(const ViewMsg_UploadFile_Params& p) {
2488 webkit_glue::FileUploadData* f = new webkit_glue::FileUploadData;
2489 f->file_path = p.file_path;
2490 f->form_name = p.form;
2491 f->file_name = p.file;
2492 f->submit_name = p.submit;
2493
2494 // Build the other form values map.
2495 if (!p.other_values.empty()) {
2496 std::vector<std::wstring> e;
2497 std::vector<std::wstring> kvp;
2498 std::vector<std::wstring>::iterator i;
2499
2500 SplitString(p.other_values, L'\n', &e);
2501 for (i = e.begin(); i != e.end(); ++i) {
2502 SplitString(*i, L'=', &kvp);
2503 if (kvp.size() == 2)
2504 f->other_form_values[kvp[0]] = kvp[1];
2505 kvp.clear();
2506 }
2507 }
2508
2509 pending_upload_data_.reset(f);
2510 ProcessPendingUpload();
2511}
2512
2513void RenderView::ProcessPendingUpload() {
2514 webkit_glue::FileUploadData* f = pending_upload_data_.get();
2515 if (f && webview() && webkit_glue::FillFormToUploadFile(webview(), *f))
2516 ResetPendingUpload();
2517}
2518
2519void RenderView::ResetPendingUpload() {
2520 pending_upload_data_.reset();
2521}
2522
2523void RenderView::OnFormFill(const FormData& form) {
2524 webkit_glue::FillForm(this->webview(), form);
2525}
2526
2527void RenderView::OnFillPasswordForm(
[email protected]daa8c58e2009-06-15 17:21:102528 const webkit_glue::PasswordFormDomManager::FillData& form_data) {
initial.commit09911bf2008-07-26 23:55:292529 webkit_glue::FillPasswordForm(this->webview(), form_data);
2530}
2531
2532void RenderView::OnDragTargetDragEnter(const WebDropData& drop_data,
[email protected]e80c73b2009-04-07 23:24:582533 const gfx::Point& client_point,
2534 const gfx::Point& screen_point) {
2535 bool is_drop_target = webview()->DragTargetDragEnter(
2536 drop_data.ToDragData(),
2537 drop_data.identity,
2538 client_point,
2539 screen_point);
initial.commit09911bf2008-07-26 23:55:292540
2541 Send(new ViewHostMsg_UpdateDragCursor(routing_id_, is_drop_target));
2542}
2543
[email protected]e80c73b2009-04-07 23:24:582544void RenderView::OnDragTargetDragOver(const gfx::Point& client_point,
2545 const gfx::Point& screen_point) {
2546 bool is_drop_target =
2547 webview()->DragTargetDragOver(client_point, screen_point);
initial.commit09911bf2008-07-26 23:55:292548
2549 Send(new ViewHostMsg_UpdateDragCursor(routing_id_, is_drop_target));
2550}
2551
2552void RenderView::OnDragTargetDragLeave() {
2553 webview()->DragTargetDragLeave();
2554}
2555
[email protected]e80c73b2009-04-07 23:24:582556void RenderView::OnDragTargetDrop(const gfx::Point& client_point,
2557 const gfx::Point& screen_point) {
2558 webview()->DragTargetDrop(client_point, screen_point);
initial.commit09911bf2008-07-26 23:55:292559}
2560
2561void RenderView::OnUpdateWebPreferences(const WebPreferences& prefs) {
2562 webview()->SetPreferences(prefs);
2563}
2564
2565void RenderView::OnSetAltErrorPageURL(const GURL& url) {
2566 alternate_error_page_url_ = url;
2567}
2568
initial.commit09911bf2008-07-26 23:55:292569void RenderView::OnInstallMissingPlugin() {
2570 // This could happen when the first default plugin is deleted.
2571 if (first_default_plugin_ == NULL)
2572 return;
2573 first_default_plugin_->InstallMissingPlugin();
2574}
2575
[email protected]b62d1a8c2009-01-13 23:54:572576void RenderView::OnFileChooserResponse(
[email protected]561abe62009-04-06 18:08:342577 const std::vector<FilePath>& file_names) {
[email protected]8029f5672009-03-20 22:33:362578 // This could happen if we navigated to a different page before the user
2579 // closed the chooser.
2580 if (!file_chooser_.get())
2581 return;
2582
[email protected]b62d1a8c2009-01-13 23:54:572583 file_chooser_->OnFileChoose(file_names);
initial.commit09911bf2008-07-26 23:55:292584 file_chooser_.reset();
2585}
2586
2587void RenderView::OnEnableViewSourceMode() {
2588 if (!webview())
2589 return;
2590 WebFrame* main_frame = webview()->GetMainFrame();
2591 if (!main_frame)
2592 return;
2593
2594 main_frame->SetInViewSourceMode(true);
2595}
2596
[email protected]0666aef2009-05-13 19:48:082597void RenderView::OnEnableIntrinsicWidthChangedMode() {
2598 send_preferred_width_changes_ = true;
2599}
2600
[email protected]80d96fa2009-06-10 22:34:512601void RenderView::OnSetRendererPrefs(const RendererPreferences& renderer_prefs) {
2602 renderer_preferences_ = renderer_prefs;
2603}
2604
initial.commit09911bf2008-07-26 23:55:292605void RenderView::OnUpdateBackForwardListCount(int back_list_count,
2606 int forward_list_count) {
2607 history_back_list_count_ = back_list_count;
2608 history_forward_list_count_ = forward_list_count;
2609}
2610
[email protected]266eb6f2008-09-30 23:56:502611void RenderView::OnGetAccessibilityInfo(
[email protected]6a983b42009-03-20 20:12:252612 const webkit_glue::WebAccessibility::InParams& in_params,
2613 webkit_glue::WebAccessibility::OutParams* out_params) {
[email protected]6c8afae52009-01-22 02:24:572614#if defined(OS_WIN)
[email protected]6a983b42009-03-20 20:12:252615 if (!web_accessibility_manager_.get()) {
2616 web_accessibility_manager_.reset(
2617 webkit_glue::WebAccessibilityManager::Create());
2618 }
[email protected]266eb6f2008-09-30 23:56:502619
[email protected]6a983b42009-03-20 20:12:252620 if (!web_accessibility_manager_->GetAccObjInfo(webview(), in_params,
2621 out_params)) {
[email protected]266eb6f2008-09-30 23:56:502622 return;
2623 }
[email protected]6c8afae52009-01-22 02:24:572624#else // defined(OS_WIN)
2625 // TODO(port): accessibility not yet implemented
2626 NOTIMPLEMENTED();
2627#endif
[email protected]266eb6f2008-09-30 23:56:502628}
2629
[email protected]6a983b42009-03-20 20:12:252630void RenderView::OnClearAccessibilityInfo(int acc_obj_id, bool clear_all) {
[email protected]6c8afae52009-01-22 02:24:572631#if defined(OS_WIN)
[email protected]6a983b42009-03-20 20:12:252632 if (!web_accessibility_manager_.get()) {
[email protected]266eb6f2008-09-30 23:56:502633 // If accessibility is not activated, ignore clearing message.
2634 return;
2635 }
[email protected]e846d0d2009-05-20 00:53:062636
[email protected]6a983b42009-03-20 20:12:252637 if (!web_accessibility_manager_->ClearAccObjMap(acc_obj_id, clear_all))
[email protected]266eb6f2008-09-30 23:56:502638 return;
[email protected]e846d0d2009-05-20 00:53:062639
[email protected]6c8afae52009-01-22 02:24:572640#else // defined(OS_WIN)
2641 // TODO(port): accessibility not yet implemented
2642 NOTIMPLEMENTED();
2643#endif
[email protected]266eb6f2008-09-30 23:56:502644}
2645
initial.commit09911bf2008-07-26 23:55:292646void RenderView::OnGetAllSavableResourceLinksForCurrentPage(
2647 const GURL& page_url) {
2648 // Prepare list to storage all savable resource links.
2649 std::vector<GURL> resources_list;
2650 std::vector<GURL> referrers_list;
2651 std::vector<GURL> frames_list;
2652 webkit_glue::SavableResourcesResult result(&resources_list,
2653 &referrers_list,
2654 &frames_list);
2655
2656 if (!webkit_glue::GetAllSavableResourceLinksForCurrentPage(webview(),
2657 page_url,
2658 &result)) {
2659 // If something is wrong when collecting all savable resource links,
2660 // send empty list to embedder(browser) to tell it failed.
2661 referrers_list.clear();
2662 resources_list.clear();
2663 frames_list.clear();
2664 }
2665
2666 // Send result of all savable resource links to embedder.
2667 Send(new ViewHostMsg_SendCurrentPageAllSavableResourceLinks(routing_id_,
2668 resources_list,
2669 referrers_list,
2670 frames_list));
2671}
2672
2673void RenderView::OnGetSerializedHtmlDataForCurrentPageWithLocalLinks(
[email protected]f6b48532009-02-12 01:56:322674 const std::vector<GURL>& links,
[email protected]fde6714d12009-02-18 22:39:312675 const std::vector<FilePath>& local_paths,
2676 const FilePath& local_directory_name) {
initial.commit09911bf2008-07-26 23:55:292677 webkit_glue::DomSerializer dom_serializer(webview()->GetMainFrame(),
2678 true,
2679 this,
2680 links,
2681 local_paths,
2682 local_directory_name);
2683 dom_serializer.SerializeDom();
2684}
2685
2686void RenderView::DidSerializeDataForFrame(const GURL& frame_url,
2687 const std::string& data, PageSavingSerializationStatus status) {
2688 Send(new ViewHostMsg_SendSerializedHtmlData(routing_id_,
2689 frame_url, data, static_cast<int32>(status)));
2690}
2691
[email protected]04b4a6c2008-08-02 00:44:472692void RenderView::OnMsgShouldClose() {
initial.commit09911bf2008-07-26 23:55:292693 bool should_close = webview()->ShouldClose();
[email protected]04b4a6c2008-08-02 00:44:472694 Send(new ViewHostMsg_ShouldClose_ACK(routing_id_, should_close));
initial.commit09911bf2008-07-26 23:55:292695}
2696
2697void RenderView::OnClosePage(int new_render_process_host_id,
[email protected]04b4a6c2008-08-02 00:44:472698 int new_request_id) {
initial.commit09911bf2008-07-26 23:55:292699 // TODO(creis): We'd rather use webview()->Close() here, but that currently
2700 // sets the WebView's delegate_ to NULL, preventing any JavaScript dialogs
2701 // in the onunload handler from appearing. For now, we're bypassing that and
2702 // calling the FrameLoader's CloseURL method directly. This should be
2703 // revisited to avoid having two ways to close a page. Having a single way
2704 // to close that can run onunload is also useful for fixing
2705 // http://b/issue?id=753080.
2706 WebFrame* main_frame = webview()->GetMainFrame();
[email protected]7a9b51f2009-06-29 21:28:292707 if (main_frame) {
2708 const GURL& url = main_frame->GetURL();
2709 // TODO(davemoore) this code should be removed once WillCloseFrame() gets
2710 // called when a page is destroyed. DumpLoadHistograms() is safe to call
2711 // multiple times for the same frame, but it will simplify things.
2712 if (url.SchemeIs("http") || url.SchemeIs("https"))
2713 DumpLoadHistograms();
initial.commit09911bf2008-07-26 23:55:292714 main_frame->ClosePage();
[email protected]7a9b51f2009-06-29 21:28:292715 }
initial.commit09911bf2008-07-26 23:55:292716
2717 Send(new ViewHostMsg_ClosePage_ACK(routing_id_,
2718 new_render_process_host_id,
[email protected]04b4a6c2008-08-02 00:44:472719 new_request_id));
initial.commit09911bf2008-07-26 23:55:292720}
2721
2722void RenderView::OnThemeChanged() {
[email protected]6c8afae52009-01-22 02:24:572723#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:292724 gfx::NativeTheme::instance()->CloseHandles();
2725 gfx::Rect view_rect(0, 0, size_.width(), size_.height());
2726 DidInvalidateRect(webwidget_, view_rect);
[email protected]6c8afae52009-01-22 02:24:572727#else // defined(OS_WIN)
2728 // TODO(port): we don't support theming on non-Windows platforms yet
2729 NOTIMPLEMENTED();
2730#endif
initial.commit09911bf2008-07-26 23:55:292731}
2732
[email protected]f46aff62008-10-16 07:58:052733void RenderView::DidAddHistoryItem() {
[email protected]f8901082008-10-31 23:34:032734 // We don't want to update the history length for the start page
2735 // navigation.
2736 WebFrame* main_frame = webview()->GetMainFrame();
2737 DCHECK(main_frame != NULL);
2738
2739 WebDataSource* ds = main_frame->GetDataSource();
2740 DCHECK(ds != NULL);
2741
[email protected]daa8c58e2009-06-15 17:21:102742 NavigationState* navigation_state = NavigationState::FromDataSource(ds);
[email protected]78a3a6f2009-07-02 16:15:012743 DCHECK(navigation_state);
[email protected]daa8c58e2009-06-15 17:21:102744 if (navigation_state->transition_type() == PageTransition::START_PAGE)
[email protected]f8901082008-10-31 23:34:032745 return;
2746
[email protected]f46aff62008-10-16 07:58:052747 history_back_list_count_++;
2748 history_forward_list_count_ = 0;
2749}
2750
[email protected]28790922009-03-09 19:48:372751void RenderView::OnMessageFromExternalHost(const std::string& message,
2752 const std::string& origin,
2753 const std::string& target) {
[email protected]3ac14a052008-08-15 21:22:152754 if (message.empty())
2755 return;
2756
[email protected]28790922009-03-09 19:48:372757 external_host_bindings_.ForwardMessageFromExternalHost(message, origin,
2758 target);
[email protected]3ac14a052008-08-15 21:22:152759}
2760
[email protected]0aa55312008-10-17 21:53:082761void RenderView::OnDisassociateFromPopupCount() {
2762 if (decrement_shared_popup_at_destruction_)
2763 shared_popup_counter_->data--;
2764 shared_popup_counter_ = new SharedRenderViewCounter(0);
2765 decrement_shared_popup_at_destruction_ = false;
2766}
2767
initial.commit09911bf2008-07-26 23:55:292768std::string RenderView::GetAltHTMLForTemplate(
2769 const DictionaryValue& error_strings, int template_resource_id) const {
2770 const StringPiece template_html(
2771 ResourceBundle::GetSharedInstance().GetRawDataResource(
2772 template_resource_id));
2773
2774 if (template_html.empty()) {
2775 NOTREACHED() << "unable to load template. ID: " << template_resource_id;
2776 return "";
2777 }
2778 // "t" is the id of the templates root node.
2779 return jstemplate_builder::GetTemplateHtml(
2780 template_html, &error_strings, "t");
2781}
[email protected]0e79b9e2009-02-13 04:20:482782
2783MessageLoop* RenderView::GetMessageLoopForIO() {
2784 // Assume that we have only one RenderThread in the process and the owner loop
2785 // of RenderThread is an IO message loop.
[email protected]8930d472009-02-21 08:05:282786 if (RenderThread::current())
2787 return RenderThread::current()->owner_loop();
[email protected]0e79b9e2009-02-13 04:20:482788 return NULL;
2789}
[email protected]6f56d482009-02-20 05:02:562790
[email protected]30f75e62009-02-25 22:01:002791void RenderView::OnMoveOrResizeStarted() {
2792 if (webview())
2793 webview()->HideAutofillPopup();
2794}
2795
[email protected]30f75e62009-02-25 22:01:002796void RenderView::OnResize(const gfx::Size& new_size,
2797 const gfx::Rect& resizer_rect) {
2798 if (webview())
2799 webview()->HideAutofillPopup();
2800 RenderWidget::OnResize(new_size, resizer_rect);
2801}
[email protected]0aa477bd2009-03-23 22:21:432802
[email protected]05d478752009-04-08 23:38:162803void RenderView::OnClearFocusedNode() {
2804 if (webview())
2805 webview()->ClearFocusedNode();
2806}
2807
[email protected]699ab0d2009-04-23 23:19:142808void RenderView::OnSetBackground(const SkBitmap& background) {
2809 if (webview())
2810 webview()->SetIsTransparent(!background.empty());
2811
2812 SetBackground(background);
2813}
2814
[email protected]309d7a282009-03-24 09:18:272815void RenderView::SendExtensionRequest(const std::string& name,
2816 const std::string& args,
[email protected]c6619182009-05-12 14:59:322817 int request_id,
[email protected]2f25d7b92009-06-10 00:06:472818 bool has_callback) {
[email protected]c6619182009-05-12 14:59:322819 Send(new ViewHostMsg_ExtensionRequest(routing_id_, name, args, request_id,
[email protected]2f25d7b92009-06-10 00:06:472820 has_callback));
[email protected]309d7a282009-03-24 09:18:272821}
2822
[email protected]c6619182009-05-12 14:59:322823void RenderView::OnExtensionResponse(int request_id,
2824 bool success,
2825 const std::string& response,
2826 const std::string& error) {
[email protected]0f6053962009-07-09 19:26:352827 ExtensionProcessBindings::HandleResponse(
2828 request_id, success, response, error);
[email protected]309d7a282009-03-24 09:18:272829}
[email protected]c20210e62009-04-03 21:39:262830
[email protected]e7e4f3c2009-04-21 15:24:082831// Dump all load time histograms.
[email protected]c20210e62009-04-03 21:39:262832//
[email protected]7a9b51f2009-06-29 21:28:292833// There are 13 histograms measuring various times.
[email protected]c20210e62009-04-03 21:39:262834// The time points we keep are
2835// request: time document was requested by user
2836// start: time load of document started
[email protected]a2f6bc112009-06-27 16:27:252837// commit: time load of document started
[email protected]7a9b51f2009-06-29 21:28:292838// finish_document: main document loaded, before onload()
[email protected]c20210e62009-04-03 21:39:262839// finish: after onload() and all resources are loaded
[email protected]7a9b51f2009-06-29 21:28:292840// first_paint: first paint performed
2841// first_paint_after_load: first paint performed after load is finished
2842// begin: request if it was user requested, start otherwise
2843//
[email protected]c20210e62009-04-03 21:39:262844// The times that we histogram are
[email protected]a2f6bc112009-06-27 16:27:252845// request->start,
[email protected]7a9b51f2009-06-29 21:28:292846// start->commit,
2847// commit->finish_document,
2848// finish_document->finish,
2849// begin->commit,
2850// begin->finishDoc,
2851// begin->finish,
2852// begin->first_paint,
2853// begin->first_paint_after_load
2854// commit->finishDoc,
2855// commit->first_paint,
2856// commit->first_paint_after_load,
2857// finish->first_paint_after_load,
[email protected]c20210e62009-04-03 21:39:262858//
[email protected]e7e4f3c2009-04-21 15:24:082859// It's possible for the request time not to be set, if a client
2860// redirect had been done (the user never requested the page)
2861// Also, it's possible to load a page without ever laying it out
[email protected]7a9b51f2009-06-29 21:28:292862// so first_paint and first_paint_after_load can be 0.
[email protected]c20210e62009-04-03 21:39:262863void RenderView::DumpLoadHistograms() const {
2864 WebFrame* main_frame = webview()->GetMainFrame();
[email protected]ed3fb032009-06-16 19:50:562865 NavigationState* navigation_state =
2866 NavigationState::FromDataSource(main_frame->GetDataSource());
[email protected]7a9b51f2009-06-29 21:28:292867 Time finish = navigation_state->finish_load_time();
[email protected]ed3fb032009-06-16 19:50:562868
[email protected]7a9b51f2009-06-29 21:28:292869 // If we've already dumped or we haven't finished loading, do nothing.
2870 if (navigation_state->load_histograms_recorded() || finish.is_null())
2871 return;
[email protected]ed3fb032009-06-16 19:50:562872
[email protected]7a9b51f2009-06-29 21:28:292873 Time request = navigation_state->request_time();
2874 Time start = navigation_state->start_load_time();
2875 Time commit = navigation_state->commit_load_time();
2876 Time finish_doc = navigation_state->finish_document_load_time();
2877 Time first_paint = navigation_state->first_paint_time();
2878 Time first_paint_after_load =
2879 navigation_state->first_paint_after_load_time();
[email protected]c20210e62009-04-03 21:39:262880
[email protected]7a9b51f2009-06-29 21:28:292881 Time begin;
2882 // Client side redirects will have no request time.
2883 if (request.is_null()) {
2884 begin = start;
2885 } else {
2886 begin = request;
2887 UMA_HISTOGRAM_MEDIUM_TIMES("Renderer4.RequestToStart", start - request);
[email protected]e7e4f3c2009-04-21 15:24:082888 }
[email protected]7a9b51f2009-06-29 21:28:292889 UMA_HISTOGRAM_MEDIUM_TIMES("Renderer4.StartToCommit", commit - start);
2890 UMA_HISTOGRAM_MEDIUM_TIMES(
2891 "Renderer4.CommitToFinishDoc", finish_doc - commit);
2892 UMA_HISTOGRAM_MEDIUM_TIMES(
2893 "Renderer4.FinishDocToFinish", finish - finish_doc);
2894
2895 UMA_HISTOGRAM_MEDIUM_TIMES("Renderer4.BeginToCommit", commit - begin);
2896 UMA_HISTOGRAM_MEDIUM_TIMES("Renderer4.BeginToFinishDoc", finish_doc - begin);
[email protected]e695fbd62009-06-30 16:31:542897
2898 static const TimeDelta kBeginToFinishMin(TimeDelta::FromMilliseconds(10));
2899 static const TimeDelta kBeginToFinishMax(TimeDelta::FromMinutes(10));
2900 static const size_t kBeginToFinishBucketCount(100);
2901
2902 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer4.BeginToFinish",
2903 finish - begin, kBeginToFinishMin,
2904 kBeginToFinishMax, kBeginToFinishBucketCount);
[email protected]0a32257a2009-07-09 18:10:412905 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer4.StartToFinish",
2906 finish - start, kBeginToFinishMin,
2907 kBeginToFinishMax, kBeginToFinishBucketCount);
2908 if (!request.is_null())
2909 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer4.RequestToFinish",
2910 finish - request, kBeginToFinishMin,
2911 kBeginToFinishMax, kBeginToFinishBucketCount);
[email protected]e695fbd62009-06-30 16:31:542912
[email protected]36285b52009-06-30 19:10:002913 static bool use_dns_histogram(FieldTrialList::Find("DnsImpact") &&
2914 !FieldTrialList::Find("DnsImpact")->group_name().empty());
[email protected]0a32257a2009-07-09 18:10:412915 if (use_dns_histogram) {
[email protected]36285b52009-06-30 19:10:002916 UMA_HISTOGRAM_CUSTOM_TIMES(
2917 FieldTrial::MakeName("Renderer4.BeginToFinish", "DnsImpact").data(),
2918 finish - begin, kBeginToFinishMin,
2919 kBeginToFinishMax, kBeginToFinishBucketCount);
[email protected]0a32257a2009-07-09 18:10:412920 UMA_HISTOGRAM_CUSTOM_TIMES(
2921 FieldTrial::MakeName("Renderer4.StartToFinish", "DnsImpact").data(),
2922 finish - start, kBeginToFinishMin,
2923 kBeginToFinishMax, kBeginToFinishBucketCount);
2924 if (!request.is_null())
2925 UMA_HISTOGRAM_CUSTOM_TIMES(
2926 FieldTrial::MakeName("Renderer4.RequestToFinish", "DnsImpact").data(),
2927 finish - request, kBeginToFinishMin,
2928 kBeginToFinishMax, kBeginToFinishBucketCount);
2929 }
[email protected]e695fbd62009-06-30 16:31:542930
[email protected]36285b52009-06-30 19:10:002931 static bool use_sdch_histogram(FieldTrialList::Find("GlobalSdch") &&
2932 !FieldTrialList::Find("GlobalSdch")->group_name().empty());
[email protected]0a32257a2009-07-09 18:10:412933 if (use_sdch_histogram) {
[email protected]36285b52009-06-30 19:10:002934 UMA_HISTOGRAM_CUSTOM_TIMES(
2935 FieldTrial::MakeName("Renderer4.BeginToFinish", "GlobalSdch").data(),
2936 finish - begin, kBeginToFinishMin,
2937 kBeginToFinishMax, kBeginToFinishBucketCount);
[email protected]0a32257a2009-07-09 18:10:412938 UMA_HISTOGRAM_CUSTOM_TIMES(
2939 FieldTrial::MakeName("Renderer4.StartToFinish", "GlobalSdch").data(),
2940 finish - start, kBeginToFinishMin,
2941 kBeginToFinishMax, kBeginToFinishBucketCount);
2942 if (!request.is_null())
2943 UMA_HISTOGRAM_CUSTOM_TIMES(
2944 FieldTrial::MakeName("Renderer4.RequestToFinish",
2945 "GlobalSdch").data(),
2946 finish - request, kBeginToFinishMin,
2947 kBeginToFinishMax, kBeginToFinishBucketCount);
2948 }
[email protected]7a9b51f2009-06-29 21:28:292949
[email protected]7e05f6c42009-07-11 01:50:482950 static bool use_cache_histogram1(FieldTrialList::Find("CacheSize") &&
2951 !FieldTrialList::Find("CacheSize")->group_name().empty());
2952 if (use_cache_histogram1)
2953 UMA_HISTOGRAM_CUSTOM_TIMES(
2954 FieldTrial::MakeName("Renderer4.StartToFinish", "CacheSize").data(),
2955 finish - start, kBeginToFinishMin,
2956 kBeginToFinishMax, kBeginToFinishBucketCount);
2957
2958 static bool use_cache_histogram2(FieldTrialList::Find("NewEviction") &&
2959 !FieldTrialList::Find("NewEviction")->group_name().empty());
2960 if (use_cache_histogram2)
2961 UMA_HISTOGRAM_CUSTOM_TIMES(
2962 FieldTrial::MakeName("Renderer4.StartToFinish", "NewEviction").data(),
2963 finish - start, kBeginToFinishMin,
2964 kBeginToFinishMax, kBeginToFinishBucketCount);
2965
[email protected]7a9b51f2009-06-29 21:28:292966 UMA_HISTOGRAM_MEDIUM_TIMES("Renderer4.CommitToFinish", finish - commit);
2967
2968 if (!first_paint.is_null()) {
2969 UMA_HISTOGRAM_MEDIUM_TIMES(
2970 "Renderer4.BeginToFirstPaint", first_paint - begin);
2971 UMA_HISTOGRAM_MEDIUM_TIMES(
2972 "Renderer4.CommitToFirstPaint", first_paint - commit);
[email protected]c20210e62009-04-03 21:39:262973 }
[email protected]7a9b51f2009-06-29 21:28:292974
2975 if (!first_paint_after_load.is_null()) {
2976 UMA_HISTOGRAM_MEDIUM_TIMES(
2977 "Renderer4.BeginToFirstPaintAfterLoad", first_paint_after_load - begin);
2978 UMA_HISTOGRAM_MEDIUM_TIMES(
2979 "Renderer4.CommitToFirstPaintAfterLoad",
2980 first_paint_after_load - commit);
2981 UMA_HISTOGRAM_MEDIUM_TIMES(
2982 "Renderer4.FinishToFirstPaintAfterLoad",
2983 first_paint_after_load - finish);
2984 }
2985
2986 navigation_state->set_load_histograms_recorded(true);
[email protected]c20210e62009-04-03 21:39:262987}
[email protected]e846d0d2009-05-20 00:53:062988
2989void RenderView::FocusAccessibilityObject(
2990 WebCore::AccessibilityObject* acc_obj) {
2991#if defined(OS_WIN)
2992 if (!web_accessibility_manager_.get()) {
2993 web_accessibility_manager_.reset(
2994 webkit_glue::WebAccessibilityManager::Create());
2995 }
2996
2997 // Retrieve the accessibility object id of the AccessibilityObject.
2998 int acc_obj_id = web_accessibility_manager_->FocusAccObj(acc_obj);
2999
3000 // If id is valid, alert the browser side that an accessibility focus change
3001 // occurred.
3002 if (acc_obj_id >= 0)
3003 Send(new ViewHostMsg_AccessibilityFocusChange(routing_id_, acc_obj_id));
3004
3005#else // defined(OS_WIN)
3006 // TODO(port): accessibility not yet implemented
3007 NOTIMPLEMENTED();
3008#endif
3009}
[email protected]daa8c58e2009-06-15 17:21:103010
3011void RenderView::SendPasswordForms(WebFrame* frame) {
3012 std::vector<WebForm> forms;
3013 frame->GetForms(&forms);
3014
3015 std::vector<PasswordForm> password_forms;
3016 for (size_t i = 0; i < forms.size(); ++i) {
3017 const WebForm& form = forms[i];
3018
3019 // Respect autocomplete=off.
3020 if (form.isAutoCompleteEnabled()) {
3021 scoped_ptr<PasswordForm> password_form(
3022 PasswordFormDomManager::CreatePasswordForm(form));
3023 if (password_form.get())
3024 password_forms.push_back(*password_form);
3025 }
3026 }
3027
3028 if (!password_forms.empty())
3029 Send(new ViewHostMsg_PasswordFormsSeen(routing_id_, password_forms));
3030}
[email protected]0fda7272009-06-26 15:49:333031
3032void RenderView::Print(WebFrame* frame, bool script_initiated) {
3033 DCHECK(frame);
3034 if (print_helper_.get() == NULL) {
3035 print_helper_.reset(new PrintWebViewHelper(this));
3036 }
3037 print_helper_->Print(frame, script_initiated);
3038}