blob: a38a710d96fef8e96051f087c89436b4e1b9feff [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"
initial.commit09911bf2008-07-26 23:55:2918#include "base/gfx/png_encoder.h"
[email protected]18bcc3c2009-01-27 21:39:1519#include "base/gfx/native_widget_types.h"
initial.commit09911bf2008-07-26 23:55:2920#include "base/string_piece.h"
21#include "base/string_util.h"
[email protected]6c8afae52009-01-22 02:24:5722#include "build/build_config.h"
[email protected]81e63782009-02-27 19:35:0923#include "chrome/common/bindings_policy.h"
initial.commit09911bf2008-07-26 23:55:2924#include "chrome/common/chrome_switches.h"
initial.commit09911bf2008-07-26 23:55:2925#include "chrome/common/jstemplate_builder.h"
[email protected]630e26b2008-10-14 22:55:1726#include "chrome/common/page_zoom.h"
[email protected]e09ba552009-02-05 03:26:2927#include "chrome/common/render_messages.h"
initial.commit09911bf2008-07-26 23:55:2928#include "chrome/common/thumbnail_score.h"
[email protected]6de74452009-02-25 18:04:5929#include "chrome/common/url_constants.h"
initial.commit09911bf2008-07-26 23:55:2930#include "chrome/renderer/about_handler.h"
[email protected]5fb88962009-04-16 19:03:2531#include "chrome/renderer/audio_message_filter.h"
initial.commit09911bf2008-07-26 23:55:2932#include "chrome/renderer/debug_message_handler.h"
[email protected]e4ac5df2009-03-17 15:33:1133#include "chrome/renderer/devtools_agent.h"
34#include "chrome/renderer/devtools_client.h"
[email protected]309d7a282009-03-24 09:18:2735#include "chrome/renderer/extensions/extension_process_bindings.h"
initial.commit09911bf2008-07-26 23:55:2936#include "chrome/renderer/localized_error.h"
[email protected]6f56d482009-02-20 05:02:5637#include "chrome/renderer/media/audio_renderer_impl.h"
[email protected]39008c02009-02-11 23:59:2538#include "chrome/renderer/render_process.h"
[email protected]fcf19542009-03-30 21:24:0739#include "chrome/renderer/renderer_logging.h"
[email protected]0938d3c2009-01-09 20:37:3540#include "chrome/renderer/user_script_slave.h"
initial.commit09911bf2008-07-26 23:55:2941#include "chrome/renderer/visitedlink_slave.h"
[email protected]4e6be3f2009-05-07 02:24:4442#include "chrome/renderer/webmediaplayer_impl.h"
[email protected]ba4b17f2009-02-11 21:32:2943#include "chrome/renderer/webplugin_delegate_proxy.h"
[email protected]eb47a132009-03-04 00:39:5644#include "chrome/renderer/webworker_proxy.h"
[email protected]34ac8f32009-02-22 23:03:2745#include "grit/generated_resources.h"
46#include "grit/renderer_resources.h"
[email protected]f11ca0732009-04-11 00:09:3447#include "net/base/data_url.h"
initial.commit09911bf2008-07-26 23:55:2948#include "net/base/escape.h"
49#include "net/base/net_errors.h"
[email protected]88a3ecc2009-03-19 17:36:2250#include "printing/units.h"
[email protected]c399a8a2008-11-22 19:38:0051#include "skia/ext/bitmap_platform_device.h"
[email protected]83c9e6552008-12-03 16:22:1052#include "skia/ext/image_operations.h"
[email protected]afdcf5c2009-05-10 20:30:4153#include "webkit/api/public/WebDragData.h"
54#include "webkit/api/public/WebPoint.h"
55#include "webkit/api/public/WebRect.h"
56#include "webkit/api/public/WebScriptSource.h"
57#include "webkit/api/public/WebSize.h"
[email protected]ba4b17f2009-02-11 21:32:2958#include "webkit/default_plugin/default_plugin_shared.h"
initial.commit09911bf2008-07-26 23:55:2959#include "webkit/glue/dom_operations.h"
60#include "webkit/glue/dom_serializer.h"
[email protected]f11ca0732009-04-11 00:09:3461#include "webkit/glue/image_decoder.h"
initial.commit09911bf2008-07-26 23:55:2962#include "webkit/glue/password_form.h"
[email protected]ba4b17f2009-02-11 21:32:2963#include "webkit/glue/plugins/plugin_list.h"
initial.commit09911bf2008-07-26 23:55:2964#include "webkit/glue/searchable_form_data.h"
[email protected]6a983b42009-03-20 20:12:2565#include "webkit/glue/webaccessibilitymanager_impl.h"
initial.commit09911bf2008-07-26 23:55:2966#include "webkit/glue/webdatasource.h"
[email protected]611cad42009-03-16 18:51:3467#include "webkit/glue/webdevtoolsagent_delegate.h"
initial.commit09911bf2008-07-26 23:55:2968#include "webkit/glue/webdropdata.h"
69#include "webkit/glue/weberror.h"
70#include "webkit/glue/webframe.h"
[email protected]47811562009-05-13 06:21:0171#include "webkit/glue/webhistoryitem.h"
initial.commit09911bf2008-07-26 23:55:2972#include "webkit/glue/webkit_glue.h"
73#include "webkit/glue/webpreferences.h"
[email protected]b94d3322009-02-12 19:49:0474#include "webkit/glue/webplugin_delegate.h"
initial.commit09911bf2008-07-26 23:55:2975#include "webkit/glue/webresponse.h"
[email protected]00d7e622009-04-21 23:06:0576#include "webkit/glue/webtextinput.h"
initial.commit09911bf2008-07-26 23:55:2977#include "webkit/glue/weburlrequest.h"
78#include "webkit/glue/webview.h"
initial.commit09911bf2008-07-26 23:55:2979
[email protected]6c8afae52009-01-22 02:24:5780#if defined(OS_WIN)
81// TODO(port): these files are currently Windows only because they concern:
[email protected]f8b6b6f2009-03-10 16:48:2682// * logging
[email protected]6c8afae52009-01-22 02:24:5783// * printing
84// * theming
85// * views
86#include "base/gfx/gdi_util.h"
87#include "base/gfx/native_theme.h"
88#include "chrome/common/gfx/emf.h"
[email protected]6c8afae52009-01-22 02:24:5789#include "skia/ext/vector_canvas.h"
[email protected]2362e4f2009-05-08 00:34:0590#include "views/controls/message_box_view.h"
[email protected]6c8afae52009-01-22 02:24:5791#endif
92
[email protected]c20210e62009-04-03 21:39:2693using base::Time;
[email protected]e1acf6f2008-10-27 20:43:3394using base::TimeDelta;
[email protected]6a983b42009-03-20 20:12:2595using webkit_glue::WebAccessibility;
[email protected]0dea3ea2009-03-31 23:30:5996using WebKit::WebConsoleMessage;
[email protected]e80c73b2009-04-07 23:24:5897using WebKit::WebDragData;
[email protected]b3f2b912009-04-09 16:18:5298using WebKit::WebRect;
[email protected]4f999132009-03-31 18:08:4099using WebKit::WebScriptSource;
[email protected]27ba8532009-04-24 20:22:43100using WebKit::WebWorker;
101using WebKit::WebWorkerClient;
[email protected]e1acf6f2008-10-27 20:43:33102
initial.commit09911bf2008-07-26 23:55:29103//-----------------------------------------------------------------------------
104
105// define to write the time necessary for thumbnail/DOM text retrieval,
106// respectively, into the system debug log
107// #define TIME_BITMAP_RETRIEVAL
108// #define TIME_TEXT_RETRIEVAL
109
110// maximum number of characters in the document to index, any text beyond this
111// point will be clipped
[email protected]6c8afae52009-01-22 02:24:57112static const size_t kMaxIndexChars = 65535;
initial.commit09911bf2008-07-26 23:55:29113
114// Size of the thumbnails that we'll generate
115static const int kThumbnailWidth = 196;
116static const int kThumbnailHeight = 136;
117
118// Delay in milliseconds that we'll wait before capturing the page contents
119// and thumbnail.
120static const int kDelayForCaptureMs = 500;
121
122// Typically, we capture the page data once the page is loaded.
123// Sometimes, the page never finishes to load, preventing the page capture
124// To workaround this problem, we always perform a capture after the following
125// delay.
126static const int kDelayForForcedCaptureMs = 6000;
127
[email protected]81a34412009-01-05 19:17:24128// The default value for RenderView.delay_seconds_for_form_state_sync_, see
129// that variable for more.
130const int kDefaultDelaySecondsForFormStateSync = 5;
initial.commit09911bf2008-07-26 23:55:29131
132// The next available page ID to use. This ensures that the page IDs are
133// globally unique in the renderer.
134static int32 next_page_id_ = 1;
135
[email protected]0aa55312008-10-17 21:53:08136// The maximum number of popups that can be spawned from one page.
137static const int kMaximumNumberOfUnacknowledgedPopups = 25;
138
initial.commit09911bf2008-07-26 23:55:29139static const char* const kUnreachableWebDataURL =
[email protected]60e448982009-05-06 04:21:16140 "chrome://chromewebdata/";
initial.commit09911bf2008-07-26 23:55:29141
[email protected]50b691c2008-10-31 19:08:35142static const char* const kBackForwardNavigationScheme = "history";
143
initial.commit09911bf2008-07-26 23:55:29144namespace {
145
146// Associated with browser-initiated navigations to hold tracking data.
147class RenderViewExtraRequestData : public WebRequest::ExtraData {
148 public:
149 RenderViewExtraRequestData(int32 pending_page_id,
[email protected]c20210e62009-04-03 21:39:26150 PageTransition::Type transition,
151 Time request_time)
[email protected]6c8afae52009-01-22 02:24:57152 : transition_type(transition),
[email protected]c20210e62009-04-03 21:39:26153 request_time(request_time),
[email protected]6c8afae52009-01-22 02:24:57154 request_committed(false),
155 pending_page_id_(pending_page_id) {
initial.commit09911bf2008-07-26 23:55:29156 }
157
158 // Contains the page_id for this navigation or -1 if there is none yet.
159 int32 pending_page_id() const { return pending_page_id_; }
160
161 // Is this a new navigation?
162 bool is_new_navigation() const { return pending_page_id_ == -1; }
163
164 // Contains the transition type that the browser specified when it
165 // initiated the load.
166 PageTransition::Type transition_type;
[email protected]c20210e62009-04-03 21:39:26167 Time request_time;
initial.commit09911bf2008-07-26 23:55:29168
169 // True if we have already processed the "DidCommitLoad" event for this
170 // request. Used by session history.
171 bool request_committed;
172
173 private:
174 int32 pending_page_id_;
175
[email protected]4f3dc372009-02-24 00:10:29176 DISALLOW_COPY_AND_ASSIGN(RenderViewExtraRequestData);
initial.commit09911bf2008-07-26 23:55:29177};
178
179} // namespace
180
181///////////////////////////////////////////////////////////////////////////////
182
[email protected]81a34412009-01-05 19:17:24183RenderView::RenderView(RenderThreadBase* render_thread)
184 : RenderWidget(render_thread, true),
[email protected]81e63782009-02-27 19:35:09185 enabled_bindings_(0),
[email protected]e75cb49e2009-01-05 23:13:21186 target_url_status_(TARGET_NONE),
[email protected]81a34412009-01-05 19:17:24187 is_loading_(false),
[email protected]e75cb49e2009-01-05 23:13:21188 navigation_gesture_(NavigationGestureUnknown),
[email protected]81a34412009-01-05 19:17:24189 page_id_(-1),
190 last_page_id_sent_to_browser_(-1),
191 last_indexed_page_id_(-1),
[email protected]81a34412009-01-05 19:17:24192 opened_by_user_gesture_(true),
[email protected]bb063b72009-03-27 23:18:50193 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
[email protected]81a34412009-01-05 19:17:24194 first_default_plugin_(NULL),
[email protected]e4ac5df2009-03-17 15:33:11195 devtools_agent_(NULL),
196 devtools_client_(NULL),
[email protected]81a34412009-01-05 19:17:24197 history_back_list_count_(0),
198 history_forward_list_count_(0),
[email protected]81a34412009-01-05 19:17:24199 has_unload_listener_(false),
200 decrement_shared_popup_at_destruction_(false),
[email protected]81a34412009-01-05 19:17:24201 form_field_autofill_request_id_(0),
202 popup_notification_visible_(false),
[email protected]0666aef2009-05-13 19:48:08203 delay_seconds_for_form_state_sync_(kDefaultDelaySecondsForFormStateSync),
204 preferred_width_(0),
205 send_preferred_width_changes_(false) {
initial.commit09911bf2008-07-26 23:55:29206}
207
208RenderView::~RenderView() {
[email protected]0aa55312008-10-17 21:53:08209 if (decrement_shared_popup_at_destruction_)
210 shared_popup_counter_->data--;
211
initial.commit09911bf2008-07-26 23:55:29212 // Clear any back-pointers that might still be held by plugins.
213 PluginDelegateList::iterator it = plugin_delegates_.begin();
214 while (it != plugin_delegates_.end()) {
215 (*it)->DropRenderView();
216 it = plugin_delegates_.erase(it);
217 }
218
[email protected]afccd9a2009-05-12 19:02:02219 // Clear any pending extension api call requests.
220 IDMap<ExtensionProcessBindings::CallContext>::const_iterator call =
221 pending_extension_requests_.begin();
222 for (; call != pending_extension_requests_.end(); ++call) {
223 delete call->second;
224 }
225
[email protected]81a34412009-01-05 19:17:24226 render_thread_->RemoveFilter(debug_message_handler_);
[email protected]5fb88962009-04-16 19:03:25227 render_thread_->RemoveFilter(audio_message_filter_);
initial.commit09911bf2008-07-26 23:55:29228}
229
230/*static*/
[email protected]0aa55312008-10-17 21:53:08231RenderView* RenderView::Create(
[email protected]81a34412009-01-05 19:17:24232 RenderThreadBase* render_thread,
[email protected]18bcc3c2009-01-27 21:39:15233 gfx::NativeViewId parent_hwnd,
[email protected]1c4947f2009-01-15 22:25:11234 base::WaitableEvent* modal_dialog_event,
[email protected]0aa55312008-10-17 21:53:08235 int32 opener_id,
236 const WebPreferences& webkit_prefs,
237 SharedRenderViewCounter* counter,
238 int32 routing_id) {
initial.commit09911bf2008-07-26 23:55:29239 DCHECK(routing_id != MSG_ROUTING_NONE);
[email protected]81a34412009-01-05 19:17:24240 scoped_refptr<RenderView> view = new RenderView(render_thread);
initial.commit09911bf2008-07-26 23:55:29241 view->Init(parent_hwnd,
242 modal_dialog_event,
243 opener_id,
244 webkit_prefs,
[email protected]0aa55312008-10-17 21:53:08245 counter,
initial.commit09911bf2008-07-26 23:55:29246 routing_id); // adds reference
247 return view;
248}
249
250/*static*/
251void RenderView::SetNextPageID(int32 next_page_id) {
252 // This method should only be called during process startup, and the given
253 // page id had better not exceed our current next page id!
254 DCHECK(next_page_id_ == 1);
255 DCHECK(next_page_id >= next_page_id_);
256 next_page_id_ = next_page_id;
257}
258
259void RenderView::PluginDestroyed(WebPluginDelegateProxy* proxy) {
260 PluginDelegateList::iterator it =
261 std::find(plugin_delegates_.begin(), plugin_delegates_.end(), proxy);
262 DCHECK(it != plugin_delegates_.end());
263 plugin_delegates_.erase(it);
264 // If the plugin is deleted, we need to clear our reference in case user
265 // clicks the info bar to install. Unfortunately we are getting
266 // PluginDestroyed in single process mode. However, that is not a huge
267 // concern.
268 if (proxy == first_default_plugin_)
269 first_default_plugin_ = NULL;
270}
271
[email protected]690a99c2009-01-06 16:48:45272void RenderView::PluginCrashed(const FilePath& plugin_path) {
initial.commit09911bf2008-07-26 23:55:29273 Send(new ViewHostMsg_CrashedPlugin(routing_id_, plugin_path));
274}
275
276
277void RenderView::JSOutOfMemory() {
278 Send(new ViewHostMsg_JSOutOfMemory(routing_id_));
279}
280
[email protected]18bcc3c2009-01-27 21:39:15281void RenderView::Init(gfx::NativeViewId parent_hwnd,
[email protected]1c4947f2009-01-15 22:25:11282 base::WaitableEvent* modal_dialog_event,
initial.commit09911bf2008-07-26 23:55:29283 int32 opener_id,
284 const WebPreferences& webkit_prefs,
[email protected]0aa55312008-10-17 21:53:08285 SharedRenderViewCounter* counter,
initial.commit09911bf2008-07-26 23:55:29286 int32 routing_id) {
287 DCHECK(!webview());
288
289 if (opener_id != MSG_ROUTING_NONE)
290 opener_id_ = opener_id;
291
[email protected]0aa55312008-10-17 21:53:08292 if (counter) {
293 shared_popup_counter_ = counter;
294 shared_popup_counter_->data++;
295 decrement_shared_popup_at_destruction_ = true;
296 } else {
297 shared_popup_counter_ = new SharedRenderViewCounter(0);
298 decrement_shared_popup_at_destruction_ = false;
299 }
300
[email protected]90ca3692009-04-09 16:09:43301 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
302
[email protected]2ef9c452009-05-13 13:03:14303 bool dev_tools_enabled = !command_line.HasSwitch(
304 switches::kDisableOutOfProcessDevTools);
[email protected]90ca3692009-04-09 16:09:43305 if (dev_tools_enabled)
306 devtools_agent_.reset(new DevToolsAgent(routing_id, this));
[email protected]9b9d7282009-04-08 14:13:04307
[email protected]c5b3b5e2009-02-13 06:41:11308 webwidget_ = WebView::Create(this, webkit_prefs);
initial.commit09911bf2008-07-26 23:55:29309
[email protected]2e417c82009-04-02 22:30:26310#if defined(OS_LINUX)
311 // We have to enable ourselves as the editor delegate on linux so we can copy
312 // text selections to the X clipboard.
313 webview()->SetUseEditorDelegate(true);
314#endif
315
initial.commit09911bf2008-07-26 23:55:29316 // Don't let WebCore keep a B/F list - we have our own.
317 // We let it keep 1 entry because FrameLoader::goToItem expects an item in the
318 // backForwardList, which is used only in ASSERTs.
319 webview()->SetBackForwardListSize(1);
320
321 routing_id_ = routing_id;
[email protected]81a34412009-01-05 19:17:24322 render_thread_->AddRoute(routing_id_, this);
initial.commit09911bf2008-07-26 23:55:29323 // Take a reference on behalf of the RenderThread. This will be balanced
324 // when we receive ViewMsg_Close.
325 AddRef();
326
327 // If this is a popup, we must wait for the CreatingNew_ACK message before
328 // completing initialization. Otherwise, we can finish it now.
329 if (opener_id == MSG_ROUTING_NONE) {
330 did_show_ = true;
331 CompleteInit(parent_hwnd);
332 }
333
334 host_window_ = parent_hwnd;
[email protected]1c4947f2009-01-15 22:25:11335 modal_dialog_event_.reset(modal_dialog_event);
initial.commit09911bf2008-07-26 23:55:29336
[email protected]81e63782009-02-27 19:35:09337 if (command_line.HasSwitch(switches::kDomAutomationController))
338 enabled_bindings_ |= BindingsPolicy::DOM_AUTOMATION;
initial.commit09911bf2008-07-26 23:55:29339
340 debug_message_handler_ = new DebugMessageHandler(this);
[email protected]81a34412009-01-05 19:17:24341 render_thread_->AddFilter(debug_message_handler_);
[email protected]5fb88962009-04-16 19:03:25342
343 audio_message_filter_ = new AudioMessageFilter(routing_id_);
344 render_thread_->AddFilter(audio_message_filter_);
initial.commit09911bf2008-07-26 23:55:29345}
346
347void RenderView::OnMessageReceived(const IPC::Message& message) {
[email protected]f8b6b6f2009-03-10 16:48:26348 WebFrame* main_frame = webview() ? webview()->GetMainFrame() : NULL;
349 renderer_logging::ScopedActiveRenderingURLSetter url_setter(
350 main_frame ? main_frame->GetURL() : GURL());
[email protected]f8b6b6f2009-03-10 16:48:26351
[email protected]b2abac72009-02-26 12:39:28352 // If this is developer tools renderer intercept tools messages first.
[email protected]e4ac5df2009-03-17 15:33:11353 if (devtools_client_.get() && devtools_client_->OnMessageReceived(message))
[email protected]b2abac72009-02-26 12:39:28354 return;
[email protected]b4b967e2009-04-22 11:33:05355 if (devtools_agent_.get() && devtools_agent_->OnMessageReceived(message))
356 return;
[email protected]b2abac72009-02-26 12:39:28357
initial.commit09911bf2008-07-26 23:55:29358 IPC_BEGIN_MESSAGE_MAP(RenderView, message)
initial.commit09911bf2008-07-26 23:55:29359 IPC_MESSAGE_HANDLER(ViewMsg_CaptureThumbnail, SendThumbnail)
initial.commit09911bf2008-07-26 23:55:29360 IPC_MESSAGE_HANDLER(ViewMsg_PrintPages, OnPrintPages)
361 IPC_MESSAGE_HANDLER(ViewMsg_Navigate, OnNavigate)
362 IPC_MESSAGE_HANDLER(ViewMsg_Stop, OnStop)
363 IPC_MESSAGE_HANDLER(ViewMsg_LoadAlternateHTMLText, OnLoadAlternateHTMLText)
364 IPC_MESSAGE_HANDLER(ViewMsg_StopFinding, OnStopFinding)
365 IPC_MESSAGE_HANDLER(ViewMsg_Undo, OnUndo)
366 IPC_MESSAGE_HANDLER(ViewMsg_Redo, OnRedo)
367 IPC_MESSAGE_HANDLER(ViewMsg_Cut, OnCut)
368 IPC_MESSAGE_HANDLER(ViewMsg_Copy, OnCopy)
369 IPC_MESSAGE_HANDLER(ViewMsg_Paste, OnPaste)
370 IPC_MESSAGE_HANDLER(ViewMsg_Replace, OnReplace)
[email protected]bbbd545c2008-12-15 20:18:04371 IPC_MESSAGE_HANDLER(ViewMsg_ToggleSpellCheck, OnToggleSpellCheck)
initial.commit09911bf2008-07-26 23:55:29372 IPC_MESSAGE_HANDLER(ViewMsg_Delete, OnDelete)
373 IPC_MESSAGE_HANDLER(ViewMsg_SelectAll, OnSelectAll)
374 IPC_MESSAGE_HANDLER(ViewMsg_CopyImageAt, OnCopyImageAt)
375 IPC_MESSAGE_HANDLER(ViewMsg_Find, OnFind)
[email protected]630e26b2008-10-14 22:55:17376 IPC_MESSAGE_HANDLER(ViewMsg_Zoom, OnZoom)
[email protected]ea8c7452009-04-02 20:47:06377 IPC_MESSAGE_HANDLER(ViewMsg_InsertText, OnInsertText)
initial.commit09911bf2008-07-26 23:55:29378 IPC_MESSAGE_HANDLER(ViewMsg_SetPageEncoding, OnSetPageEncoding)
379 IPC_MESSAGE_HANDLER(ViewMsg_InspectElement, OnInspectElement)
380 IPC_MESSAGE_HANDLER(ViewMsg_ShowJavaScriptConsole, OnShowJavaScriptConsole)
[email protected]b2abac72009-02-26 12:39:28381 IPC_MESSAGE_HANDLER(ViewMsg_SetupDevToolsClient, OnSetupDevToolsClient)
initial.commit09911bf2008-07-26 23:55:29382 IPC_MESSAGE_HANDLER(ViewMsg_DownloadImage, OnDownloadImage)
383 IPC_MESSAGE_HANDLER(ViewMsg_ScriptEvalRequest, OnScriptEvalRequest)
[email protected]1810e132009-03-24 23:35:48384 IPC_MESSAGE_HANDLER(ViewMsg_CSSInsertRequest, OnCSSInsertRequest)
initial.commit09911bf2008-07-26 23:55:29385 IPC_MESSAGE_HANDLER(ViewMsg_AddMessageToConsole, OnAddMessageToConsole)
386 IPC_MESSAGE_HANDLER(ViewMsg_DebugAttach, OnDebugAttach)
[email protected]88010e082008-08-29 11:07:40387 IPC_MESSAGE_HANDLER(ViewMsg_DebugDetach, OnDebugDetach)
initial.commit09911bf2008-07-26 23:55:29388 IPC_MESSAGE_HANDLER(ViewMsg_ReservePageIDRange, OnReservePageIDRange)
389 IPC_MESSAGE_HANDLER(ViewMsg_UploadFile, OnUploadFileRequest)
390 IPC_MESSAGE_HANDLER(ViewMsg_FormFill, OnFormFill)
391 IPC_MESSAGE_HANDLER(ViewMsg_FillPasswordForm, OnFillPasswordForm)
392 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragEnter, OnDragTargetDragEnter)
393 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragOver, OnDragTargetDragOver)
394 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragLeave, OnDragTargetDragLeave)
395 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDrop, OnDragTargetDrop)
[email protected]18cb2572008-08-21 20:34:45396 IPC_MESSAGE_HANDLER(ViewMsg_AllowBindings, OnAllowBindings)
initial.commit09911bf2008-07-26 23:55:29397 IPC_MESSAGE_HANDLER(ViewMsg_SetDOMUIProperty, OnSetDOMUIProperty)
[email protected]266eb6f2008-09-30 23:56:50398 IPC_MESSAGE_HANDLER(ViewMsg_DragSourceEndedOrMoved,
399 OnDragSourceEndedOrMoved)
initial.commit09911bf2008-07-26 23:55:29400 IPC_MESSAGE_HANDLER(ViewMsg_DragSourceSystemDragEnded,
401 OnDragSourceSystemDragEnded)
402 IPC_MESSAGE_HANDLER(ViewMsg_SetInitialFocus, OnSetInitialFocus)
403 IPC_MESSAGE_HANDLER(ViewMsg_FindReplyACK, OnFindReplyAck)
404 IPC_MESSAGE_HANDLER(ViewMsg_UpdateTargetURL_ACK, OnUpdateTargetURLAck)
405 IPC_MESSAGE_HANDLER(ViewMsg_UpdateWebPreferences, OnUpdateWebPreferences)
406 IPC_MESSAGE_HANDLER(ViewMsg_SetAltErrorPageURL, OnSetAltErrorPageURL)
407 IPC_MESSAGE_HANDLER(ViewMsg_InstallMissingPlugin, OnInstallMissingPlugin)
408 IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse)
409 IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode, OnEnableViewSourceMode)
410 IPC_MESSAGE_HANDLER(ViewMsg_UpdateBackForwardListCount,
411 OnUpdateBackForwardListCount)
412 IPC_MESSAGE_HANDLER(ViewMsg_GetAllSavableResourceLinksForCurrentPage,
413 OnGetAllSavableResourceLinksForCurrentPage)
[email protected]f09c7182009-03-10 12:54:04414 IPC_MESSAGE_HANDLER(
415 ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks,
416 OnGetSerializedHtmlDataForCurrentPageWithLocalLinks)
initial.commit09911bf2008-07-26 23:55:29417 IPC_MESSAGE_HANDLER(ViewMsg_GetApplicationInfo, OnGetApplicationInfo)
[email protected]266eb6f2008-09-30 23:56:50418 IPC_MESSAGE_HANDLER(ViewMsg_GetAccessibilityInfo, OnGetAccessibilityInfo)
419 IPC_MESSAGE_HANDLER(ViewMsg_ClearAccessibilityInfo,
420 OnClearAccessibilityInfo)
initial.commit09911bf2008-07-26 23:55:29421 IPC_MESSAGE_HANDLER(ViewMsg_ShouldClose, OnMsgShouldClose)
422 IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage)
423 IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged)
[email protected]18cb2572008-08-21 20:34:45424 IPC_MESSAGE_HANDLER(ViewMsg_HandleMessageFromExternalHost,
425 OnMessageFromExternalHost)
[email protected]0aa55312008-10-17 21:53:08426 IPC_MESSAGE_HANDLER(ViewMsg_DisassociateFromPopupCount,
427 OnDisassociateFromPopupCount)
[email protected]0ebf3872008-11-07 21:35:03428 IPC_MESSAGE_HANDLER(ViewMsg_AutofillSuggestions,
429 OnReceivedAutofillSuggestions)
[email protected]2c4410d2009-05-06 23:46:22430 IPC_MESSAGE_HANDLER(ViewMsg_PopupNotificationVisibilityChanged,
431 OnPopupNotificationVisibilityChanged)
[email protected]30f75e62009-02-25 22:01:00432 IPC_MESSAGE_HANDLER(ViewMsg_MoveOrResizeStarted, OnMoveOrResizeStarted)
[email protected]309d7a282009-03-24 09:18:27433 IPC_MESSAGE_HANDLER(ViewMsg_ExtensionResponse, OnExtensionResponse)
[email protected]05d478752009-04-08 23:38:16434 IPC_MESSAGE_HANDLER(ViewMsg_ClearFocusedNode, OnClearFocusedNode)
[email protected]699ab0d2009-04-23 23:19:14435 IPC_MESSAGE_HANDLER(ViewMsg_SetBackground, OnSetBackground)
[email protected]0666aef2009-05-13 19:48:08436 IPC_MESSAGE_HANDLER(ViewMsg_EnableIntrinsicWidthChangedMode,
437 OnEnableIntrinsicWidthChangedMode)
[email protected]634a6f92008-12-01 21:39:31438
initial.commit09911bf2008-07-26 23:55:29439 // Have the super handle all other messages.
440 IPC_MESSAGE_UNHANDLED(RenderWidget::OnMessageReceived(message))
441 IPC_END_MESSAGE_MAP()
442}
443
initial.commit09911bf2008-07-26 23:55:29444void RenderView::SendThumbnail() {
445 WebFrame* main_frame = webview()->GetMainFrame();
446 if (!main_frame)
447 return;
448
449 // get the URL for this page
450 GURL url(main_frame->GetURL());
451 if (url.is_empty())
452 return;
453
454 if (size_.IsEmpty())
455 return; // Don't create an empty thumbnail!
456
457 ThumbnailScore score;
458 SkBitmap thumbnail;
[email protected]b6e4bec2008-11-12 01:17:15459 if (!CaptureThumbnail(main_frame, kThumbnailWidth, kThumbnailHeight,
460 &thumbnail, &score))
461 return;
462
initial.commit09911bf2008-07-26 23:55:29463 // send the thumbnail message to the browser process
[email protected]674741932009-02-04 23:44:46464 Send(new ViewHostMsg_Thumbnail(routing_id_, url, score, thumbnail));
initial.commit09911bf2008-07-26 23:55:29465}
466
initial.commit09911bf2008-07-26 23:55:29467void RenderView::PrintPage(const ViewMsg_PrintPage_Params& params,
[email protected]88a3ecc2009-03-19 17:36:22468 const gfx::Size& canvas_size,
initial.commit09911bf2008-07-26 23:55:29469 WebFrame* frame) {
[email protected]6c8afae52009-01-22 02:24:57470#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29471 // Generate a memory-based EMF file. The EMF will use the current screen's
472 // DPI.
473 gfx::Emf emf;
474
475 emf.CreateDc(NULL, NULL);
476 HDC hdc = emf.hdc();
477 DCHECK(hdc);
[email protected]21f527e2008-12-17 23:29:40478 skia::PlatformDeviceWin::InitializeDC(hdc);
[email protected]0e92fa32009-03-31 20:39:33479 // Since WebKit extends the page width depending on the magical shrink
[email protected]0dea3ea2009-03-31 23:30:59480 // factor we make sure the canvas covers the worst case scenario
[email protected]0e92fa32009-03-31 20:39:33481 // (x2.0 currently). PrintContext will then set the correct clipping region.
482 int size_x = static_cast<int>(canvas_size.width() * params.params.max_shrink);
483 int size_y = static_cast<int>(canvas_size.height() *
484 params.params.max_shrink);
[email protected]88a3ecc2009-03-19 17:36:22485 // Calculate the dpi adjustment.
486 float shrink = static_cast<float>(canvas_size.width()) /
487 params.params.printable_size.width();
initial.commit09911bf2008-07-26 23:55:29488#if 0
489 // TODO(maruel): This code is kept for testing until the 100% GDI drawing
490 // code is stable. maruels use this code's output as a reference when the
491 // GDI drawing code fails.
492
493 // Mix of Skia and GDI based.
[email protected]88a3ecc2009-03-19 17:36:22494 skia::PlatformCanvasWin canvas(size_x, size_y, true);
initial.commit09911bf2008-07-26 23:55:29495 canvas.drawARGB(255, 255, 255, 255, SkPorterDuff::kSrc_Mode);
[email protected]88a3ecc2009-03-19 17:36:22496 float webkit_shrink = frame->PrintPage(params.page_number, &canvas);
497 if (shrink <= 0) {
initial.commit09911bf2008-07-26 23:55:29498 NOTREACHED() << "Printing page " << params.page_number << " failed.";
[email protected]88a3ecc2009-03-19 17:36:22499 } else {
500 // Update the dpi adjustment with the "page shrink" calculated in webkit.
501 shrink /= webkit_shrink;
initial.commit09911bf2008-07-26 23:55:29502 }
503
504 // Create a BMP v4 header that we can serialize.
505 BITMAPV4HEADER bitmap_header;
[email protected]88a3ecc2009-03-19 17:36:22506 gfx::CreateBitmapV4Header(size_x, size_y, &bitmap_header);
initial.commit09911bf2008-07-26 23:55:29507 const SkBitmap& src_bmp = canvas.getDevice()->accessBitmap(true);
508 SkAutoLockPixels src_lock(src_bmp);
509 int retval = StretchDIBits(hdc,
510 0,
511 0,
[email protected]88a3ecc2009-03-19 17:36:22512 size_x, size_y,
initial.commit09911bf2008-07-26 23:55:29513 0, 0,
[email protected]88a3ecc2009-03-19 17:36:22514 size_x, size_y,
initial.commit09911bf2008-07-26 23:55:29515 src_bmp.getPixels(),
516 reinterpret_cast<BITMAPINFO*>(&bitmap_header),
517 DIB_RGB_COLORS,
518 SRCCOPY);
519 DCHECK(retval != GDI_ERROR);
520#else
521 // 100% GDI based.
[email protected]88a3ecc2009-03-19 17:36:22522 skia::VectorCanvas canvas(hdc, size_x, size_y);
523 float webkit_shrink = frame->PrintPage(params.page_number, &canvas);
524 if (shrink <= 0) {
initial.commit09911bf2008-07-26 23:55:29525 NOTREACHED() << "Printing page " << params.page_number << " failed.";
[email protected]88a3ecc2009-03-19 17:36:22526 } else {
527 // Update the dpi adjustment with the "page shrink" calculated in webkit.
528 shrink /= webkit_shrink;
initial.commit09911bf2008-07-26 23:55:29529 }
530#endif
531
532 // Done printing. Close the device context to retrieve the compiled EMF.
533 if (!emf.CloseDc()) {
534 NOTREACHED() << "EMF failed";
535 }
536
537 // Get the size of the compiled EMF.
538 unsigned buf_size = emf.GetDataSize();
539 DCHECK(buf_size > 128);
540 ViewHostMsg_DidPrintPage_Params page_params;
541 page_params.data_size = 0;
542 page_params.emf_data_handle = NULL;
543 page_params.page_number = params.page_number;
544 page_params.document_cookie = params.params.document_cookie;
545 page_params.actual_shrink = shrink;
[email protected]176aa482008-11-14 03:25:15546 base::SharedMemory shared_buf;
initial.commit09911bf2008-07-26 23:55:29547
548 // http://msdn2.microsoft.com/en-us/library/ms535522.aspx
549 // Windows 2000/XP: When a page in a spooled file exceeds approximately 350
550 // MB, it can fail to print and not send an error message.
551 if (buf_size < 350*1024*1024) {
552 // Allocate a shared memory buffer to hold the generated EMF data.
553 if (shared_buf.Create(L"", false, false, buf_size) &&
554 shared_buf.Map(buf_size)) {
555 // Copy the bits into shared memory.
556 if (emf.GetData(shared_buf.memory(), buf_size)) {
557 page_params.emf_data_handle = shared_buf.handle();
558 page_params.data_size = buf_size;
559 } else {
560 NOTREACHED() << "GetData() failed";
561 }
562 shared_buf.Unmap();
563 } else {
564 NOTREACHED() << "Buffer allocation failed";
565 }
566 } else {
567 NOTREACHED() << "Buffer too large: " << buf_size;
568 }
569 emf.CloseEmf();
570 if (Send(new ViewHostMsg_DuplicateSection(routing_id_,
571 page_params.emf_data_handle,
572 &page_params.emf_data_handle))) {
573 Send(new ViewHostMsg_DidPrintPage(routing_id_, page_params));
574 }
[email protected]6c8afae52009-01-22 02:24:57575#else // defined(OS_WIN)
576 // TODO(port) implement printing
577 NOTIMPLEMENTED();
578#endif
initial.commit09911bf2008-07-26 23:55:29579}
580
[email protected]068637222009-01-29 16:58:07581void RenderView::OnPrintPages() {
initial.commit09911bf2008-07-26 23:55:29582 DCHECK(webview());
[email protected]068637222009-01-29 16:58:07583 if (webview()) {
584 // The renderer own the control flow as if it was a window.print() call.
585 ScriptedPrint(webview()->GetMainFrame());
initial.commit09911bf2008-07-26 23:55:29586 }
initial.commit09911bf2008-07-26 23:55:29587}
588
589void RenderView::PrintPages(const ViewMsg_PrintPages_Params& params,
590 WebFrame* frame) {
[email protected]88a3ecc2009-03-19 17:36:22591 int page_count = 0;
592 gfx::Size canvas_size;
593 canvas_size.set_width(
594 printing::ConvertUnit(params.params.printable_size.width(),
595 static_cast<int>(params.params.dpi),
596 params.params.desired_dpi));
597 canvas_size.set_height(
598 printing::ConvertUnit(params.params.printable_size.height(),
599 static_cast<int>(params.params.dpi),
600 params.params.desired_dpi));
601 frame->BeginPrint(canvas_size, &page_count);
initial.commit09911bf2008-07-26 23:55:29602 Send(new ViewHostMsg_DidGetPrintedPagesCount(routing_id_,
603 params.params.document_cookie,
[email protected]88a3ecc2009-03-19 17:36:22604 page_count));
605 if (page_count) {
initial.commit09911bf2008-07-26 23:55:29606 ViewMsg_PrintPage_Params page_params;
607 page_params.params = params.params;
608 if (params.pages.empty()) {
[email protected]88a3ecc2009-03-19 17:36:22609 for (int i = 0; i < page_count; ++i) {
initial.commit09911bf2008-07-26 23:55:29610 page_params.page_number = i;
[email protected]88a3ecc2009-03-19 17:36:22611 PrintPage(page_params, canvas_size, frame);
initial.commit09911bf2008-07-26 23:55:29612 }
613 } else {
614 for (size_t i = 0; i < params.pages.size(); ++i) {
615 page_params.page_number = params.pages[i];
[email protected]88a3ecc2009-03-19 17:36:22616 PrintPage(page_params, canvas_size, frame);
initial.commit09911bf2008-07-26 23:55:29617 }
618 }
619 }
[email protected]88a3ecc2009-03-19 17:36:22620 frame->EndPrint();
initial.commit09911bf2008-07-26 23:55:29621}
622
623void RenderView::CapturePageInfo(int load_id, bool preliminary_capture) {
624 if (load_id != page_id_)
625 return; // this capture call is no longer relevant due to navigation
626 if (load_id == last_indexed_page_id_)
627 return; // we already indexed this page
628
629 if (!webview())
630 return;
631
632 WebFrame* main_frame = webview()->GetMainFrame();
633 if (!main_frame)
634 return;
635
636 // Don't index/capture pages that are in view source mode.
637 if (main_frame->GetInViewSourceMode())
638 return;
639
640 // Don't index/capture pages that failed to load. This only checks the top
641 // level frame so the thumbnail may contain a frame that failed to load.
642 WebDataSource* ds = main_frame->GetDataSource();
643 if (ds && ds->HasUnreachableURL())
644 return;
645
646 if (!preliminary_capture)
647 last_indexed_page_id_ = load_id;
648
649 // get the URL for this page
650 GURL url(main_frame->GetURL());
651 if (url.is_empty())
652 return;
653
654 // full text
655 std::wstring contents;
656 CaptureText(main_frame, &contents);
657 if (contents.size()) {
658 // Send the text to the browser for indexing.
659 Send(new ViewHostMsg_PageContents(url, load_id, contents));
660 }
661
662 // thumbnail
663 SendThumbnail();
664}
665
666void RenderView::CaptureText(WebFrame* frame, std::wstring* contents) {
667 contents->clear();
668 if (!frame)
669 return;
670
[email protected]0faf0bd92008-09-09 20:53:27671 // Don't index any https pages. People generally don't want their bank
672 // accounts, etc. indexed on their computer, especially since some of these
673 // things are not marked cachable.
674 // TODO(brettw) we may want to consider more elaborate heuristics such as
675 // the cachability of the page. We may also want to consider subframes (this
676 // test will still index subframes if the subframe is SSL).
677 if (frame->GetURL().SchemeIsSecure())
678 return;
679
initial.commit09911bf2008-07-26 23:55:29680#ifdef TIME_TEXT_RETRIEVAL
681 double begin = time_util::GetHighResolutionTimeNow();
682#endif
683
684 // get the contents of the frame
685 frame->GetContentAsPlainText(kMaxIndexChars, contents);
686
687#ifdef TIME_TEXT_RETRIEVAL
688 double end = time_util::GetHighResolutionTimeNow();
689 char buf[128];
690 sprintf_s(buf, "%d chars retrieved for indexing in %gms\n",
691 contents.size(), (end - begin)*1000);
692 OutputDebugStringA(buf);
693#endif
694
695 // When the contents are clipped to the maximum, we don't want to have a
696 // partial word indexed at the end that might have been clipped. Therefore,
697 // terminate the string at the last space to ensure no words are clipped.
698 if (contents->size() == kMaxIndexChars) {
699 size_t last_space_index = contents->find_last_of(kWhitespaceWide);
700 if (last_space_index == std::wstring::npos)
701 return; // don't index if we got a huge block of text with no spaces
702 contents->resize(last_space_index);
703 }
704}
705
[email protected]b6e4bec2008-11-12 01:17:15706bool RenderView::CaptureThumbnail(WebFrame* frame,
initial.commit09911bf2008-07-26 23:55:29707 int w,
708 int h,
709 SkBitmap* thumbnail,
710 ThumbnailScore* score) {
711#ifdef TIME_BITMAP_RETRIEVAL
712 double begin = time_util::GetHighResolutionTimeNow();
713#endif
714
[email protected]21f527e2008-12-17 23:29:40715 scoped_ptr<skia::BitmapPlatformDevice> device;
[email protected]b6e4bec2008-11-12 01:17:15716 if (!frame->CaptureImage(&device, true))
717 return false;
718
719 const SkBitmap& src_bmp = device->accessBitmap(false);
initial.commit09911bf2008-07-26 23:55:29720
721 SkRect dest_rect;
722 dest_rect.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
723 float dest_aspect = dest_rect.width() / dest_rect.height();
724
725 // Get the src rect so that we can preserve the aspect ratio while filling
726 // the destination.
727 SkIRect src_rect;
728 if (src_bmp.width() < dest_rect.width() ||
729 src_bmp.height() < dest_rect.height()) {
730 // Source image is smaller: we clip the part of source image within the
731 // dest rect, and then stretch it to fill the dest rect. We don't respect
732 // the aspect ratio in this case.
733 src_rect.set(0, 0, static_cast<S16CPU>(dest_rect.width()),
734 static_cast<S16CPU>(dest_rect.height()));
735 score->good_clipping = false;
736 } else {
737 float src_aspect = static_cast<float>(src_bmp.width()) / src_bmp.height();
738 if (src_aspect > dest_aspect) {
739 // Wider than tall, clip horizontally: we center the smaller thumbnail in
740 // the wider screen.
741 S16CPU new_width = static_cast<S16CPU>(src_bmp.height() * dest_aspect);
742 S16CPU x_offset = (src_bmp.width() - new_width) / 2;
743 src_rect.set(x_offset, 0, new_width + x_offset, src_bmp.height());
744 score->good_clipping = false;
745 } else {
746 src_rect.set(0, 0, src_bmp.width(),
747 static_cast<S16CPU>(src_bmp.width() / dest_aspect));
748 score->good_clipping = true;
749 }
750 }
751
[email protected]b3f2b912009-04-09 16:18:52752 score->at_top = (frame->ScrollOffset().height == 0);
initial.commit09911bf2008-07-26 23:55:29753
754 SkBitmap subset;
[email protected]b6e4bec2008-11-12 01:17:15755 device->accessBitmap(false).extractSubset(&subset, src_rect);
initial.commit09911bf2008-07-26 23:55:29756
757 // Resample the subset that we want to get it the right size.
[email protected]465b34b72008-12-12 20:19:14758 *thumbnail = skia::ImageOperations::Resize(
759 subset, skia::ImageOperations::RESIZE_LANCZOS3, w, h);
initial.commit09911bf2008-07-26 23:55:29760
761 score->boring_score = CalculateBoringScore(thumbnail);
762
763#ifdef TIME_BITMAP_RETRIEVAL
764 double end = time_util::GetHighResolutionTimeNow();
765 char buf[128];
766 sprintf_s(buf, "thumbnail in %gms\n", (end - begin) * 1000);
767 OutputDebugStringA(buf);
768#endif
[email protected]b6e4bec2008-11-12 01:17:15769 return true;
initial.commit09911bf2008-07-26 23:55:29770}
771
772double RenderView::CalculateBoringScore(SkBitmap* bitmap) {
773 int histogram[256] = {0};
774 color_utils::BuildLumaHistogram(bitmap, histogram);
775
776 int color_count = *std::max_element(histogram, histogram + 256);
777 int pixel_count = bitmap->width() * bitmap->height();
778 return static_cast<double>(color_count) / pixel_count;
779}
780
781void RenderView::OnNavigate(const ViewMsg_Navigate_Params& params) {
782 if (!webview())
783 return;
784
[email protected]f8b6b6f2009-03-10 16:48:26785 renderer_logging::ScopedActiveRenderingURLSetter url_setter(params.url);
[email protected]f8b6b6f2009-03-10 16:48:26786
initial.commit09911bf2008-07-26 23:55:29787 AboutHandler::MaybeHandle(params.url);
788
789 bool is_reload = params.reload;
790
791 WebFrame* main_frame = webview()->GetMainFrame();
[email protected]606843fa2008-12-02 19:08:56792 if (is_reload && !main_frame->HasCurrentHistoryState()) {
initial.commit09911bf2008-07-26 23:55:29793 // We cannot reload if we do not have any history state. This happens, for
794 // example, when recovering from a crash. Our workaround here is a bit of
795 // a hack since it means that reload after a crashed tab does not cause an
796 // end-to-end cache validation.
797 is_reload = false;
798 }
799
800 WebRequestCachePolicy cache_policy;
801 if (is_reload) {
802 cache_policy = WebRequestReloadIgnoringCacheData;
803 } else if (params.page_id != -1 || main_frame->GetInViewSourceMode()) {
804 cache_policy = WebRequestReturnCacheDataElseLoad;
805 } else {
806 cache_policy = WebRequestUseProtocolCachePolicy;
807 }
808
809 scoped_ptr<WebRequest> request(WebRequest::Create(params.url));
810 request->SetCachePolicy(cache_policy);
811 request->SetExtraData(new RenderViewExtraRequestData(
[email protected]c20210e62009-04-03 21:39:26812 params.page_id, params.transition, params.request_time));
initial.commit09911bf2008-07-26 23:55:29813
814 // If we are reloading, then WebKit will use the state of the current page.
815 // Otherwise, we give it the state to navigate to.
816 if (!is_reload)
817 request->SetHistoryState(params.state);
818
[email protected]4c6f2c92008-10-28 20:26:15819 if (params.referrer.is_valid()) {
[email protected]8e3c1a72008-11-25 01:13:32820 request->SetHttpHeaderValue("Referer",
821 params.referrer.spec());
[email protected]c0588052008-10-27 23:01:50822 }
823
initial.commit09911bf2008-07-26 23:55:29824 main_frame->LoadRequest(request.get());
825}
826
827// Stop loading the current page
828void RenderView::OnStop() {
829 if (webview())
830 webview()->StopLoading();
831}
832
833void RenderView::OnLoadAlternateHTMLText(const std::string& html_contents,
834 bool new_navigation,
835 const GURL& display_url,
836 const std::string& security_info) {
837 if (!webview())
838 return;
839
840 scoped_ptr<WebRequest> request(WebRequest::Create(
841 GURL(kUnreachableWebDataURL)));
842 request->SetSecurityInfo(security_info);
843
844 webview()->GetMainFrame()->LoadAlternateHTMLString(request.get(),
845 html_contents,
846 display_url,
847 !new_navigation);
848}
849
850void RenderView::OnCopyImageAt(int x, int y) {
851 webview()->CopyImageAt(x, y);
852}
853
854void RenderView::OnInspectElement(int x, int y) {
855 webview()->InspectElement(x, y);
856}
857
858void RenderView::OnShowJavaScriptConsole() {
859 webview()->ShowJavaScriptConsole();
860}
861
[email protected]b2abac72009-02-26 12:39:28862void RenderView::OnSetupDevToolsClient() {
[email protected]e4ac5df2009-03-17 15:33:11863 DCHECK(!devtools_client_.get());
864 devtools_client_.reset(new DevToolsClient(this));
[email protected]b2abac72009-02-26 12:39:28865}
866
initial.commit09911bf2008-07-26 23:55:29867void RenderView::OnStopFinding(bool clear_selection) {
868 WebView* view = webview();
869 if (!view)
870 return;
871
872 if (clear_selection)
873 view->GetFocusedFrame()->ClearSelection();
874
875 WebFrame* frame = view->GetMainFrame();
876 while (frame) {
[email protected]65134c432008-09-26 21:47:20877 frame->StopFinding(clear_selection);
initial.commit09911bf2008-07-26 23:55:29878 frame = view->GetNextFrameAfter(frame, false);
879 }
880}
881
882void RenderView::OnFindReplyAck() {
883 // Check if there is any queued up request waiting to be sent.
884 if (queued_find_reply_message_.get()) {
885 // Send the search result over to the browser process.
886 Send(queued_find_reply_message_.get());
887 queued_find_reply_message_.release();
888 }
889}
890
891void RenderView::OnUpdateTargetURLAck() {
892 // Check if there is a targeturl waiting to be sent.
893 if (target_url_status_ == TARGET_PENDING) {
894 Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_,
895 pending_target_url_));
896 }
897
898 target_url_status_ = TARGET_NONE;
899}
900
901void RenderView::OnUndo() {
902 if (!webview())
903 return;
904
905 webview()->GetFocusedFrame()->Undo();
906}
907
908void RenderView::OnRedo() {
909 if (!webview())
910 return;
911
912 webview()->GetFocusedFrame()->Redo();
913}
914
915void RenderView::OnCut() {
916 if (!webview())
917 return;
918
919 webview()->GetFocusedFrame()->Cut();
920}
921
922void RenderView::OnCopy() {
923 if (!webview())
924 return;
925
926 webview()->GetFocusedFrame()->Copy();
927}
928
929void RenderView::OnPaste() {
930 if (!webview())
931 return;
932
933 webview()->GetFocusedFrame()->Paste();
934}
935
936void RenderView::OnReplace(const std::wstring& text) {
937 if (!webview())
938 return;
939
940 webview()->GetFocusedFrame()->Replace(text);
941}
942
[email protected]bbbd545c2008-12-15 20:18:04943void RenderView::OnToggleSpellCheck() {
944 if (!webview())
945 return;
946
947 webview()->GetFocusedFrame()->ToggleSpellCheck();
948}
949
initial.commit09911bf2008-07-26 23:55:29950void RenderView::OnDelete() {
951 if (!webview())
952 return;
953
954 webview()->GetFocusedFrame()->Delete();
955}
956
957void RenderView::OnSelectAll() {
958 if (!webview())
959 return;
960
961 webview()->GetFocusedFrame()->SelectAll();
962}
963
964void RenderView::OnSetInitialFocus(bool reverse) {
965 if (!webview())
966 return;
967 webview()->SetInitialFocus(reverse);
968}
969
970///////////////////////////////////////////////////////////////////////////////
971
972// Tell the embedding application that the URL of the active page has changed
973void RenderView::UpdateURL(WebFrame* frame) {
974 WebDataSource* ds = frame->GetDataSource();
975 DCHECK(ds);
976
977 const WebRequest& request = ds->GetRequest();
978 const WebRequest& initial_request = ds->GetInitialRequest();
979 const WebResponse& response = ds->GetResponse();
980
981 // We don't hold a reference to the extra data. The request's reference will
982 // be sufficient because we won't modify it during our call. MAY BE NULL.
983 RenderViewExtraRequestData* extra_data =
984 static_cast<RenderViewExtraRequestData*>(request.GetExtraData());
985
986 ViewHostMsg_FrameNavigate_Params params;
[email protected]2e39d2e2009-02-19 18:41:31987 params.http_status_code = response.GetHttpStatusCode();
initial.commit09911bf2008-07-26 23:55:29988 params.is_post = false;
989 params.page_id = page_id_;
[email protected]8a3422c92008-09-24 17:42:42990 params.is_content_filtered = response.IsContentFiltered();
initial.commit09911bf2008-07-26 23:55:29991 if (!request.GetSecurityInfo().empty()) {
992 // SSL state specified in the request takes precedence over the one in the
993 // response.
994 // So far this is only intended for error pages that are not expected to be
995 // over ssl, so we should not get any clash.
996 DCHECK(response.GetSecurityInfo().empty());
997 params.security_info = request.GetSecurityInfo();
998 } else {
999 params.security_info = response.GetSecurityInfo();
1000 }
1001
1002 // Set the URL to be displayed in the browser UI to the user.
1003 if (ds->HasUnreachableURL()) {
1004 params.url = ds->GetUnreachableURL();
1005 } else {
1006 params.url = request.GetURL();
1007 }
1008
1009 params.redirects = ds->GetRedirectChain();
1010 params.should_update_history = !ds->HasUnreachableURL();
1011
1012 const SearchableFormData* searchable_form_data =
1013 frame->GetDataSource()->GetSearchableFormData();
1014 if (searchable_form_data) {
1015 params.searchable_form_url = searchable_form_data->url();
1016 params.searchable_form_element_name = searchable_form_data->element_name();
1017 params.searchable_form_encoding = searchable_form_data->encoding();
1018 }
1019
1020 const PasswordForm* password_form_data =
1021 frame->GetDataSource()->GetPasswordFormData();
1022 if (password_form_data)
1023 params.password_form = *password_form_data;
1024
1025 params.gesture = navigation_gesture_;
1026 navigation_gesture_ = NavigationGestureUnknown;
1027
1028 if (webview()->GetMainFrame() == frame) {
1029 // Top-level navigation.
1030
1031 // Update contents MIME type for main frame.
[email protected]9d806f52009-03-12 22:50:541032 params.contents_mime_type = ds->GetResponse().GetMimeType();
initial.commit09911bf2008-07-26 23:55:291033
1034 // We assume top level navigations initiated by the renderer are link
1035 // clicks.
1036 params.transition = extra_data ?
1037 extra_data->transition_type : PageTransition::LINK;
1038 if (!PageTransition::IsMainFrame(params.transition)) {
1039 // If the main frame does a load, it should not be reported as a subframe
1040 // navigation. This can occur in the following case:
1041 // 1. You're on a site with frames.
1042 // 2. You do a subframe navigation. This is stored with transition type
1043 // MANUAL_SUBFRAME.
1044 // 3. You navigate to some non-frame site, say, google.com.
1045 // 4. You navigate back to the page from step 2. Since it was initially
1046 // MANUAL_SUBFRAME, it will be that same transition type here.
1047 // We don't want that, because any navigation that changes the toplevel
1048 // frame should be tracked as a toplevel navigation (this allows us to
1049 // update the URL bar, etc).
1050 params.transition = PageTransition::LINK;
1051 }
1052
1053 if (params.transition == PageTransition::LINK &&
1054 frame->GetDataSource()->IsFormSubmit()) {
1055 params.transition = PageTransition::FORM_SUBMIT;
1056 }
1057
1058 // If we have a valid consumed client redirect source,
1059 // the page contained a client redirect (meta refresh, document.loc...),
1060 // so we set the referrer and transition to match.
1061 if (completed_client_redirect_src_.is_valid()) {
[email protected]77e09a92008-08-01 18:11:041062 DCHECK(completed_client_redirect_src_ == params.redirects[0]);
initial.commit09911bf2008-07-26 23:55:291063 params.referrer = completed_client_redirect_src_;
1064 params.transition = static_cast<PageTransition::Type>(
1065 params.transition | PageTransition::CLIENT_REDIRECT);
1066 } else {
1067 // Bug 654101: the referrer will be empty on https->http transitions. It
1068 // would be nice if we could get the real referrer from somewhere.
1069 params.referrer = GURL(initial_request.GetHttpReferrer());
1070 }
1071
[email protected]8e3c1a72008-11-25 01:13:321072 std::string method = request.GetHttpMethod();
1073 if (method == "POST")
initial.commit09911bf2008-07-26 23:55:291074 params.is_post = true;
1075
1076 Send(new ViewHostMsg_FrameNavigate(routing_id_, params));
1077 } else {
1078 // Subframe navigation: the type depends on whether this navigation
1079 // generated a new session history entry. When they do generate a session
1080 // history entry, it means the user initiated the navigation and we should
1081 // mark it as such. This test checks if this is the first time UpdateURL
1082 // has been called since WillNavigateToURL was called to initiate the load.
1083 if (page_id_ > last_page_id_sent_to_browser_)
1084 params.transition = PageTransition::MANUAL_SUBFRAME;
1085 else
1086 params.transition = PageTransition::AUTO_SUBFRAME;
1087
1088 // The browser should never initiate a subframe navigation.
1089 DCHECK(!extra_data);
1090 Send(new ViewHostMsg_FrameNavigate(routing_id_, params));
1091 }
1092
1093 last_page_id_sent_to_browser_ =
1094 std::max(last_page_id_sent_to_browser_, page_id_);
1095
1096 // If we end up reusing this WebRequest (for example, due to a #ref click),
1097 // we don't want the transition type to persist.
1098 if (extra_data)
1099 extra_data->transition_type = PageTransition::LINK; // Just clear it.
[email protected]266eb6f2008-09-30 23:56:501100
[email protected]6c8afae52009-01-22 02:24:571101#if defined(OS_WIN)
[email protected]6a983b42009-03-20 20:12:251102 if (web_accessibility_manager_.get()) {
[email protected]be645db2009-02-06 20:36:331103 // Clear accessibility info cache.
[email protected]6a983b42009-03-20 20:12:251104 web_accessibility_manager_->ClearAccObjMap(-1, true);
[email protected]266eb6f2008-09-30 23:56:501105 }
[email protected]6c8afae52009-01-22 02:24:571106#else
[email protected]7d926f92009-03-03 14:26:541107 // TODO(port): accessibility not yet implemented. See http://crbug.com/8288.
[email protected]6c8afae52009-01-22 02:24:571108#endif
initial.commit09911bf2008-07-26 23:55:291109}
1110
1111// Tell the embedding application that the title of the active page has changed
1112void RenderView::UpdateTitle(WebFrame* frame, const std::wstring& title) {
1113 // Ignore all but top level navigations...
1114 if (webview()->GetMainFrame() == frame)
1115 Send(new ViewHostMsg_UpdateTitle(routing_id_, page_id_, title));
1116}
1117
1118void RenderView::UpdateEncoding(WebFrame* frame,
[email protected]e38f40152008-09-12 23:08:301119 const std::wstring& encoding_name) {
initial.commit09911bf2008-07-26 23:55:291120 // Only update main frame's encoding_name.
1121 if (webview()->GetMainFrame() == frame &&
1122 last_encoding_name_ != encoding_name) {
[email protected]e38f40152008-09-12 23:08:301123 // Save the encoding name for later comparing.
initial.commit09911bf2008-07-26 23:55:291124 last_encoding_name_ = encoding_name;
1125
[email protected]e38f40152008-09-12 23:08:301126 Send(new ViewHostMsg_UpdateEncoding(routing_id_, last_encoding_name_));
initial.commit09911bf2008-07-26 23:55:291127 }
1128}
1129
[email protected]f4d34b52008-11-24 23:05:011130// Sends the previous session history state to the browser so it will be saved
1131// before we navigate to a new page. This must be called *before* the page ID
1132// has been updated so we know what it was.
initial.commit09911bf2008-07-26 23:55:291133void RenderView::UpdateSessionHistory(WebFrame* frame) {
1134 // If we have a valid page ID at this point, then it corresponds to the page
1135 // we are navigating away from. Otherwise, this is the first navigation, so
1136 // there is no past session history to record.
1137 if (page_id_ == -1)
1138 return;
1139
initial.commit09911bf2008-07-26 23:55:291140 std::string state;
[email protected]606843fa2008-12-02 19:08:561141 if (!webview()->GetMainFrame()->GetPreviousHistoryState(&state))
initial.commit09911bf2008-07-26 23:55:291142 return;
[email protected]606843fa2008-12-02 19:08:561143 Send(new ViewHostMsg_UpdateState(routing_id_, page_id_, state));
initial.commit09911bf2008-07-26 23:55:291144}
1145
1146///////////////////////////////////////////////////////////////////////////////
1147// WebViewDelegate
1148
1149void RenderView::DidStartLoading(WebView* webview) {
1150 if (is_loading_) {
1151 DLOG(WARNING) << "DidStartLoading called while loading";
1152 return;
1153 }
1154
1155 is_loading_ = true;
1156 // Clear the pointer so that we can assign it only when there is an unknown
1157 // plugin on a page.
1158 first_default_plugin_ = NULL;
1159
[email protected]329581b2009-04-28 06:52:351160 Send(new ViewHostMsg_DidStartLoading(routing_id_));
initial.commit09911bf2008-07-26 23:55:291161}
1162
1163void RenderView::DidStopLoading(WebView* webview) {
1164 if (!is_loading_) {
1165 DLOG(WARNING) << "DidStopLoading called while not loading";
1166 return;
1167 }
1168
1169 is_loading_ = false;
1170
1171 // NOTE: For now we're doing the safest thing, and sending out notification
1172 // when done loading. This currently isn't an issue as the favicon is only
1173 // displayed when done loading. Ideally we would send notification when
1174 // finished parsing the head, but webkit doesn't support that yet.
1175 // The feed discovery code would also benefit from access to the head.
1176 GURL favicon_url(webview->GetMainFrame()->GetFavIconURL());
1177 if (!favicon_url.is_empty())
1178 Send(new ViewHostMsg_UpdateFavIconURL(routing_id_, page_id_, favicon_url));
1179
1180 AddGURLSearchProvider(webview->GetMainFrame()->GetOSDDURL(),
1181 true); // autodetected
1182
[email protected]329581b2009-04-28 06:52:351183 Send(new ViewHostMsg_DidStopLoading(routing_id_));
initial.commit09911bf2008-07-26 23:55:291184
1185 MessageLoop::current()->PostDelayedTask(FROM_HERE,
1186 method_factory_.NewRunnableMethod(&RenderView::CapturePageInfo, page_id_,
1187 false),
1188 kDelayForCaptureMs);
1189
1190 // The page is loaded. Try to process the file we need to upload if any.
1191 ProcessPendingUpload();
1192
1193 // Since the page is done loading, we are sure we don't need to try
1194 // again.
1195 ResetPendingUpload();
1196}
1197
1198void RenderView::DidStartProvisionalLoadForFrame(
1199 WebView* webview,
1200 WebFrame* frame,
1201 NavigationGesture gesture) {
[email protected]77e09a92008-08-01 18:11:041202 if (webview->GetMainFrame() == frame) {
initial.commit09911bf2008-07-26 23:55:291203 navigation_gesture_ = gesture;
[email protected]266eb6f2008-09-30 23:56:501204
[email protected]77e09a92008-08-01 18:11:041205 // Make sure redirect tracking state is clear for the new load.
1206 completed_client_redirect_src_ = GURL();
1207 }
initial.commit09911bf2008-07-26 23:55:291208
[email protected]c20210e62009-04-03 21:39:261209 WebDataSource* ds = frame->GetProvisionalDataSource();
1210 if (ds) {
1211 const WebRequest& req = ds->GetRequest();
1212 RenderViewExtraRequestData* extra_data =
1213 static_cast<RenderViewExtraRequestData*>(req.GetExtraData());
1214 if (extra_data) {
1215 ds->SetRequestTime(extra_data->request_time);
1216 }
1217 }
initial.commit09911bf2008-07-26 23:55:291218 Send(new ViewHostMsg_DidStartProvisionalLoadForFrame(
1219 routing_id_, webview->GetMainFrame() == frame,
1220 frame->GetProvisionalDataSource()->GetRequest().GetURL()));
1221}
1222
1223bool RenderView::DidLoadResourceFromMemoryCache(WebView* webview,
1224 const WebRequest& request,
1225 const WebResponse& response,
1226 WebFrame* frame) {
1227 // Let the browser know we loaded a resource from the memory cache. This
1228 // message is needed to display the correct SSL indicators.
1229 Send(new ViewHostMsg_DidLoadResourceFromMemoryCache(routing_id_,
[email protected]ffc45862009-03-17 06:11:081230 request.GetURL(), frame->GetSecurityOrigin(),
1231 frame->GetTop()->GetSecurityOrigin(),
1232 response.GetSecurityInfo()));
initial.commit09911bf2008-07-26 23:55:291233
1234 return false;
1235}
1236
1237void RenderView::DidReceiveProvisionalLoadServerRedirect(WebView* webview,
1238 WebFrame* frame) {
1239 if (frame == webview->GetMainFrame()) {
1240 // Received a redirect on the main frame.
1241 WebDataSource* data_source =
1242 webview->GetMainFrame()->GetProvisionalDataSource();
1243 if (!data_source) {
1244 // Should only be invoked when we have a data source.
1245 NOTREACHED();
1246 return;
1247 }
1248 const std::vector<GURL>& redirects = data_source->GetRedirectChain();
1249 if (redirects.size() >= 2) {
1250 Send(new ViewHostMsg_DidRedirectProvisionalLoad(
1251 routing_id_, page_id_, redirects[redirects.size() - 2],
1252 redirects[redirects.size() - 1]));
1253 }
1254 }
1255}
1256
1257void RenderView::DidFailProvisionalLoadWithError(WebView* webview,
1258 const WebError& error,
1259 WebFrame* frame) {
1260 // Notify the browser that we failed a provisional load with an error.
1261 //
1262 // Note: It is important this notification occur before DidStopLoading so the
1263 // SSL manager can react to the provisional load failure before being
1264 // notified the load stopped.
1265 //
1266 WebDataSource* ds = frame->GetProvisionalDataSource();
1267 DCHECK(ds);
1268
1269 const WebRequest& failed_request = ds->GetRequest();
1270
1271 bool show_repost_interstitial =
1272 (error.GetErrorCode() == net::ERR_CACHE_MISS &&
1273 LowerCaseEqualsASCII(failed_request.GetHttpMethod(), "post"));
1274 Send(new ViewHostMsg_DidFailProvisionalLoadWithError(
1275 routing_id_, frame == webview->GetMainFrame(),
1276 error.GetErrorCode(), error.GetFailedURL(),
1277 show_repost_interstitial));
1278
initial.commit09911bf2008-07-26 23:55:291279 // Don't display an error page if this is simply a cancelled load. Aside
1280 // from being dumb, WebCore doesn't expect it and it will cause a crash.
1281 if (error.GetErrorCode() == net::ERR_ABORTED)
1282 return;
1283
1284 // If this is a failed back/forward/reload navigation, then we need to do a
1285 // 'replace' load. This is necessary to avoid messing up session history.
1286 // Otherwise, we do a normal load, which simulates a 'go' navigation as far
1287 // as session history is concerned.
1288 RenderViewExtraRequestData* extra_data =
1289 static_cast<RenderViewExtraRequestData*>(failed_request.GetExtraData());
1290 bool replace = extra_data && !extra_data->is_new_navigation();
1291
[email protected]5df266ac2008-10-15 19:50:131292 // Use the alternate error page service if this is a DNS failure or
1293 // connection failure. ERR_CONNECTION_FAILED can be dropped once we no longer
1294 // use winhttp.
1295 int ec = error.GetErrorCode();
1296 if (ec == net::ERR_NAME_NOT_RESOLVED ||
1297 ec == net::ERR_CONNECTION_FAILED ||
1298 ec == net::ERR_CONNECTION_REFUSED ||
1299 ec == net::ERR_ADDRESS_UNREACHABLE ||
1300 ec == net::ERR_TIMED_OUT) {
1301 const GURL& failed_url = error.GetFailedURL();
1302 const GURL& error_page_url = GetAlternateErrorPageURL(failed_url,
1303 ec == net::ERR_NAME_NOT_RESOLVED ? WebViewDelegate::DNS_ERROR
1304 : WebViewDelegate::CONNECTION_ERROR);
1305 if (error_page_url.is_valid()) {
1306 // Ask the WebFrame to fetch the alternate error page for us.
1307 frame->LoadAlternateHTMLErrorPage(&failed_request, error, error_page_url,
1308 replace, GURL(kUnreachableWebDataURL));
1309 return;
1310 }
initial.commit09911bf2008-07-26 23:55:291311 }
[email protected]5df266ac2008-10-15 19:50:131312
[email protected]be645db2009-02-06 20:36:331313 // Fallback to a local error page.
[email protected]5df266ac2008-10-15 19:50:131314 LoadNavigationErrorPage(frame, &failed_request, error, std::string(),
1315 replace);
initial.commit09911bf2008-07-26 23:55:291316}
1317
1318void RenderView::LoadNavigationErrorPage(WebFrame* frame,
1319 const WebRequest* failed_request,
1320 const WebError& error,
1321 const std::string& html,
1322 bool replace) {
1323 const GURL& failed_url = error.GetFailedURL();
1324
1325 std::string alt_html;
1326 if (html.empty()) {
1327 // Use a local error page.
1328 int resource_id;
1329 DictionaryValue error_strings;
1330 if (error.GetErrorCode() == net::ERR_CACHE_MISS &&
1331 LowerCaseEqualsASCII(failed_request->GetHttpMethod(), "post")) {
1332 GetFormRepostErrorValues(failed_url, &error_strings);
1333 resource_id = IDR_ERROR_NO_DETAILS_HTML;
1334 } else {
1335 GetLocalizedErrorValues(error, &error_strings);
1336 resource_id = IDR_NET_ERROR_HTML;
1337 }
[email protected]8e50b602009-03-03 22:59:431338 error_strings.SetString(L"textdirection",
1339 (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) ?
1340 L"rtl" : L"ltr");
initial.commit09911bf2008-07-26 23:55:291341
1342 alt_html = GetAltHTMLForTemplate(error_strings, resource_id);
1343 } else {
1344 alt_html = html;
1345 }
1346
1347 // Use a data: URL as the site URL to prevent against XSS attacks.
1348 scoped_ptr<WebRequest> request(failed_request->Clone());
1349 request->SetURL(GURL(kUnreachableWebDataURL));
1350
1351 frame->LoadAlternateHTMLString(request.get(), alt_html, failed_url,
1352 replace);
1353}
1354
1355void RenderView::DidCommitLoadForFrame(WebView *webview, WebFrame* frame,
1356 bool is_new_navigation) {
1357 const WebRequest& request =
1358 webview->GetMainFrame()->GetDataSource()->GetRequest();
1359 RenderViewExtraRequestData* extra_data =
1360 static_cast<RenderViewExtraRequestData*>(request.GetExtraData());
1361
1362 if (is_new_navigation) {
1363 // When we perform a new navigation, we need to update the previous session
1364 // history entry with state for the page we are leaving.
1365 UpdateSessionHistory(frame);
1366
1367 // We bump our Page ID to correspond with the new session history entry.
1368 page_id_ = next_page_id_++;
1369
1370 MessageLoop::current()->PostDelayedTask(FROM_HERE,
1371 method_factory_.NewRunnableMethod(&RenderView::CapturePageInfo,
1372 page_id_, true),
1373 kDelayForForcedCaptureMs);
1374 } else {
1375 // Inspect the extra_data on the main frame (set in our Navigate method) to
1376 // see if the navigation corresponds to a session history navigation...
1377 // Note: |frame| may or may not be the toplevel frame, but for the case
1378 // of capturing session history, the first committed frame suffices. We
1379 // keep track of whether we've seen this commit before so that only capture
1380 // session history once per navigation.
[email protected]f4d34b52008-11-24 23:05:011381 //
1382 // Note that we need to check if the page ID changed. In the case of a
1383 // reload, the page ID doesn't change, and UpdateSessionHistory gets the
1384 // previous URL and the current page ID, which would be wrong.
initial.commit09911bf2008-07-26 23:55:291385 if (extra_data && !extra_data->is_new_navigation() &&
[email protected]f4d34b52008-11-24 23:05:011386 !extra_data->request_committed &&
1387 page_id_ != extra_data->pending_page_id()) {
initial.commit09911bf2008-07-26 23:55:291388 // This is a successful session history navigation!
1389 UpdateSessionHistory(frame);
initial.commit09911bf2008-07-26 23:55:291390 page_id_ = extra_data->pending_page_id();
1391 }
1392 }
1393
1394 // Remember that we've already processed this request, so we don't update
1395 // the session history again. We do this regardless of whether this is
1396 // a session history navigation, because if we attempted a session history
1397 // navigation without valid HistoryItem state, WebCore will think it is a
1398 // new navigation.
1399 if (extra_data)
1400 extra_data->request_committed = true;
1401
1402 UpdateURL(frame);
1403
1404 // If this committed load was initiated by a client redirect, we're
1405 // at the last stop now, so clear it.
1406 completed_client_redirect_src_ = GURL();
1407
1408 // Check whether we have new encoding name.
1409 UpdateEncoding(frame, webview->GetMainFrameEncodingName());
1410}
1411
1412void RenderView::DidReceiveTitle(WebView* webview,
1413 const std::wstring& title,
1414 WebFrame* frame) {
1415 UpdateTitle(frame, title);
1416
1417 // Also check whether we have new encoding name.
1418 UpdateEncoding(frame, webview->GetMainFrameEncodingName());
1419}
1420
1421void RenderView::DidFinishLoadForFrame(WebView* webview, WebFrame* frame) {
[email protected]c20210e62009-04-03 21:39:261422 if (webview->GetMainFrame() == frame) {
1423 const GURL& url = frame->GetURL();
1424 if (url.SchemeIs("http") || url.SchemeIs("https"))
1425 DumpLoadHistograms();
1426 }
initial.commit09911bf2008-07-26 23:55:291427}
1428
1429void RenderView::DidFailLoadWithError(WebView* webview,
1430 const WebError& error,
1431 WebFrame* frame) {
1432}
1433
1434void RenderView::DidFinishDocumentLoadForFrame(WebView* webview,
1435 WebFrame* frame) {
1436 // Check whether we have new encoding name.
1437 UpdateEncoding(frame, webview->GetMainFrameEncodingName());
[email protected]1e0f70402008-10-16 23:57:471438
[email protected]8930d472009-02-21 08:05:281439 if (RenderThread::current()) // Will be NULL during unit tests.
1440 RenderThread::current()->user_script_slave()->InjectScripts(
[email protected]0afe8272009-02-14 04:15:161441 frame, UserScript::DOCUMENT_END);
initial.commit09911bf2008-07-26 23:55:291442}
1443
1444void RenderView::DidHandleOnloadEventsForFrame(WebView* webview,
1445 WebFrame* frame) {
1446}
1447
1448void RenderView::DidChangeLocationWithinPageForFrame(WebView* webview,
1449 WebFrame* frame,
1450 bool is_new_navigation) {
1451 DidCommitLoadForFrame(webview, frame, is_new_navigation);
[email protected]9d806f52009-03-12 22:50:541452 const string16& title =
[email protected]de56f3782008-10-01 22:31:351453 webview->GetMainFrame()->GetDataSource()->GetPageTitle();
[email protected]9d806f52009-03-12 22:50:541454 UpdateTitle(frame, UTF16ToWideHack(title));
initial.commit09911bf2008-07-26 23:55:291455}
1456
1457void RenderView::DidReceiveIconForFrame(WebView* webview,
1458 WebFrame* frame) {
1459}
1460
1461void RenderView::WillPerformClientRedirect(WebView* webview,
1462 WebFrame* frame,
1463 const GURL& src_url,
1464 const GURL& dest_url,
1465 unsigned int delay_seconds,
1466 unsigned int fire_date) {
1467}
1468
1469void RenderView::DidCancelClientRedirect(WebView* webview,
1470 WebFrame* frame) {
1471}
1472
[email protected]309d7a282009-03-24 09:18:271473void RenderView::WillCloseFrame(WebView* view, WebFrame* frame) {
1474 // Remove all the pending extension callbacks for this frame.
[email protected]c6619182009-05-12 14:59:321475 if (pending_extension_requests_.IsEmpty())
[email protected]309d7a282009-03-24 09:18:271476 return;
1477
[email protected]c6619182009-05-12 14:59:321478 std::vector<int> orphaned_requests;
1479 for (IDMap<ExtensionProcessBindings::CallContext>::const_iterator iter =
1480 pending_extension_requests_.begin();
1481 iter != pending_extension_requests_.end(); ++iter) {
1482 if (iter->second->frame_ == frame)
1483 orphaned_requests.push_back(iter->first);
[email protected]309d7a282009-03-24 09:18:271484 }
1485
[email protected]c6619182009-05-12 14:59:321486 for (std::vector<int>::const_iterator iter = orphaned_requests.begin();
1487 iter != orphaned_requests.end(); ++iter) {
1488 delete pending_extension_requests_.Lookup(*iter);
1489 pending_extension_requests_.Remove(*iter);
[email protected]309d7a282009-03-24 09:18:271490 }
1491}
1492
initial.commit09911bf2008-07-26 23:55:291493void RenderView::DidCompleteClientRedirect(WebView* webview,
1494 WebFrame* frame,
1495 const GURL& source) {
1496 if (webview->GetMainFrame() == frame)
1497 completed_client_redirect_src_ = source;
1498}
1499
[email protected]5b35a6b2009-03-16 19:58:081500void RenderView::WillSendRequest(WebView* webview,
1501 uint32 identifier,
1502 WebRequest* request) {
1503 request->SetRequestorID(routing_id_);
1504}
1505
initial.commit09911bf2008-07-26 23:55:291506void RenderView::BindDOMAutomationController(WebFrame* webframe) {
1507 dom_automation_controller_.set_message_sender(this);
1508 dom_automation_controller_.set_routing_id(routing_id_);
1509 dom_automation_controller_.BindToJavascript(webframe,
1510 L"domAutomationController");
1511}
1512
1513void RenderView::WindowObjectCleared(WebFrame* webframe) {
[email protected]81e63782009-02-27 19:35:091514 if (BindingsPolicy::is_dom_automation_enabled(enabled_bindings_))
initial.commit09911bf2008-07-26 23:55:291515 BindDOMAutomationController(webframe);
[email protected]81e63782009-02-27 19:35:091516 if (BindingsPolicy::is_dom_ui_enabled(enabled_bindings_)) {
initial.commit09911bf2008-07-26 23:55:291517 dom_ui_bindings_.set_message_sender(this);
1518 dom_ui_bindings_.set_routing_id(routing_id_);
1519 dom_ui_bindings_.BindToJavascript(webframe, L"chrome");
1520 }
[email protected]81e63782009-02-27 19:35:091521 if (BindingsPolicy::is_external_host_enabled(enabled_bindings_)) {
[email protected]18cb2572008-08-21 20:34:451522 external_host_bindings_.set_message_sender(this);
1523 external_host_bindings_.set_routing_id(routing_id_);
1524 external_host_bindings_.BindToJavascript(webframe, L"externalHost");
1525 }
initial.commit09911bf2008-07-26 23:55:291526}
1527
[email protected]0afe8272009-02-14 04:15:161528void RenderView::DocumentElementAvailable(WebFrame* frame) {
[email protected]4b8323b2009-04-17 18:45:441529 // TODO(mpcomplete): remove this before Chrome extensions ship.
1530 // HACK. This is a temporary workaround to allow cross-origin XHR for Chrome
1531 // extensions. It grants full access to every origin, when we really want
1532 // to be able to restrict them more specifically.
[email protected]d959ce22009-04-15 21:03:421533 if (frame->GetURL().SchemeIs(chrome::kExtensionScheme))
[email protected]4b8323b2009-04-17 18:45:441534 frame->GrantUniversalAccess();
[email protected]d959ce22009-04-15 21:03:421535
[email protected]8930d472009-02-21 08:05:281536 if (RenderThread::current()) // Will be NULL during unit tests.
1537 RenderThread::current()->user_script_slave()->InjectScripts(
[email protected]0afe8272009-02-14 04:15:161538 frame, UserScript::DOCUMENT_START);
1539}
1540
initial.commit09911bf2008-07-26 23:55:291541WindowOpenDisposition RenderView::DispositionForNavigationAction(
1542 WebView* webview,
1543 WebFrame* frame,
1544 const WebRequest* request,
1545 WebNavigationType type,
1546 WindowOpenDisposition disposition,
1547 bool is_redirect) {
1548 // Webkit is asking whether to navigate to a new URL.
1549 // This is fine normally, except if we're showing UI from one security
1550 // context and they're trying to navigate to a different context.
1551 const GURL& url = request->GetURL();
1552 // We only care about navigations that are within the current tab (as opposed
1553 // to, for example, opening a new window).
1554 // But we sometimes navigate to about:blank to clear a tab, and we want to
1555 // still allow that.
[email protected]6de74452009-02-25 18:04:591556 if (disposition == CURRENT_TAB && !(url.SchemeIs(chrome::kAboutScheme))) {
initial.commit09911bf2008-07-26 23:55:291557 // GetExtraData is NULL when we did not issue the request ourselves (see
1558 // OnNavigate), and so such a request may correspond to a link-click,
1559 // script, or drag-n-drop initiated navigation.
1560 if (frame == webview->GetMainFrame() && !request->GetExtraData()) {
1561 // When we received such unsolicited navigations, we sometimes want to
1562 // punt them up to the browser to handle.
[email protected]81e63782009-02-27 19:35:091563 if (BindingsPolicy::is_dom_ui_enabled(enabled_bindings_) ||
initial.commit09911bf2008-07-26 23:55:291564 frame->GetInViewSourceMode() ||
[email protected]6de74452009-02-25 18:04:591565 url.SchemeIs(chrome::kViewSourceScheme)) {
[email protected]c0588052008-10-27 23:01:501566 OpenURL(webview, url, GURL(), disposition);
initial.commit09911bf2008-07-26 23:55:291567 return IGNORE_ACTION; // Suppress the load here.
[email protected]47811562009-05-13 06:21:011568 } else if (url.SchemeIs(kBackForwardNavigationScheme)) {
1569 std::string offset_str = url.ExtractFileName();
1570 int offset;
1571 if (StringToInt(offset_str, &offset)) {
1572 GoToEntryAtOffset(offset);
1573 return IGNORE_ACTION; // The browser process handles this one.
1574 }
initial.commit09911bf2008-07-26 23:55:291575 }
1576 }
1577 }
1578
1579 // Detect when a page is "forking" a new tab that can be safely rendered in
1580 // its own process. This is done by sites like Gmail that try to open links
1581 // in new windows without script connections back to the original page. We
1582 // treat such cases as browser navigations (in which we will create a new
1583 // renderer for a cross-site navigation), rather than WebKit navigations.
1584 //
1585 // We use the following heuristic to decide whether to fork a new page in its
1586 // own process:
1587 // The parent page must open a new tab to about:blank, set the new tab's
1588 // window.opener to null, and then redirect the tab to a cross-site URL using
1589 // JavaScript.
1590 bool is_fork =
1591 // Must start from a tab showing about:blank, which is later redirected.
[email protected]6aad4bd2009-02-26 22:55:171592 frame->GetURL() == GURL("about:blank") &&
initial.commit09911bf2008-07-26 23:55:291593 // Must be the first real navigation of the tab.
1594 GetHistoryBackListCount() < 1 &&
1595 GetHistoryForwardListCount() < 1 &&
1596 // The parent page must have set the child's window.opener to null before
1597 // redirecting to the desired URL.
1598 frame->GetOpener() == NULL &&
1599 // Must be a top-level frame.
1600 frame->GetParent() == NULL &&
1601 // Must not have issued the request from this page. GetExtraData is NULL
1602 // when the navigation is being done by something outside the page.
1603 !request->GetExtraData() &&
1604 // Must be targeted at the current tab.
1605 disposition == CURRENT_TAB &&
1606 // Must be a JavaScript navigation, which appears as "other".
1607 type == WebNavigationTypeOther;
1608 if (is_fork) {
1609 // Open the URL via the browser, not via WebKit.
[email protected]c0588052008-10-27 23:01:501610 OpenURL(webview, url, GURL(), disposition);
initial.commit09911bf2008-07-26 23:55:291611 return IGNORE_ACTION;
1612 }
1613
1614 return disposition;
1615}
1616
[email protected]a455d3812009-03-05 20:18:071617void RenderView::RunJavaScriptAlert(WebFrame* webframe,
initial.commit09911bf2008-07-26 23:55:291618 const std::wstring& message) {
[email protected]478ff2ed2009-04-21 23:49:181619 RunJavaScriptMessage(MessageBoxFlags::kIsJavascriptAlert,
initial.commit09911bf2008-07-26 23:55:291620 message,
1621 std::wstring(),
[email protected]a455d3812009-03-05 20:18:071622 webframe->GetURL(),
initial.commit09911bf2008-07-26 23:55:291623 NULL);
1624}
1625
[email protected]a455d3812009-03-05 20:18:071626bool RenderView::RunJavaScriptConfirm(WebFrame* webframe,
initial.commit09911bf2008-07-26 23:55:291627 const std::wstring& message) {
[email protected]478ff2ed2009-04-21 23:49:181628 return RunJavaScriptMessage(MessageBoxFlags::kIsJavascriptConfirm,
initial.commit09911bf2008-07-26 23:55:291629 message,
1630 std::wstring(),
[email protected]a455d3812009-03-05 20:18:071631 webframe->GetURL(),
initial.commit09911bf2008-07-26 23:55:291632 NULL);
1633}
1634
[email protected]a455d3812009-03-05 20:18:071635bool RenderView::RunJavaScriptPrompt(WebFrame* webframe,
initial.commit09911bf2008-07-26 23:55:291636 const std::wstring& message,
1637 const std::wstring& default_value,
1638 std::wstring* result) {
[email protected]478ff2ed2009-04-21 23:49:181639 return RunJavaScriptMessage(MessageBoxFlags::kIsJavascriptPrompt,
initial.commit09911bf2008-07-26 23:55:291640 message,
1641 default_value,
[email protected]a455d3812009-03-05 20:18:071642 webframe->GetURL(),
initial.commit09911bf2008-07-26 23:55:291643 result);
1644}
1645
1646bool RenderView::RunJavaScriptMessage(int type,
1647 const std::wstring& message,
1648 const std::wstring& default_value,
[email protected]a455d3812009-03-05 20:18:071649 const GURL& frame_url,
initial.commit09911bf2008-07-26 23:55:291650 std::wstring* result) {
1651 bool success = false;
1652 std::wstring result_temp;
1653 if (!result)
1654 result = &result_temp;
1655 IPC::SyncMessage* msg = new ViewHostMsg_RunJavaScriptMessage(
[email protected]a455d3812009-03-05 20:18:071656 routing_id_, message, default_value, frame_url, type, &success, result);
initial.commit09911bf2008-07-26 23:55:291657
[email protected]1c4947f2009-01-15 22:25:111658 msg->set_pump_messages_event(modal_dialog_event_.get());
initial.commit09911bf2008-07-26 23:55:291659 Send(msg);
1660
1661 return success;
1662}
1663
1664void RenderView::AddGURLSearchProvider(const GURL& osd_url, bool autodetected) {
1665 if (!osd_url.is_empty())
1666 Send(new ViewHostMsg_PageHasOSDD(routing_id_, page_id_, osd_url,
1667 autodetected));
1668}
1669
[email protected]a455d3812009-03-05 20:18:071670bool RenderView::RunBeforeUnloadConfirm(WebFrame* webframe,
initial.commit09911bf2008-07-26 23:55:291671 const std::wstring& message) {
1672 bool success = false;
1673 // This is an ignored return value, but is included so we can accept the same
1674 // response as RunJavaScriptMessage.
1675 std::wstring ignored_result;
1676 IPC::SyncMessage* msg = new ViewHostMsg_RunBeforeUnloadConfirm(
[email protected]a455d3812009-03-05 20:18:071677 routing_id_, webframe->GetURL(), message, &success, &ignored_result);
initial.commit09911bf2008-07-26 23:55:291678
[email protected]1c4947f2009-01-15 22:25:111679 msg->set_pump_messages_event(modal_dialog_event_.get());
initial.commit09911bf2008-07-26 23:55:291680 Send(msg);
1681
1682 return success;
1683}
1684
[email protected]0ebf3872008-11-07 21:35:031685void RenderView::QueryFormFieldAutofill(const std::wstring& field_name,
1686 const std::wstring& text,
1687 int64 node_id) {
1688 static int message_id_counter = 0;
1689 form_field_autofill_request_id_ = message_id_counter++;
1690 Send(new ViewHostMsg_QueryFormFieldAutofill(routing_id_,
1691 field_name, text,
1692 node_id,
1693 form_field_autofill_request_id_));
1694}
1695
[email protected]4d2b6fb2009-03-20 22:28:171696void RenderView::RemoveStoredAutofillEntry(const std::wstring& name,
1697 const std::wstring& value) {
1698 Send(new ViewHostMsg_RemoveAutofillEntry(routing_id_, name, value));
1699}
1700
[email protected]0ebf3872008-11-07 21:35:031701void RenderView::OnReceivedAutofillSuggestions(
1702 int64 node_id,
1703 int request_id,
[email protected]8d0f15c2008-11-11 01:01:091704 const std::vector<std::wstring>& suggestions,
[email protected]0ebf3872008-11-07 21:35:031705 int default_suggestion_index) {
1706 if (!webview() || request_id != form_field_autofill_request_id_)
1707 return;
1708
1709 webview()->AutofillSuggestionsForNode(node_id, suggestions,
1710 default_suggestion_index);
1711}
1712
[email protected]2c4410d2009-05-06 23:46:221713void RenderView::OnPopupNotificationVisibilityChanged(bool visible) {
[email protected]634a6f92008-12-01 21:39:311714 popup_notification_visible_ = visible;
1715}
1716
initial.commit09911bf2008-07-26 23:55:291717void RenderView::ShowModalHTMLDialog(const GURL& url, int width, int height,
1718 const std::string& json_arguments,
1719 std::string* json_retval) {
1720 IPC::SyncMessage* msg = new ViewHostMsg_ShowModalHTMLDialog(
1721 routing_id_, url, width, height, json_arguments, json_retval);
1722
[email protected]1c4947f2009-01-15 22:25:111723 msg->set_pump_messages_event(modal_dialog_event_.get());
initial.commit09911bf2008-07-26 23:55:291724 Send(msg);
1725}
1726
1727uint32 RenderView::GetCPBrowsingContext() {
1728 uint32 context = 0;
1729 Send(new ViewHostMsg_GetCPBrowsingContext(&context));
1730 return context;
1731}
1732
1733// Tell the browser to display a destination link.
1734void RenderView::UpdateTargetURL(WebView* webview, const GURL& url) {
1735 if (url != target_url_) {
1736 if (target_url_status_ == TARGET_INFLIGHT ||
1737 target_url_status_ == TARGET_PENDING) {
1738 // If we have a request in-flight, save the URL to be sent when we
1739 // receive an ACK to the in-flight request. We can happily overwrite
1740 // any existing pending sends.
1741 pending_target_url_ = url;
1742 target_url_status_ = TARGET_PENDING;
1743 } else {
1744 Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_, url));
1745 target_url_ = url;
1746 target_url_status_ = TARGET_INFLIGHT;
1747 }
1748 }
1749}
1750
[email protected]b62d1a8c2009-01-13 23:54:571751void RenderView::RunFileChooser(bool multi_select,
[email protected]b949f1112009-04-12 20:03:081752 const string16& title,
1753 const FilePath& default_filename,
initial.commit09911bf2008-07-26 23:55:291754 WebFileChooserCallback* file_chooser) {
1755 if (file_chooser_.get()) {
1756 // TODO(brettw): bug 1235154: This should be a synchronous message to deal
1757 // with the fact that web pages can programatically trigger this. With the
1758 // asnychronous messages, we can get an additional call when one is pending,
1759 // which this test is for. For now, we just ignore the additional file
1760 // chooser request. WebKit doesn't do anything to expect the callback, so
1761 // we can just ignore calling it.
1762 delete file_chooser;
1763 return;
1764 }
1765 file_chooser_.reset(file_chooser);
[email protected]b62d1a8c2009-01-13 23:54:571766 Send(new ViewHostMsg_RunFileChooser(routing_id_, multi_select, title,
[email protected]b949f1112009-04-12 20:03:081767 default_filename));
initial.commit09911bf2008-07-26 23:55:291768}
1769
1770void RenderView::AddMessageToConsole(WebView* webview,
1771 const std::wstring& message,
1772 unsigned int line_no,
1773 const std::wstring& source_id) {
1774 Send(new ViewHostMsg_AddMessageToConsole(routing_id_, message,
1775 static_cast<int32>(line_no),
1776 source_id));
1777}
1778
1779void RenderView::AddSearchProvider(const std::string& url) {
1780 AddGURLSearchProvider(GURL(url),
1781 false); // not autodetected
1782}
1783
1784void RenderView::DebuggerOutput(const std::wstring& out) {
1785 Send(new ViewHostMsg_DebuggerOutput(routing_id_, out));
1786}
1787
[email protected]c88a70fe2009-05-05 20:00:221788WebView* RenderView::CreateWebView(WebView* webview,
1789 bool user_gesture,
1790 const GURL& creator_url) {
[email protected]0aa55312008-10-17 21:53:081791 // Check to make sure we aren't overloading on popups.
1792 if (shared_popup_counter_->data > kMaximumNumberOfUnacknowledgedPopups)
1793 return NULL;
1794
[email protected]634a6f92008-12-01 21:39:311795 // This window can't be closed from a window.close() call until we receive a
1796 // message from the Browser process explicitly allowing it.
1797 popup_notification_visible_ = true;
1798
initial.commit09911bf2008-07-26 23:55:291799 int32 routing_id = MSG_ROUTING_NONE;
[email protected]6c8afae52009-01-22 02:24:571800
[email protected]18bcc3c2009-01-27 21:39:151801 ModalDialogEvent modal_dialog_event;
[email protected]6c8afae52009-01-22 02:24:571802 render_thread_->Send(
[email protected]15787f8f2008-10-17 15:29:031803 new ViewHostMsg_CreateWindow(routing_id_, user_gesture, &routing_id,
1804 &modal_dialog_event));
initial.commit09911bf2008-07-26 23:55:291805 if (routing_id == MSG_ROUTING_NONE) {
initial.commit09911bf2008-07-26 23:55:291806 return NULL;
1807 }
1808
1809 // The WebView holds a reference to this new RenderView
1810 const WebPreferences& prefs = webview->GetPreferences();
[email protected]6c8afae52009-01-22 02:24:571811 base::WaitableEvent* waitable_event = new base::WaitableEvent
1812#if defined(OS_WIN)
[email protected]18bcc3c2009-01-27 21:39:151813 (modal_dialog_event.event);
[email protected]6c8afae52009-01-22 02:24:571814#else
1815 (true, false);
1816#endif
[email protected]81a34412009-01-05 19:17:241817 RenderView* view = RenderView::Create(render_thread_,
[email protected]1c4947f2009-01-15 22:25:111818 NULL, waitable_event, routing_id_,
[email protected]0aa55312008-10-17 21:53:081819 prefs, shared_popup_counter_,
1820 routing_id);
[email protected]ed4bf2d2009-05-05 00:10:061821 view->opened_by_user_gesture_ = user_gesture;
[email protected]c88a70fe2009-05-05 20:00:221822 view->creator_url_ = creator_url;
initial.commit09911bf2008-07-26 23:55:291823
1824 // Copy over the alternate error page URL so we can have alt error pages in
1825 // the new render view (we don't need the browser to send the URL back down).
1826 view->alternate_error_page_url_ = alternate_error_page_url_;
1827
1828 return view->webview();
1829}
1830
[email protected]0ebf3872008-11-07 21:35:031831WebWidget* RenderView::CreatePopupWidget(WebView* webview,
[email protected]cfd727f2009-01-09 20:21:111832 bool activatable) {
[email protected]8085dbc82008-09-26 22:53:441833 RenderWidget* widget = RenderWidget::Create(routing_id_,
[email protected]81a34412009-01-05 19:17:241834 render_thread_,
[email protected]cfd727f2009-01-09 20:21:111835 activatable);
initial.commit09911bf2008-07-26 23:55:291836 return widget->webwidget();
1837}
1838
1839WebPluginDelegate* RenderView::CreatePluginDelegate(
1840 WebView* webview,
1841 const GURL& url,
1842 const std::string& mime_type,
1843 const std::string& clsid,
1844 std::string* actual_mime_type) {
[email protected]ffeba6d2009-04-27 20:43:261845#if defined(OS_WIN) || defined(OS_LINUX)
[email protected]6273e2e72009-04-17 00:13:551846 if (!PluginChannelHost::IsListening())
1847 return NULL;
1848
[email protected]ffeba6d2009-04-27 20:43:261849#if !defined(OS_LINUX) // In-proc plugins aren't supported on Linux.
[email protected]88a1fb47a2009-03-13 00:18:061850 if (RenderProcess::current()->in_process_plugins()) {
[email protected]690a99c2009-01-06 16:48:451851 FilePath path;
[email protected]81a34412009-01-05 19:17:241852 render_thread_->Send(
initial.commit09911bf2008-07-26 23:55:291853 new ViewHostMsg_GetPluginPath(url, mime_type, clsid, &path,
1854 actual_mime_type));
[email protected]690a99c2009-01-06 16:48:451855 if (path.value().empty())
initial.commit09911bf2008-07-26 23:55:291856 return NULL;
1857
1858 std::string mime_type_to_use;
1859 if (actual_mime_type && !actual_mime_type->empty())
1860 mime_type_to_use = *actual_mime_type;
1861 else
1862 mime_type_to_use = mime_type;
1863
[email protected]b94d3322009-02-12 19:49:041864 return WebPluginDelegate::Create(path,
1865 mime_type_to_use,
1866 gfx::NativeViewFromId(host_window_));
initial.commit09911bf2008-07-26 23:55:291867 }
[email protected]ffeba6d2009-04-27 20:43:261868#endif
initial.commit09911bf2008-07-26 23:55:291869
1870 WebPluginDelegateProxy* proxy =
1871 WebPluginDelegateProxy::Create(url, mime_type, clsid, this);
1872 if (!proxy)
1873 return NULL;
1874
1875 // We hold onto the proxy so we can poke it when we are painting. See our
1876 // DidPaint implementation below.
1877 plugin_delegates_.push_back(proxy);
1878
1879 return proxy;
[email protected]6c8afae52009-01-22 02:24:571880#else
[email protected]157e5d22009-04-23 18:43:351881 // TODO(port): Plugins currently not supported
1882 NOTIMPLEMENTED();
1883 return NULL;
[email protected]6c8afae52009-01-22 02:24:571884#endif
initial.commit09911bf2008-07-26 23:55:291885}
1886
[email protected]4e6be3f2009-05-07 02:24:441887WebKit::WebMediaPlayer* RenderView::CreateWebMediaPlayer(
1888 WebKit::WebMediaPlayerClient* client) {
[email protected]4e6be3f2009-05-07 02:24:441889 return new WebMediaPlayerImpl(this, client);
[email protected]ec9212f2008-12-18 21:40:361890}
1891
initial.commit09911bf2008-07-26 23:55:291892void RenderView::OnMissingPluginStatus(WebPluginDelegate* delegate,
1893 int status) {
[email protected]6c8afae52009-01-22 02:24:571894#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:291895 if (first_default_plugin_ == NULL) {
1896 // Show the InfoBar for the first available plugin.
1897 if (status == default_plugin::MISSING_PLUGIN_AVAILABLE) {
1898 first_default_plugin_ = delegate;
1899 Send(new ViewHostMsg_MissingPluginStatus(routing_id_, status));
1900 }
1901 } else {
1902 // Closes the InfoBar if user clicks on the plugin (instead of the InfoBar)
1903 // to start the download/install.
1904 if (status == default_plugin::MISSING_PLUGIN_USER_STARTED_DOWNLOAD) {
1905 Send(new ViewHostMsg_MissingPluginStatus(routing_id_, status));
1906 }
1907 }
[email protected]6c8afae52009-01-22 02:24:571908#else
1909 // TODO(port): plugins current not supported
1910 NOTIMPLEMENTED();
1911#endif
initial.commit09911bf2008-07-26 23:55:291912}
1913
[email protected]eb47a132009-03-04 00:39:561914WebWorker* RenderView::CreateWebWorker(WebWorkerClient* client) {
1915#if defined(OS_WIN)
[email protected]ec775ef2009-05-01 21:20:471916 return new WebWorkerProxy(client, RenderThread::current(), routing_id_);
[email protected]eb47a132009-03-04 00:39:561917#else
1918 // TODO(port): out of process workers
1919 NOTIMPLEMENTED();
1920 return NULL;
1921#endif
1922}
1923
initial.commit09911bf2008-07-26 23:55:291924void RenderView::OpenURL(WebView* webview, const GURL& url,
[email protected]c0588052008-10-27 23:01:501925 const GURL& referrer,
initial.commit09911bf2008-07-26 23:55:291926 WindowOpenDisposition disposition) {
[email protected]c0588052008-10-27 23:01:501927 Send(new ViewHostMsg_OpenURL(routing_id_, url, referrer, disposition));
initial.commit09911bf2008-07-26 23:55:291928}
1929
[email protected]1d522202009-04-04 01:56:421930void RenderView::DidContentsSizeChange(WebWidget* webwidget,
1931 int new_width,
1932 int new_height) {
[email protected]0666aef2009-05-13 19:48:081933 // We don't always want to send the change messages over IPC, only if we've
1934 // be put in that mode by getting a |ViewMsg_EnableIntrinsicWidthChangedMode|
1935 // message.
1936 // TODO(rafaelw): Figure out where the best place to set this for extensions
1937 // is. It isn't clean to test for ExtensionView by examining the
1938 // enabled_bindings. This needs to be generalized as it becomes clear what
1939 // extension toolbars need.
1940 if (BindingsPolicy::is_extension_enabled(enabled_bindings_) ||
1941 send_preferred_width_changes_) {
1942 // WebCore likes to tell us things have changed even when they haven't, so
1943 // cache the width and only send the IPC message when we're sure the
1944 // width is different.
[email protected]1d522202009-04-04 01:56:421945 int width = webview()->GetMainFrame()->GetContentsPreferredWidth();
[email protected]0666aef2009-05-13 19:48:081946 if (width != preferred_width_) {
1947 Send(new ViewHostMsg_DidContentsPreferredWidthChange(routing_id_, width));
1948 preferred_width_ = width;
1949 }
[email protected]1d522202009-04-04 01:56:421950 }
1951}
1952
initial.commit09911bf2008-07-26 23:55:291953// We are supposed to get a single call to Show for a newly created RenderView
1954// that was created via RenderView::CreateWebView. So, we wait until this
1955// point to dispatch the ShowView message.
1956//
1957// This method provides us with the information about how to display the newly
1958// created RenderView (i.e., as a constrained popup or as a new tab).
1959//
1960void RenderView::Show(WebWidget* webwidget, WindowOpenDisposition disposition) {
1961 DCHECK(!did_show_) << "received extraneous Show call";
1962 DCHECK(opener_id_ != MSG_ROUTING_NONE);
1963
1964 if (did_show_)
1965 return;
1966 did_show_ = true;
1967
1968 // NOTE: initial_pos_ may still have its default values at this point, but
1969 // that's okay. It'll be ignored if disposition is not NEW_POPUP, or the
1970 // browser process will impose a default position otherwise.
[email protected]35f7d212009-04-29 21:19:271971 Send(new ViewHostMsg_ShowView(opener_id_, routing_id_, disposition,
[email protected]c88a70fe2009-05-05 20:00:221972 initial_pos_, opened_by_user_gesture_, creator_url_));
[email protected]2533ce12009-05-09 00:02:241973 SetPendingWindowRect(initial_pos_);
initial.commit09911bf2008-07-26 23:55:291974}
1975
[email protected]634a6f92008-12-01 21:39:311976void RenderView::CloseWidgetSoon(WebWidget* webwidget) {
[email protected]2c4410d2009-05-06 23:46:221977 if (!popup_notification_visible_)
[email protected]634a6f92008-12-01 21:39:311978 RenderWidget::CloseWidgetSoon(webwidget);
1979}
1980
initial.commit09911bf2008-07-26 23:55:291981void RenderView::RunModal(WebWidget* webwidget) {
1982 DCHECK(did_show_) << "should already have shown the view";
1983
1984 IPC::SyncMessage* msg = new ViewHostMsg_RunModal(routing_id_);
1985
[email protected]1c4947f2009-01-15 22:25:111986 msg->set_pump_messages_event(modal_dialog_event_.get());
initial.commit09911bf2008-07-26 23:55:291987 Send(msg);
1988}
1989
1990void RenderView::SyncNavigationState() {
1991 if (!webview())
1992 return;
1993
initial.commit09911bf2008-07-26 23:55:291994 std::string state;
[email protected]606843fa2008-12-02 19:08:561995 if (!webview()->GetMainFrame()->GetCurrentHistoryState(&state))
initial.commit09911bf2008-07-26 23:55:291996 return;
[email protected]606843fa2008-12-02 19:08:561997 Send(new ViewHostMsg_UpdateState(routing_id_, page_id_, state));
initial.commit09911bf2008-07-26 23:55:291998}
1999
2000void RenderView::ShowContextMenu(WebView* webview,
[email protected]124646932009-01-28 18:39:022001 ContextNode node,
initial.commit09911bf2008-07-26 23:55:292002 int x,
2003 int y,
2004 const GURL& link_url,
2005 const GURL& image_url,
2006 const GURL& page_url,
2007 const GURL& frame_url,
2008 const std::wstring& selection_text,
2009 const std::wstring& misspelled_word,
[email protected]6aa376b2008-09-23 18:49:522010 int edit_flags,
[email protected]c9825a42009-05-01 22:51:502011 const std::string& security_info,
2012 const std::string& frame_charset) {
[email protected]e09ba552009-02-05 03:26:292013 ContextMenuParams params;
[email protected]124646932009-01-28 18:39:022014 params.node = node;
initial.commit09911bf2008-07-26 23:55:292015 params.x = x;
2016 params.y = y;
2017 params.image_url = image_url;
2018 params.link_url = link_url;
[email protected]e6c79812009-04-22 22:31:422019 params.unfiltered_link_url = link_url;
initial.commit09911bf2008-07-26 23:55:292020 params.page_url = page_url;
2021 params.frame_url = frame_url;
2022 params.selection_text = selection_text;
2023 params.misspelled_word = misspelled_word;
[email protected]be645db2009-02-06 20:36:332024 params.spellcheck_enabled =
[email protected]bbbd545c2008-12-15 20:18:042025 webview->GetFocusedFrame()->SpellCheckEnabled();
initial.commit09911bf2008-07-26 23:55:292026 params.edit_flags = edit_flags;
[email protected]6aa376b2008-09-23 18:49:522027 params.security_info = security_info;
[email protected]c9825a42009-05-01 22:51:502028 params.frame_charset = frame_charset;
initial.commit09911bf2008-07-26 23:55:292029 Send(new ViewHostMsg_ContextMenu(routing_id_, params));
2030}
2031
[email protected]e80c73b2009-04-07 23:24:582032void RenderView::StartDragging(WebView* webview,
2033 const WebDragData& drag_data) {
2034 Send(new ViewHostMsg_StartDragging(routing_id_, WebDropData(drag_data)));
initial.commit09911bf2008-07-26 23:55:292035}
2036
2037void RenderView::TakeFocus(WebView* webview, bool reverse) {
2038 Send(new ViewHostMsg_TakeFocus(routing_id_, reverse));
2039}
2040
2041void RenderView::DidDownloadImage(int id,
2042 const GURL& image_url,
2043 bool errored,
2044 const SkBitmap& image) {
2045 Send(new ViewHostMsg_DidDownloadImage(routing_id_, id, image_url, errored,
2046 image));
2047}
2048
2049
2050void RenderView::OnDownloadImage(int id,
2051 const GURL& image_url,
2052 int image_size) {
[email protected]f11ca0732009-04-11 00:09:342053
2054 bool data_image_failed = false;
2055 if (image_url.SchemeIs("data")) {
2056 SkBitmap data_image = ImageFromDataUrl(image_url);
2057 data_image_failed = data_image.empty();
2058 if (!data_image_failed) {
2059 Send(new ViewHostMsg_DidDownloadImage(routing_id_, id, image_url, false,
2060 data_image));
2061 }
2062 }
2063
2064 if (data_image_failed || !webview()->DownloadImage(id, image_url, image_size))
initial.commit09911bf2008-07-26 23:55:292065 Send(new ViewHostMsg_DidDownloadImage(routing_id_, id, image_url, true,
2066 SkBitmap()));
2067}
2068
[email protected]f11ca0732009-04-11 00:09:342069SkBitmap RenderView::ImageFromDataUrl(const GURL& url) const {
2070 std::string mime_type, char_set, data;
2071 if (net::DataURL::Parse(url, &mime_type, &char_set, &data) && !data.empty()) {
2072 // Decode the favicon using WebKit's image decoder.
2073 webkit_glue::ImageDecoder decoder(gfx::Size(kFavIconSize, kFavIconSize));
2074 const unsigned char* src_data =
2075 reinterpret_cast<const unsigned char*>(&data[0]);
2076
2077 return decoder.Decode(src_data, data.size());
2078 }
2079 return SkBitmap();
2080}
2081
initial.commit09911bf2008-07-26 23:55:292082void RenderView::OnGetApplicationInfo(int page_id) {
2083 webkit_glue::WebApplicationInfo app_info;
2084 if (page_id == page_id_)
2085 webkit_glue::GetApplicationInfo(webview(), &app_info);
2086
2087 // Prune out any data URLs in the set of icons. The browser process expects
2088 // any icon with a data URL to have originated from a favicon. We don't want
2089 // to decode arbitrary data URLs in the browser process. See
2090 // http://b/issue?id=1162972
2091 for (size_t i = 0; i < app_info.icons.size(); ++i) {
[email protected]6de74452009-02-25 18:04:592092 if (app_info.icons[i].url.SchemeIs(chrome::kDataScheme)) {
initial.commit09911bf2008-07-26 23:55:292093 app_info.icons.erase(app_info.icons.begin() + i);
2094 --i;
2095 }
2096 }
2097
2098 Send(new ViewHostMsg_DidGetApplicationInfo(routing_id_, page_id, app_info));
2099}
2100
2101GURL RenderView::GetAlternateErrorPageURL(const GURL& failedURL,
2102 ErrorPageType error_type) {
2103 if (failedURL.SchemeIsSecure()) {
2104 // If the URL that failed was secure, then the embedding web page was not
2105 // expecting a network attacker to be able to manipulate its contents. As
2106 // we fetch alternate error pages over HTTP, we would be allowing a network
2107 // attacker to manipulate the contents of the response if we tried to use
2108 // the link doctor here.
2109 return GURL::EmptyGURL();
2110 }
2111
2112 // Grab the base URL from the browser process.
2113 if (!alternate_error_page_url_.is_valid())
2114 return GURL::EmptyGURL();
2115
2116 // Strip query params from the failed URL.
2117 GURL::Replacements remove_params;
2118 remove_params.ClearUsername();
2119 remove_params.ClearPassword();
2120 remove_params.ClearQuery();
2121 remove_params.ClearRef();
2122 const GURL url_to_send = failedURL.ReplaceComponents(remove_params);
2123
2124 // Construct the query params to send to link doctor.
2125 std::string params(alternate_error_page_url_.query());
2126 params.append("&url=");
2127 params.append(EscapeQueryParamValue(url_to_send.spec()));
2128 params.append("&sourceid=chrome");
2129 params.append("&error=");
2130 switch (error_type) {
2131 case DNS_ERROR:
2132 params.append("dnserror");
2133 break;
2134
2135 case HTTP_404:
2136 params.append("http404");
2137 break;
2138
[email protected]5df266ac2008-10-15 19:50:132139 case CONNECTION_ERROR:
[email protected]e1f934b2009-01-26 20:41:332140 params.append("connectionfailure");
[email protected]5df266ac2008-10-15 19:50:132141 break;
2142
initial.commit09911bf2008-07-26 23:55:292143 default:
2144 NOTREACHED() << "unknown ErrorPageType";
2145 }
2146
2147 // OK, build the final url to return.
2148 GURL::Replacements link_doctor_params;
2149 link_doctor_params.SetQueryStr(params);
2150 GURL url = alternate_error_page_url_.ReplaceComponents(link_doctor_params);
2151 return url;
2152}
2153
[email protected]7ea066a2009-04-06 20:21:592154void RenderView::OnFind(int request_id,
2155 const string16& search_text,
2156 const WebKit::WebFindOptions& options) {
initial.commit09911bf2008-07-26 23:55:292157 WebFrame* main_frame = webview()->GetMainFrame();
2158 WebFrame* frame_after_main = webview()->GetNextFrameAfter(main_frame, true);
2159 WebFrame* focused_frame = webview()->GetFocusedFrame();
2160 WebFrame* search_frame = focused_frame; // start searching focused frame.
2161
2162 bool multi_frame = (frame_after_main != main_frame);
2163
2164 // If we have multiple frames, we don't want to wrap the search within the
2165 // frame, so we check here if we only have main_frame in the chain.
2166 bool wrap_within_frame = !multi_frame;
2167
[email protected]b3f2b912009-04-09 16:18:522168 WebRect selection_rect;
initial.commit09911bf2008-07-26 23:55:292169 bool result = false;
2170
2171 do {
[email protected]7ea066a2009-04-06 20:21:592172 result = search_frame->Find(
2173 request_id, search_text, options, wrap_within_frame, &selection_rect);
initial.commit09911bf2008-07-26 23:55:292174
2175 if (!result) {
2176 // don't leave text selected as you move to the next frame.
2177 search_frame->ClearSelection();
2178
2179 // Find the next frame, but skip the invisible ones.
2180 do {
2181 // What is the next frame to search? (we might be going backwards). Note
2182 // that we specify wrap=true so that search_frame never becomes NULL.
[email protected]7ea066a2009-04-06 20:21:592183 search_frame = options.forward ?
initial.commit09911bf2008-07-26 23:55:292184 webview()->GetNextFrameAfter(search_frame, true) :
2185 webview()->GetPreviousFrameBefore(search_frame, true);
2186 } while (!search_frame->Visible() && search_frame != focused_frame);
2187
[email protected]884db412008-11-24 23:46:502188 // Make sure selection doesn't affect the search operation in new frame.
initial.commit09911bf2008-07-26 23:55:292189 search_frame->ClearSelection();
2190
2191 // If we have multiple frames and we have wrapped back around to the
2192 // focused frame, we need to search it once more allowing wrap within
2193 // the frame, otherwise it will report 'no match' if the focused frame has
2194 // reported matches, but no frames after the focused_frame contain a
2195 // match for the search word(s).
2196 if (multi_frame && search_frame == focused_frame) {
[email protected]7ea066a2009-04-06 20:21:592197 result = search_frame->Find(
2198 request_id, search_text, options, true, // Force wrapping.
2199 &selection_rect);
initial.commit09911bf2008-07-26 23:55:292200 }
2201 }
2202
2203 // TODO(jcampan): http://b/issue?id=1157486 Remove StoreForFocus call once
2204 // we have the fix for 792423.
2205 search_frame->GetView()->StoreFocusForFrame(search_frame);
2206 webview()->SetFocusedFrame(search_frame);
2207 } while (!result && search_frame != focused_frame);
2208
2209 // Make sure we don't leave any frame focused or the focus won't be restored
2210 // properly in WebViewImpl::SetFocus(). Note that we are talking here about
2211 // focused on the SelectionController, not FocusController.
2212 // webview()->GetFocusedFrame() will still return the last focused frame (as
2213 // it queries the FocusController).
2214 // TODO(jcampan): http://b/issue?id=1157486 Remove next line once we have the
2215 // fix for 792423.
2216 webview()->SetFocusedFrame(NULL);
2217
[email protected]7ea066a2009-04-06 20:21:592218 if (options.findNext) {
[email protected]4f3dc372009-02-24 00:10:292219 // Force the main_frame to report the actual count.
[email protected]7ea066a2009-04-06 20:21:592220 main_frame->IncreaseMatchCount(0, request_id);
[email protected]4f3dc372009-02-24 00:10:292221 } else {
2222 // If nothing is found, set result to "0 of 0", otherwise, set it to
2223 // "-1 of 1" to indicate that we found at least one item, but we don't know
2224 // yet what is active.
2225 int ordinal = result ? -1 : 0; // -1 here means, we might know more later.
2226 int match_count = result ? 1 : 0; // 1 here means possibly more coming.
initial.commit09911bf2008-07-26 23:55:292227
[email protected]4f3dc372009-02-24 00:10:292228 // If we find no matches then this will be our last status update.
2229 // Otherwise the scoping effort will send more results.
2230 bool final_status_update = !result;
initial.commit09911bf2008-07-26 23:55:292231
[email protected]4f3dc372009-02-24 00:10:292232 // Send the search result over to the browser process.
[email protected]4f999132009-03-31 18:08:402233 Send(new ViewHostMsg_Find_Reply(routing_id_,
[email protected]7ea066a2009-04-06 20:21:592234 request_id,
[email protected]4f3dc372009-02-24 00:10:292235 match_count,
2236 selection_rect,
2237 ordinal,
2238 final_status_update));
initial.commit09911bf2008-07-26 23:55:292239
initial.commit09911bf2008-07-26 23:55:292240 // Scoping effort begins, starting with the mainframe.
2241 search_frame = main_frame;
2242
2243 main_frame->ResetMatchCount();
2244
2245 do {
2246 // Cancel all old scoping requests before starting a new one.
2247 search_frame->CancelPendingScopingEffort();
2248
2249 // We don't start another scoping effort unless at least one match has
2250 // been found.
2251 if (result) {
2252 // Start new scoping request. If the scoping function determines that it
2253 // needs to scope, it will defer until later.
[email protected]7ea066a2009-04-06 20:21:592254 search_frame->ScopeStringMatches(request_id,
2255 search_text,
2256 options,
initial.commit09911bf2008-07-26 23:55:292257 true); // reset the tickmarks
2258 }
2259
2260 // Iterate to the next frame. The frame will not necessarily scope, for
2261 // example if it is not visible.
2262 search_frame = webview()->GetNextFrameAfter(search_frame, true);
2263 } while (search_frame != main_frame);
2264 }
2265}
2266
2267void RenderView::ReportFindInPageMatchCount(int count, int request_id,
2268 bool final_update) {
2269 // If we have a message that has been queued up, then we should just replace
2270 // it. The ACK from the browser will make sure it gets sent when the browser
2271 // wants it.
2272 if (queued_find_reply_message_.get()) {
2273 IPC::Message* msg = new ViewHostMsg_Find_Reply(
2274 routing_id_,
2275 request_id,
2276 count,
[email protected]b3f2b912009-04-09 16:18:522277 gfx::Rect(),
initial.commit09911bf2008-07-26 23:55:292278 -1, // Don't update active match ordinal.
2279 final_update);
2280 queued_find_reply_message_.reset(msg);
2281 } else {
2282 // Send the search result over to the browser process.
2283 Send(new ViewHostMsg_Find_Reply(
2284 routing_id_,
2285 request_id,
2286 count,
[email protected]b3f2b912009-04-09 16:18:522287 gfx::Rect(),
initial.commit09911bf2008-07-26 23:55:292288 -1, // // Don't update active match ordinal.
2289 final_update));
2290 }
2291}
2292
2293void RenderView::ReportFindInPageSelection(int request_id,
2294 int active_match_ordinal,
[email protected]b3f2b912009-04-09 16:18:522295 const WebRect& selection_rect) {
initial.commit09911bf2008-07-26 23:55:292296 // Send the search result over to the browser process.
2297 Send(new ViewHostMsg_Find_Reply(routing_id_,
2298 request_id,
2299 -1,
2300 selection_rect,
2301 active_match_ordinal,
2302 false));
2303}
2304
[email protected]ed4bf2d2009-05-05 00:10:062305bool RenderView::WasOpenedByUserGesture() const {
initial.commit09911bf2008-07-26 23:55:292306 return opened_by_user_gesture_;
2307}
2308
2309void RenderView::SpellCheck(const std::wstring& word, int& misspell_location,
2310 int& misspell_length) {
2311 Send(new ViewHostMsg_SpellCheck(routing_id_, word, &misspell_location,
2312 &misspell_length));
2313}
2314
[email protected]eda2b5a2009-05-12 19:30:212315void RenderView::GetAutoCorrectWord(const std::wstring& misspelled_word,
2316 std::wstring& autocorrect_word) {
2317 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
2318 if (command_line.HasSwitch(switches::kAutoSpellCorrect)) {
2319 Send(new ViewHostMsg_GetAutoCorrectWord(routing_id_, misspelled_word,
2320 &autocorrect_word));
2321 }
2322}
2323
initial.commit09911bf2008-07-26 23:55:292324void RenderView::SetInputMethodState(bool enabled) {
2325 // Save the updated IME status and mark the input focus has been updated.
2326 // The IME status is to be sent to a browser process next time when
2327 // the input caret is rendered.
[email protected]9f23f592008-11-17 08:36:342328 if (!ime_control_busy_) {
2329 ime_control_updated_ = true;
2330 ime_control_new_state_ = enabled;
2331 }
initial.commit09911bf2008-07-26 23:55:292332}
2333
2334void RenderView::ScriptedPrint(WebFrame* frame) {
[email protected]6c8afae52009-01-22 02:24:572335#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:292336 // Retrieve the default print settings to calculate the expected number of
2337 // pages.
2338 ViewMsg_Print_Params default_settings;
2339 IPC::SyncMessage* msg =
2340 new ViewHostMsg_GetDefaultPrintSettings(routing_id_, &default_settings);
2341 if (Send(msg)) {
2342 msg = NULL;
[email protected]378f0e822009-04-28 15:27:122343 // Check if the printer returned any settings, if the settings is empty, we
2344 // can safely assume there are no printer drivers configured. So we safely
2345 // terminate.
2346 if (default_settings.IsEmpty()) {
2347 RunJavaScriptAlert(frame,
2348 l10n_util::GetString(IDS_DEFAULT_PRINTER_NOT_FOUND_WARNING_TITLE));
2349 return;
2350 }
2351
initial.commit09911bf2008-07-26 23:55:292352 // Continue only if the settings are valid.
2353 if (default_settings.dpi && default_settings.document_cookie) {
[email protected]88a3ecc2009-03-19 17:36:222354 int expected_pages_count = 0;
2355 gfx::Size canvas_size;
2356 canvas_size.set_width(
2357 printing::ConvertUnit(default_settings.printable_size.width(),
2358 static_cast<int>(default_settings.dpi),
2359 default_settings.desired_dpi));
2360 canvas_size.set_height(
2361 printing::ConvertUnit(default_settings.printable_size.height(),
2362 static_cast<int>(default_settings.dpi),
2363 default_settings.desired_dpi));
2364 frame->BeginPrint(canvas_size, &expected_pages_count);
initial.commit09911bf2008-07-26 23:55:292365 DCHECK(expected_pages_count);
[email protected]88a3ecc2009-03-19 17:36:222366 frame->EndPrint();
initial.commit09911bf2008-07-26 23:55:292367
2368 // Ask the browser to show UI to retrieve the final print settings.
2369 ViewMsg_PrintPages_Params print_settings;
2370 // host_window_ may be NULL at this point if the current window is a popup
2371 // and the print() command has been issued from the parent. The receiver
2372 // of this message has to deal with this.
2373 msg = new ViewHostMsg_ScriptedPrint(routing_id_,
2374 host_window_,
2375 default_settings.document_cookie,
2376 expected_pages_count,
2377 &print_settings);
2378 if (Send(msg)) {
2379 msg = NULL;
2380
2381 // If the settings are invalid, early quit.
2382 if (print_settings.params.dpi &&
2383 print_settings.params.document_cookie) {
2384 // Render the printed pages. It will implicitly revert the document to
2385 // display CSS media type.
2386 PrintPages(print_settings, frame);
2387 // All went well.
2388 return;
2389 } else {
2390 // The user cancelled.
2391 }
2392 } else {
2393 // Send() failed.
2394 NOTREACHED();
2395 }
2396 } else {
2397 // The user cancelled.
2398 }
2399 } else {
2400 // Send() failed.
2401 NOTREACHED();
2402 }
2403 // TODO(maruel): bug 1123882 Alert the user that printing failed.
[email protected]6c8afae52009-01-22 02:24:572404#else // defined(OS_WIN)
2405 // TODO(port): print not implemented
2406 NOTIMPLEMENTED();
2407#endif
initial.commit09911bf2008-07-26 23:55:292408}
2409
2410void RenderView::WebInspectorOpened(int num_resources) {
2411 Send(new ViewHostMsg_InspectElement_Reply(routing_id_, num_resources));
2412}
2413
2414void RenderView::UserMetricsRecordAction(const std::wstring& action) {
2415 Send(new ViewHostMsg_UserMetricsRecordAction(routing_id_, action));
2416}
2417
2418void RenderView::DnsPrefetch(const std::vector<std::string>& host_names) {
2419 Send(new ViewHostMsg_DnsPrefetch(host_names));
2420}
2421
[email protected]630e26b2008-10-14 22:55:172422void RenderView::OnZoom(int function) {
2423 static const bool kZoomIsTextOnly = false;
2424 switch (function) {
2425 case PageZoom::SMALLER:
2426 webview()->ZoomOut(kZoomIsTextOnly);
initial.commit09911bf2008-07-26 23:55:292427 break;
[email protected]630e26b2008-10-14 22:55:172428 case PageZoom::STANDARD:
2429 webview()->ResetZoom();
initial.commit09911bf2008-07-26 23:55:292430 break;
[email protected]630e26b2008-10-14 22:55:172431 case PageZoom::LARGER:
2432 webview()->ZoomIn(kZoomIsTextOnly);
initial.commit09911bf2008-07-26 23:55:292433 break;
2434 default:
2435 NOTREACHED();
2436 }
2437}
2438
[email protected]ea8c7452009-04-02 20:47:062439void RenderView::OnInsertText(const string16& text) {
[email protected]5f9e0b82009-05-08 22:13:392440 WebFrame* frame = webview()->GetFocusedFrame();
2441 if (!frame)
2442 return;
2443 WebTextInput* text_input = frame->GetTextInput();
[email protected]00d7e622009-04-21 23:06:052444 if (text_input)
2445 text_input->InsertText(UTF16ToUTF8(text));
[email protected]ea8c7452009-04-02 20:47:062446}
2447
[email protected]e38f40152008-09-12 23:08:302448void RenderView::OnSetPageEncoding(const std::wstring& encoding_name) {
initial.commit09911bf2008-07-26 23:55:292449 webview()->SetPageEncoding(encoding_name);
2450}
2451
2452void RenderView::OnPasswordFormsSeen(WebView* webview,
2453 const std::vector<PasswordForm>& forms) {
2454 Send(new ViewHostMsg_PasswordFormsSeen(routing_id_, forms));
2455}
2456
[email protected]8d0f15c2008-11-11 01:01:092457void RenderView::OnAutofillFormSubmitted(WebView* webview,
2458 const AutofillForm& form) {
2459 Send(new ViewHostMsg_AutofillFormSubmitted(routing_id_, form));
2460}
2461
[email protected]47811562009-05-13 06:21:012462WebHistoryItem* RenderView::GetHistoryEntryAtOffset(int offset) {
2463 // Our history list is kept in the browser process on the UI thread. Since
2464 // we can't make a sync IPC call to that thread without risking deadlock,
2465 // we use a trick: construct a fake history item of the form:
2466 // history://go/OFFSET
2467 // When WebCore tells us to navigate to it, we tell the browser process to
2468 // do a back/forward navigation instead.
2469
2470 GURL url(StringPrintf("%s://go/%d", kBackForwardNavigationScheme, offset));
2471 history_navigation_item_ = WebHistoryItem::Create(url, L"", "", NULL);
2472 return history_navigation_item_.get();
2473}
2474
2475void RenderView::GoToEntryAtOffset(int offset) {
[email protected]f46aff62008-10-16 07:58:052476 history_back_list_count_ += offset;
2477 history_forward_list_count_ -= offset;
2478
initial.commit09911bf2008-07-26 23:55:292479 Send(new ViewHostMsg_GoToEntryAtOffset(routing_id_, offset));
2480}
2481
2482int RenderView::GetHistoryBackListCount() {
2483 return history_back_list_count_;
2484}
2485
2486int RenderView::GetHistoryForwardListCount() {
2487 return history_forward_list_count_;
2488}
2489
2490void RenderView::OnNavStateChanged(WebView* webview) {
[email protected]81a34412009-01-05 19:17:242491 if (!nav_state_sync_timer_.IsRunning()) {
2492 nav_state_sync_timer_.Start(
2493 TimeDelta::FromSeconds(delay_seconds_for_form_state_sync_), this,
2494 &RenderView::SyncNavigationState);
2495 }
initial.commit09911bf2008-07-26 23:55:292496}
2497
2498void RenderView::SetTooltipText(WebView* webview,
2499 const std::wstring& tooltip_text) {
2500 Send(new ViewHostMsg_SetTooltipText(routing_id_, tooltip_text));
2501}
2502
[email protected]2e417c82009-04-02 22:30:262503void RenderView::DidChangeSelection(bool is_empty_selection) {
2504#if defined(OS_LINUX)
2505 if (!is_empty_selection) {
[email protected]dbadbcc2009-04-09 00:57:102506 Send(new ViewHostMsg_SelectionChanged(routing_id_,
[email protected]5f9e0b82009-05-08 22:13:392507 webview()->GetFocusedFrame()->GetSelection(false)));
[email protected]2e417c82009-04-02 22:30:262508 }
2509#endif
2510}
2511
initial.commit09911bf2008-07-26 23:55:292512void RenderView::DownloadUrl(const GURL& url, const GURL& referrer) {
2513 Send(new ViewHostMsg_DownloadUrl(routing_id_, url, referrer));
2514}
2515
[email protected]611cad42009-03-16 18:51:342516WebDevToolsAgentDelegate* RenderView::GetWebDevToolsAgentDelegate() {
[email protected]b75b7d072009-04-06 13:47:002517 return devtools_agent_.get();
[email protected]611cad42009-03-16 18:51:342518}
2519
[email protected]ea8c7452009-04-02 20:47:062520void RenderView::PasteFromSelectionClipboard() {
2521 Send(new ViewHostMsg_PasteFromSelectionClipboard(routing_id_));
2522}
2523
initial.commit09911bf2008-07-26 23:55:292524WebFrame* RenderView::GetChildFrame(const std::wstring& frame_xpath) const {
2525 WebFrame* web_frame;
2526 if (frame_xpath.empty()) {
2527 web_frame = webview()->GetMainFrame();
2528 } else {
2529 web_frame = webview()->GetMainFrame()->GetChildFrame(frame_xpath);
2530 }
2531
2532 return web_frame;
2533}
2534
[email protected]f29acf52008-11-03 20:08:332535void RenderView::EvaluateScript(const std::wstring& frame_xpath,
2536 const std::wstring& script) {
initial.commit09911bf2008-07-26 23:55:292537 WebFrame* web_frame = GetChildFrame(frame_xpath);
2538 if (!web_frame)
2539 return;
2540
[email protected]4f999132009-03-31 18:08:402541 web_frame->ExecuteScript(WebScriptSource(WideToUTF16Hack(script)));
initial.commit09911bf2008-07-26 23:55:292542}
2543
[email protected]1810e132009-03-24 23:35:482544void RenderView::InsertCSS(const std::wstring& frame_xpath,
2545 const std::string& css) {
2546 WebFrame* web_frame = GetChildFrame(frame_xpath);
2547 if (!web_frame)
2548 return;
2549
2550 web_frame->InsertCSSStyles(css);
2551}
2552
initial.commit09911bf2008-07-26 23:55:292553void RenderView::OnScriptEvalRequest(const std::wstring& frame_xpath,
2554 const std::wstring& jscript) {
[email protected]f29acf52008-11-03 20:08:332555 EvaluateScript(frame_xpath, jscript);
initial.commit09911bf2008-07-26 23:55:292556}
2557
[email protected]1810e132009-03-24 23:35:482558void RenderView::OnCSSInsertRequest(const std::wstring& frame_xpath,
2559 const std::string& css) {
2560 InsertCSS(frame_xpath, css);
2561}
2562
[email protected]7ea066a2009-04-06 20:21:592563void RenderView::OnAddMessageToConsole(
2564 const string16& frame_xpath,
2565 const string16& message,
2566 const WebConsoleMessage::Level& level) {
2567 WebFrame* web_frame = GetChildFrame(UTF16ToWideHack(frame_xpath));
[email protected]0dea3ea2009-03-31 23:30:592568 if (web_frame)
[email protected]7ea066a2009-04-06 20:21:592569 web_frame->AddMessageToConsole(WebConsoleMessage(level, message));
initial.commit09911bf2008-07-26 23:55:292570}
2571
[email protected]6c8afae52009-01-22 02:24:572572#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:292573void RenderView::OnDebugAttach() {
initial.commit09911bf2008-07-26 23:55:292574 Send(new ViewHostMsg_DidDebugAttach(routing_id_));
2575 // Tell the plugin host to stop accepting messages in order to avoid
2576 // hangs while the renderer is paused.
2577 // TODO(1243929): It might be an improvement to add more plumbing to do this
2578 // when the renderer is actually paused vs. just the debugger being attached.
2579 PluginChannelHost::SetListening(false);
2580}
2581
2582void RenderView::OnDebugDetach() {
2583 // Tell the plugin host to start accepting plugin messages again.
2584 PluginChannelHost::SetListening(true);
2585}
[email protected]6c8afae52009-01-22 02:24:572586#else // defined(OS_WIN)
2587// TODO(port): plugins not yet supported
2588void RenderView::OnDebugAttach() { NOTIMPLEMENTED(); }
2589void RenderView::OnDebugDetach() { NOTIMPLEMENTED(); }
2590#endif
initial.commit09911bf2008-07-26 23:55:292591
[email protected]81e63782009-02-27 19:35:092592void RenderView::OnAllowBindings(int enabled_bindings_flags) {
2593 enabled_bindings_ |= enabled_bindings_flags;
initial.commit09911bf2008-07-26 23:55:292594}
2595
2596void RenderView::OnSetDOMUIProperty(const std::string& name,
2597 const std::string& value) {
[email protected]81e63782009-02-27 19:35:092598 DCHECK(BindingsPolicy::is_dom_ui_enabled(enabled_bindings_));
initial.commit09911bf2008-07-26 23:55:292599 dom_ui_bindings_.SetProperty(name, value);
2600}
2601
2602void RenderView::OnReservePageIDRange(int size_of_range) {
2603 next_page_id_ += size_of_range + 1;
2604}
2605
[email protected]e80c73b2009-04-07 23:24:582606void RenderView::OnDragSourceEndedOrMoved(const gfx::Point& client_point,
2607 const gfx::Point& screen_point,
initial.commit09911bf2008-07-26 23:55:292608 bool ended) {
2609 if (ended)
[email protected]e80c73b2009-04-07 23:24:582610 webview()->DragSourceEndedAt(client_point, screen_point);
initial.commit09911bf2008-07-26 23:55:292611 else
[email protected]e80c73b2009-04-07 23:24:582612 webview()->DragSourceMovedTo(client_point, screen_point);
initial.commit09911bf2008-07-26 23:55:292613}
2614
2615void RenderView::OnDragSourceSystemDragEnded() {
2616 webview()->DragSourceSystemDragEnded();
2617}
2618
2619void RenderView::OnUploadFileRequest(const ViewMsg_UploadFile_Params& p) {
2620 webkit_glue::FileUploadData* f = new webkit_glue::FileUploadData;
2621 f->file_path = p.file_path;
2622 f->form_name = p.form;
2623 f->file_name = p.file;
2624 f->submit_name = p.submit;
2625
2626 // Build the other form values map.
2627 if (!p.other_values.empty()) {
2628 std::vector<std::wstring> e;
2629 std::vector<std::wstring> kvp;
2630 std::vector<std::wstring>::iterator i;
2631
2632 SplitString(p.other_values, L'\n', &e);
2633 for (i = e.begin(); i != e.end(); ++i) {
2634 SplitString(*i, L'=', &kvp);
2635 if (kvp.size() == 2)
2636 f->other_form_values[kvp[0]] = kvp[1];
2637 kvp.clear();
2638 }
2639 }
2640
2641 pending_upload_data_.reset(f);
2642 ProcessPendingUpload();
2643}
2644
2645void RenderView::ProcessPendingUpload() {
2646 webkit_glue::FileUploadData* f = pending_upload_data_.get();
2647 if (f && webview() && webkit_glue::FillFormToUploadFile(webview(), *f))
2648 ResetPendingUpload();
2649}
2650
2651void RenderView::ResetPendingUpload() {
2652 pending_upload_data_.reset();
2653}
2654
2655void RenderView::OnFormFill(const FormData& form) {
2656 webkit_glue::FillForm(this->webview(), form);
2657}
2658
2659void RenderView::OnFillPasswordForm(
2660 const PasswordFormDomManager::FillData& form_data) {
2661 webkit_glue::FillPasswordForm(this->webview(), form_data);
2662}
2663
2664void RenderView::OnDragTargetDragEnter(const WebDropData& drop_data,
[email protected]e80c73b2009-04-07 23:24:582665 const gfx::Point& client_point,
2666 const gfx::Point& screen_point) {
2667 bool is_drop_target = webview()->DragTargetDragEnter(
2668 drop_data.ToDragData(),
2669 drop_data.identity,
2670 client_point,
2671 screen_point);
initial.commit09911bf2008-07-26 23:55:292672
2673 Send(new ViewHostMsg_UpdateDragCursor(routing_id_, is_drop_target));
2674}
2675
[email protected]e80c73b2009-04-07 23:24:582676void RenderView::OnDragTargetDragOver(const gfx::Point& client_point,
2677 const gfx::Point& screen_point) {
2678 bool is_drop_target =
2679 webview()->DragTargetDragOver(client_point, screen_point);
initial.commit09911bf2008-07-26 23:55:292680
2681 Send(new ViewHostMsg_UpdateDragCursor(routing_id_, is_drop_target));
2682}
2683
2684void RenderView::OnDragTargetDragLeave() {
2685 webview()->DragTargetDragLeave();
2686}
2687
[email protected]e80c73b2009-04-07 23:24:582688void RenderView::OnDragTargetDrop(const gfx::Point& client_point,
2689 const gfx::Point& screen_point) {
2690 webview()->DragTargetDrop(client_point, screen_point);
initial.commit09911bf2008-07-26 23:55:292691}
2692
2693void RenderView::OnUpdateWebPreferences(const WebPreferences& prefs) {
2694 webview()->SetPreferences(prefs);
2695}
2696
2697void RenderView::OnSetAltErrorPageURL(const GURL& url) {
2698 alternate_error_page_url_ = url;
2699}
2700
2701void RenderView::DidPaint() {
2702 PluginDelegateList::iterator it = plugin_delegates_.begin();
2703 while (it != plugin_delegates_.end()) {
2704 (*it)->FlushGeometryUpdates();
2705 ++it;
2706 }
2707}
2708
2709void RenderView::OnInstallMissingPlugin() {
2710 // This could happen when the first default plugin is deleted.
2711 if (first_default_plugin_ == NULL)
2712 return;
2713 first_default_plugin_->InstallMissingPlugin();
2714}
2715
[email protected]b62d1a8c2009-01-13 23:54:572716void RenderView::OnFileChooserResponse(
[email protected]561abe62009-04-06 18:08:342717 const std::vector<FilePath>& file_names) {
[email protected]8029f5672009-03-20 22:33:362718 // This could happen if we navigated to a different page before the user
2719 // closed the chooser.
2720 if (!file_chooser_.get())
2721 return;
2722
[email protected]b62d1a8c2009-01-13 23:54:572723 file_chooser_->OnFileChoose(file_names);
initial.commit09911bf2008-07-26 23:55:292724 file_chooser_.reset();
2725}
2726
2727void RenderView::OnEnableViewSourceMode() {
2728 if (!webview())
2729 return;
2730 WebFrame* main_frame = webview()->GetMainFrame();
2731 if (!main_frame)
2732 return;
2733
2734 main_frame->SetInViewSourceMode(true);
2735}
2736
[email protected]0666aef2009-05-13 19:48:082737void RenderView::OnEnableIntrinsicWidthChangedMode() {
2738 send_preferred_width_changes_ = true;
2739}
2740
initial.commit09911bf2008-07-26 23:55:292741void RenderView::OnUpdateBackForwardListCount(int back_list_count,
2742 int forward_list_count) {
2743 history_back_list_count_ = back_list_count;
2744 history_forward_list_count_ = forward_list_count;
2745}
2746
[email protected]266eb6f2008-09-30 23:56:502747void RenderView::OnGetAccessibilityInfo(
[email protected]6a983b42009-03-20 20:12:252748 const webkit_glue::WebAccessibility::InParams& in_params,
2749 webkit_glue::WebAccessibility::OutParams* out_params) {
[email protected]6c8afae52009-01-22 02:24:572750#if defined(OS_WIN)
[email protected]6a983b42009-03-20 20:12:252751 if (!web_accessibility_manager_.get()) {
2752 web_accessibility_manager_.reset(
2753 webkit_glue::WebAccessibilityManager::Create());
2754 }
[email protected]266eb6f2008-09-30 23:56:502755
[email protected]6a983b42009-03-20 20:12:252756 if (!web_accessibility_manager_->GetAccObjInfo(webview(), in_params,
2757 out_params)) {
[email protected]266eb6f2008-09-30 23:56:502758 return;
2759 }
[email protected]6c8afae52009-01-22 02:24:572760#else // defined(OS_WIN)
2761 // TODO(port): accessibility not yet implemented
2762 NOTIMPLEMENTED();
2763#endif
[email protected]266eb6f2008-09-30 23:56:502764}
2765
[email protected]6a983b42009-03-20 20:12:252766void RenderView::OnClearAccessibilityInfo(int acc_obj_id, bool clear_all) {
[email protected]6c8afae52009-01-22 02:24:572767#if defined(OS_WIN)
[email protected]6a983b42009-03-20 20:12:252768 if (!web_accessibility_manager_.get()) {
[email protected]266eb6f2008-09-30 23:56:502769 // If accessibility is not activated, ignore clearing message.
2770 return;
2771 }
[email protected]6a983b42009-03-20 20:12:252772 if (!web_accessibility_manager_->ClearAccObjMap(acc_obj_id, clear_all))
[email protected]266eb6f2008-09-30 23:56:502773 return;
[email protected]6c8afae52009-01-22 02:24:572774#else // defined(OS_WIN)
2775 // TODO(port): accessibility not yet implemented
2776 NOTIMPLEMENTED();
2777#endif
[email protected]266eb6f2008-09-30 23:56:502778}
2779
initial.commit09911bf2008-07-26 23:55:292780void RenderView::OnGetAllSavableResourceLinksForCurrentPage(
2781 const GURL& page_url) {
2782 // Prepare list to storage all savable resource links.
2783 std::vector<GURL> resources_list;
2784 std::vector<GURL> referrers_list;
2785 std::vector<GURL> frames_list;
2786 webkit_glue::SavableResourcesResult result(&resources_list,
2787 &referrers_list,
2788 &frames_list);
2789
2790 if (!webkit_glue::GetAllSavableResourceLinksForCurrentPage(webview(),
2791 page_url,
2792 &result)) {
2793 // If something is wrong when collecting all savable resource links,
2794 // send empty list to embedder(browser) to tell it failed.
2795 referrers_list.clear();
2796 resources_list.clear();
2797 frames_list.clear();
2798 }
2799
2800 // Send result of all savable resource links to embedder.
2801 Send(new ViewHostMsg_SendCurrentPageAllSavableResourceLinks(routing_id_,
2802 resources_list,
2803 referrers_list,
2804 frames_list));
2805}
2806
2807void RenderView::OnGetSerializedHtmlDataForCurrentPageWithLocalLinks(
[email protected]f6b48532009-02-12 01:56:322808 const std::vector<GURL>& links,
[email protected]fde6714d12009-02-18 22:39:312809 const std::vector<FilePath>& local_paths,
2810 const FilePath& local_directory_name) {
initial.commit09911bf2008-07-26 23:55:292811 webkit_glue::DomSerializer dom_serializer(webview()->GetMainFrame(),
2812 true,
2813 this,
2814 links,
2815 local_paths,
2816 local_directory_name);
2817 dom_serializer.SerializeDom();
2818}
2819
2820void RenderView::DidSerializeDataForFrame(const GURL& frame_url,
2821 const std::string& data, PageSavingSerializationStatus status) {
2822 Send(new ViewHostMsg_SendSerializedHtmlData(routing_id_,
2823 frame_url, data, static_cast<int32>(status)));
2824}
2825
[email protected]04b4a6c2008-08-02 00:44:472826void RenderView::OnMsgShouldClose() {
initial.commit09911bf2008-07-26 23:55:292827 bool should_close = webview()->ShouldClose();
[email protected]04b4a6c2008-08-02 00:44:472828 Send(new ViewHostMsg_ShouldClose_ACK(routing_id_, should_close));
initial.commit09911bf2008-07-26 23:55:292829}
2830
2831void RenderView::OnClosePage(int new_render_process_host_id,
[email protected]04b4a6c2008-08-02 00:44:472832 int new_request_id) {
initial.commit09911bf2008-07-26 23:55:292833 // TODO(creis): We'd rather use webview()->Close() here, but that currently
2834 // sets the WebView's delegate_ to NULL, preventing any JavaScript dialogs
2835 // in the onunload handler from appearing. For now, we're bypassing that and
2836 // calling the FrameLoader's CloseURL method directly. This should be
2837 // revisited to avoid having two ways to close a page. Having a single way
2838 // to close that can run onunload is also useful for fixing
2839 // http://b/issue?id=753080.
2840 WebFrame* main_frame = webview()->GetMainFrame();
2841 if (main_frame)
2842 main_frame->ClosePage();
2843
2844 Send(new ViewHostMsg_ClosePage_ACK(routing_id_,
2845 new_render_process_host_id,
[email protected]04b4a6c2008-08-02 00:44:472846 new_request_id));
initial.commit09911bf2008-07-26 23:55:292847}
2848
2849void RenderView::OnThemeChanged() {
[email protected]6c8afae52009-01-22 02:24:572850#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:292851 gfx::NativeTheme::instance()->CloseHandles();
2852 gfx::Rect view_rect(0, 0, size_.width(), size_.height());
2853 DidInvalidateRect(webwidget_, view_rect);
[email protected]6c8afae52009-01-22 02:24:572854#else // defined(OS_WIN)
2855 // TODO(port): we don't support theming on non-Windows platforms yet
2856 NOTIMPLEMENTED();
2857#endif
initial.commit09911bf2008-07-26 23:55:292858}
2859
[email protected]f46aff62008-10-16 07:58:052860void RenderView::DidAddHistoryItem() {
[email protected]f8901082008-10-31 23:34:032861 // We don't want to update the history length for the start page
2862 // navigation.
2863 WebFrame* main_frame = webview()->GetMainFrame();
2864 DCHECK(main_frame != NULL);
2865
2866 WebDataSource* ds = main_frame->GetDataSource();
2867 DCHECK(ds != NULL);
2868
2869 const WebRequest& request = ds->GetRequest();
2870 RenderViewExtraRequestData* extra_data =
2871 static_cast<RenderViewExtraRequestData*>(request.GetExtraData());
2872
2873 if (extra_data && extra_data->transition_type == PageTransition::START_PAGE)
2874 return;
2875
[email protected]f46aff62008-10-16 07:58:052876 history_back_list_count_++;
2877 history_forward_list_count_ = 0;
2878}
2879
[email protected]28790922009-03-09 19:48:372880void RenderView::OnMessageFromExternalHost(const std::string& message,
2881 const std::string& origin,
2882 const std::string& target) {
[email protected]3ac14a052008-08-15 21:22:152883 if (message.empty())
2884 return;
2885
[email protected]28790922009-03-09 19:48:372886 external_host_bindings_.ForwardMessageFromExternalHost(message, origin,
2887 target);
[email protected]3ac14a052008-08-15 21:22:152888}
2889
[email protected]0aa55312008-10-17 21:53:082890void RenderView::OnDisassociateFromPopupCount() {
2891 if (decrement_shared_popup_at_destruction_)
2892 shared_popup_counter_->data--;
2893 shared_popup_counter_ = new SharedRenderViewCounter(0);
2894 decrement_shared_popup_at_destruction_ = false;
2895}
2896
initial.commit09911bf2008-07-26 23:55:292897std::string RenderView::GetAltHTMLForTemplate(
2898 const DictionaryValue& error_strings, int template_resource_id) const {
2899 const StringPiece template_html(
2900 ResourceBundle::GetSharedInstance().GetRawDataResource(
2901 template_resource_id));
2902
2903 if (template_html.empty()) {
2904 NOTREACHED() << "unable to load template. ID: " << template_resource_id;
2905 return "";
2906 }
2907 // "t" is the id of the templates root node.
2908 return jstemplate_builder::GetTemplateHtml(
2909 template_html, &error_strings, "t");
2910}
[email protected]0e79b9e2009-02-13 04:20:482911
2912MessageLoop* RenderView::GetMessageLoopForIO() {
2913 // Assume that we have only one RenderThread in the process and the owner loop
2914 // of RenderThread is an IO message loop.
[email protected]8930d472009-02-21 08:05:282915 if (RenderThread::current())
2916 return RenderThread::current()->owner_loop();
[email protected]0e79b9e2009-02-13 04:20:482917 return NULL;
2918}
[email protected]6f56d482009-02-20 05:02:562919
[email protected]30f75e62009-02-25 22:01:002920void RenderView::OnMoveOrResizeStarted() {
2921 if (webview())
2922 webview()->HideAutofillPopup();
2923}
2924
[email protected]30f75e62009-02-25 22:01:002925void RenderView::OnResize(const gfx::Size& new_size,
2926 const gfx::Rect& resizer_rect) {
2927 if (webview())
2928 webview()->HideAutofillPopup();
2929 RenderWidget::OnResize(new_size, resizer_rect);
2930}
[email protected]0aa477bd2009-03-23 22:21:432931
[email protected]05d478752009-04-08 23:38:162932void RenderView::OnClearFocusedNode() {
2933 if (webview())
2934 webview()->ClearFocusedNode();
2935}
2936
[email protected]699ab0d2009-04-23 23:19:142937void RenderView::OnSetBackground(const SkBitmap& background) {
2938 if (webview())
2939 webview()->SetIsTransparent(!background.empty());
2940
2941 SetBackground(background);
2942}
2943
[email protected]309d7a282009-03-24 09:18:272944void RenderView::SendExtensionRequest(const std::string& name,
2945 const std::string& args,
[email protected]c6619182009-05-12 14:59:322946 int request_id,
2947 bool has_callback,
2948 WebFrame* request_frame) {
2949 DCHECK(request_frame) << "Request specified without frame";
2950 pending_extension_requests_.AddWithID(
2951 new ExtensionProcessBindings::CallContext(request_frame, name),
2952 request_id);
[email protected]309d7a282009-03-24 09:18:272953
[email protected]c6619182009-05-12 14:59:322954 Send(new ViewHostMsg_ExtensionRequest(routing_id_, name, args, request_id,
2955 has_callback));
[email protected]309d7a282009-03-24 09:18:272956}
2957
[email protected]c6619182009-05-12 14:59:322958void RenderView::OnExtensionResponse(int request_id,
2959 bool success,
2960 const std::string& response,
2961 const std::string& error) {
2962 ExtensionProcessBindings::CallContext* call =
2963 pending_extension_requests_.Lookup(request_id);
2964
2965 if (!call)
[email protected]309d7a282009-03-24 09:18:272966 return; // The frame went away.
2967
[email protected]c6619182009-05-12 14:59:322968 ExtensionProcessBindings::ExecuteResponseInFrame(call, request_id,
2969 success, response,
2970 error);
2971 pending_extension_requests_.Remove(request_id);
2972 delete call;
[email protected]309d7a282009-03-24 09:18:272973}
[email protected]c20210e62009-04-03 21:39:262974
[email protected]e7e4f3c2009-04-21 15:24:082975// Dump all load time histograms.
[email protected]c20210e62009-04-03 21:39:262976//
[email protected]e7e4f3c2009-04-21 15:24:082977// There are 7 histograms measuring various times.
[email protected]c20210e62009-04-03 21:39:262978// The time points we keep are
2979// request: time document was requested by user
2980// start: time load of document started
2981// finishDoc: main document loaded, before onload()
2982// finish: after onload() and all resources are loaded
[email protected]e7e4f3c2009-04-21 15:24:082983// firstLayout: first layout performed
[email protected]c20210e62009-04-03 21:39:262984// The times that we histogram are
2985// requestToStart,
2986// startToFinishDoc,
2987// finishDocToFinish,
2988// startToFinish,
2989// requestToFinish,
[email protected]e7e4f3c2009-04-21 15:24:082990// requestToFirstLayout
2991// startToFirstLayout
[email protected]c20210e62009-04-03 21:39:262992//
[email protected]e7e4f3c2009-04-21 15:24:082993// It's possible for the request time not to be set, if a client
2994// redirect had been done (the user never requested the page)
2995// Also, it's possible to load a page without ever laying it out
2996// so firstLayout can be 0.
[email protected]c20210e62009-04-03 21:39:262997void RenderView::DumpLoadHistograms() const {
2998 WebFrame* main_frame = webview()->GetMainFrame();
2999 WebDataSource* ds = main_frame->GetDataSource();
[email protected]c20210e62009-04-03 21:39:263000 Time request_time = ds->GetRequestTime();
3001 Time start_load_time = ds->GetStartLoadTime();
3002 Time finish_document_load_time = ds->GetFinishDocumentLoadTime();
3003 Time finish_load_time = ds->GetFinishLoadTime();
[email protected]e7e4f3c2009-04-21 15:24:083004 Time first_layout_time = ds->GetFirstLayoutTime();
[email protected]c20210e62009-04-03 21:39:263005 TimeDelta request_to_start = start_load_time - request_time;
3006 TimeDelta start_to_finish_doc = finish_document_load_time - start_load_time;
[email protected]e7e4f3c2009-04-21 15:24:083007 TimeDelta finish_doc_to_finish =
3008 finish_load_time - finish_document_load_time;
[email protected]c20210e62009-04-03 21:39:263009 TimeDelta start_to_finish = finish_load_time - start_load_time;
3010 TimeDelta request_to_finish = finish_load_time - start_load_time;
[email protected]e7e4f3c2009-04-21 15:24:083011 TimeDelta request_to_first_layout = first_layout_time - request_time;
3012 TimeDelta start_to_first_layout = first_layout_time - start_load_time;
[email protected]c20210e62009-04-03 21:39:263013
[email protected]e7e4f3c2009-04-21 15:24:083014 // Client side redirects will have no request time
3015 if (request_time.ToInternalValue() != 0) {
3016 UMA_HISTOGRAM_TIMES("Renderer.All.RequestToStart", request_to_start);
3017 UMA_HISTOGRAM_TIMES("Renderer.All.RequestToFinish", request_to_finish);
3018 if (request_to_first_layout.ToInternalValue() >= 0) {
3019 UMA_HISTOGRAM_TIMES(
3020 "Renderer.All.RequestToFirstLayout", request_to_first_layout);
3021 }
3022 }
[email protected]c20210e62009-04-03 21:39:263023 UMA_HISTOGRAM_TIMES("Renderer.All.StartToFinishDoc", start_to_finish_doc);
3024 UMA_HISTOGRAM_TIMES("Renderer.All.FinishDocToFinish", finish_doc_to_finish);
3025 UMA_HISTOGRAM_TIMES("Renderer.All.StartToFinish", start_to_finish);
[email protected]e7e4f3c2009-04-21 15:24:083026 if (start_to_first_layout.ToInternalValue() >= 0) {
3027 UMA_HISTOGRAM_TIMES(
3028 "Renderer.All.StartToFirstLayout", start_to_first_layout);
[email protected]c20210e62009-04-03 21:39:263029 }
3030}