blob: 967e2a1c4122cdeaa69943648f887228097950c6 [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
11#include "base/command_line.h"
[email protected]bb063b72009-03-27 23:18:5012#include "base/compiler_specific.h"
initial.commit09911bf2008-07-26 23:55:2913#include "base/gfx/png_encoder.h"
[email protected]18bcc3c2009-01-27 21:39:1514#include "base/gfx/native_widget_types.h"
initial.commit09911bf2008-07-26 23:55:2915#include "base/string_piece.h"
16#include "base/string_util.h"
[email protected]6c8afae52009-01-22 02:24:5717#include "build/build_config.h"
[email protected]81e63782009-02-27 19:35:0918#include "chrome/common/bindings_policy.h"
initial.commit09911bf2008-07-26 23:55:2919#include "chrome/common/chrome_switches.h"
initial.commit09911bf2008-07-26 23:55:2920#include "chrome/common/gfx/favicon_size.h"
21#include "chrome/common/gfx/color_utils.h"
22#include "chrome/common/jstemplate_builder.h"
23#include "chrome/common/l10n_util.h"
[email protected]2e4bdcdc2009-03-27 23:07:3024#include "chrome/common/message_box_flags.h"
[email protected]630e26b2008-10-14 22:55:1725#include "chrome/common/page_zoom.h"
[email protected]e09ba552009-02-05 03:26:2926#include "chrome/common/render_messages.h"
initial.commit09911bf2008-07-26 23:55:2927#include "chrome/common/resource_bundle.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"
31#include "chrome/renderer/debug_message_handler.h"
[email protected]e4ac5df2009-03-17 15:33:1132#include "chrome/renderer/devtools_agent.h"
[email protected]b75b7d072009-04-06 13:47:0033#include "chrome/renderer/devtools_agent_filter.h"
[email protected]e4ac5df2009-03-17 15:33:1134#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]ec9212f2008-12-18 21:40:3642#include "chrome/renderer/webmediaplayer_delegate_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]e80c73b2009-04-07 23:24:5853#include "third_party/WebKit/WebKit/chromium/public/WebDragData.h"
54#include "third_party/WebKit/WebKit/chromium/public/WebPoint.h"
[email protected]b3f2b912009-04-09 16:18:5255#include "third_party/WebKit/WebKit/chromium/public/WebRect.h"
[email protected]4f999132009-03-31 18:08:4056#include "third_party/WebKit/WebKit/chromium/public/WebScriptSource.h"
[email protected]b3f2b912009-04-09 16:18:5257#include "third_party/WebKit/WebKit/chromium/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"
71#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"
76#include "webkit/glue/weburlrequest.h"
77#include "webkit/glue/webview.h"
initial.commit09911bf2008-07-26 23:55:2978
[email protected]6c8afae52009-01-22 02:24:5779#if defined(OS_WIN)
80// TODO(port): these files are currently Windows only because they concern:
[email protected]f8b6b6f2009-03-10 16:48:2681// * logging
[email protected]6c8afae52009-01-22 02:24:5782// * printing
83// * theming
84// * views
85#include "base/gfx/gdi_util.h"
86#include "base/gfx/native_theme.h"
87#include "chrome/common/gfx/emf.h"
[email protected]fcf19542009-03-30 21:24:0788#include "chrome/views/controls/message_box_view.h"
[email protected]6c8afae52009-01-22 02:24:5789#include "skia/ext/vector_canvas.h"
[email protected]6c8afae52009-01-22 02:24:5790#endif
91
[email protected]c20210e62009-04-03 21:39:2692using base::Time;
[email protected]e1acf6f2008-10-27 20:43:3393using base::TimeDelta;
[email protected]6a983b42009-03-20 20:12:2594using webkit_glue::WebAccessibility;
[email protected]0dea3ea2009-03-31 23:30:5995using WebKit::WebConsoleMessage;
[email protected]e80c73b2009-04-07 23:24:5896using WebKit::WebDragData;
[email protected]b3f2b912009-04-09 16:18:5297using WebKit::WebRect;
[email protected]4f999132009-03-31 18:08:4098using WebKit::WebScriptSource;
[email protected]e1acf6f2008-10-27 20:43:3399
initial.commit09911bf2008-07-26 23:55:29100//-----------------------------------------------------------------------------
101
102// define to write the time necessary for thumbnail/DOM text retrieval,
103// respectively, into the system debug log
104// #define TIME_BITMAP_RETRIEVAL
105// #define TIME_TEXT_RETRIEVAL
106
107// maximum number of characters in the document to index, any text beyond this
108// point will be clipped
[email protected]6c8afae52009-01-22 02:24:57109static const size_t kMaxIndexChars = 65535;
initial.commit09911bf2008-07-26 23:55:29110
111// Size of the thumbnails that we'll generate
112static const int kThumbnailWidth = 196;
113static const int kThumbnailHeight = 136;
114
115// Delay in milliseconds that we'll wait before capturing the page contents
116// and thumbnail.
117static const int kDelayForCaptureMs = 500;
118
119// Typically, we capture the page data once the page is loaded.
120// Sometimes, the page never finishes to load, preventing the page capture
121// To workaround this problem, we always perform a capture after the following
122// delay.
123static const int kDelayForForcedCaptureMs = 6000;
124
[email protected]81a34412009-01-05 19:17:24125// The default value for RenderView.delay_seconds_for_form_state_sync_, see
126// that variable for more.
127const int kDefaultDelaySecondsForFormStateSync = 5;
initial.commit09911bf2008-07-26 23:55:29128
129// The next available page ID to use. This ensures that the page IDs are
130// globally unique in the renderer.
131static int32 next_page_id_ = 1;
132
[email protected]0aa55312008-10-17 21:53:08133// The maximum number of popups that can be spawned from one page.
134static const int kMaximumNumberOfUnacknowledgedPopups = 25;
135
initial.commit09911bf2008-07-26 23:55:29136static const char* const kUnreachableWebDataURL =
[email protected]9527f9c2009-01-29 18:35:42137 "chrome-ui://chromewebdata/";
initial.commit09911bf2008-07-26 23:55:29138
[email protected]50b691c2008-10-31 19:08:35139static const char* const kBackForwardNavigationScheme = "history";
140
initial.commit09911bf2008-07-26 23:55:29141namespace {
142
143// Associated with browser-initiated navigations to hold tracking data.
144class RenderViewExtraRequestData : public WebRequest::ExtraData {
145 public:
146 RenderViewExtraRequestData(int32 pending_page_id,
[email protected]c20210e62009-04-03 21:39:26147 PageTransition::Type transition,
148 Time request_time)
[email protected]6c8afae52009-01-22 02:24:57149 : transition_type(transition),
[email protected]c20210e62009-04-03 21:39:26150 request_time(request_time),
[email protected]6c8afae52009-01-22 02:24:57151 request_committed(false),
152 pending_page_id_(pending_page_id) {
initial.commit09911bf2008-07-26 23:55:29153 }
154
155 // Contains the page_id for this navigation or -1 if there is none yet.
156 int32 pending_page_id() const { return pending_page_id_; }
157
158 // Is this a new navigation?
159 bool is_new_navigation() const { return pending_page_id_ == -1; }
160
161 // Contains the transition type that the browser specified when it
162 // initiated the load.
163 PageTransition::Type transition_type;
[email protected]c20210e62009-04-03 21:39:26164 Time request_time;
initial.commit09911bf2008-07-26 23:55:29165
166 // True if we have already processed the "DidCommitLoad" event for this
167 // request. Used by session history.
168 bool request_committed;
169
170 private:
171 int32 pending_page_id_;
172
[email protected]4f3dc372009-02-24 00:10:29173 DISALLOW_COPY_AND_ASSIGN(RenderViewExtraRequestData);
initial.commit09911bf2008-07-26 23:55:29174};
175
176} // namespace
177
178///////////////////////////////////////////////////////////////////////////////
179
[email protected]81a34412009-01-05 19:17:24180RenderView::RenderView(RenderThreadBase* render_thread)
181 : RenderWidget(render_thread, true),
[email protected]81e63782009-02-27 19:35:09182 enabled_bindings_(0),
[email protected]e75cb49e2009-01-05 23:13:21183 target_url_status_(TARGET_NONE),
[email protected]81a34412009-01-05 19:17:24184 is_loading_(false),
[email protected]e75cb49e2009-01-05 23:13:21185 navigation_gesture_(NavigationGestureUnknown),
[email protected]81a34412009-01-05 19:17:24186 page_id_(-1),
187 last_page_id_sent_to_browser_(-1),
188 last_indexed_page_id_(-1),
[email protected]81a34412009-01-05 19:17:24189 opened_by_user_gesture_(true),
[email protected]bb063b72009-03-27 23:18:50190 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
[email protected]81a34412009-01-05 19:17:24191 first_default_plugin_(NULL),
[email protected]e4ac5df2009-03-17 15:33:11192 devtools_agent_(NULL),
[email protected]b75b7d072009-04-06 13:47:00193 devtools_agent_filter_(NULL),
[email protected]e4ac5df2009-03-17 15:33:11194 devtools_client_(NULL),
[email protected]81a34412009-01-05 19:17:24195 history_back_list_count_(0),
196 history_forward_list_count_(0),
197 disable_popup_blocking_(false),
198 has_unload_listener_(false),
199 decrement_shared_popup_at_destruction_(false),
[email protected]81a34412009-01-05 19:17:24200 form_field_autofill_request_id_(0),
201 popup_notification_visible_(false),
202 delay_seconds_for_form_state_sync_(kDefaultDelaySecondsForFormStateSync) {
[email protected]3a453fa2008-08-15 18:46:34203#ifdef CHROME_PERSONALIZATION
204 personalization_ = Personalization::CreateRendererPersonalization();
205#endif
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]81a34412009-01-05 19:17:24219 render_thread_->RemoveFilter(debug_message_handler_);
[email protected]90ca3692009-04-09 16:09:43220 if (devtools_agent_filter_.get())
221 render_thread_->RemoveFilter(devtools_agent_filter_);
[email protected]3a453fa2008-08-15 18:46:34222
223#ifdef CHROME_PERSONALIZATION
224 Personalization::CleanupRendererPersonalization(personalization_);
225 personalization_ = NULL;
226#endif
initial.commit09911bf2008-07-26 23:55:29227}
228
229/*static*/
[email protected]0aa55312008-10-17 21:53:08230RenderView* RenderView::Create(
[email protected]81a34412009-01-05 19:17:24231 RenderThreadBase* render_thread,
[email protected]18bcc3c2009-01-27 21:39:15232 gfx::NativeViewId parent_hwnd,
[email protected]1c4947f2009-01-15 22:25:11233 base::WaitableEvent* modal_dialog_event,
[email protected]0aa55312008-10-17 21:53:08234 int32 opener_id,
235 const WebPreferences& webkit_prefs,
236 SharedRenderViewCounter* counter,
237 int32 routing_id) {
initial.commit09911bf2008-07-26 23:55:29238 DCHECK(routing_id != MSG_ROUTING_NONE);
[email protected]81a34412009-01-05 19:17:24239 scoped_refptr<RenderView> view = new RenderView(render_thread);
initial.commit09911bf2008-07-26 23:55:29240 view->Init(parent_hwnd,
241 modal_dialog_event,
242 opener_id,
243 webkit_prefs,
[email protected]0aa55312008-10-17 21:53:08244 counter,
initial.commit09911bf2008-07-26 23:55:29245 routing_id); // adds reference
246 return view;
247}
248
249/*static*/
250void RenderView::SetNextPageID(int32 next_page_id) {
251 // This method should only be called during process startup, and the given
252 // page id had better not exceed our current next page id!
253 DCHECK(next_page_id_ == 1);
254 DCHECK(next_page_id >= next_page_id_);
255 next_page_id_ = next_page_id;
256}
257
258void RenderView::PluginDestroyed(WebPluginDelegateProxy* proxy) {
259 PluginDelegateList::iterator it =
260 std::find(plugin_delegates_.begin(), plugin_delegates_.end(), proxy);
261 DCHECK(it != plugin_delegates_.end());
262 plugin_delegates_.erase(it);
263 // If the plugin is deleted, we need to clear our reference in case user
264 // clicks the info bar to install. Unfortunately we are getting
265 // PluginDestroyed in single process mode. However, that is not a huge
266 // concern.
[email protected]6c8afae52009-01-22 02:24:57267#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29268 if (proxy == first_default_plugin_)
269 first_default_plugin_ = NULL;
[email protected]6c8afae52009-01-22 02:24:57270#else
271 // TODO(port): because of the headers that we aren't including, the compiler
272 // has only seen a forward decl, not the subclass relation. Thus it doesn't
273 // know that the two pointer types compared above are comparable. Once we
274 // port and include the headers this problem should go away.
275 NOTIMPLEMENTED();
276#endif
initial.commit09911bf2008-07-26 23:55:29277}
278
[email protected]690a99c2009-01-06 16:48:45279void RenderView::PluginCrashed(const FilePath& plugin_path) {
initial.commit09911bf2008-07-26 23:55:29280 Send(new ViewHostMsg_CrashedPlugin(routing_id_, plugin_path));
281}
282
283
284void RenderView::JSOutOfMemory() {
285 Send(new ViewHostMsg_JSOutOfMemory(routing_id_));
286}
287
[email protected]18bcc3c2009-01-27 21:39:15288void RenderView::Init(gfx::NativeViewId parent_hwnd,
[email protected]1c4947f2009-01-15 22:25:11289 base::WaitableEvent* modal_dialog_event,
initial.commit09911bf2008-07-26 23:55:29290 int32 opener_id,
291 const WebPreferences& webkit_prefs,
[email protected]0aa55312008-10-17 21:53:08292 SharedRenderViewCounter* counter,
initial.commit09911bf2008-07-26 23:55:29293 int32 routing_id) {
294 DCHECK(!webview());
295
296 if (opener_id != MSG_ROUTING_NONE)
297 opener_id_ = opener_id;
298
[email protected]0aa55312008-10-17 21:53:08299 if (counter) {
300 shared_popup_counter_ = counter;
301 shared_popup_counter_->data++;
302 decrement_shared_popup_at_destruction_ = true;
303 } else {
304 shared_popup_counter_ = new SharedRenderViewCounter(0);
305 decrement_shared_popup_at_destruction_ = false;
306 }
307
[email protected]90ca3692009-04-09 16:09:43308 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
309
310 bool dev_tools_enabled = command_line.HasSwitch(
311 switches::kEnableOutOfProcessDevTools);
312 if (dev_tools_enabled)
313 devtools_agent_.reset(new DevToolsAgent(routing_id, this));
[email protected]9b9d7282009-04-08 14:13:04314
[email protected]c5b3b5e2009-02-13 06:41:11315 webwidget_ = WebView::Create(this, webkit_prefs);
initial.commit09911bf2008-07-26 23:55:29316
[email protected]90ca3692009-04-09 16:09:43317 if (dev_tools_enabled)
318 devtools_agent_filter_ = new DevToolsAgentFilter(
319 webview()->GetWebDevToolsAgent(),
320 routing_id);
[email protected]9b9d7282009-04-08 14:13:04321
[email protected]2e417c82009-04-02 22:30:26322#if defined(OS_LINUX)
323 // We have to enable ourselves as the editor delegate on linux so we can copy
324 // text selections to the X clipboard.
325 webview()->SetUseEditorDelegate(true);
326#endif
327
initial.commit09911bf2008-07-26 23:55:29328 // Don't let WebCore keep a B/F list - we have our own.
329 // We let it keep 1 entry because FrameLoader::goToItem expects an item in the
330 // backForwardList, which is used only in ASSERTs.
331 webview()->SetBackForwardListSize(1);
332
333 routing_id_ = routing_id;
[email protected]81a34412009-01-05 19:17:24334 render_thread_->AddRoute(routing_id_, this);
initial.commit09911bf2008-07-26 23:55:29335 // Take a reference on behalf of the RenderThread. This will be balanced
336 // when we receive ViewMsg_Close.
337 AddRef();
338
339 // If this is a popup, we must wait for the CreatingNew_ACK message before
340 // completing initialization. Otherwise, we can finish it now.
341 if (opener_id == MSG_ROUTING_NONE) {
342 did_show_ = true;
343 CompleteInit(parent_hwnd);
344 }
345
346 host_window_ = parent_hwnd;
[email protected]1c4947f2009-01-15 22:25:11347 modal_dialog_event_.reset(modal_dialog_event);
initial.commit09911bf2008-07-26 23:55:29348
[email protected]81e63782009-02-27 19:35:09349 if (command_line.HasSwitch(switches::kDomAutomationController))
350 enabled_bindings_ |= BindingsPolicy::DOM_AUTOMATION;
initial.commit09911bf2008-07-26 23:55:29351 disable_popup_blocking_ =
352 command_line.HasSwitch(switches::kDisablePopupBlocking);
353
354 debug_message_handler_ = new DebugMessageHandler(this);
[email protected]81a34412009-01-05 19:17:24355 render_thread_->AddFilter(debug_message_handler_);
[email protected]90ca3692009-04-09 16:09:43356 if (dev_tools_enabled)
357 render_thread_->AddFilter(devtools_agent_filter_);
initial.commit09911bf2008-07-26 23:55:29358}
359
360void RenderView::OnMessageReceived(const IPC::Message& message) {
[email protected]f8b6b6f2009-03-10 16:48:26361 WebFrame* main_frame = webview() ? webview()->GetMainFrame() : NULL;
362 renderer_logging::ScopedActiveRenderingURLSetter url_setter(
363 main_frame ? main_frame->GetURL() : GURL());
[email protected]f8b6b6f2009-03-10 16:48:26364
[email protected]b2abac72009-02-26 12:39:28365 // If this is developer tools renderer intercept tools messages first.
[email protected]e4ac5df2009-03-17 15:33:11366 if (devtools_client_.get() && devtools_client_->OnMessageReceived(message))
[email protected]b2abac72009-02-26 12:39:28367 return;
[email protected]90ca3692009-04-09 16:09:43368 if (devtools_agent_.get() && devtools_agent_->OnMessageReceived(message))
[email protected]b75b7d072009-04-06 13:47:00369 return;
[email protected]b2abac72009-02-26 12:39:28370
initial.commit09911bf2008-07-26 23:55:29371 IPC_BEGIN_MESSAGE_MAP(RenderView, message)
initial.commit09911bf2008-07-26 23:55:29372 IPC_MESSAGE_HANDLER(ViewMsg_CaptureThumbnail, SendThumbnail)
initial.commit09911bf2008-07-26 23:55:29373 IPC_MESSAGE_HANDLER(ViewMsg_PrintPages, OnPrintPages)
374 IPC_MESSAGE_HANDLER(ViewMsg_Navigate, OnNavigate)
375 IPC_MESSAGE_HANDLER(ViewMsg_Stop, OnStop)
376 IPC_MESSAGE_HANDLER(ViewMsg_LoadAlternateHTMLText, OnLoadAlternateHTMLText)
377 IPC_MESSAGE_HANDLER(ViewMsg_StopFinding, OnStopFinding)
378 IPC_MESSAGE_HANDLER(ViewMsg_Undo, OnUndo)
379 IPC_MESSAGE_HANDLER(ViewMsg_Redo, OnRedo)
380 IPC_MESSAGE_HANDLER(ViewMsg_Cut, OnCut)
381 IPC_MESSAGE_HANDLER(ViewMsg_Copy, OnCopy)
382 IPC_MESSAGE_HANDLER(ViewMsg_Paste, OnPaste)
383 IPC_MESSAGE_HANDLER(ViewMsg_Replace, OnReplace)
[email protected]bbbd545c2008-12-15 20:18:04384 IPC_MESSAGE_HANDLER(ViewMsg_ToggleSpellCheck, OnToggleSpellCheck)
initial.commit09911bf2008-07-26 23:55:29385 IPC_MESSAGE_HANDLER(ViewMsg_Delete, OnDelete)
386 IPC_MESSAGE_HANDLER(ViewMsg_SelectAll, OnSelectAll)
387 IPC_MESSAGE_HANDLER(ViewMsg_CopyImageAt, OnCopyImageAt)
388 IPC_MESSAGE_HANDLER(ViewMsg_Find, OnFind)
[email protected]630e26b2008-10-14 22:55:17389 IPC_MESSAGE_HANDLER(ViewMsg_Zoom, OnZoom)
[email protected]ea8c7452009-04-02 20:47:06390 IPC_MESSAGE_HANDLER(ViewMsg_InsertText, OnInsertText)
initial.commit09911bf2008-07-26 23:55:29391 IPC_MESSAGE_HANDLER(ViewMsg_SetPageEncoding, OnSetPageEncoding)
392 IPC_MESSAGE_HANDLER(ViewMsg_InspectElement, OnInspectElement)
393 IPC_MESSAGE_HANDLER(ViewMsg_ShowJavaScriptConsole, OnShowJavaScriptConsole)
[email protected]b2abac72009-02-26 12:39:28394 IPC_MESSAGE_HANDLER(ViewMsg_SetupDevToolsClient, OnSetupDevToolsClient)
initial.commit09911bf2008-07-26 23:55:29395 IPC_MESSAGE_HANDLER(ViewMsg_DownloadImage, OnDownloadImage)
396 IPC_MESSAGE_HANDLER(ViewMsg_ScriptEvalRequest, OnScriptEvalRequest)
[email protected]1810e132009-03-24 23:35:48397 IPC_MESSAGE_HANDLER(ViewMsg_CSSInsertRequest, OnCSSInsertRequest)
initial.commit09911bf2008-07-26 23:55:29398 IPC_MESSAGE_HANDLER(ViewMsg_AddMessageToConsole, OnAddMessageToConsole)
399 IPC_MESSAGE_HANDLER(ViewMsg_DebugAttach, OnDebugAttach)
[email protected]88010e082008-08-29 11:07:40400 IPC_MESSAGE_HANDLER(ViewMsg_DebugDetach, OnDebugDetach)
initial.commit09911bf2008-07-26 23:55:29401 IPC_MESSAGE_HANDLER(ViewMsg_ReservePageIDRange, OnReservePageIDRange)
402 IPC_MESSAGE_HANDLER(ViewMsg_UploadFile, OnUploadFileRequest)
403 IPC_MESSAGE_HANDLER(ViewMsg_FormFill, OnFormFill)
404 IPC_MESSAGE_HANDLER(ViewMsg_FillPasswordForm, OnFillPasswordForm)
405 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragEnter, OnDragTargetDragEnter)
406 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragOver, OnDragTargetDragOver)
407 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragLeave, OnDragTargetDragLeave)
408 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDrop, OnDragTargetDrop)
[email protected]18cb2572008-08-21 20:34:45409 IPC_MESSAGE_HANDLER(ViewMsg_AllowBindings, OnAllowBindings)
initial.commit09911bf2008-07-26 23:55:29410 IPC_MESSAGE_HANDLER(ViewMsg_SetDOMUIProperty, OnSetDOMUIProperty)
[email protected]266eb6f2008-09-30 23:56:50411 IPC_MESSAGE_HANDLER(ViewMsg_DragSourceEndedOrMoved,
412 OnDragSourceEndedOrMoved)
initial.commit09911bf2008-07-26 23:55:29413 IPC_MESSAGE_HANDLER(ViewMsg_DragSourceSystemDragEnded,
414 OnDragSourceSystemDragEnded)
415 IPC_MESSAGE_HANDLER(ViewMsg_SetInitialFocus, OnSetInitialFocus)
416 IPC_MESSAGE_HANDLER(ViewMsg_FindReplyACK, OnFindReplyAck)
417 IPC_MESSAGE_HANDLER(ViewMsg_UpdateTargetURL_ACK, OnUpdateTargetURLAck)
418 IPC_MESSAGE_HANDLER(ViewMsg_UpdateWebPreferences, OnUpdateWebPreferences)
419 IPC_MESSAGE_HANDLER(ViewMsg_SetAltErrorPageURL, OnSetAltErrorPageURL)
420 IPC_MESSAGE_HANDLER(ViewMsg_InstallMissingPlugin, OnInstallMissingPlugin)
421 IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse)
422 IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode, OnEnableViewSourceMode)
423 IPC_MESSAGE_HANDLER(ViewMsg_UpdateBackForwardListCount,
424 OnUpdateBackForwardListCount)
425 IPC_MESSAGE_HANDLER(ViewMsg_GetAllSavableResourceLinksForCurrentPage,
426 OnGetAllSavableResourceLinksForCurrentPage)
[email protected]f09c7182009-03-10 12:54:04427 IPC_MESSAGE_HANDLER(
428 ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks,
429 OnGetSerializedHtmlDataForCurrentPageWithLocalLinks)
initial.commit09911bf2008-07-26 23:55:29430 IPC_MESSAGE_HANDLER(ViewMsg_GetApplicationInfo, OnGetApplicationInfo)
[email protected]266eb6f2008-09-30 23:56:50431 IPC_MESSAGE_HANDLER(ViewMsg_GetAccessibilityInfo, OnGetAccessibilityInfo)
432 IPC_MESSAGE_HANDLER(ViewMsg_ClearAccessibilityInfo,
433 OnClearAccessibilityInfo)
initial.commit09911bf2008-07-26 23:55:29434 IPC_MESSAGE_HANDLER(ViewMsg_ShouldClose, OnMsgShouldClose)
435 IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage)
436 IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged)
[email protected]3c17b9c2008-08-26 02:08:00437#ifdef CHROME_PERSONALIZATION
[email protected]1cc879642008-08-26 01:27:35438 IPC_MESSAGE_HANDLER(ViewMsg_PersonalizationEvent, OnPersonalizationEvent)
[email protected]3c17b9c2008-08-26 02:08:00439#endif
[email protected]18cb2572008-08-21 20:34:45440 IPC_MESSAGE_HANDLER(ViewMsg_HandleMessageFromExternalHost,
441 OnMessageFromExternalHost)
[email protected]0aa55312008-10-17 21:53:08442 IPC_MESSAGE_HANDLER(ViewMsg_DisassociateFromPopupCount,
443 OnDisassociateFromPopupCount)
[email protected]0ebf3872008-11-07 21:35:03444 IPC_MESSAGE_HANDLER(ViewMsg_AutofillSuggestions,
445 OnReceivedAutofillSuggestions)
[email protected]634a6f92008-12-01 21:39:31446 IPC_MESSAGE_HANDLER(ViewMsg_PopupNotificationVisiblityChanged,
447 OnPopupNotificationVisiblityChanged)
[email protected]6f56d482009-02-20 05:02:56448 IPC_MESSAGE_HANDLER(ViewMsg_RequestAudioPacket, OnRequestAudioPacket)
449 IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamCreated, OnAudioStreamCreated)
450 IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamStateChanged,
451 OnAudioStreamStateChanged)
452 IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamVolume, OnAudioStreamVolume)
[email protected]30f75e62009-02-25 22:01:00453 IPC_MESSAGE_HANDLER(ViewMsg_MoveOrResizeStarted, OnMoveOrResizeStarted)
[email protected]309d7a282009-03-24 09:18:27454 IPC_MESSAGE_HANDLER(ViewMsg_ExtensionResponse, OnExtensionResponse)
[email protected]05d478752009-04-08 23:38:16455 IPC_MESSAGE_HANDLER(ViewMsg_ClearFocusedNode, OnClearFocusedNode)
[email protected]634a6f92008-12-01 21:39:31456
initial.commit09911bf2008-07-26 23:55:29457 // Have the super handle all other messages.
458 IPC_MESSAGE_UNHANDLED(RenderWidget::OnMessageReceived(message))
459 IPC_END_MESSAGE_MAP()
460}
461
initial.commit09911bf2008-07-26 23:55:29462void RenderView::SendThumbnail() {
463 WebFrame* main_frame = webview()->GetMainFrame();
464 if (!main_frame)
465 return;
466
467 // get the URL for this page
468 GURL url(main_frame->GetURL());
469 if (url.is_empty())
470 return;
471
472 if (size_.IsEmpty())
473 return; // Don't create an empty thumbnail!
474
475 ThumbnailScore score;
476 SkBitmap thumbnail;
[email protected]b6e4bec2008-11-12 01:17:15477 if (!CaptureThumbnail(main_frame, kThumbnailWidth, kThumbnailHeight,
478 &thumbnail, &score))
479 return;
480
initial.commit09911bf2008-07-26 23:55:29481 // send the thumbnail message to the browser process
[email protected]674741932009-02-04 23:44:46482 Send(new ViewHostMsg_Thumbnail(routing_id_, url, score, thumbnail));
initial.commit09911bf2008-07-26 23:55:29483}
484
initial.commit09911bf2008-07-26 23:55:29485void RenderView::PrintPage(const ViewMsg_PrintPage_Params& params,
[email protected]88a3ecc2009-03-19 17:36:22486 const gfx::Size& canvas_size,
initial.commit09911bf2008-07-26 23:55:29487 WebFrame* frame) {
[email protected]6c8afae52009-01-22 02:24:57488#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29489 // Generate a memory-based EMF file. The EMF will use the current screen's
490 // DPI.
491 gfx::Emf emf;
492
493 emf.CreateDc(NULL, NULL);
494 HDC hdc = emf.hdc();
495 DCHECK(hdc);
[email protected]21f527e2008-12-17 23:29:40496 skia::PlatformDeviceWin::InitializeDC(hdc);
[email protected]0e92fa32009-03-31 20:39:33497 // Since WebKit extends the page width depending on the magical shrink
[email protected]0dea3ea2009-03-31 23:30:59498 // factor we make sure the canvas covers the worst case scenario
[email protected]0e92fa32009-03-31 20:39:33499 // (x2.0 currently). PrintContext will then set the correct clipping region.
500 int size_x = static_cast<int>(canvas_size.width() * params.params.max_shrink);
501 int size_y = static_cast<int>(canvas_size.height() *
502 params.params.max_shrink);
[email protected]88a3ecc2009-03-19 17:36:22503 // Calculate the dpi adjustment.
504 float shrink = static_cast<float>(canvas_size.width()) /
505 params.params.printable_size.width();
initial.commit09911bf2008-07-26 23:55:29506#if 0
507 // TODO(maruel): This code is kept for testing until the 100% GDI drawing
508 // code is stable. maruels use this code's output as a reference when the
509 // GDI drawing code fails.
510
511 // Mix of Skia and GDI based.
[email protected]88a3ecc2009-03-19 17:36:22512 skia::PlatformCanvasWin canvas(size_x, size_y, true);
initial.commit09911bf2008-07-26 23:55:29513 canvas.drawARGB(255, 255, 255, 255, SkPorterDuff::kSrc_Mode);
[email protected]88a3ecc2009-03-19 17:36:22514 float webkit_shrink = frame->PrintPage(params.page_number, &canvas);
515 if (shrink <= 0) {
initial.commit09911bf2008-07-26 23:55:29516 NOTREACHED() << "Printing page " << params.page_number << " failed.";
[email protected]88a3ecc2009-03-19 17:36:22517 } else {
518 // Update the dpi adjustment with the "page shrink" calculated in webkit.
519 shrink /= webkit_shrink;
initial.commit09911bf2008-07-26 23:55:29520 }
521
522 // Create a BMP v4 header that we can serialize.
523 BITMAPV4HEADER bitmap_header;
[email protected]88a3ecc2009-03-19 17:36:22524 gfx::CreateBitmapV4Header(size_x, size_y, &bitmap_header);
initial.commit09911bf2008-07-26 23:55:29525 const SkBitmap& src_bmp = canvas.getDevice()->accessBitmap(true);
526 SkAutoLockPixels src_lock(src_bmp);
527 int retval = StretchDIBits(hdc,
528 0,
529 0,
[email protected]88a3ecc2009-03-19 17:36:22530 size_x, size_y,
initial.commit09911bf2008-07-26 23:55:29531 0, 0,
[email protected]88a3ecc2009-03-19 17:36:22532 size_x, size_y,
initial.commit09911bf2008-07-26 23:55:29533 src_bmp.getPixels(),
534 reinterpret_cast<BITMAPINFO*>(&bitmap_header),
535 DIB_RGB_COLORS,
536 SRCCOPY);
537 DCHECK(retval != GDI_ERROR);
538#else
539 // 100% GDI based.
[email protected]88a3ecc2009-03-19 17:36:22540 skia::VectorCanvas canvas(hdc, size_x, size_y);
541 float webkit_shrink = frame->PrintPage(params.page_number, &canvas);
542 if (shrink <= 0) {
initial.commit09911bf2008-07-26 23:55:29543 NOTREACHED() << "Printing page " << params.page_number << " failed.";
[email protected]88a3ecc2009-03-19 17:36:22544 } else {
545 // Update the dpi adjustment with the "page shrink" calculated in webkit.
546 shrink /= webkit_shrink;
initial.commit09911bf2008-07-26 23:55:29547 }
548#endif
549
550 // Done printing. Close the device context to retrieve the compiled EMF.
551 if (!emf.CloseDc()) {
552 NOTREACHED() << "EMF failed";
553 }
554
555 // Get the size of the compiled EMF.
556 unsigned buf_size = emf.GetDataSize();
557 DCHECK(buf_size > 128);
558 ViewHostMsg_DidPrintPage_Params page_params;
559 page_params.data_size = 0;
560 page_params.emf_data_handle = NULL;
561 page_params.page_number = params.page_number;
562 page_params.document_cookie = params.params.document_cookie;
563 page_params.actual_shrink = shrink;
[email protected]176aa482008-11-14 03:25:15564 base::SharedMemory shared_buf;
initial.commit09911bf2008-07-26 23:55:29565
566 // http://msdn2.microsoft.com/en-us/library/ms535522.aspx
567 // Windows 2000/XP: When a page in a spooled file exceeds approximately 350
568 // MB, it can fail to print and not send an error message.
569 if (buf_size < 350*1024*1024) {
570 // Allocate a shared memory buffer to hold the generated EMF data.
571 if (shared_buf.Create(L"", false, false, buf_size) &&
572 shared_buf.Map(buf_size)) {
573 // Copy the bits into shared memory.
574 if (emf.GetData(shared_buf.memory(), buf_size)) {
575 page_params.emf_data_handle = shared_buf.handle();
576 page_params.data_size = buf_size;
577 } else {
578 NOTREACHED() << "GetData() failed";
579 }
580 shared_buf.Unmap();
581 } else {
582 NOTREACHED() << "Buffer allocation failed";
583 }
584 } else {
585 NOTREACHED() << "Buffer too large: " << buf_size;
586 }
587 emf.CloseEmf();
588 if (Send(new ViewHostMsg_DuplicateSection(routing_id_,
589 page_params.emf_data_handle,
590 &page_params.emf_data_handle))) {
591 Send(new ViewHostMsg_DidPrintPage(routing_id_, page_params));
592 }
[email protected]6c8afae52009-01-22 02:24:57593#else // defined(OS_WIN)
594 // TODO(port) implement printing
595 NOTIMPLEMENTED();
596#endif
initial.commit09911bf2008-07-26 23:55:29597}
598
[email protected]068637222009-01-29 16:58:07599void RenderView::OnPrintPages() {
initial.commit09911bf2008-07-26 23:55:29600 DCHECK(webview());
[email protected]068637222009-01-29 16:58:07601 if (webview()) {
602 // The renderer own the control flow as if it was a window.print() call.
603 ScriptedPrint(webview()->GetMainFrame());
initial.commit09911bf2008-07-26 23:55:29604 }
initial.commit09911bf2008-07-26 23:55:29605}
606
607void RenderView::PrintPages(const ViewMsg_PrintPages_Params& params,
608 WebFrame* frame) {
[email protected]88a3ecc2009-03-19 17:36:22609 int page_count = 0;
610 gfx::Size canvas_size;
611 canvas_size.set_width(
612 printing::ConvertUnit(params.params.printable_size.width(),
613 static_cast<int>(params.params.dpi),
614 params.params.desired_dpi));
615 canvas_size.set_height(
616 printing::ConvertUnit(params.params.printable_size.height(),
617 static_cast<int>(params.params.dpi),
618 params.params.desired_dpi));
619 frame->BeginPrint(canvas_size, &page_count);
initial.commit09911bf2008-07-26 23:55:29620 Send(new ViewHostMsg_DidGetPrintedPagesCount(routing_id_,
621 params.params.document_cookie,
[email protected]88a3ecc2009-03-19 17:36:22622 page_count));
623 if (page_count) {
initial.commit09911bf2008-07-26 23:55:29624 ViewMsg_PrintPage_Params page_params;
625 page_params.params = params.params;
626 if (params.pages.empty()) {
[email protected]88a3ecc2009-03-19 17:36:22627 for (int i = 0; i < page_count; ++i) {
initial.commit09911bf2008-07-26 23:55:29628 page_params.page_number = i;
[email protected]88a3ecc2009-03-19 17:36:22629 PrintPage(page_params, canvas_size, frame);
initial.commit09911bf2008-07-26 23:55:29630 }
631 } else {
632 for (size_t i = 0; i < params.pages.size(); ++i) {
633 page_params.page_number = params.pages[i];
[email protected]88a3ecc2009-03-19 17:36:22634 PrintPage(page_params, canvas_size, frame);
initial.commit09911bf2008-07-26 23:55:29635 }
636 }
637 }
[email protected]88a3ecc2009-03-19 17:36:22638 frame->EndPrint();
initial.commit09911bf2008-07-26 23:55:29639}
640
641void RenderView::CapturePageInfo(int load_id, bool preliminary_capture) {
642 if (load_id != page_id_)
643 return; // this capture call is no longer relevant due to navigation
644 if (load_id == last_indexed_page_id_)
645 return; // we already indexed this page
646
647 if (!webview())
648 return;
649
650 WebFrame* main_frame = webview()->GetMainFrame();
651 if (!main_frame)
652 return;
653
654 // Don't index/capture pages that are in view source mode.
655 if (main_frame->GetInViewSourceMode())
656 return;
657
658 // Don't index/capture pages that failed to load. This only checks the top
659 // level frame so the thumbnail may contain a frame that failed to load.
660 WebDataSource* ds = main_frame->GetDataSource();
661 if (ds && ds->HasUnreachableURL())
662 return;
663
664 if (!preliminary_capture)
665 last_indexed_page_id_ = load_id;
666
667 // get the URL for this page
668 GURL url(main_frame->GetURL());
669 if (url.is_empty())
670 return;
671
672 // full text
673 std::wstring contents;
674 CaptureText(main_frame, &contents);
675 if (contents.size()) {
676 // Send the text to the browser for indexing.
677 Send(new ViewHostMsg_PageContents(url, load_id, contents));
678 }
679
680 // thumbnail
681 SendThumbnail();
682}
683
684void RenderView::CaptureText(WebFrame* frame, std::wstring* contents) {
685 contents->clear();
686 if (!frame)
687 return;
688
[email protected]0faf0bd92008-09-09 20:53:27689 // Don't index any https pages. People generally don't want their bank
690 // accounts, etc. indexed on their computer, especially since some of these
691 // things are not marked cachable.
692 // TODO(brettw) we may want to consider more elaborate heuristics such as
693 // the cachability of the page. We may also want to consider subframes (this
694 // test will still index subframes if the subframe is SSL).
695 if (frame->GetURL().SchemeIsSecure())
696 return;
697
initial.commit09911bf2008-07-26 23:55:29698#ifdef TIME_TEXT_RETRIEVAL
699 double begin = time_util::GetHighResolutionTimeNow();
700#endif
701
702 // get the contents of the frame
703 frame->GetContentAsPlainText(kMaxIndexChars, contents);
704
705#ifdef TIME_TEXT_RETRIEVAL
706 double end = time_util::GetHighResolutionTimeNow();
707 char buf[128];
708 sprintf_s(buf, "%d chars retrieved for indexing in %gms\n",
709 contents.size(), (end - begin)*1000);
710 OutputDebugStringA(buf);
711#endif
712
713 // When the contents are clipped to the maximum, we don't want to have a
714 // partial word indexed at the end that might have been clipped. Therefore,
715 // terminate the string at the last space to ensure no words are clipped.
716 if (contents->size() == kMaxIndexChars) {
717 size_t last_space_index = contents->find_last_of(kWhitespaceWide);
718 if (last_space_index == std::wstring::npos)
719 return; // don't index if we got a huge block of text with no spaces
720 contents->resize(last_space_index);
721 }
722}
723
[email protected]b6e4bec2008-11-12 01:17:15724bool RenderView::CaptureThumbnail(WebFrame* frame,
initial.commit09911bf2008-07-26 23:55:29725 int w,
726 int h,
727 SkBitmap* thumbnail,
728 ThumbnailScore* score) {
729#ifdef TIME_BITMAP_RETRIEVAL
730 double begin = time_util::GetHighResolutionTimeNow();
731#endif
732
[email protected]21f527e2008-12-17 23:29:40733 scoped_ptr<skia::BitmapPlatformDevice> device;
[email protected]b6e4bec2008-11-12 01:17:15734 if (!frame->CaptureImage(&device, true))
735 return false;
736
737 const SkBitmap& src_bmp = device->accessBitmap(false);
initial.commit09911bf2008-07-26 23:55:29738
739 SkRect dest_rect;
740 dest_rect.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
741 float dest_aspect = dest_rect.width() / dest_rect.height();
742
743 // Get the src rect so that we can preserve the aspect ratio while filling
744 // the destination.
745 SkIRect src_rect;
746 if (src_bmp.width() < dest_rect.width() ||
747 src_bmp.height() < dest_rect.height()) {
748 // Source image is smaller: we clip the part of source image within the
749 // dest rect, and then stretch it to fill the dest rect. We don't respect
750 // the aspect ratio in this case.
751 src_rect.set(0, 0, static_cast<S16CPU>(dest_rect.width()),
752 static_cast<S16CPU>(dest_rect.height()));
753 score->good_clipping = false;
754 } else {
755 float src_aspect = static_cast<float>(src_bmp.width()) / src_bmp.height();
756 if (src_aspect > dest_aspect) {
757 // Wider than tall, clip horizontally: we center the smaller thumbnail in
758 // the wider screen.
759 S16CPU new_width = static_cast<S16CPU>(src_bmp.height() * dest_aspect);
760 S16CPU x_offset = (src_bmp.width() - new_width) / 2;
761 src_rect.set(x_offset, 0, new_width + x_offset, src_bmp.height());
762 score->good_clipping = false;
763 } else {
764 src_rect.set(0, 0, src_bmp.width(),
765 static_cast<S16CPU>(src_bmp.width() / dest_aspect));
766 score->good_clipping = true;
767 }
768 }
769
[email protected]b3f2b912009-04-09 16:18:52770 score->at_top = (frame->ScrollOffset().height == 0);
initial.commit09911bf2008-07-26 23:55:29771
772 SkBitmap subset;
[email protected]b6e4bec2008-11-12 01:17:15773 device->accessBitmap(false).extractSubset(&subset, src_rect);
initial.commit09911bf2008-07-26 23:55:29774
775 // Resample the subset that we want to get it the right size.
[email protected]465b34b72008-12-12 20:19:14776 *thumbnail = skia::ImageOperations::Resize(
777 subset, skia::ImageOperations::RESIZE_LANCZOS3, w, h);
initial.commit09911bf2008-07-26 23:55:29778
779 score->boring_score = CalculateBoringScore(thumbnail);
780
781#ifdef TIME_BITMAP_RETRIEVAL
782 double end = time_util::GetHighResolutionTimeNow();
783 char buf[128];
784 sprintf_s(buf, "thumbnail in %gms\n", (end - begin) * 1000);
785 OutputDebugStringA(buf);
786#endif
[email protected]b6e4bec2008-11-12 01:17:15787 return true;
initial.commit09911bf2008-07-26 23:55:29788}
789
790double RenderView::CalculateBoringScore(SkBitmap* bitmap) {
791 int histogram[256] = {0};
792 color_utils::BuildLumaHistogram(bitmap, histogram);
793
794 int color_count = *std::max_element(histogram, histogram + 256);
795 int pixel_count = bitmap->width() * bitmap->height();
796 return static_cast<double>(color_count) / pixel_count;
797}
798
799void RenderView::OnNavigate(const ViewMsg_Navigate_Params& params) {
800 if (!webview())
801 return;
802
[email protected]f8b6b6f2009-03-10 16:48:26803 renderer_logging::ScopedActiveRenderingURLSetter url_setter(params.url);
[email protected]f8b6b6f2009-03-10 16:48:26804
initial.commit09911bf2008-07-26 23:55:29805 AboutHandler::MaybeHandle(params.url);
806
807 bool is_reload = params.reload;
808
809 WebFrame* main_frame = webview()->GetMainFrame();
[email protected]606843fa2008-12-02 19:08:56810 if (is_reload && !main_frame->HasCurrentHistoryState()) {
initial.commit09911bf2008-07-26 23:55:29811 // We cannot reload if we do not have any history state. This happens, for
812 // example, when recovering from a crash. Our workaround here is a bit of
813 // a hack since it means that reload after a crashed tab does not cause an
814 // end-to-end cache validation.
815 is_reload = false;
816 }
817
818 WebRequestCachePolicy cache_policy;
819 if (is_reload) {
820 cache_policy = WebRequestReloadIgnoringCacheData;
821 } else if (params.page_id != -1 || main_frame->GetInViewSourceMode()) {
822 cache_policy = WebRequestReturnCacheDataElseLoad;
823 } else {
824 cache_policy = WebRequestUseProtocolCachePolicy;
825 }
826
827 scoped_ptr<WebRequest> request(WebRequest::Create(params.url));
828 request->SetCachePolicy(cache_policy);
829 request->SetExtraData(new RenderViewExtraRequestData(
[email protected]c20210e62009-04-03 21:39:26830 params.page_id, params.transition, params.request_time));
initial.commit09911bf2008-07-26 23:55:29831
832 // If we are reloading, then WebKit will use the state of the current page.
833 // Otherwise, we give it the state to navigate to.
834 if (!is_reload)
835 request->SetHistoryState(params.state);
836
[email protected]4c6f2c92008-10-28 20:26:15837 if (params.referrer.is_valid()) {
[email protected]8e3c1a72008-11-25 01:13:32838 request->SetHttpHeaderValue("Referer",
839 params.referrer.spec());
[email protected]c0588052008-10-27 23:01:50840 }
841
initial.commit09911bf2008-07-26 23:55:29842 main_frame->LoadRequest(request.get());
843}
844
845// Stop loading the current page
846void RenderView::OnStop() {
847 if (webview())
848 webview()->StopLoading();
849}
850
851void RenderView::OnLoadAlternateHTMLText(const std::string& html_contents,
852 bool new_navigation,
853 const GURL& display_url,
854 const std::string& security_info) {
855 if (!webview())
856 return;
857
858 scoped_ptr<WebRequest> request(WebRequest::Create(
859 GURL(kUnreachableWebDataURL)));
860 request->SetSecurityInfo(security_info);
861
862 webview()->GetMainFrame()->LoadAlternateHTMLString(request.get(),
863 html_contents,
864 display_url,
865 !new_navigation);
866}
867
868void RenderView::OnCopyImageAt(int x, int y) {
869 webview()->CopyImageAt(x, y);
870}
871
872void RenderView::OnInspectElement(int x, int y) {
873 webview()->InspectElement(x, y);
874}
875
876void RenderView::OnShowJavaScriptConsole() {
877 webview()->ShowJavaScriptConsole();
878}
879
[email protected]b2abac72009-02-26 12:39:28880void RenderView::OnSetupDevToolsClient() {
[email protected]e4ac5df2009-03-17 15:33:11881 DCHECK(!devtools_client_.get());
882 devtools_client_.reset(new DevToolsClient(this));
[email protected]b2abac72009-02-26 12:39:28883}
884
initial.commit09911bf2008-07-26 23:55:29885void RenderView::OnStopFinding(bool clear_selection) {
886 WebView* view = webview();
887 if (!view)
888 return;
889
890 if (clear_selection)
891 view->GetFocusedFrame()->ClearSelection();
892
893 WebFrame* frame = view->GetMainFrame();
894 while (frame) {
[email protected]65134c432008-09-26 21:47:20895 frame->StopFinding(clear_selection);
initial.commit09911bf2008-07-26 23:55:29896 frame = view->GetNextFrameAfter(frame, false);
897 }
898}
899
900void RenderView::OnFindReplyAck() {
901 // Check if there is any queued up request waiting to be sent.
902 if (queued_find_reply_message_.get()) {
903 // Send the search result over to the browser process.
904 Send(queued_find_reply_message_.get());
905 queued_find_reply_message_.release();
906 }
907}
908
909void RenderView::OnUpdateTargetURLAck() {
910 // Check if there is a targeturl waiting to be sent.
911 if (target_url_status_ == TARGET_PENDING) {
912 Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_,
913 pending_target_url_));
914 }
915
916 target_url_status_ = TARGET_NONE;
917}
918
919void RenderView::OnUndo() {
920 if (!webview())
921 return;
922
923 webview()->GetFocusedFrame()->Undo();
924}
925
926void RenderView::OnRedo() {
927 if (!webview())
928 return;
929
930 webview()->GetFocusedFrame()->Redo();
931}
932
933void RenderView::OnCut() {
934 if (!webview())
935 return;
936
937 webview()->GetFocusedFrame()->Cut();
938}
939
940void RenderView::OnCopy() {
941 if (!webview())
942 return;
943
944 webview()->GetFocusedFrame()->Copy();
945}
946
947void RenderView::OnPaste() {
948 if (!webview())
949 return;
950
951 webview()->GetFocusedFrame()->Paste();
952}
953
954void RenderView::OnReplace(const std::wstring& text) {
955 if (!webview())
956 return;
957
958 webview()->GetFocusedFrame()->Replace(text);
959}
960
[email protected]bbbd545c2008-12-15 20:18:04961void RenderView::OnToggleSpellCheck() {
962 if (!webview())
963 return;
964
965 webview()->GetFocusedFrame()->ToggleSpellCheck();
966}
967
initial.commit09911bf2008-07-26 23:55:29968void RenderView::OnDelete() {
969 if (!webview())
970 return;
971
972 webview()->GetFocusedFrame()->Delete();
973}
974
975void RenderView::OnSelectAll() {
976 if (!webview())
977 return;
978
979 webview()->GetFocusedFrame()->SelectAll();
980}
981
982void RenderView::OnSetInitialFocus(bool reverse) {
983 if (!webview())
984 return;
985 webview()->SetInitialFocus(reverse);
986}
987
988///////////////////////////////////////////////////////////////////////////////
989
990// Tell the embedding application that the URL of the active page has changed
991void RenderView::UpdateURL(WebFrame* frame) {
992 WebDataSource* ds = frame->GetDataSource();
993 DCHECK(ds);
994
995 const WebRequest& request = ds->GetRequest();
996 const WebRequest& initial_request = ds->GetInitialRequest();
997 const WebResponse& response = ds->GetResponse();
998
999 // We don't hold a reference to the extra data. The request's reference will
1000 // be sufficient because we won't modify it during our call. MAY BE NULL.
1001 RenderViewExtraRequestData* extra_data =
1002 static_cast<RenderViewExtraRequestData*>(request.GetExtraData());
1003
1004 ViewHostMsg_FrameNavigate_Params params;
[email protected]2e39d2e2009-02-19 18:41:311005 params.http_status_code = response.GetHttpStatusCode();
initial.commit09911bf2008-07-26 23:55:291006 params.is_post = false;
1007 params.page_id = page_id_;
[email protected]8a3422c92008-09-24 17:42:421008 params.is_content_filtered = response.IsContentFiltered();
initial.commit09911bf2008-07-26 23:55:291009 if (!request.GetSecurityInfo().empty()) {
1010 // SSL state specified in the request takes precedence over the one in the
1011 // response.
1012 // So far this is only intended for error pages that are not expected to be
1013 // over ssl, so we should not get any clash.
1014 DCHECK(response.GetSecurityInfo().empty());
1015 params.security_info = request.GetSecurityInfo();
1016 } else {
1017 params.security_info = response.GetSecurityInfo();
1018 }
1019
1020 // Set the URL to be displayed in the browser UI to the user.
1021 if (ds->HasUnreachableURL()) {
1022 params.url = ds->GetUnreachableURL();
1023 } else {
1024 params.url = request.GetURL();
1025 }
1026
1027 params.redirects = ds->GetRedirectChain();
1028 params.should_update_history = !ds->HasUnreachableURL();
1029
1030 const SearchableFormData* searchable_form_data =
1031 frame->GetDataSource()->GetSearchableFormData();
1032 if (searchable_form_data) {
1033 params.searchable_form_url = searchable_form_data->url();
1034 params.searchable_form_element_name = searchable_form_data->element_name();
1035 params.searchable_form_encoding = searchable_form_data->encoding();
1036 }
1037
1038 const PasswordForm* password_form_data =
1039 frame->GetDataSource()->GetPasswordFormData();
1040 if (password_form_data)
1041 params.password_form = *password_form_data;
1042
1043 params.gesture = navigation_gesture_;
1044 navigation_gesture_ = NavigationGestureUnknown;
1045
1046 if (webview()->GetMainFrame() == frame) {
1047 // Top-level navigation.
1048
1049 // Update contents MIME type for main frame.
[email protected]9d806f52009-03-12 22:50:541050 params.contents_mime_type = ds->GetResponse().GetMimeType();
initial.commit09911bf2008-07-26 23:55:291051
1052 // We assume top level navigations initiated by the renderer are link
1053 // clicks.
1054 params.transition = extra_data ?
1055 extra_data->transition_type : PageTransition::LINK;
1056 if (!PageTransition::IsMainFrame(params.transition)) {
1057 // If the main frame does a load, it should not be reported as a subframe
1058 // navigation. This can occur in the following case:
1059 // 1. You're on a site with frames.
1060 // 2. You do a subframe navigation. This is stored with transition type
1061 // MANUAL_SUBFRAME.
1062 // 3. You navigate to some non-frame site, say, google.com.
1063 // 4. You navigate back to the page from step 2. Since it was initially
1064 // MANUAL_SUBFRAME, it will be that same transition type here.
1065 // We don't want that, because any navigation that changes the toplevel
1066 // frame should be tracked as a toplevel navigation (this allows us to
1067 // update the URL bar, etc).
1068 params.transition = PageTransition::LINK;
1069 }
1070
1071 if (params.transition == PageTransition::LINK &&
1072 frame->GetDataSource()->IsFormSubmit()) {
1073 params.transition = PageTransition::FORM_SUBMIT;
1074 }
1075
1076 // If we have a valid consumed client redirect source,
1077 // the page contained a client redirect (meta refresh, document.loc...),
1078 // so we set the referrer and transition to match.
1079 if (completed_client_redirect_src_.is_valid()) {
[email protected]77e09a92008-08-01 18:11:041080 DCHECK(completed_client_redirect_src_ == params.redirects[0]);
initial.commit09911bf2008-07-26 23:55:291081 params.referrer = completed_client_redirect_src_;
1082 params.transition = static_cast<PageTransition::Type>(
1083 params.transition | PageTransition::CLIENT_REDIRECT);
1084 } else {
1085 // Bug 654101: the referrer will be empty on https->http transitions. It
1086 // would be nice if we could get the real referrer from somewhere.
1087 params.referrer = GURL(initial_request.GetHttpReferrer());
1088 }
1089
[email protected]8e3c1a72008-11-25 01:13:321090 std::string method = request.GetHttpMethod();
1091 if (method == "POST")
initial.commit09911bf2008-07-26 23:55:291092 params.is_post = true;
1093
1094 Send(new ViewHostMsg_FrameNavigate(routing_id_, params));
1095 } else {
1096 // Subframe navigation: the type depends on whether this navigation
1097 // generated a new session history entry. When they do generate a session
1098 // history entry, it means the user initiated the navigation and we should
1099 // mark it as such. This test checks if this is the first time UpdateURL
1100 // has been called since WillNavigateToURL was called to initiate the load.
1101 if (page_id_ > last_page_id_sent_to_browser_)
1102 params.transition = PageTransition::MANUAL_SUBFRAME;
1103 else
1104 params.transition = PageTransition::AUTO_SUBFRAME;
1105
1106 // The browser should never initiate a subframe navigation.
1107 DCHECK(!extra_data);
1108 Send(new ViewHostMsg_FrameNavigate(routing_id_, params));
1109 }
1110
1111 last_page_id_sent_to_browser_ =
1112 std::max(last_page_id_sent_to_browser_, page_id_);
1113
1114 // If we end up reusing this WebRequest (for example, due to a #ref click),
1115 // we don't want the transition type to persist.
1116 if (extra_data)
1117 extra_data->transition_type = PageTransition::LINK; // Just clear it.
[email protected]266eb6f2008-09-30 23:56:501118
[email protected]6c8afae52009-01-22 02:24:571119#if defined(OS_WIN)
[email protected]6a983b42009-03-20 20:12:251120 if (web_accessibility_manager_.get()) {
[email protected]be645db2009-02-06 20:36:331121 // Clear accessibility info cache.
[email protected]6a983b42009-03-20 20:12:251122 web_accessibility_manager_->ClearAccObjMap(-1, true);
[email protected]266eb6f2008-09-30 23:56:501123 }
[email protected]6c8afae52009-01-22 02:24:571124#else
[email protected]7d926f92009-03-03 14:26:541125 // TODO(port): accessibility not yet implemented. See http://crbug.com/8288.
[email protected]6c8afae52009-01-22 02:24:571126#endif
initial.commit09911bf2008-07-26 23:55:291127}
1128
1129// Tell the embedding application that the title of the active page has changed
1130void RenderView::UpdateTitle(WebFrame* frame, const std::wstring& title) {
1131 // Ignore all but top level navigations...
1132 if (webview()->GetMainFrame() == frame)
1133 Send(new ViewHostMsg_UpdateTitle(routing_id_, page_id_, title));
1134}
1135
1136void RenderView::UpdateEncoding(WebFrame* frame,
[email protected]e38f40152008-09-12 23:08:301137 const std::wstring& encoding_name) {
initial.commit09911bf2008-07-26 23:55:291138 // Only update main frame's encoding_name.
1139 if (webview()->GetMainFrame() == frame &&
1140 last_encoding_name_ != encoding_name) {
[email protected]e38f40152008-09-12 23:08:301141 // Save the encoding name for later comparing.
initial.commit09911bf2008-07-26 23:55:291142 last_encoding_name_ = encoding_name;
1143
[email protected]e38f40152008-09-12 23:08:301144 Send(new ViewHostMsg_UpdateEncoding(routing_id_, last_encoding_name_));
initial.commit09911bf2008-07-26 23:55:291145 }
1146}
1147
[email protected]f4d34b52008-11-24 23:05:011148// Sends the previous session history state to the browser so it will be saved
1149// before we navigate to a new page. This must be called *before* the page ID
1150// has been updated so we know what it was.
initial.commit09911bf2008-07-26 23:55:291151void RenderView::UpdateSessionHistory(WebFrame* frame) {
1152 // If we have a valid page ID at this point, then it corresponds to the page
1153 // we are navigating away from. Otherwise, this is the first navigation, so
1154 // there is no past session history to record.
1155 if (page_id_ == -1)
1156 return;
1157
initial.commit09911bf2008-07-26 23:55:291158 std::string state;
[email protected]606843fa2008-12-02 19:08:561159 if (!webview()->GetMainFrame()->GetPreviousHistoryState(&state))
initial.commit09911bf2008-07-26 23:55:291160 return;
[email protected]606843fa2008-12-02 19:08:561161 Send(new ViewHostMsg_UpdateState(routing_id_, page_id_, state));
initial.commit09911bf2008-07-26 23:55:291162}
1163
1164///////////////////////////////////////////////////////////////////////////////
1165// WebViewDelegate
1166
1167void RenderView::DidStartLoading(WebView* webview) {
1168 if (is_loading_) {
1169 DLOG(WARNING) << "DidStartLoading called while loading";
1170 return;
1171 }
1172
1173 is_loading_ = true;
1174 // Clear the pointer so that we can assign it only when there is an unknown
1175 // plugin on a page.
1176 first_default_plugin_ = NULL;
1177
1178 Send(new ViewHostMsg_DidStartLoading(routing_id_, page_id_));
1179}
1180
1181void RenderView::DidStopLoading(WebView* webview) {
1182 if (!is_loading_) {
1183 DLOG(WARNING) << "DidStopLoading called while not loading";
1184 return;
1185 }
1186
1187 is_loading_ = false;
1188
1189 // NOTE: For now we're doing the safest thing, and sending out notification
1190 // when done loading. This currently isn't an issue as the favicon is only
1191 // displayed when done loading. Ideally we would send notification when
1192 // finished parsing the head, but webkit doesn't support that yet.
1193 // The feed discovery code would also benefit from access to the head.
1194 GURL favicon_url(webview->GetMainFrame()->GetFavIconURL());
1195 if (!favicon_url.is_empty())
1196 Send(new ViewHostMsg_UpdateFavIconURL(routing_id_, page_id_, favicon_url));
1197
1198 AddGURLSearchProvider(webview->GetMainFrame()->GetOSDDURL(),
1199 true); // autodetected
1200
1201 Send(new ViewHostMsg_DidStopLoading(routing_id_, page_id_));
1202
1203 MessageLoop::current()->PostDelayedTask(FROM_HERE,
1204 method_factory_.NewRunnableMethod(&RenderView::CapturePageInfo, page_id_,
1205 false),
1206 kDelayForCaptureMs);
1207
1208 // The page is loaded. Try to process the file we need to upload if any.
1209 ProcessPendingUpload();
1210
1211 // Since the page is done loading, we are sure we don't need to try
1212 // again.
1213 ResetPendingUpload();
1214}
1215
1216void RenderView::DidStartProvisionalLoadForFrame(
1217 WebView* webview,
1218 WebFrame* frame,
1219 NavigationGesture gesture) {
[email protected]77e09a92008-08-01 18:11:041220 if (webview->GetMainFrame() == frame) {
initial.commit09911bf2008-07-26 23:55:291221 navigation_gesture_ = gesture;
[email protected]266eb6f2008-09-30 23:56:501222
[email protected]77e09a92008-08-01 18:11:041223 // Make sure redirect tracking state is clear for the new load.
1224 completed_client_redirect_src_ = GURL();
1225 }
initial.commit09911bf2008-07-26 23:55:291226
[email protected]c20210e62009-04-03 21:39:261227 WebDataSource* ds = frame->GetProvisionalDataSource();
1228 if (ds) {
1229 const WebRequest& req = ds->GetRequest();
1230 RenderViewExtraRequestData* extra_data =
1231 static_cast<RenderViewExtraRequestData*>(req.GetExtraData());
1232 if (extra_data) {
1233 ds->SetRequestTime(extra_data->request_time);
1234 }
1235 }
initial.commit09911bf2008-07-26 23:55:291236 Send(new ViewHostMsg_DidStartProvisionalLoadForFrame(
1237 routing_id_, webview->GetMainFrame() == frame,
1238 frame->GetProvisionalDataSource()->GetRequest().GetURL()));
1239}
1240
1241bool RenderView::DidLoadResourceFromMemoryCache(WebView* webview,
1242 const WebRequest& request,
1243 const WebResponse& response,
1244 WebFrame* frame) {
1245 // Let the browser know we loaded a resource from the memory cache. This
1246 // message is needed to display the correct SSL indicators.
1247 Send(new ViewHostMsg_DidLoadResourceFromMemoryCache(routing_id_,
[email protected]ffc45862009-03-17 06:11:081248 request.GetURL(), frame->GetSecurityOrigin(),
1249 frame->GetTop()->GetSecurityOrigin(),
1250 response.GetSecurityInfo()));
initial.commit09911bf2008-07-26 23:55:291251
1252 return false;
1253}
1254
1255void RenderView::DidReceiveProvisionalLoadServerRedirect(WebView* webview,
1256 WebFrame* frame) {
1257 if (frame == webview->GetMainFrame()) {
1258 // Received a redirect on the main frame.
1259 WebDataSource* data_source =
1260 webview->GetMainFrame()->GetProvisionalDataSource();
1261 if (!data_source) {
1262 // Should only be invoked when we have a data source.
1263 NOTREACHED();
1264 return;
1265 }
1266 const std::vector<GURL>& redirects = data_source->GetRedirectChain();
1267 if (redirects.size() >= 2) {
1268 Send(new ViewHostMsg_DidRedirectProvisionalLoad(
1269 routing_id_, page_id_, redirects[redirects.size() - 2],
1270 redirects[redirects.size() - 1]));
1271 }
1272 }
1273}
1274
1275void RenderView::DidFailProvisionalLoadWithError(WebView* webview,
1276 const WebError& error,
1277 WebFrame* frame) {
1278 // Notify the browser that we failed a provisional load with an error.
1279 //
1280 // Note: It is important this notification occur before DidStopLoading so the
1281 // SSL manager can react to the provisional load failure before being
1282 // notified the load stopped.
1283 //
1284 WebDataSource* ds = frame->GetProvisionalDataSource();
1285 DCHECK(ds);
1286
1287 const WebRequest& failed_request = ds->GetRequest();
1288
1289 bool show_repost_interstitial =
1290 (error.GetErrorCode() == net::ERR_CACHE_MISS &&
1291 LowerCaseEqualsASCII(failed_request.GetHttpMethod(), "post"));
1292 Send(new ViewHostMsg_DidFailProvisionalLoadWithError(
1293 routing_id_, frame == webview->GetMainFrame(),
1294 error.GetErrorCode(), error.GetFailedURL(),
1295 show_repost_interstitial));
1296
initial.commit09911bf2008-07-26 23:55:291297 // Don't display an error page if this is simply a cancelled load. Aside
1298 // from being dumb, WebCore doesn't expect it and it will cause a crash.
1299 if (error.GetErrorCode() == net::ERR_ABORTED)
1300 return;
1301
1302 // If this is a failed back/forward/reload navigation, then we need to do a
1303 // 'replace' load. This is necessary to avoid messing up session history.
1304 // Otherwise, we do a normal load, which simulates a 'go' navigation as far
1305 // as session history is concerned.
1306 RenderViewExtraRequestData* extra_data =
1307 static_cast<RenderViewExtraRequestData*>(failed_request.GetExtraData());
1308 bool replace = extra_data && !extra_data->is_new_navigation();
1309
[email protected]5df266ac2008-10-15 19:50:131310 // Use the alternate error page service if this is a DNS failure or
1311 // connection failure. ERR_CONNECTION_FAILED can be dropped once we no longer
1312 // use winhttp.
1313 int ec = error.GetErrorCode();
1314 if (ec == net::ERR_NAME_NOT_RESOLVED ||
1315 ec == net::ERR_CONNECTION_FAILED ||
1316 ec == net::ERR_CONNECTION_REFUSED ||
1317 ec == net::ERR_ADDRESS_UNREACHABLE ||
1318 ec == net::ERR_TIMED_OUT) {
1319 const GURL& failed_url = error.GetFailedURL();
1320 const GURL& error_page_url = GetAlternateErrorPageURL(failed_url,
1321 ec == net::ERR_NAME_NOT_RESOLVED ? WebViewDelegate::DNS_ERROR
1322 : WebViewDelegate::CONNECTION_ERROR);
1323 if (error_page_url.is_valid()) {
1324 // Ask the WebFrame to fetch the alternate error page for us.
1325 frame->LoadAlternateHTMLErrorPage(&failed_request, error, error_page_url,
1326 replace, GURL(kUnreachableWebDataURL));
1327 return;
1328 }
initial.commit09911bf2008-07-26 23:55:291329 }
[email protected]5df266ac2008-10-15 19:50:131330
[email protected]be645db2009-02-06 20:36:331331 // Fallback to a local error page.
[email protected]5df266ac2008-10-15 19:50:131332 LoadNavigationErrorPage(frame, &failed_request, error, std::string(),
1333 replace);
initial.commit09911bf2008-07-26 23:55:291334}
1335
1336void RenderView::LoadNavigationErrorPage(WebFrame* frame,
1337 const WebRequest* failed_request,
1338 const WebError& error,
1339 const std::string& html,
1340 bool replace) {
1341 const GURL& failed_url = error.GetFailedURL();
1342
1343 std::string alt_html;
1344 if (html.empty()) {
1345 // Use a local error page.
1346 int resource_id;
1347 DictionaryValue error_strings;
1348 if (error.GetErrorCode() == net::ERR_CACHE_MISS &&
1349 LowerCaseEqualsASCII(failed_request->GetHttpMethod(), "post")) {
1350 GetFormRepostErrorValues(failed_url, &error_strings);
1351 resource_id = IDR_ERROR_NO_DETAILS_HTML;
1352 } else {
1353 GetLocalizedErrorValues(error, &error_strings);
1354 resource_id = IDR_NET_ERROR_HTML;
1355 }
[email protected]8e50b602009-03-03 22:59:431356 error_strings.SetString(L"textdirection",
1357 (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) ?
1358 L"rtl" : L"ltr");
initial.commit09911bf2008-07-26 23:55:291359
1360 alt_html = GetAltHTMLForTemplate(error_strings, resource_id);
1361 } else {
1362 alt_html = html;
1363 }
1364
1365 // Use a data: URL as the site URL to prevent against XSS attacks.
1366 scoped_ptr<WebRequest> request(failed_request->Clone());
1367 request->SetURL(GURL(kUnreachableWebDataURL));
1368
1369 frame->LoadAlternateHTMLString(request.get(), alt_html, failed_url,
1370 replace);
1371}
1372
1373void RenderView::DidCommitLoadForFrame(WebView *webview, WebFrame* frame,
1374 bool is_new_navigation) {
1375 const WebRequest& request =
1376 webview->GetMainFrame()->GetDataSource()->GetRequest();
1377 RenderViewExtraRequestData* extra_data =
1378 static_cast<RenderViewExtraRequestData*>(request.GetExtraData());
1379
1380 if (is_new_navigation) {
1381 // When we perform a new navigation, we need to update the previous session
1382 // history entry with state for the page we are leaving.
1383 UpdateSessionHistory(frame);
1384
1385 // We bump our Page ID to correspond with the new session history entry.
1386 page_id_ = next_page_id_++;
1387
1388 MessageLoop::current()->PostDelayedTask(FROM_HERE,
1389 method_factory_.NewRunnableMethod(&RenderView::CapturePageInfo,
1390 page_id_, true),
1391 kDelayForForcedCaptureMs);
1392 } else {
1393 // Inspect the extra_data on the main frame (set in our Navigate method) to
1394 // see if the navigation corresponds to a session history navigation...
1395 // Note: |frame| may or may not be the toplevel frame, but for the case
1396 // of capturing session history, the first committed frame suffices. We
1397 // keep track of whether we've seen this commit before so that only capture
1398 // session history once per navigation.
[email protected]f4d34b52008-11-24 23:05:011399 //
1400 // Note that we need to check if the page ID changed. In the case of a
1401 // reload, the page ID doesn't change, and UpdateSessionHistory gets the
1402 // previous URL and the current page ID, which would be wrong.
initial.commit09911bf2008-07-26 23:55:291403 if (extra_data && !extra_data->is_new_navigation() &&
[email protected]f4d34b52008-11-24 23:05:011404 !extra_data->request_committed &&
1405 page_id_ != extra_data->pending_page_id()) {
initial.commit09911bf2008-07-26 23:55:291406 // This is a successful session history navigation!
1407 UpdateSessionHistory(frame);
initial.commit09911bf2008-07-26 23:55:291408 page_id_ = extra_data->pending_page_id();
1409 }
1410 }
1411
1412 // Remember that we've already processed this request, so we don't update
1413 // the session history again. We do this regardless of whether this is
1414 // a session history navigation, because if we attempted a session history
1415 // navigation without valid HistoryItem state, WebCore will think it is a
1416 // new navigation.
1417 if (extra_data)
1418 extra_data->request_committed = true;
1419
1420 UpdateURL(frame);
1421
1422 // If this committed load was initiated by a client redirect, we're
1423 // at the last stop now, so clear it.
1424 completed_client_redirect_src_ = GURL();
1425
1426 // Check whether we have new encoding name.
1427 UpdateEncoding(frame, webview->GetMainFrameEncodingName());
1428}
1429
1430void RenderView::DidReceiveTitle(WebView* webview,
1431 const std::wstring& title,
1432 WebFrame* frame) {
1433 UpdateTitle(frame, title);
1434
1435 // Also check whether we have new encoding name.
1436 UpdateEncoding(frame, webview->GetMainFrameEncodingName());
1437}
1438
1439void RenderView::DidFinishLoadForFrame(WebView* webview, WebFrame* frame) {
[email protected]c20210e62009-04-03 21:39:261440 if (webview->GetMainFrame() == frame) {
1441 const GURL& url = frame->GetURL();
1442 if (url.SchemeIs("http") || url.SchemeIs("https"))
1443 DumpLoadHistograms();
1444 }
initial.commit09911bf2008-07-26 23:55:291445}
1446
1447void RenderView::DidFailLoadWithError(WebView* webview,
1448 const WebError& error,
1449 WebFrame* frame) {
1450}
1451
1452void RenderView::DidFinishDocumentLoadForFrame(WebView* webview,
1453 WebFrame* frame) {
1454 // Check whether we have new encoding name.
1455 UpdateEncoding(frame, webview->GetMainFrameEncodingName());
[email protected]1e0f70402008-10-16 23:57:471456
[email protected]8930d472009-02-21 08:05:281457 if (RenderThread::current()) // Will be NULL during unit tests.
1458 RenderThread::current()->user_script_slave()->InjectScripts(
[email protected]0afe8272009-02-14 04:15:161459 frame, UserScript::DOCUMENT_END);
initial.commit09911bf2008-07-26 23:55:291460}
1461
1462void RenderView::DidHandleOnloadEventsForFrame(WebView* webview,
1463 WebFrame* frame) {
1464}
1465
1466void RenderView::DidChangeLocationWithinPageForFrame(WebView* webview,
1467 WebFrame* frame,
1468 bool is_new_navigation) {
1469 DidCommitLoadForFrame(webview, frame, is_new_navigation);
[email protected]9d806f52009-03-12 22:50:541470 const string16& title =
[email protected]de56f3782008-10-01 22:31:351471 webview->GetMainFrame()->GetDataSource()->GetPageTitle();
[email protected]9d806f52009-03-12 22:50:541472 UpdateTitle(frame, UTF16ToWideHack(title));
initial.commit09911bf2008-07-26 23:55:291473}
1474
1475void RenderView::DidReceiveIconForFrame(WebView* webview,
1476 WebFrame* frame) {
1477}
1478
1479void RenderView::WillPerformClientRedirect(WebView* webview,
1480 WebFrame* frame,
1481 const GURL& src_url,
1482 const GURL& dest_url,
1483 unsigned int delay_seconds,
1484 unsigned int fire_date) {
1485}
1486
1487void RenderView::DidCancelClientRedirect(WebView* webview,
1488 WebFrame* frame) {
1489}
1490
[email protected]309d7a282009-03-24 09:18:271491void RenderView::WillCloseFrame(WebView* view, WebFrame* frame) {
1492 // Remove all the pending extension callbacks for this frame.
1493 if (pending_extension_callbacks_.IsEmpty())
1494 return;
1495
1496 std::vector<int> orphaned_callbacks;
1497 for (IDMap<WebFrame>::const_iterator iter =
1498 pending_extension_callbacks_.begin();
1499 iter != pending_extension_callbacks_.end(); ++iter) {
1500 if (iter->second == frame)
1501 orphaned_callbacks.push_back(iter->first);
1502 }
1503
1504 for (std::vector<int>::const_iterator iter = orphaned_callbacks.begin();
1505 iter != orphaned_callbacks.end(); ++iter) {
1506 pending_extension_callbacks_.Remove(*iter);
1507 }
1508}
1509
initial.commit09911bf2008-07-26 23:55:291510void RenderView::DidCompleteClientRedirect(WebView* webview,
1511 WebFrame* frame,
1512 const GURL& source) {
1513 if (webview->GetMainFrame() == frame)
1514 completed_client_redirect_src_ = source;
1515}
1516
[email protected]5b35a6b2009-03-16 19:58:081517void RenderView::WillSendRequest(WebView* webview,
1518 uint32 identifier,
1519 WebRequest* request) {
1520 request->SetRequestorID(routing_id_);
1521}
1522
initial.commit09911bf2008-07-26 23:55:291523void RenderView::BindDOMAutomationController(WebFrame* webframe) {
1524 dom_automation_controller_.set_message_sender(this);
1525 dom_automation_controller_.set_routing_id(routing_id_);
1526 dom_automation_controller_.BindToJavascript(webframe,
1527 L"domAutomationController");
1528}
1529
1530void RenderView::WindowObjectCleared(WebFrame* webframe) {
1531 external_js_object_.set_render_view(this);
1532 external_js_object_.BindToJavascript(webframe, L"external");
[email protected]81e63782009-02-27 19:35:091533 if (BindingsPolicy::is_dom_automation_enabled(enabled_bindings_))
initial.commit09911bf2008-07-26 23:55:291534 BindDOMAutomationController(webframe);
[email protected]81e63782009-02-27 19:35:091535 if (BindingsPolicy::is_dom_ui_enabled(enabled_bindings_)) {
initial.commit09911bf2008-07-26 23:55:291536 dom_ui_bindings_.set_message_sender(this);
1537 dom_ui_bindings_.set_routing_id(routing_id_);
1538 dom_ui_bindings_.BindToJavascript(webframe, L"chrome");
1539 }
[email protected]81e63782009-02-27 19:35:091540 if (BindingsPolicy::is_external_host_enabled(enabled_bindings_)) {
[email protected]18cb2572008-08-21 20:34:451541 external_host_bindings_.set_message_sender(this);
1542 external_host_bindings_.set_routing_id(routing_id_);
1543 external_host_bindings_.BindToJavascript(webframe, L"externalHost");
1544 }
[email protected]9a2051d2008-08-15 20:12:421545
[email protected]3a453fa2008-08-15 18:46:341546#ifdef CHROME_PERSONALIZATION
1547 Personalization::ConfigureRendererPersonalization(personalization_, this,
1548 routing_id_, webframe);
1549#endif
initial.commit09911bf2008-07-26 23:55:291550}
1551
[email protected]0afe8272009-02-14 04:15:161552void RenderView::DocumentElementAvailable(WebFrame* frame) {
[email protected]d959ce22009-04-15 21:03:421553 if (frame->GetURL().SchemeIs(chrome::kExtensionScheme))
1554 frame->AllowCrossOriginAccessHack();
1555
[email protected]8930d472009-02-21 08:05:281556 if (RenderThread::current()) // Will be NULL during unit tests.
1557 RenderThread::current()->user_script_slave()->InjectScripts(
[email protected]0afe8272009-02-14 04:15:161558 frame, UserScript::DOCUMENT_START);
1559}
1560
initial.commit09911bf2008-07-26 23:55:291561WindowOpenDisposition RenderView::DispositionForNavigationAction(
1562 WebView* webview,
1563 WebFrame* frame,
1564 const WebRequest* request,
1565 WebNavigationType type,
1566 WindowOpenDisposition disposition,
1567 bool is_redirect) {
1568 // Webkit is asking whether to navigate to a new URL.
1569 // This is fine normally, except if we're showing UI from one security
1570 // context and they're trying to navigate to a different context.
1571 const GURL& url = request->GetURL();
1572 // We only care about navigations that are within the current tab (as opposed
1573 // to, for example, opening a new window).
1574 // But we sometimes navigate to about:blank to clear a tab, and we want to
1575 // still allow that.
[email protected]6de74452009-02-25 18:04:591576 if (disposition == CURRENT_TAB && !(url.SchemeIs(chrome::kAboutScheme))) {
initial.commit09911bf2008-07-26 23:55:291577 // GetExtraData is NULL when we did not issue the request ourselves (see
1578 // OnNavigate), and so such a request may correspond to a link-click,
1579 // script, or drag-n-drop initiated navigation.
1580 if (frame == webview->GetMainFrame() && !request->GetExtraData()) {
1581 // When we received such unsolicited navigations, we sometimes want to
1582 // punt them up to the browser to handle.
[email protected]81e63782009-02-27 19:35:091583 if (BindingsPolicy::is_dom_ui_enabled(enabled_bindings_) ||
initial.commit09911bf2008-07-26 23:55:291584 frame->GetInViewSourceMode() ||
[email protected]6de74452009-02-25 18:04:591585 url.SchemeIs(chrome::kViewSourceScheme)) {
[email protected]c0588052008-10-27 23:01:501586 OpenURL(webview, url, GURL(), disposition);
initial.commit09911bf2008-07-26 23:55:291587 return IGNORE_ACTION; // Suppress the load here.
[email protected]50b691c2008-10-31 19:08:351588 } else if (url.SchemeIs(kBackForwardNavigationScheme)) {
1589 std::string offset_str = url.ExtractFileName();
1590 int offset;
1591 if (StringToInt(offset_str, &offset)) {
[email protected]0c0383772008-11-04 00:48:311592 GoToEntryAtOffset(offset);
[email protected]50b691c2008-10-31 19:08:351593 return IGNORE_ACTION; // The browser process handles this one.
1594 }
initial.commit09911bf2008-07-26 23:55:291595 }
1596 }
1597 }
1598
1599 // Detect when a page is "forking" a new tab that can be safely rendered in
1600 // its own process. This is done by sites like Gmail that try to open links
1601 // in new windows without script connections back to the original page. We
1602 // treat such cases as browser navigations (in which we will create a new
1603 // renderer for a cross-site navigation), rather than WebKit navigations.
1604 //
1605 // We use the following heuristic to decide whether to fork a new page in its
1606 // own process:
1607 // The parent page must open a new tab to about:blank, set the new tab's
1608 // window.opener to null, and then redirect the tab to a cross-site URL using
1609 // JavaScript.
1610 bool is_fork =
1611 // Must start from a tab showing about:blank, which is later redirected.
[email protected]6aad4bd2009-02-26 22:55:171612 frame->GetURL() == GURL("about:blank") &&
initial.commit09911bf2008-07-26 23:55:291613 // Must be the first real navigation of the tab.
1614 GetHistoryBackListCount() < 1 &&
1615 GetHistoryForwardListCount() < 1 &&
1616 // The parent page must have set the child's window.opener to null before
1617 // redirecting to the desired URL.
1618 frame->GetOpener() == NULL &&
1619 // Must be a top-level frame.
1620 frame->GetParent() == NULL &&
1621 // Must not have issued the request from this page. GetExtraData is NULL
1622 // when the navigation is being done by something outside the page.
1623 !request->GetExtraData() &&
1624 // Must be targeted at the current tab.
1625 disposition == CURRENT_TAB &&
1626 // Must be a JavaScript navigation, which appears as "other".
1627 type == WebNavigationTypeOther;
1628 if (is_fork) {
1629 // Open the URL via the browser, not via WebKit.
[email protected]c0588052008-10-27 23:01:501630 OpenURL(webview, url, GURL(), disposition);
initial.commit09911bf2008-07-26 23:55:291631 return IGNORE_ACTION;
1632 }
1633
1634 return disposition;
1635}
1636
[email protected]a455d3812009-03-05 20:18:071637void RenderView::RunJavaScriptAlert(WebFrame* webframe,
initial.commit09911bf2008-07-26 23:55:291638 const std::wstring& message) {
[email protected]2e4bdcdc2009-03-27 23:07:301639 RunJavaScriptMessage(MessageBox::kIsJavascriptAlert,
initial.commit09911bf2008-07-26 23:55:291640 message,
1641 std::wstring(),
[email protected]a455d3812009-03-05 20:18:071642 webframe->GetURL(),
initial.commit09911bf2008-07-26 23:55:291643 NULL);
1644}
1645
[email protected]a455d3812009-03-05 20:18:071646bool RenderView::RunJavaScriptConfirm(WebFrame* webframe,
initial.commit09911bf2008-07-26 23:55:291647 const std::wstring& message) {
[email protected]2e4bdcdc2009-03-27 23:07:301648 return RunJavaScriptMessage(MessageBox::kIsJavascriptConfirm,
initial.commit09911bf2008-07-26 23:55:291649 message,
1650 std::wstring(),
[email protected]a455d3812009-03-05 20:18:071651 webframe->GetURL(),
initial.commit09911bf2008-07-26 23:55:291652 NULL);
1653}
1654
[email protected]a455d3812009-03-05 20:18:071655bool RenderView::RunJavaScriptPrompt(WebFrame* webframe,
initial.commit09911bf2008-07-26 23:55:291656 const std::wstring& message,
1657 const std::wstring& default_value,
1658 std::wstring* result) {
[email protected]2e4bdcdc2009-03-27 23:07:301659 return RunJavaScriptMessage(MessageBox::kIsJavascriptPrompt,
initial.commit09911bf2008-07-26 23:55:291660 message,
1661 default_value,
[email protected]a455d3812009-03-05 20:18:071662 webframe->GetURL(),
initial.commit09911bf2008-07-26 23:55:291663 result);
1664}
1665
1666bool RenderView::RunJavaScriptMessage(int type,
1667 const std::wstring& message,
1668 const std::wstring& default_value,
[email protected]a455d3812009-03-05 20:18:071669 const GURL& frame_url,
initial.commit09911bf2008-07-26 23:55:291670 std::wstring* result) {
1671 bool success = false;
1672 std::wstring result_temp;
1673 if (!result)
1674 result = &result_temp;
1675 IPC::SyncMessage* msg = new ViewHostMsg_RunJavaScriptMessage(
[email protected]a455d3812009-03-05 20:18:071676 routing_id_, message, default_value, frame_url, type, &success, result);
initial.commit09911bf2008-07-26 23:55:291677
[email protected]1c4947f2009-01-15 22:25:111678 msg->set_pump_messages_event(modal_dialog_event_.get());
initial.commit09911bf2008-07-26 23:55:291679 Send(msg);
1680
1681 return success;
1682}
1683
1684void RenderView::AddGURLSearchProvider(const GURL& osd_url, bool autodetected) {
1685 if (!osd_url.is_empty())
1686 Send(new ViewHostMsg_PageHasOSDD(routing_id_, page_id_, osd_url,
1687 autodetected));
1688}
1689
[email protected]4604d1f42009-03-13 21:52:321690void RenderView::UpdateFeedList(scoped_refptr<FeedList> feedlist) {
1691 ViewHostMsg_UpdateFeedList_Params params;
1692 params.page_id = page_id_;
1693 params.feedlist = feedlist;
1694 Send(new ViewHostMsg_UpdateFeedList(routing_id_, params));
1695}
1696
[email protected]a455d3812009-03-05 20:18:071697bool RenderView::RunBeforeUnloadConfirm(WebFrame* webframe,
initial.commit09911bf2008-07-26 23:55:291698 const std::wstring& message) {
1699 bool success = false;
1700 // This is an ignored return value, but is included so we can accept the same
1701 // response as RunJavaScriptMessage.
1702 std::wstring ignored_result;
1703 IPC::SyncMessage* msg = new ViewHostMsg_RunBeforeUnloadConfirm(
[email protected]a455d3812009-03-05 20:18:071704 routing_id_, webframe->GetURL(), message, &success, &ignored_result);
initial.commit09911bf2008-07-26 23:55:291705
[email protected]1c4947f2009-01-15 22:25:111706 msg->set_pump_messages_event(modal_dialog_event_.get());
initial.commit09911bf2008-07-26 23:55:291707 Send(msg);
1708
1709 return success;
1710}
1711
[email protected]0578a502008-11-10 19:34:431712void RenderView::EnableSuddenTermination() {
1713 Send(new ViewHostMsg_UnloadListenerChanged(routing_id_, false));
1714}
1715
1716void RenderView::DisableSuddenTermination() {
1717 Send(new ViewHostMsg_UnloadListenerChanged(routing_id_, true));
initial.commit09911bf2008-07-26 23:55:291718}
1719
[email protected]0ebf3872008-11-07 21:35:031720void RenderView::QueryFormFieldAutofill(const std::wstring& field_name,
1721 const std::wstring& text,
1722 int64 node_id) {
1723 static int message_id_counter = 0;
1724 form_field_autofill_request_id_ = message_id_counter++;
1725 Send(new ViewHostMsg_QueryFormFieldAutofill(routing_id_,
1726 field_name, text,
1727 node_id,
1728 form_field_autofill_request_id_));
1729}
1730
[email protected]4d2b6fb2009-03-20 22:28:171731void RenderView::RemoveStoredAutofillEntry(const std::wstring& name,
1732 const std::wstring& value) {
1733 Send(new ViewHostMsg_RemoveAutofillEntry(routing_id_, name, value));
1734}
1735
[email protected]0ebf3872008-11-07 21:35:031736void RenderView::OnReceivedAutofillSuggestions(
1737 int64 node_id,
1738 int request_id,
[email protected]8d0f15c2008-11-11 01:01:091739 const std::vector<std::wstring>& suggestions,
[email protected]0ebf3872008-11-07 21:35:031740 int default_suggestion_index) {
1741 if (!webview() || request_id != form_field_autofill_request_id_)
1742 return;
1743
1744 webview()->AutofillSuggestionsForNode(node_id, suggestions,
1745 default_suggestion_index);
1746}
1747
[email protected]634a6f92008-12-01 21:39:311748void RenderView::OnPopupNotificationVisiblityChanged(bool visible) {
1749 popup_notification_visible_ = visible;
1750}
1751
initial.commit09911bf2008-07-26 23:55:291752void RenderView::ShowModalHTMLDialog(const GURL& url, int width, int height,
1753 const std::string& json_arguments,
1754 std::string* json_retval) {
1755 IPC::SyncMessage* msg = new ViewHostMsg_ShowModalHTMLDialog(
1756 routing_id_, url, width, height, json_arguments, json_retval);
1757
[email protected]1c4947f2009-01-15 22:25:111758 msg->set_pump_messages_event(modal_dialog_event_.get());
initial.commit09911bf2008-07-26 23:55:291759 Send(msg);
1760}
1761
1762uint32 RenderView::GetCPBrowsingContext() {
1763 uint32 context = 0;
1764 Send(new ViewHostMsg_GetCPBrowsingContext(&context));
1765 return context;
1766}
1767
1768// Tell the browser to display a destination link.
1769void RenderView::UpdateTargetURL(WebView* webview, const GURL& url) {
1770 if (url != target_url_) {
1771 if (target_url_status_ == TARGET_INFLIGHT ||
1772 target_url_status_ == TARGET_PENDING) {
1773 // If we have a request in-flight, save the URL to be sent when we
1774 // receive an ACK to the in-flight request. We can happily overwrite
1775 // any existing pending sends.
1776 pending_target_url_ = url;
1777 target_url_status_ = TARGET_PENDING;
1778 } else {
1779 Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_, url));
1780 target_url_ = url;
1781 target_url_status_ = TARGET_INFLIGHT;
1782 }
1783 }
1784}
1785
[email protected]b62d1a8c2009-01-13 23:54:571786void RenderView::RunFileChooser(bool multi_select,
[email protected]b949f1112009-04-12 20:03:081787 const string16& title,
1788 const FilePath& default_filename,
initial.commit09911bf2008-07-26 23:55:291789 WebFileChooserCallback* file_chooser) {
1790 if (file_chooser_.get()) {
1791 // TODO(brettw): bug 1235154: This should be a synchronous message to deal
1792 // with the fact that web pages can programatically trigger this. With the
1793 // asnychronous messages, we can get an additional call when one is pending,
1794 // which this test is for. For now, we just ignore the additional file
1795 // chooser request. WebKit doesn't do anything to expect the callback, so
1796 // we can just ignore calling it.
1797 delete file_chooser;
1798 return;
1799 }
1800 file_chooser_.reset(file_chooser);
[email protected]b62d1a8c2009-01-13 23:54:571801 Send(new ViewHostMsg_RunFileChooser(routing_id_, multi_select, title,
[email protected]b949f1112009-04-12 20:03:081802 default_filename));
initial.commit09911bf2008-07-26 23:55:291803}
1804
1805void RenderView::AddMessageToConsole(WebView* webview,
1806 const std::wstring& message,
1807 unsigned int line_no,
1808 const std::wstring& source_id) {
1809 Send(new ViewHostMsg_AddMessageToConsole(routing_id_, message,
1810 static_cast<int32>(line_no),
1811 source_id));
1812}
1813
1814void RenderView::AddSearchProvider(const std::string& url) {
1815 AddGURLSearchProvider(GURL(url),
1816 false); // not autodetected
1817}
1818
1819void RenderView::DebuggerOutput(const std::wstring& out) {
1820 Send(new ViewHostMsg_DebuggerOutput(routing_id_, out));
1821}
1822
1823WebView* RenderView::CreateWebView(WebView* webview, bool user_gesture) {
[email protected]0aa55312008-10-17 21:53:081824 // Check to make sure we aren't overloading on popups.
1825 if (shared_popup_counter_->data > kMaximumNumberOfUnacknowledgedPopups)
1826 return NULL;
1827
[email protected]634a6f92008-12-01 21:39:311828 // This window can't be closed from a window.close() call until we receive a
1829 // message from the Browser process explicitly allowing it.
1830 popup_notification_visible_ = true;
1831
initial.commit09911bf2008-07-26 23:55:291832 int32 routing_id = MSG_ROUTING_NONE;
[email protected]6c8afae52009-01-22 02:24:571833
[email protected]18bcc3c2009-01-27 21:39:151834 ModalDialogEvent modal_dialog_event;
[email protected]6c8afae52009-01-22 02:24:571835 render_thread_->Send(
[email protected]15787f8f2008-10-17 15:29:031836 new ViewHostMsg_CreateWindow(routing_id_, user_gesture, &routing_id,
1837 &modal_dialog_event));
initial.commit09911bf2008-07-26 23:55:291838 if (routing_id == MSG_ROUTING_NONE) {
initial.commit09911bf2008-07-26 23:55:291839 return NULL;
1840 }
1841
1842 // The WebView holds a reference to this new RenderView
1843 const WebPreferences& prefs = webview->GetPreferences();
[email protected]6c8afae52009-01-22 02:24:571844 base::WaitableEvent* waitable_event = new base::WaitableEvent
1845#if defined(OS_WIN)
[email protected]18bcc3c2009-01-27 21:39:151846 (modal_dialog_event.event);
[email protected]6c8afae52009-01-22 02:24:571847#else
1848 (true, false);
1849#endif
[email protected]81a34412009-01-05 19:17:241850 RenderView* view = RenderView::Create(render_thread_,
[email protected]1c4947f2009-01-15 22:25:111851 NULL, waitable_event, routing_id_,
[email protected]0aa55312008-10-17 21:53:081852 prefs, shared_popup_counter_,
1853 routing_id);
initial.commit09911bf2008-07-26 23:55:291854 view->set_opened_by_user_gesture(user_gesture);
1855
1856 // Copy over the alternate error page URL so we can have alt error pages in
1857 // the new render view (we don't need the browser to send the URL back down).
1858 view->alternate_error_page_url_ = alternate_error_page_url_;
1859
1860 return view->webview();
1861}
1862
[email protected]0ebf3872008-11-07 21:35:031863WebWidget* RenderView::CreatePopupWidget(WebView* webview,
[email protected]cfd727f2009-01-09 20:21:111864 bool activatable) {
[email protected]8085dbc82008-09-26 22:53:441865 RenderWidget* widget = RenderWidget::Create(routing_id_,
[email protected]81a34412009-01-05 19:17:241866 render_thread_,
[email protected]cfd727f2009-01-09 20:21:111867 activatable);
initial.commit09911bf2008-07-26 23:55:291868 return widget->webwidget();
1869}
1870
1871WebPluginDelegate* RenderView::CreatePluginDelegate(
1872 WebView* webview,
1873 const GURL& url,
1874 const std::string& mime_type,
1875 const std::string& clsid,
1876 std::string* actual_mime_type) {
[email protected]6c8afae52009-01-22 02:24:571877#if defined(OS_WIN)
[email protected]88a1fb47a2009-03-13 00:18:061878 if (RenderProcess::current()->in_process_plugins()) {
[email protected]690a99c2009-01-06 16:48:451879 FilePath path;
[email protected]81a34412009-01-05 19:17:241880 render_thread_->Send(
initial.commit09911bf2008-07-26 23:55:291881 new ViewHostMsg_GetPluginPath(url, mime_type, clsid, &path,
1882 actual_mime_type));
[email protected]690a99c2009-01-06 16:48:451883 if (path.value().empty())
initial.commit09911bf2008-07-26 23:55:291884 return NULL;
1885
1886 std::string mime_type_to_use;
1887 if (actual_mime_type && !actual_mime_type->empty())
1888 mime_type_to_use = *actual_mime_type;
1889 else
1890 mime_type_to_use = mime_type;
1891
[email protected]b94d3322009-02-12 19:49:041892 return WebPluginDelegate::Create(path,
1893 mime_type_to_use,
1894 gfx::NativeViewFromId(host_window_));
initial.commit09911bf2008-07-26 23:55:291895 }
1896
1897 WebPluginDelegateProxy* proxy =
1898 WebPluginDelegateProxy::Create(url, mime_type, clsid, this);
1899 if (!proxy)
1900 return NULL;
1901
1902 // We hold onto the proxy so we can poke it when we are painting. See our
1903 // DidPaint implementation below.
1904 plugin_delegates_.push_back(proxy);
1905
1906 return proxy;
[email protected]6c8afae52009-01-22 02:24:571907#else
1908 // TODO(port): Plugins currently not supported
1909 NOTIMPLEMENTED();
1910 return NULL;
1911#endif
initial.commit09911bf2008-07-26 23:55:291912}
1913
[email protected]ec9212f2008-12-18 21:40:361914webkit_glue::WebMediaPlayerDelegate* RenderView::CreateMediaPlayerDelegate() {
[email protected]be645db2009-02-06 20:36:331915#if defined(OS_WIN)
[email protected]d43ed912009-02-03 04:52:531916 return new WebMediaPlayerDelegateImpl(this);
[email protected]be645db2009-02-06 20:36:331917#else
1918 // TODO(port)
1919 NOTIMPLEMENTED();
1920 return NULL;
1921#endif
[email protected]ec9212f2008-12-18 21:40:361922}
1923
initial.commit09911bf2008-07-26 23:55:291924void RenderView::OnMissingPluginStatus(WebPluginDelegate* delegate,
1925 int status) {
[email protected]6c8afae52009-01-22 02:24:571926#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:291927 if (first_default_plugin_ == NULL) {
1928 // Show the InfoBar for the first available plugin.
1929 if (status == default_plugin::MISSING_PLUGIN_AVAILABLE) {
1930 first_default_plugin_ = delegate;
1931 Send(new ViewHostMsg_MissingPluginStatus(routing_id_, status));
1932 }
1933 } else {
1934 // Closes the InfoBar if user clicks on the plugin (instead of the InfoBar)
1935 // to start the download/install.
1936 if (status == default_plugin::MISSING_PLUGIN_USER_STARTED_DOWNLOAD) {
1937 Send(new ViewHostMsg_MissingPluginStatus(routing_id_, status));
1938 }
1939 }
[email protected]6c8afae52009-01-22 02:24:571940#else
1941 // TODO(port): plugins current not supported
1942 NOTIMPLEMENTED();
1943#endif
initial.commit09911bf2008-07-26 23:55:291944}
1945
[email protected]eb47a132009-03-04 00:39:561946WebWorker* RenderView::CreateWebWorker(WebWorkerClient* client) {
1947#if defined(OS_WIN)
[email protected]fd0995032009-03-24 02:01:111948 return new WebWorkerProxy(client, routing_id_);
[email protected]eb47a132009-03-04 00:39:561949#else
1950 // TODO(port): out of process workers
1951 NOTIMPLEMENTED();
1952 return NULL;
1953#endif
1954}
1955
initial.commit09911bf2008-07-26 23:55:291956void RenderView::OpenURL(WebView* webview, const GURL& url,
[email protected]c0588052008-10-27 23:01:501957 const GURL& referrer,
initial.commit09911bf2008-07-26 23:55:291958 WindowOpenDisposition disposition) {
[email protected]c0588052008-10-27 23:01:501959 Send(new ViewHostMsg_OpenURL(routing_id_, url, referrer, disposition));
initial.commit09911bf2008-07-26 23:55:291960}
1961
[email protected]1d522202009-04-04 01:56:421962void RenderView::DidContentsSizeChange(WebWidget* webwidget,
1963 int new_width,
1964 int new_height) {
1965 // TODO(rafaelw): This is a temporary solution. Only the ExtensionView wants
1966 // this notification at the moment. It isn't clean to test for ExtensionView
1967 // by examining the enabled_bindings. This needs to be generalized as it
1968 // becomes clear what extension toolbars need.
1969 if (BindingsPolicy::is_extension_enabled(enabled_bindings_)) {
1970 int width = webview()->GetMainFrame()->GetContentsPreferredWidth();
1971 Send(new ViewHostMsg_DidContentsPreferredWidthChange(routing_id_, width));
1972 }
1973}
1974
initial.commit09911bf2008-07-26 23:55:291975// We are supposed to get a single call to Show for a newly created RenderView
1976// that was created via RenderView::CreateWebView. So, we wait until this
1977// point to dispatch the ShowView message.
1978//
1979// This method provides us with the information about how to display the newly
1980// created RenderView (i.e., as a constrained popup or as a new tab).
1981//
1982void RenderView::Show(WebWidget* webwidget, WindowOpenDisposition disposition) {
1983 DCHECK(!did_show_) << "received extraneous Show call";
1984 DCHECK(opener_id_ != MSG_ROUTING_NONE);
1985
1986 if (did_show_)
1987 return;
1988 did_show_ = true;
1989
1990 // NOTE: initial_pos_ may still have its default values at this point, but
1991 // that's okay. It'll be ignored if disposition is not NEW_POPUP, or the
1992 // browser process will impose a default position otherwise.
1993 Send(new ViewHostMsg_ShowView(
1994 opener_id_, routing_id_, disposition, initial_pos_,
1995 WasOpenedByUserGestureHelper()));
1996}
1997
[email protected]634a6f92008-12-01 21:39:311998void RenderView::CloseWidgetSoon(WebWidget* webwidget) {
1999 if (popup_notification_visible_ == false)
2000 RenderWidget::CloseWidgetSoon(webwidget);
2001}
2002
initial.commit09911bf2008-07-26 23:55:292003void RenderView::RunModal(WebWidget* webwidget) {
2004 DCHECK(did_show_) << "should already have shown the view";
2005
2006 IPC::SyncMessage* msg = new ViewHostMsg_RunModal(routing_id_);
2007
[email protected]1c4947f2009-01-15 22:25:112008 msg->set_pump_messages_event(modal_dialog_event_.get());
initial.commit09911bf2008-07-26 23:55:292009 Send(msg);
2010}
2011
2012void RenderView::SyncNavigationState() {
2013 if (!webview())
2014 return;
2015
initial.commit09911bf2008-07-26 23:55:292016 std::string state;
[email protected]606843fa2008-12-02 19:08:562017 if (!webview()->GetMainFrame()->GetCurrentHistoryState(&state))
initial.commit09911bf2008-07-26 23:55:292018 return;
[email protected]606843fa2008-12-02 19:08:562019 Send(new ViewHostMsg_UpdateState(routing_id_, page_id_, state));
initial.commit09911bf2008-07-26 23:55:292020}
2021
2022void RenderView::ShowContextMenu(WebView* webview,
[email protected]124646932009-01-28 18:39:022023 ContextNode node,
initial.commit09911bf2008-07-26 23:55:292024 int x,
2025 int y,
2026 const GURL& link_url,
2027 const GURL& image_url,
2028 const GURL& page_url,
2029 const GURL& frame_url,
2030 const std::wstring& selection_text,
2031 const std::wstring& misspelled_word,
[email protected]6aa376b2008-09-23 18:49:522032 int edit_flags,
2033 const std::string& security_info) {
[email protected]e09ba552009-02-05 03:26:292034 ContextMenuParams params;
[email protected]124646932009-01-28 18:39:022035 params.node = node;
initial.commit09911bf2008-07-26 23:55:292036 params.x = x;
2037 params.y = y;
2038 params.image_url = image_url;
2039 params.link_url = link_url;
2040 params.page_url = page_url;
2041 params.frame_url = frame_url;
2042 params.selection_text = selection_text;
2043 params.misspelled_word = misspelled_word;
[email protected]be645db2009-02-06 20:36:332044 params.spellcheck_enabled =
[email protected]bbbd545c2008-12-15 20:18:042045 webview->GetFocusedFrame()->SpellCheckEnabled();
initial.commit09911bf2008-07-26 23:55:292046 params.edit_flags = edit_flags;
[email protected]6aa376b2008-09-23 18:49:522047 params.security_info = security_info;
initial.commit09911bf2008-07-26 23:55:292048 Send(new ViewHostMsg_ContextMenu(routing_id_, params));
2049}
2050
[email protected]e80c73b2009-04-07 23:24:582051void RenderView::StartDragging(WebView* webview,
2052 const WebDragData& drag_data) {
2053 Send(new ViewHostMsg_StartDragging(routing_id_, WebDropData(drag_data)));
initial.commit09911bf2008-07-26 23:55:292054}
2055
2056void RenderView::TakeFocus(WebView* webview, bool reverse) {
2057 Send(new ViewHostMsg_TakeFocus(routing_id_, reverse));
2058}
2059
2060void RenderView::DidDownloadImage(int id,
2061 const GURL& image_url,
2062 bool errored,
2063 const SkBitmap& image) {
2064 Send(new ViewHostMsg_DidDownloadImage(routing_id_, id, image_url, errored,
2065 image));
2066}
2067
2068
2069void RenderView::OnDownloadImage(int id,
2070 const GURL& image_url,
2071 int image_size) {
[email protected]f11ca0732009-04-11 00:09:342072
2073 bool data_image_failed = false;
2074 if (image_url.SchemeIs("data")) {
2075 SkBitmap data_image = ImageFromDataUrl(image_url);
2076 data_image_failed = data_image.empty();
2077 if (!data_image_failed) {
2078 Send(new ViewHostMsg_DidDownloadImage(routing_id_, id, image_url, false,
2079 data_image));
2080 }
2081 }
2082
2083 if (data_image_failed || !webview()->DownloadImage(id, image_url, image_size))
initial.commit09911bf2008-07-26 23:55:292084 Send(new ViewHostMsg_DidDownloadImage(routing_id_, id, image_url, true,
2085 SkBitmap()));
2086}
2087
[email protected]f11ca0732009-04-11 00:09:342088SkBitmap RenderView::ImageFromDataUrl(const GURL& url) const {
2089 std::string mime_type, char_set, data;
2090 if (net::DataURL::Parse(url, &mime_type, &char_set, &data) && !data.empty()) {
2091 // Decode the favicon using WebKit's image decoder.
2092 webkit_glue::ImageDecoder decoder(gfx::Size(kFavIconSize, kFavIconSize));
2093 const unsigned char* src_data =
2094 reinterpret_cast<const unsigned char*>(&data[0]);
2095
2096 return decoder.Decode(src_data, data.size());
2097 }
2098 return SkBitmap();
2099}
2100
initial.commit09911bf2008-07-26 23:55:292101void RenderView::OnGetApplicationInfo(int page_id) {
2102 webkit_glue::WebApplicationInfo app_info;
2103 if (page_id == page_id_)
2104 webkit_glue::GetApplicationInfo(webview(), &app_info);
2105
2106 // Prune out any data URLs in the set of icons. The browser process expects
2107 // any icon with a data URL to have originated from a favicon. We don't want
2108 // to decode arbitrary data URLs in the browser process. See
2109 // http://b/issue?id=1162972
2110 for (size_t i = 0; i < app_info.icons.size(); ++i) {
[email protected]6de74452009-02-25 18:04:592111 if (app_info.icons[i].url.SchemeIs(chrome::kDataScheme)) {
initial.commit09911bf2008-07-26 23:55:292112 app_info.icons.erase(app_info.icons.begin() + i);
2113 --i;
2114 }
2115 }
2116
2117 Send(new ViewHostMsg_DidGetApplicationInfo(routing_id_, page_id, app_info));
2118}
2119
2120GURL RenderView::GetAlternateErrorPageURL(const GURL& failedURL,
2121 ErrorPageType error_type) {
2122 if (failedURL.SchemeIsSecure()) {
2123 // If the URL that failed was secure, then the embedding web page was not
2124 // expecting a network attacker to be able to manipulate its contents. As
2125 // we fetch alternate error pages over HTTP, we would be allowing a network
2126 // attacker to manipulate the contents of the response if we tried to use
2127 // the link doctor here.
2128 return GURL::EmptyGURL();
2129 }
2130
2131 // Grab the base URL from the browser process.
2132 if (!alternate_error_page_url_.is_valid())
2133 return GURL::EmptyGURL();
2134
2135 // Strip query params from the failed URL.
2136 GURL::Replacements remove_params;
2137 remove_params.ClearUsername();
2138 remove_params.ClearPassword();
2139 remove_params.ClearQuery();
2140 remove_params.ClearRef();
2141 const GURL url_to_send = failedURL.ReplaceComponents(remove_params);
2142
2143 // Construct the query params to send to link doctor.
2144 std::string params(alternate_error_page_url_.query());
2145 params.append("&url=");
2146 params.append(EscapeQueryParamValue(url_to_send.spec()));
2147 params.append("&sourceid=chrome");
2148 params.append("&error=");
2149 switch (error_type) {
2150 case DNS_ERROR:
2151 params.append("dnserror");
2152 break;
2153
2154 case HTTP_404:
2155 params.append("http404");
2156 break;
2157
[email protected]5df266ac2008-10-15 19:50:132158 case CONNECTION_ERROR:
[email protected]e1f934b2009-01-26 20:41:332159 params.append("connectionfailure");
[email protected]5df266ac2008-10-15 19:50:132160 break;
2161
initial.commit09911bf2008-07-26 23:55:292162 default:
2163 NOTREACHED() << "unknown ErrorPageType";
2164 }
2165
2166 // OK, build the final url to return.
2167 GURL::Replacements link_doctor_params;
2168 link_doctor_params.SetQueryStr(params);
2169 GURL url = alternate_error_page_url_.ReplaceComponents(link_doctor_params);
2170 return url;
2171}
2172
[email protected]7ea066a2009-04-06 20:21:592173void RenderView::OnFind(int request_id,
2174 const string16& search_text,
2175 const WebKit::WebFindOptions& options) {
initial.commit09911bf2008-07-26 23:55:292176 WebFrame* main_frame = webview()->GetMainFrame();
2177 WebFrame* frame_after_main = webview()->GetNextFrameAfter(main_frame, true);
2178 WebFrame* focused_frame = webview()->GetFocusedFrame();
2179 WebFrame* search_frame = focused_frame; // start searching focused frame.
2180
2181 bool multi_frame = (frame_after_main != main_frame);
2182
2183 // If we have multiple frames, we don't want to wrap the search within the
2184 // frame, so we check here if we only have main_frame in the chain.
2185 bool wrap_within_frame = !multi_frame;
2186
[email protected]b3f2b912009-04-09 16:18:522187 WebRect selection_rect;
initial.commit09911bf2008-07-26 23:55:292188 bool result = false;
2189
2190 do {
[email protected]7ea066a2009-04-06 20:21:592191 result = search_frame->Find(
2192 request_id, search_text, options, wrap_within_frame, &selection_rect);
initial.commit09911bf2008-07-26 23:55:292193
2194 if (!result) {
2195 // don't leave text selected as you move to the next frame.
2196 search_frame->ClearSelection();
2197
2198 // Find the next frame, but skip the invisible ones.
2199 do {
2200 // What is the next frame to search? (we might be going backwards). Note
2201 // that we specify wrap=true so that search_frame never becomes NULL.
[email protected]7ea066a2009-04-06 20:21:592202 search_frame = options.forward ?
initial.commit09911bf2008-07-26 23:55:292203 webview()->GetNextFrameAfter(search_frame, true) :
2204 webview()->GetPreviousFrameBefore(search_frame, true);
2205 } while (!search_frame->Visible() && search_frame != focused_frame);
2206
[email protected]884db412008-11-24 23:46:502207 // Make sure selection doesn't affect the search operation in new frame.
initial.commit09911bf2008-07-26 23:55:292208 search_frame->ClearSelection();
2209
2210 // If we have multiple frames and we have wrapped back around to the
2211 // focused frame, we need to search it once more allowing wrap within
2212 // the frame, otherwise it will report 'no match' if the focused frame has
2213 // reported matches, but no frames after the focused_frame contain a
2214 // match for the search word(s).
2215 if (multi_frame && search_frame == focused_frame) {
[email protected]7ea066a2009-04-06 20:21:592216 result = search_frame->Find(
2217 request_id, search_text, options, true, // Force wrapping.
2218 &selection_rect);
initial.commit09911bf2008-07-26 23:55:292219 }
2220 }
2221
2222 // TODO(jcampan): http://b/issue?id=1157486 Remove StoreForFocus call once
2223 // we have the fix for 792423.
2224 search_frame->GetView()->StoreFocusForFrame(search_frame);
2225 webview()->SetFocusedFrame(search_frame);
2226 } while (!result && search_frame != focused_frame);
2227
2228 // Make sure we don't leave any frame focused or the focus won't be restored
2229 // properly in WebViewImpl::SetFocus(). Note that we are talking here about
2230 // focused on the SelectionController, not FocusController.
2231 // webview()->GetFocusedFrame() will still return the last focused frame (as
2232 // it queries the FocusController).
2233 // TODO(jcampan): http://b/issue?id=1157486 Remove next line once we have the
2234 // fix for 792423.
2235 webview()->SetFocusedFrame(NULL);
2236
[email protected]7ea066a2009-04-06 20:21:592237 if (options.findNext) {
[email protected]4f3dc372009-02-24 00:10:292238 // Force the main_frame to report the actual count.
[email protected]7ea066a2009-04-06 20:21:592239 main_frame->IncreaseMatchCount(0, request_id);
[email protected]4f3dc372009-02-24 00:10:292240 } else {
2241 // If nothing is found, set result to "0 of 0", otherwise, set it to
2242 // "-1 of 1" to indicate that we found at least one item, but we don't know
2243 // yet what is active.
2244 int ordinal = result ? -1 : 0; // -1 here means, we might know more later.
2245 int match_count = result ? 1 : 0; // 1 here means possibly more coming.
initial.commit09911bf2008-07-26 23:55:292246
[email protected]4f3dc372009-02-24 00:10:292247 // If we find no matches then this will be our last status update.
2248 // Otherwise the scoping effort will send more results.
2249 bool final_status_update = !result;
initial.commit09911bf2008-07-26 23:55:292250
[email protected]4f3dc372009-02-24 00:10:292251 // Send the search result over to the browser process.
[email protected]4f999132009-03-31 18:08:402252 Send(new ViewHostMsg_Find_Reply(routing_id_,
[email protected]7ea066a2009-04-06 20:21:592253 request_id,
[email protected]4f3dc372009-02-24 00:10:292254 match_count,
2255 selection_rect,
2256 ordinal,
2257 final_status_update));
initial.commit09911bf2008-07-26 23:55:292258
initial.commit09911bf2008-07-26 23:55:292259 // Scoping effort begins, starting with the mainframe.
2260 search_frame = main_frame;
2261
2262 main_frame->ResetMatchCount();
2263
2264 do {
2265 // Cancel all old scoping requests before starting a new one.
2266 search_frame->CancelPendingScopingEffort();
2267
2268 // We don't start another scoping effort unless at least one match has
2269 // been found.
2270 if (result) {
2271 // Start new scoping request. If the scoping function determines that it
2272 // needs to scope, it will defer until later.
[email protected]7ea066a2009-04-06 20:21:592273 search_frame->ScopeStringMatches(request_id,
2274 search_text,
2275 options,
initial.commit09911bf2008-07-26 23:55:292276 true); // reset the tickmarks
2277 }
2278
2279 // Iterate to the next frame. The frame will not necessarily scope, for
2280 // example if it is not visible.
2281 search_frame = webview()->GetNextFrameAfter(search_frame, true);
2282 } while (search_frame != main_frame);
2283 }
2284}
2285
2286void RenderView::ReportFindInPageMatchCount(int count, int request_id,
2287 bool final_update) {
2288 // If we have a message that has been queued up, then we should just replace
2289 // it. The ACK from the browser will make sure it gets sent when the browser
2290 // wants it.
2291 if (queued_find_reply_message_.get()) {
2292 IPC::Message* msg = new ViewHostMsg_Find_Reply(
2293 routing_id_,
2294 request_id,
2295 count,
[email protected]b3f2b912009-04-09 16:18:522296 gfx::Rect(),
initial.commit09911bf2008-07-26 23:55:292297 -1, // Don't update active match ordinal.
2298 final_update);
2299 queued_find_reply_message_.reset(msg);
2300 } else {
2301 // Send the search result over to the browser process.
2302 Send(new ViewHostMsg_Find_Reply(
2303 routing_id_,
2304 request_id,
2305 count,
[email protected]b3f2b912009-04-09 16:18:522306 gfx::Rect(),
initial.commit09911bf2008-07-26 23:55:292307 -1, // // Don't update active match ordinal.
2308 final_update));
2309 }
2310}
2311
2312void RenderView::ReportFindInPageSelection(int request_id,
2313 int active_match_ordinal,
[email protected]b3f2b912009-04-09 16:18:522314 const WebRect& selection_rect) {
initial.commit09911bf2008-07-26 23:55:292315 // Send the search result over to the browser process.
2316 Send(new ViewHostMsg_Find_Reply(routing_id_,
2317 request_id,
2318 -1,
2319 selection_rect,
2320 active_match_ordinal,
2321 false));
2322}
2323
2324bool RenderView::WasOpenedByUserGesture(WebView* webview) const {
2325 return WasOpenedByUserGestureHelper();
2326}
2327
2328bool RenderView::WasOpenedByUserGestureHelper() const {
2329 // If pop-up blocking has been disabled, then treat all new windows as if
2330 // they were opened by a user gesture. This will prevent them from being
2331 // blocked. This is a bit of a hack, there should be a more straightforward
2332 // way to disable pop-up blocking.
2333 if (disable_popup_blocking_)
2334 return true;
2335
2336 return opened_by_user_gesture_;
2337}
2338
2339void RenderView::SpellCheck(const std::wstring& word, int& misspell_location,
2340 int& misspell_length) {
2341 Send(new ViewHostMsg_SpellCheck(routing_id_, word, &misspell_location,
2342 &misspell_length));
2343}
2344
2345void RenderView::SetInputMethodState(bool enabled) {
2346 // Save the updated IME status and mark the input focus has been updated.
2347 // The IME status is to be sent to a browser process next time when
2348 // the input caret is rendered.
[email protected]9f23f592008-11-17 08:36:342349 if (!ime_control_busy_) {
2350 ime_control_updated_ = true;
2351 ime_control_new_state_ = enabled;
2352 }
initial.commit09911bf2008-07-26 23:55:292353}
2354
2355void RenderView::ScriptedPrint(WebFrame* frame) {
[email protected]6c8afae52009-01-22 02:24:572356#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:292357 // Retrieve the default print settings to calculate the expected number of
2358 // pages.
2359 ViewMsg_Print_Params default_settings;
2360 IPC::SyncMessage* msg =
2361 new ViewHostMsg_GetDefaultPrintSettings(routing_id_, &default_settings);
2362 if (Send(msg)) {
2363 msg = NULL;
2364 // Continue only if the settings are valid.
2365 if (default_settings.dpi && default_settings.document_cookie) {
[email protected]88a3ecc2009-03-19 17:36:222366 int expected_pages_count = 0;
2367 gfx::Size canvas_size;
2368 canvas_size.set_width(
2369 printing::ConvertUnit(default_settings.printable_size.width(),
2370 static_cast<int>(default_settings.dpi),
2371 default_settings.desired_dpi));
2372 canvas_size.set_height(
2373 printing::ConvertUnit(default_settings.printable_size.height(),
2374 static_cast<int>(default_settings.dpi),
2375 default_settings.desired_dpi));
2376 frame->BeginPrint(canvas_size, &expected_pages_count);
initial.commit09911bf2008-07-26 23:55:292377 DCHECK(expected_pages_count);
[email protected]88a3ecc2009-03-19 17:36:222378 frame->EndPrint();
initial.commit09911bf2008-07-26 23:55:292379
2380 // Ask the browser to show UI to retrieve the final print settings.
2381 ViewMsg_PrintPages_Params print_settings;
2382 // host_window_ may be NULL at this point if the current window is a popup
2383 // and the print() command has been issued from the parent. The receiver
2384 // of this message has to deal with this.
2385 msg = new ViewHostMsg_ScriptedPrint(routing_id_,
2386 host_window_,
2387 default_settings.document_cookie,
2388 expected_pages_count,
2389 &print_settings);
2390 if (Send(msg)) {
2391 msg = NULL;
2392
2393 // If the settings are invalid, early quit.
2394 if (print_settings.params.dpi &&
2395 print_settings.params.document_cookie) {
2396 // Render the printed pages. It will implicitly revert the document to
2397 // display CSS media type.
2398 PrintPages(print_settings, frame);
2399 // All went well.
2400 return;
2401 } else {
2402 // The user cancelled.
2403 }
2404 } else {
2405 // Send() failed.
2406 NOTREACHED();
2407 }
2408 } else {
2409 // The user cancelled.
2410 }
2411 } else {
2412 // Send() failed.
2413 NOTREACHED();
2414 }
2415 // TODO(maruel): bug 1123882 Alert the user that printing failed.
[email protected]6c8afae52009-01-22 02:24:572416#else // defined(OS_WIN)
2417 // TODO(port): print not implemented
2418 NOTIMPLEMENTED();
2419#endif
initial.commit09911bf2008-07-26 23:55:292420}
2421
2422void RenderView::WebInspectorOpened(int num_resources) {
2423 Send(new ViewHostMsg_InspectElement_Reply(routing_id_, num_resources));
2424}
2425
2426void RenderView::UserMetricsRecordAction(const std::wstring& action) {
2427 Send(new ViewHostMsg_UserMetricsRecordAction(routing_id_, action));
2428}
2429
2430void RenderView::DnsPrefetch(const std::vector<std::string>& host_names) {
2431 Send(new ViewHostMsg_DnsPrefetch(host_names));
2432}
2433
[email protected]630e26b2008-10-14 22:55:172434void RenderView::OnZoom(int function) {
2435 static const bool kZoomIsTextOnly = false;
2436 switch (function) {
2437 case PageZoom::SMALLER:
2438 webview()->ZoomOut(kZoomIsTextOnly);
initial.commit09911bf2008-07-26 23:55:292439 break;
[email protected]630e26b2008-10-14 22:55:172440 case PageZoom::STANDARD:
2441 webview()->ResetZoom();
initial.commit09911bf2008-07-26 23:55:292442 break;
[email protected]630e26b2008-10-14 22:55:172443 case PageZoom::LARGER:
2444 webview()->ZoomIn(kZoomIsTextOnly);
initial.commit09911bf2008-07-26 23:55:292445 break;
2446 default:
2447 NOTREACHED();
2448 }
2449}
2450
[email protected]ea8c7452009-04-02 20:47:062451void RenderView::OnInsertText(const string16& text) {
2452 webview()->InsertText(text);
2453}
2454
[email protected]e38f40152008-09-12 23:08:302455void RenderView::OnSetPageEncoding(const std::wstring& encoding_name) {
initial.commit09911bf2008-07-26 23:55:292456 webview()->SetPageEncoding(encoding_name);
2457}
2458
2459void RenderView::OnPasswordFormsSeen(WebView* webview,
2460 const std::vector<PasswordForm>& forms) {
2461 Send(new ViewHostMsg_PasswordFormsSeen(routing_id_, forms));
2462}
2463
[email protected]8d0f15c2008-11-11 01:01:092464void RenderView::OnAutofillFormSubmitted(WebView* webview,
2465 const AutofillForm& form) {
2466 Send(new ViewHostMsg_AutofillFormSubmitted(routing_id_, form));
2467}
2468
initial.commit09911bf2008-07-26 23:55:292469WebHistoryItem* RenderView::GetHistoryEntryAtOffset(int offset) {
[email protected]50b691c2008-10-31 19:08:352470 // Our history list is kept in the browser process on the UI thread. Since
2471 // we can't make a sync IPC call to that thread without risking deadlock,
2472 // we use a trick: construct a fake history item of the form:
2473 // history://go/OFFSET
2474 // When WebCore tells us to navigate to it, we tell the browser process to
2475 // do a back/forward navigation instead.
2476
2477 GURL url(StringPrintf("%s://go/%d", kBackForwardNavigationScheme, offset));
2478 history_navigation_item_ = WebHistoryItem::Create(url, L"", "", NULL);
2479 return history_navigation_item_.get();
initial.commit09911bf2008-07-26 23:55:292480}
2481
[email protected]0c0383772008-11-04 00:48:312482void RenderView::GoToEntryAtOffset(int offset) {
[email protected]f46aff62008-10-16 07:58:052483 history_back_list_count_ += offset;
2484 history_forward_list_count_ -= offset;
2485
initial.commit09911bf2008-07-26 23:55:292486 Send(new ViewHostMsg_GoToEntryAtOffset(routing_id_, offset));
2487}
2488
2489int RenderView::GetHistoryBackListCount() {
2490 return history_back_list_count_;
2491}
2492
2493int RenderView::GetHistoryForwardListCount() {
2494 return history_forward_list_count_;
2495}
2496
2497void RenderView::OnNavStateChanged(WebView* webview) {
[email protected]81a34412009-01-05 19:17:242498 if (!nav_state_sync_timer_.IsRunning()) {
2499 nav_state_sync_timer_.Start(
2500 TimeDelta::FromSeconds(delay_seconds_for_form_state_sync_), this,
2501 &RenderView::SyncNavigationState);
2502 }
initial.commit09911bf2008-07-26 23:55:292503}
2504
2505void RenderView::SetTooltipText(WebView* webview,
2506 const std::wstring& tooltip_text) {
2507 Send(new ViewHostMsg_SetTooltipText(routing_id_, tooltip_text));
2508}
2509
[email protected]2e417c82009-04-02 22:30:262510void RenderView::DidChangeSelection(bool is_empty_selection) {
2511#if defined(OS_LINUX)
2512 if (!is_empty_selection) {
[email protected]dbadbcc2009-04-09 00:57:102513 Send(new ViewHostMsg_SelectionChanged(routing_id_,
2514 webview()->GetMainFrame()->GetSelection(false)));
[email protected]2e417c82009-04-02 22:30:262515 }
2516#endif
2517}
2518
2519
initial.commit09911bf2008-07-26 23:55:292520void RenderView::DownloadUrl(const GURL& url, const GURL& referrer) {
2521 Send(new ViewHostMsg_DownloadUrl(routing_id_, url, referrer));
2522}
2523
[email protected]611cad42009-03-16 18:51:342524WebDevToolsAgentDelegate* RenderView::GetWebDevToolsAgentDelegate() {
[email protected]b75b7d072009-04-06 13:47:002525 return devtools_agent_.get();
[email protected]611cad42009-03-16 18:51:342526}
2527
[email protected]ea8c7452009-04-02 20:47:062528void RenderView::PasteFromSelectionClipboard() {
2529 Send(new ViewHostMsg_PasteFromSelectionClipboard(routing_id_));
2530}
2531
initial.commit09911bf2008-07-26 23:55:292532WebFrame* RenderView::GetChildFrame(const std::wstring& frame_xpath) const {
2533 WebFrame* web_frame;
2534 if (frame_xpath.empty()) {
2535 web_frame = webview()->GetMainFrame();
2536 } else {
2537 web_frame = webview()->GetMainFrame()->GetChildFrame(frame_xpath);
2538 }
2539
2540 return web_frame;
2541}
2542
[email protected]f29acf52008-11-03 20:08:332543void RenderView::EvaluateScript(const std::wstring& frame_xpath,
2544 const std::wstring& script) {
initial.commit09911bf2008-07-26 23:55:292545 WebFrame* web_frame = GetChildFrame(frame_xpath);
2546 if (!web_frame)
2547 return;
2548
[email protected]4f999132009-03-31 18:08:402549 web_frame->ExecuteScript(WebScriptSource(WideToUTF16Hack(script)));
initial.commit09911bf2008-07-26 23:55:292550}
2551
[email protected]1810e132009-03-24 23:35:482552void RenderView::InsertCSS(const std::wstring& frame_xpath,
2553 const std::string& css) {
2554 WebFrame* web_frame = GetChildFrame(frame_xpath);
2555 if (!web_frame)
2556 return;
2557
2558 web_frame->InsertCSSStyles(css);
2559}
2560
initial.commit09911bf2008-07-26 23:55:292561void RenderView::OnScriptEvalRequest(const std::wstring& frame_xpath,
2562 const std::wstring& jscript) {
[email protected]f29acf52008-11-03 20:08:332563 EvaluateScript(frame_xpath, jscript);
initial.commit09911bf2008-07-26 23:55:292564}
2565
[email protected]1810e132009-03-24 23:35:482566void RenderView::OnCSSInsertRequest(const std::wstring& frame_xpath,
2567 const std::string& css) {
2568 InsertCSS(frame_xpath, css);
2569}
2570
[email protected]7ea066a2009-04-06 20:21:592571void RenderView::OnAddMessageToConsole(
2572 const string16& frame_xpath,
2573 const string16& message,
2574 const WebConsoleMessage::Level& level) {
2575 WebFrame* web_frame = GetChildFrame(UTF16ToWideHack(frame_xpath));
[email protected]0dea3ea2009-03-31 23:30:592576 if (web_frame)
[email protected]7ea066a2009-04-06 20:21:592577 web_frame->AddMessageToConsole(WebConsoleMessage(level, message));
initial.commit09911bf2008-07-26 23:55:292578}
2579
[email protected]6c8afae52009-01-22 02:24:572580#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:292581void RenderView::OnDebugAttach() {
initial.commit09911bf2008-07-26 23:55:292582 Send(new ViewHostMsg_DidDebugAttach(routing_id_));
2583 // Tell the plugin host to stop accepting messages in order to avoid
2584 // hangs while the renderer is paused.
2585 // TODO(1243929): It might be an improvement to add more plumbing to do this
2586 // when the renderer is actually paused vs. just the debugger being attached.
2587 PluginChannelHost::SetListening(false);
2588}
2589
2590void RenderView::OnDebugDetach() {
2591 // Tell the plugin host to start accepting plugin messages again.
2592 PluginChannelHost::SetListening(true);
2593}
[email protected]6c8afae52009-01-22 02:24:572594#else // defined(OS_WIN)
2595// TODO(port): plugins not yet supported
2596void RenderView::OnDebugAttach() { NOTIMPLEMENTED(); }
2597void RenderView::OnDebugDetach() { NOTIMPLEMENTED(); }
2598#endif
initial.commit09911bf2008-07-26 23:55:292599
[email protected]81e63782009-02-27 19:35:092600void RenderView::OnAllowBindings(int enabled_bindings_flags) {
2601 enabled_bindings_ |= enabled_bindings_flags;
initial.commit09911bf2008-07-26 23:55:292602}
2603
2604void RenderView::OnSetDOMUIProperty(const std::string& name,
2605 const std::string& value) {
[email protected]81e63782009-02-27 19:35:092606 DCHECK(BindingsPolicy::is_dom_ui_enabled(enabled_bindings_));
initial.commit09911bf2008-07-26 23:55:292607 dom_ui_bindings_.SetProperty(name, value);
2608}
2609
2610void RenderView::OnReservePageIDRange(int size_of_range) {
2611 next_page_id_ += size_of_range + 1;
2612}
2613
[email protected]e80c73b2009-04-07 23:24:582614void RenderView::OnDragSourceEndedOrMoved(const gfx::Point& client_point,
2615 const gfx::Point& screen_point,
initial.commit09911bf2008-07-26 23:55:292616 bool ended) {
2617 if (ended)
[email protected]e80c73b2009-04-07 23:24:582618 webview()->DragSourceEndedAt(client_point, screen_point);
initial.commit09911bf2008-07-26 23:55:292619 else
[email protected]e80c73b2009-04-07 23:24:582620 webview()->DragSourceMovedTo(client_point, screen_point);
initial.commit09911bf2008-07-26 23:55:292621}
2622
2623void RenderView::OnDragSourceSystemDragEnded() {
2624 webview()->DragSourceSystemDragEnded();
2625}
2626
2627void RenderView::OnUploadFileRequest(const ViewMsg_UploadFile_Params& p) {
2628 webkit_glue::FileUploadData* f = new webkit_glue::FileUploadData;
2629 f->file_path = p.file_path;
2630 f->form_name = p.form;
2631 f->file_name = p.file;
2632 f->submit_name = p.submit;
2633
2634 // Build the other form values map.
2635 if (!p.other_values.empty()) {
2636 std::vector<std::wstring> e;
2637 std::vector<std::wstring> kvp;
2638 std::vector<std::wstring>::iterator i;
2639
2640 SplitString(p.other_values, L'\n', &e);
2641 for (i = e.begin(); i != e.end(); ++i) {
2642 SplitString(*i, L'=', &kvp);
2643 if (kvp.size() == 2)
2644 f->other_form_values[kvp[0]] = kvp[1];
2645 kvp.clear();
2646 }
2647 }
2648
2649 pending_upload_data_.reset(f);
2650 ProcessPendingUpload();
2651}
2652
2653void RenderView::ProcessPendingUpload() {
2654 webkit_glue::FileUploadData* f = pending_upload_data_.get();
2655 if (f && webview() && webkit_glue::FillFormToUploadFile(webview(), *f))
2656 ResetPendingUpload();
2657}
2658
2659void RenderView::ResetPendingUpload() {
2660 pending_upload_data_.reset();
2661}
2662
2663void RenderView::OnFormFill(const FormData& form) {
2664 webkit_glue::FillForm(this->webview(), form);
2665}
2666
2667void RenderView::OnFillPasswordForm(
2668 const PasswordFormDomManager::FillData& form_data) {
2669 webkit_glue::FillPasswordForm(this->webview(), form_data);
2670}
2671
2672void RenderView::OnDragTargetDragEnter(const WebDropData& drop_data,
[email protected]e80c73b2009-04-07 23:24:582673 const gfx::Point& client_point,
2674 const gfx::Point& screen_point) {
2675 bool is_drop_target = webview()->DragTargetDragEnter(
2676 drop_data.ToDragData(),
2677 drop_data.identity,
2678 client_point,
2679 screen_point);
initial.commit09911bf2008-07-26 23:55:292680
2681 Send(new ViewHostMsg_UpdateDragCursor(routing_id_, is_drop_target));
2682}
2683
[email protected]e80c73b2009-04-07 23:24:582684void RenderView::OnDragTargetDragOver(const gfx::Point& client_point,
2685 const gfx::Point& screen_point) {
2686 bool is_drop_target =
2687 webview()->DragTargetDragOver(client_point, screen_point);
initial.commit09911bf2008-07-26 23:55:292688
2689 Send(new ViewHostMsg_UpdateDragCursor(routing_id_, is_drop_target));
2690}
2691
2692void RenderView::OnDragTargetDragLeave() {
2693 webview()->DragTargetDragLeave();
2694}
2695
[email protected]e80c73b2009-04-07 23:24:582696void RenderView::OnDragTargetDrop(const gfx::Point& client_point,
2697 const gfx::Point& screen_point) {
2698 webview()->DragTargetDrop(client_point, screen_point);
initial.commit09911bf2008-07-26 23:55:292699}
2700
2701void RenderView::OnUpdateWebPreferences(const WebPreferences& prefs) {
2702 webview()->SetPreferences(prefs);
2703}
2704
2705void RenderView::OnSetAltErrorPageURL(const GURL& url) {
2706 alternate_error_page_url_ = url;
2707}
2708
2709void RenderView::DidPaint() {
2710 PluginDelegateList::iterator it = plugin_delegates_.begin();
2711 while (it != plugin_delegates_.end()) {
2712 (*it)->FlushGeometryUpdates();
2713 ++it;
2714 }
2715}
2716
2717void RenderView::OnInstallMissingPlugin() {
2718 // This could happen when the first default plugin is deleted.
2719 if (first_default_plugin_ == NULL)
2720 return;
2721 first_default_plugin_->InstallMissingPlugin();
2722}
2723
[email protected]b62d1a8c2009-01-13 23:54:572724void RenderView::OnFileChooserResponse(
[email protected]561abe62009-04-06 18:08:342725 const std::vector<FilePath>& file_names) {
[email protected]8029f5672009-03-20 22:33:362726 // This could happen if we navigated to a different page before the user
2727 // closed the chooser.
2728 if (!file_chooser_.get())
2729 return;
2730
[email protected]b62d1a8c2009-01-13 23:54:572731 file_chooser_->OnFileChoose(file_names);
initial.commit09911bf2008-07-26 23:55:292732 file_chooser_.reset();
2733}
2734
2735void RenderView::OnEnableViewSourceMode() {
2736 if (!webview())
2737 return;
2738 WebFrame* main_frame = webview()->GetMainFrame();
2739 if (!main_frame)
2740 return;
2741
2742 main_frame->SetInViewSourceMode(true);
2743}
2744
2745void RenderView::OnUpdateBackForwardListCount(int back_list_count,
2746 int forward_list_count) {
2747 history_back_list_count_ = back_list_count;
2748 history_forward_list_count_ = forward_list_count;
2749}
2750
[email protected]266eb6f2008-09-30 23:56:502751void RenderView::OnGetAccessibilityInfo(
[email protected]6a983b42009-03-20 20:12:252752 const webkit_glue::WebAccessibility::InParams& in_params,
2753 webkit_glue::WebAccessibility::OutParams* out_params) {
[email protected]6c8afae52009-01-22 02:24:572754#if defined(OS_WIN)
[email protected]6a983b42009-03-20 20:12:252755 if (!web_accessibility_manager_.get()) {
2756 web_accessibility_manager_.reset(
2757 webkit_glue::WebAccessibilityManager::Create());
2758 }
[email protected]266eb6f2008-09-30 23:56:502759
[email protected]6a983b42009-03-20 20:12:252760 if (!web_accessibility_manager_->GetAccObjInfo(webview(), in_params,
2761 out_params)) {
[email protected]266eb6f2008-09-30 23:56:502762 return;
2763 }
[email protected]6c8afae52009-01-22 02:24:572764#else // defined(OS_WIN)
2765 // TODO(port): accessibility not yet implemented
2766 NOTIMPLEMENTED();
2767#endif
[email protected]266eb6f2008-09-30 23:56:502768}
2769
[email protected]6a983b42009-03-20 20:12:252770void RenderView::OnClearAccessibilityInfo(int acc_obj_id, bool clear_all) {
[email protected]6c8afae52009-01-22 02:24:572771#if defined(OS_WIN)
[email protected]6a983b42009-03-20 20:12:252772 if (!web_accessibility_manager_.get()) {
[email protected]266eb6f2008-09-30 23:56:502773 // If accessibility is not activated, ignore clearing message.
2774 return;
2775 }
[email protected]6a983b42009-03-20 20:12:252776 if (!web_accessibility_manager_->ClearAccObjMap(acc_obj_id, clear_all))
[email protected]266eb6f2008-09-30 23:56:502777 return;
[email protected]6c8afae52009-01-22 02:24:572778#else // defined(OS_WIN)
2779 // TODO(port): accessibility not yet implemented
2780 NOTIMPLEMENTED();
2781#endif
[email protected]266eb6f2008-09-30 23:56:502782}
2783
initial.commit09911bf2008-07-26 23:55:292784void RenderView::OnGetAllSavableResourceLinksForCurrentPage(
2785 const GURL& page_url) {
2786 // Prepare list to storage all savable resource links.
2787 std::vector<GURL> resources_list;
2788 std::vector<GURL> referrers_list;
2789 std::vector<GURL> frames_list;
2790 webkit_glue::SavableResourcesResult result(&resources_list,
2791 &referrers_list,
2792 &frames_list);
2793
2794 if (!webkit_glue::GetAllSavableResourceLinksForCurrentPage(webview(),
2795 page_url,
2796 &result)) {
2797 // If something is wrong when collecting all savable resource links,
2798 // send empty list to embedder(browser) to tell it failed.
2799 referrers_list.clear();
2800 resources_list.clear();
2801 frames_list.clear();
2802 }
2803
2804 // Send result of all savable resource links to embedder.
2805 Send(new ViewHostMsg_SendCurrentPageAllSavableResourceLinks(routing_id_,
2806 resources_list,
2807 referrers_list,
2808 frames_list));
2809}
2810
2811void RenderView::OnGetSerializedHtmlDataForCurrentPageWithLocalLinks(
[email protected]f6b48532009-02-12 01:56:322812 const std::vector<GURL>& links,
[email protected]fde6714d12009-02-18 22:39:312813 const std::vector<FilePath>& local_paths,
2814 const FilePath& local_directory_name) {
initial.commit09911bf2008-07-26 23:55:292815 webkit_glue::DomSerializer dom_serializer(webview()->GetMainFrame(),
2816 true,
2817 this,
2818 links,
2819 local_paths,
2820 local_directory_name);
2821 dom_serializer.SerializeDom();
2822}
2823
2824void RenderView::DidSerializeDataForFrame(const GURL& frame_url,
2825 const std::string& data, PageSavingSerializationStatus status) {
2826 Send(new ViewHostMsg_SendSerializedHtmlData(routing_id_,
2827 frame_url, data, static_cast<int32>(status)));
2828}
2829
[email protected]04b4a6c2008-08-02 00:44:472830void RenderView::OnMsgShouldClose() {
initial.commit09911bf2008-07-26 23:55:292831 bool should_close = webview()->ShouldClose();
[email protected]04b4a6c2008-08-02 00:44:472832 Send(new ViewHostMsg_ShouldClose_ACK(routing_id_, should_close));
initial.commit09911bf2008-07-26 23:55:292833}
2834
2835void RenderView::OnClosePage(int new_render_process_host_id,
[email protected]04b4a6c2008-08-02 00:44:472836 int new_request_id) {
initial.commit09911bf2008-07-26 23:55:292837 // TODO(creis): We'd rather use webview()->Close() here, but that currently
2838 // sets the WebView's delegate_ to NULL, preventing any JavaScript dialogs
2839 // in the onunload handler from appearing. For now, we're bypassing that and
2840 // calling the FrameLoader's CloseURL method directly. This should be
2841 // revisited to avoid having two ways to close a page. Having a single way
2842 // to close that can run onunload is also useful for fixing
2843 // http://b/issue?id=753080.
2844 WebFrame* main_frame = webview()->GetMainFrame();
2845 if (main_frame)
2846 main_frame->ClosePage();
2847
2848 Send(new ViewHostMsg_ClosePage_ACK(routing_id_,
2849 new_render_process_host_id,
[email protected]04b4a6c2008-08-02 00:44:472850 new_request_id));
initial.commit09911bf2008-07-26 23:55:292851}
2852
2853void RenderView::OnThemeChanged() {
[email protected]6c8afae52009-01-22 02:24:572854#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:292855 gfx::NativeTheme::instance()->CloseHandles();
2856 gfx::Rect view_rect(0, 0, size_.width(), size_.height());
2857 DidInvalidateRect(webwidget_, view_rect);
[email protected]6c8afae52009-01-22 02:24:572858#else // defined(OS_WIN)
2859 // TODO(port): we don't support theming on non-Windows platforms yet
2860 NOTIMPLEMENTED();
2861#endif
initial.commit09911bf2008-07-26 23:55:292862}
2863
[email protected]f386cca792008-08-26 02:02:182864#ifdef CHROME_PERSONALIZATION
[email protected]1cc879642008-08-26 01:27:352865void RenderView::OnPersonalizationEvent(std::string event_name,
2866 std::string event_args) {
2867 Personalization::HandleViewMsgPersonalizationEvent(personalization_,
2868 webview(),
2869 event_name,
2870 event_args);
2871}
[email protected]f386cca792008-08-26 02:02:182872#endif
[email protected]1cc879642008-08-26 01:27:352873
2874void RenderView::TransitionToCommittedForNewPage() {
[email protected]f386cca792008-08-26 02:02:182875#ifdef CHROME_PERSONALIZATION
[email protected]1cc879642008-08-26 01:27:352876 Personalization::HandleTransitionToCommittedForNewPage(personalization_);
[email protected]f386cca792008-08-26 02:02:182877#endif
[email protected]1cc879642008-08-26 01:27:352878}
2879
[email protected]f46aff62008-10-16 07:58:052880void RenderView::DidAddHistoryItem() {
[email protected]f8901082008-10-31 23:34:032881 // We don't want to update the history length for the start page
2882 // navigation.
2883 WebFrame* main_frame = webview()->GetMainFrame();
2884 DCHECK(main_frame != NULL);
2885
2886 WebDataSource* ds = main_frame->GetDataSource();
2887 DCHECK(ds != NULL);
2888
2889 const WebRequest& request = ds->GetRequest();
2890 RenderViewExtraRequestData* extra_data =
2891 static_cast<RenderViewExtraRequestData*>(request.GetExtraData());
2892
2893 if (extra_data && extra_data->transition_type == PageTransition::START_PAGE)
2894 return;
2895
[email protected]f46aff62008-10-16 07:58:052896 history_back_list_count_++;
2897 history_forward_list_count_ = 0;
2898}
2899
[email protected]28790922009-03-09 19:48:372900void RenderView::OnMessageFromExternalHost(const std::string& message,
2901 const std::string& origin,
2902 const std::string& target) {
[email protected]3ac14a052008-08-15 21:22:152903 if (message.empty())
2904 return;
2905
[email protected]28790922009-03-09 19:48:372906 external_host_bindings_.ForwardMessageFromExternalHost(message, origin,
2907 target);
[email protected]3ac14a052008-08-15 21:22:152908}
2909
[email protected]0aa55312008-10-17 21:53:082910void RenderView::OnDisassociateFromPopupCount() {
2911 if (decrement_shared_popup_at_destruction_)
2912 shared_popup_counter_->data--;
2913 shared_popup_counter_ = new SharedRenderViewCounter(0);
2914 decrement_shared_popup_at_destruction_ = false;
2915}
2916
initial.commit09911bf2008-07-26 23:55:292917std::string RenderView::GetAltHTMLForTemplate(
2918 const DictionaryValue& error_strings, int template_resource_id) const {
2919 const StringPiece template_html(
2920 ResourceBundle::GetSharedInstance().GetRawDataResource(
2921 template_resource_id));
2922
2923 if (template_html.empty()) {
2924 NOTREACHED() << "unable to load template. ID: " << template_resource_id;
2925 return "";
2926 }
2927 // "t" is the id of the templates root node.
2928 return jstemplate_builder::GetTemplateHtml(
2929 template_html, &error_strings, "t");
2930}
[email protected]0e79b9e2009-02-13 04:20:482931
2932MessageLoop* RenderView::GetMessageLoopForIO() {
2933 // Assume that we have only one RenderThread in the process and the owner loop
2934 // of RenderThread is an IO message loop.
[email protected]8930d472009-02-21 08:05:282935 if (RenderThread::current())
2936 return RenderThread::current()->owner_loop();
[email protected]0e79b9e2009-02-13 04:20:482937 return NULL;
2938}
[email protected]6f56d482009-02-20 05:02:562939
2940void RenderView::OnRequestAudioPacket(int stream_id) {
2941 AudioRendererImpl* audio_renderer = audio_renderers_.Lookup(stream_id);
[email protected]4f3dc372009-02-24 00:10:292942 if (!audio_renderer) {
[email protected]cdb0835b2009-04-07 00:56:262943 // It is possible that AudioRendererImpl is un-registered but we still
2944 // receives packet requests here, because of closing a stream is not a
2945 // synchronous operation with the browser process.
[email protected]6f56d482009-02-20 05:02:562946 return;
2947 }
2948 audio_renderer->OnRequestPacket();
2949}
2950
2951void RenderView::OnAudioStreamCreated(
2952 int stream_id, base::SharedMemoryHandle handle, int length) {
2953 AudioRendererImpl* audio_renderer = audio_renderers_.Lookup(stream_id);
[email protected]4f3dc372009-02-24 00:10:292954 if (!audio_renderer) {
[email protected]6f56d482009-02-20 05:02:562955 return;
2956 }
2957 audio_renderer->OnCreated(handle, length);
2958}
2959
2960void RenderView::OnAudioStreamStateChanged(
2961 int stream_id, AudioOutputStream::State state, int info) {
2962 AudioRendererImpl* audio_renderer = audio_renderers_.Lookup(stream_id);
[email protected]4f3dc372009-02-24 00:10:292963 if (!audio_renderer) {
[email protected]6f56d482009-02-20 05:02:562964 return;
2965 }
2966 audio_renderer->OnStateChanged(state, info);
2967}
2968
2969void RenderView::OnAudioStreamVolume(int stream_id, double left, double right) {
2970 AudioRendererImpl* audio_renderer = audio_renderers_.Lookup(stream_id);
[email protected]4f3dc372009-02-24 00:10:292971 if (!audio_renderer) {
[email protected]6f56d482009-02-20 05:02:562972 return;
2973 }
2974 audio_renderer->OnVolume(left, right);
2975}
2976
[email protected]30f75e62009-02-25 22:01:002977void RenderView::OnMoveOrResizeStarted() {
2978 if (webview())
2979 webview()->HideAutofillPopup();
2980}
2981
[email protected]6f56d482009-02-20 05:02:562982int32 RenderView::CreateAudioStream(AudioRendererImpl* audio_renderer,
2983 AudioManager::Format format, int channels,
2984 int sample_rate, int bits_per_sample,
2985 size_t packet_size) {
[email protected]8db216e2009-03-10 22:40:312986 DCHECK(RenderThread::current()->message_loop() == MessageLoop::current());
[email protected]6f56d482009-02-20 05:02:562987 // Loop through the map and make sure there's no renderer already in the map.
2988 for (IDMap<AudioRendererImpl>::const_iterator iter = audio_renderers_.begin();
2989 iter != audio_renderers_.end(); ++iter) {
2990 DCHECK(iter->second != audio_renderer);
2991 }
2992
2993 // Add to map and send the IPC to browser process.
2994 int32 stream_id = audio_renderers_.Add(audio_renderer);
2995 ViewHostMsg_Audio_CreateStream params;
2996 params.format = format;
2997 params.channels = channels;
2998 params.sample_rate = sample_rate;
2999 params.bits_per_sample = bits_per_sample;
3000 params.packet_size = packet_size;
3001 Send(new ViewHostMsg_CreateAudioStream(routing_id_, stream_id, params));
3002 return stream_id;
3003}
3004
3005void RenderView::StartAudioStream(int stream_id) {
[email protected]8db216e2009-03-10 22:40:313006 DCHECK(RenderThread::current()->message_loop() == MessageLoop::current());
[email protected]6f56d482009-02-20 05:02:563007 DCHECK(audio_renderers_.Lookup(stream_id) != NULL);
3008 Send(new ViewHostMsg_StartAudioStream(routing_id_, stream_id));
3009}
3010
3011void RenderView::CloseAudioStream(int stream_id) {
[email protected]8db216e2009-03-10 22:40:313012 DCHECK(RenderThread::current()->message_loop() == MessageLoop::current());
[email protected]d1f17392009-04-03 23:05:303013 if (audio_renderers_.Lookup(stream_id) != NULL) {
3014 // Remove the entry from the map and send a close message to browser
3015 // process, we won't be getting anything back from browser even if there's
3016 // an error.
3017 audio_renderers_.Remove(stream_id);
3018 Send(new ViewHostMsg_CloseAudioStream(routing_id_, stream_id));
3019 }
[email protected]6f56d482009-02-20 05:02:563020}
3021
[email protected]2ee2329e2009-02-27 23:51:163022void RenderView::NotifyAudioPacketReady(int stream_id, size_t size) {
[email protected]8db216e2009-03-10 22:40:313023 DCHECK(RenderThread::current()->message_loop() == MessageLoop::current());
[email protected]6f56d482009-02-20 05:02:563024 DCHECK(audio_renderers_.Lookup(stream_id) != NULL);
[email protected]2ee2329e2009-02-27 23:51:163025 Send(new ViewHostMsg_NotifyAudioPacketReady(routing_id_, stream_id, size));
[email protected]6f56d482009-02-20 05:02:563026}
3027
3028void RenderView::GetAudioVolume(int stream_id) {
[email protected]8db216e2009-03-10 22:40:313029 DCHECK(RenderThread::current()->message_loop() == MessageLoop::current());
[email protected]6f56d482009-02-20 05:02:563030 DCHECK(audio_renderers_.Lookup(stream_id) != NULL);
3031 Send(new ViewHostMsg_GetAudioVolume(routing_id_, stream_id));
3032}
3033
3034void RenderView::SetAudioVolume(int stream_id, double left, double right) {
[email protected]8db216e2009-03-10 22:40:313035 DCHECK(RenderThread::current()->message_loop() == MessageLoop::current());
[email protected]6f56d482009-02-20 05:02:563036 DCHECK(audio_renderers_.Lookup(stream_id) != NULL);
3037 Send(new ViewHostMsg_SetAudioVolume(routing_id_, stream_id, left, right));
3038}
[email protected]30f75e62009-02-25 22:01:003039
3040void RenderView::OnResize(const gfx::Size& new_size,
3041 const gfx::Rect& resizer_rect) {
3042 if (webview())
3043 webview()->HideAutofillPopup();
3044 RenderWidget::OnResize(new_size, resizer_rect);
3045}
[email protected]0aa477bd2009-03-23 22:21:433046
[email protected]05d478752009-04-08 23:38:163047void RenderView::OnClearFocusedNode() {
3048 if (webview())
3049 webview()->ClearFocusedNode();
3050}
3051
[email protected]309d7a282009-03-24 09:18:273052void RenderView::SendExtensionRequest(const std::string& name,
3053 const std::string& args,
3054 int callback_id,
3055 WebFrame* callback_frame) {
[email protected]309d7a282009-03-24 09:18:273056 if (callback_id != -1) {
3057 DCHECK(callback_frame) << "Callback specified without frame";
3058 pending_extension_callbacks_.AddWithID(callback_frame, callback_id);
3059 }
3060
3061 Send(new ViewHostMsg_ExtensionRequest(routing_id_, name, args, callback_id));
3062}
3063
3064void RenderView::OnExtensionResponse(int callback_id,
3065 const std::string& response) {
3066 WebFrame* web_frame = pending_extension_callbacks_.Lookup(callback_id);
3067 if (!web_frame)
3068 return; // The frame went away.
3069
[email protected]a1a0df02009-04-09 08:18:043070 ExtensionProcessBindings::ExecuteCallbackInFrame(web_frame, callback_id,
3071 response);
[email protected]309d7a282009-03-24 09:18:273072 pending_extension_callbacks_.Remove(callback_id);
3073}
[email protected]c20210e62009-04-03 21:39:263074
3075// Dump all load time histograms. We create 2 sets time based histograms,
3076// one that is specific to the navigation type and one that aggregates all
3077// navigation types
3078//
3079// Each set contains 5 histograms measuring various times.
3080// The time points we keep are
3081// request: time document was requested by user
3082// start: time load of document started
3083// finishDoc: main document loaded, before onload()
3084// finish: after onload() and all resources are loaded
3085// finish_document_load_time and finish_load_time.
3086// The times that we histogram are
3087// requestToStart,
3088// startToFinishDoc,
3089// finishDocToFinish,
3090// startToFinish,
3091// requestToFinish,
3092//
3093void RenderView::DumpLoadHistograms() const {
3094 WebFrame* main_frame = webview()->GetMainFrame();
3095 WebDataSource* ds = main_frame->GetDataSource();
3096 WebNavigationType nav_type = ds->GetNavigationType();
3097 Time request_time = ds->GetRequestTime();
3098 Time start_load_time = ds->GetStartLoadTime();
3099 Time finish_document_load_time = ds->GetFinishDocumentLoadTime();
3100 Time finish_load_time = ds->GetFinishLoadTime();
3101 TimeDelta request_to_start = start_load_time - request_time;
3102 TimeDelta start_to_finish_doc = finish_document_load_time - start_load_time;
3103 TimeDelta finish_doc_to_finish = finish_load_time - finish_document_load_time;
3104 TimeDelta start_to_finish = finish_load_time - start_load_time;
3105 TimeDelta request_to_finish = finish_load_time - start_load_time;
3106
3107 UMA_HISTOGRAM_TIMES("Renderer.All.RequestToStart", request_to_start);
3108 UMA_HISTOGRAM_TIMES("Renderer.All.StartToFinishDoc", start_to_finish_doc);
3109 UMA_HISTOGRAM_TIMES("Renderer.All.FinishDocToFinish", finish_doc_to_finish);
3110 UMA_HISTOGRAM_TIMES("Renderer.All.StartToFinish", start_to_finish);
3111 UMA_HISTOGRAM_TIMES("Renderer.All.RequestToFinish", request_to_finish);
3112 switch (nav_type) {
3113 case WebNavigationTypeLinkClicked:
3114 UMA_HISTOGRAM_TIMES(
3115 "Renderer.LinkClicked.RequestToStart", request_to_start);
3116 UMA_HISTOGRAM_TIMES(
3117 "Renderer.LinkClicked.StartToFinishDoc", start_to_finish_doc);
3118 UMA_HISTOGRAM_TIMES(
3119 "Renderer.LinkClicked.FinishDocToFinish", finish_doc_to_finish);
3120 UMA_HISTOGRAM_TIMES(
3121 "Renderer.LinkClicked.RequestToFinish", request_to_finish);
3122 UMA_HISTOGRAM_TIMES(
3123 "Renderer.LinkClicked.StartToFinish", start_to_finish);
3124 break;
3125 case WebNavigationTypeFormSubmitted:
3126 UMA_HISTOGRAM_TIMES(
3127 "Renderer.FormSubmitted.RequestToStart", request_to_start);
3128 UMA_HISTOGRAM_TIMES(
3129 "Renderer.FormSubmitted.StartToFinishDoc", start_to_finish_doc);
3130 UMA_HISTOGRAM_TIMES(
3131 "Renderer.FormSubmitted.FinishDocToFinish", finish_doc_to_finish);
3132 UMA_HISTOGRAM_TIMES(
3133 "Renderer.FormSubmitted.RequestToFinish", request_to_finish);
3134 UMA_HISTOGRAM_TIMES(
3135 "Renderer.FormSubmitted.StartToFinish", start_to_finish);
3136 break;
3137 case WebNavigationTypeBackForward:
3138 UMA_HISTOGRAM_TIMES(
3139 "Renderer.BackForward.RequestToStart", request_to_start);
3140 UMA_HISTOGRAM_TIMES(
3141 "Renderer.BackForward.StartToFinishDoc", start_to_finish_doc);
3142 UMA_HISTOGRAM_TIMES(
3143 "Renderer.BackForward.FinishDocToFinish", finish_doc_to_finish);
3144 UMA_HISTOGRAM_TIMES(
3145 "Renderer.BackForward.RequestToFinish", request_to_finish);
3146 UMA_HISTOGRAM_TIMES(
3147 "Renderer.BackForward.StartToFinish", start_to_finish);
3148 break;
3149 case WebNavigationTypeReload:
3150 UMA_HISTOGRAM_TIMES(
3151 "Renderer.Reload.RequestToStart", request_to_start);
3152 UMA_HISTOGRAM_TIMES(
3153 "Renderer.Reload.StartToFinishDoc", start_to_finish_doc);
3154 UMA_HISTOGRAM_TIMES(
3155 "Renderer.Reload.FinishDocToFinish", finish_doc_to_finish);
3156 UMA_HISTOGRAM_TIMES(
3157 "Renderer.Reload.RequestToFinish", request_to_finish);
3158 UMA_HISTOGRAM_TIMES(
3159 "Renderer.Reload.StartToFinish", start_to_finish);
3160 break;
3161 case WebNavigationTypeFormResubmitted:
3162 UMA_HISTOGRAM_TIMES(
3163 "Renderer.FormResubmitted.RequestToStart", request_to_start);
3164 UMA_HISTOGRAM_TIMES(
3165 "Renderer.FormResubmitted.StartToFinishDoc", start_to_finish_doc);
3166 UMA_HISTOGRAM_TIMES(
3167 "Renderer.FormResubmitted.FinishDocToFinish", finish_doc_to_finish);
3168 UMA_HISTOGRAM_TIMES(
3169 "Renderer.FormResubmitted.RequestToFinish", request_to_finish);
3170 UMA_HISTOGRAM_TIMES(
3171 "Renderer.FormResubmitted.StartToFinish", start_to_finish);
3172 break;
3173 case WebNavigationTypeOther:
3174 UMA_HISTOGRAM_TIMES(
3175 "Renderer.Other.RequestToStart", request_to_start);
3176 UMA_HISTOGRAM_TIMES(
3177 "Renderer.Other.StartToFinishDoc", start_to_finish_doc);
3178 UMA_HISTOGRAM_TIMES(
3179 "Renderer.Other.FinishDocToFinish", finish_doc_to_finish);
3180 UMA_HISTOGRAM_TIMES(
3181 "Renderer.Other.RequestToFinish", request_to_finish);
3182 UMA_HISTOGRAM_TIMES(
3183 "Renderer.Other.StartToFinish", start_to_finish);
3184 break;
3185 }
3186}