blob: e94452ee48f87b5f4844b77c996f7a4237bc8dc7 [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2// 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"
initial.commit09911bf2008-07-26 23:55:2947#include "net/base/escape.h"
48#include "net/base/net_errors.h"
[email protected]88a3ecc2009-03-19 17:36:2249#include "printing/units.h"
[email protected]c399a8a2008-11-22 19:38:0050#include "skia/ext/bitmap_platform_device.h"
[email protected]83c9e6552008-12-03 16:22:1051#include "skia/ext/image_operations.h"
[email protected]4f999132009-03-31 18:08:4052#include "third_party/WebKit/WebKit/chromium/public/WebScriptSource.h"
[email protected]ba4b17f2009-02-11 21:32:2953#include "webkit/default_plugin/default_plugin_shared.h"
initial.commit09911bf2008-07-26 23:55:2954#include "webkit/glue/dom_operations.h"
55#include "webkit/glue/dom_serializer.h"
56#include "webkit/glue/password_form.h"
[email protected]ba4b17f2009-02-11 21:32:2957#include "webkit/glue/plugins/plugin_list.h"
initial.commit09911bf2008-07-26 23:55:2958#include "webkit/glue/searchable_form_data.h"
[email protected]6a983b42009-03-20 20:12:2559#include "webkit/glue/webaccessibilitymanager_impl.h"
initial.commit09911bf2008-07-26 23:55:2960#include "webkit/glue/webdatasource.h"
[email protected]611cad42009-03-16 18:51:3461#include "webkit/glue/webdevtoolsagent_delegate.h"
initial.commit09911bf2008-07-26 23:55:2962#include "webkit/glue/webdropdata.h"
63#include "webkit/glue/weberror.h"
64#include "webkit/glue/webframe.h"
65#include "webkit/glue/webhistoryitem.h"
initial.commit09911bf2008-07-26 23:55:2966#include "webkit/glue/webkit_glue.h"
67#include "webkit/glue/webpreferences.h"
[email protected]b94d3322009-02-12 19:49:0468#include "webkit/glue/webplugin_delegate.h"
initial.commit09911bf2008-07-26 23:55:2969#include "webkit/glue/webresponse.h"
70#include "webkit/glue/weburlrequest.h"
71#include "webkit/glue/webview.h"
initial.commit09911bf2008-07-26 23:55:2972
[email protected]6c8afae52009-01-22 02:24:5773#if defined(OS_WIN)
74// TODO(port): these files are currently Windows only because they concern:
[email protected]f8b6b6f2009-03-10 16:48:2675// * logging
[email protected]6c8afae52009-01-22 02:24:5776// * printing
77// * theming
78// * views
79#include "base/gfx/gdi_util.h"
80#include "base/gfx/native_theme.h"
81#include "chrome/common/gfx/emf.h"
[email protected]fcf19542009-03-30 21:24:0782#include "chrome/views/controls/message_box_view.h"
[email protected]6c8afae52009-01-22 02:24:5783#include "skia/ext/vector_canvas.h"
[email protected]6c8afae52009-01-22 02:24:5784#endif
85
[email protected]c20210e62009-04-03 21:39:2686using base::Time;
[email protected]e1acf6f2008-10-27 20:43:3387using base::TimeDelta;
[email protected]6a983b42009-03-20 20:12:2588using webkit_glue::WebAccessibility;
[email protected]0dea3ea2009-03-31 23:30:5989using WebKit::WebConsoleMessage;
[email protected]4f999132009-03-31 18:08:4090using WebKit::WebScriptSource;
[email protected]e1acf6f2008-10-27 20:43:3391
initial.commit09911bf2008-07-26 23:55:2992//-----------------------------------------------------------------------------
93
94// define to write the time necessary for thumbnail/DOM text retrieval,
95// respectively, into the system debug log
96// #define TIME_BITMAP_RETRIEVAL
97// #define TIME_TEXT_RETRIEVAL
98
99// maximum number of characters in the document to index, any text beyond this
100// point will be clipped
[email protected]6c8afae52009-01-22 02:24:57101static const size_t kMaxIndexChars = 65535;
initial.commit09911bf2008-07-26 23:55:29102
103// Size of the thumbnails that we'll generate
104static const int kThumbnailWidth = 196;
105static const int kThumbnailHeight = 136;
106
107// Delay in milliseconds that we'll wait before capturing the page contents
108// and thumbnail.
109static const int kDelayForCaptureMs = 500;
110
111// Typically, we capture the page data once the page is loaded.
112// Sometimes, the page never finishes to load, preventing the page capture
113// To workaround this problem, we always perform a capture after the following
114// delay.
115static const int kDelayForForcedCaptureMs = 6000;
116
[email protected]81a34412009-01-05 19:17:24117// The default value for RenderView.delay_seconds_for_form_state_sync_, see
118// that variable for more.
119const int kDefaultDelaySecondsForFormStateSync = 5;
initial.commit09911bf2008-07-26 23:55:29120
121// The next available page ID to use. This ensures that the page IDs are
122// globally unique in the renderer.
123static int32 next_page_id_ = 1;
124
[email protected]0aa55312008-10-17 21:53:08125// The maximum number of popups that can be spawned from one page.
126static const int kMaximumNumberOfUnacknowledgedPopups = 25;
127
initial.commit09911bf2008-07-26 23:55:29128static const char* const kUnreachableWebDataURL =
[email protected]9527f9c2009-01-29 18:35:42129 "chrome-ui://chromewebdata/";
initial.commit09911bf2008-07-26 23:55:29130
[email protected]50b691c2008-10-31 19:08:35131static const char* const kBackForwardNavigationScheme = "history";
132
initial.commit09911bf2008-07-26 23:55:29133namespace {
134
135// Associated with browser-initiated navigations to hold tracking data.
136class RenderViewExtraRequestData : public WebRequest::ExtraData {
137 public:
138 RenderViewExtraRequestData(int32 pending_page_id,
[email protected]c20210e62009-04-03 21:39:26139 PageTransition::Type transition,
140 Time request_time)
[email protected]6c8afae52009-01-22 02:24:57141 : transition_type(transition),
[email protected]c20210e62009-04-03 21:39:26142 request_time(request_time),
[email protected]6c8afae52009-01-22 02:24:57143 request_committed(false),
144 pending_page_id_(pending_page_id) {
initial.commit09911bf2008-07-26 23:55:29145 }
146
147 // Contains the page_id for this navigation or -1 if there is none yet.
148 int32 pending_page_id() const { return pending_page_id_; }
149
150 // Is this a new navigation?
151 bool is_new_navigation() const { return pending_page_id_ == -1; }
152
153 // Contains the transition type that the browser specified when it
154 // initiated the load.
155 PageTransition::Type transition_type;
[email protected]c20210e62009-04-03 21:39:26156 Time request_time;
initial.commit09911bf2008-07-26 23:55:29157
158 // True if we have already processed the "DidCommitLoad" event for this
159 // request. Used by session history.
160 bool request_committed;
161
162 private:
163 int32 pending_page_id_;
164
[email protected]4f3dc372009-02-24 00:10:29165 DISALLOW_COPY_AND_ASSIGN(RenderViewExtraRequestData);
initial.commit09911bf2008-07-26 23:55:29166};
167
168} // namespace
169
170///////////////////////////////////////////////////////////////////////////////
171
[email protected]81a34412009-01-05 19:17:24172RenderView::RenderView(RenderThreadBase* render_thread)
173 : RenderWidget(render_thread, true),
[email protected]81e63782009-02-27 19:35:09174 enabled_bindings_(0),
[email protected]e75cb49e2009-01-05 23:13:21175 target_url_status_(TARGET_NONE),
[email protected]81a34412009-01-05 19:17:24176 is_loading_(false),
[email protected]e75cb49e2009-01-05 23:13:21177 navigation_gesture_(NavigationGestureUnknown),
[email protected]81a34412009-01-05 19:17:24178 page_id_(-1),
179 last_page_id_sent_to_browser_(-1),
180 last_indexed_page_id_(-1),
[email protected]81a34412009-01-05 19:17:24181 opened_by_user_gesture_(true),
[email protected]bb063b72009-03-27 23:18:50182 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
[email protected]81a34412009-01-05 19:17:24183 first_default_plugin_(NULL),
[email protected]e4ac5df2009-03-17 15:33:11184 devtools_agent_(NULL),
[email protected]b75b7d072009-04-06 13:47:00185 devtools_agent_filter_(NULL),
[email protected]e4ac5df2009-03-17 15:33:11186 devtools_client_(NULL),
[email protected]81a34412009-01-05 19:17:24187 history_back_list_count_(0),
188 history_forward_list_count_(0),
189 disable_popup_blocking_(false),
190 has_unload_listener_(false),
191 decrement_shared_popup_at_destruction_(false),
[email protected]81a34412009-01-05 19:17:24192 form_field_autofill_request_id_(0),
193 popup_notification_visible_(false),
194 delay_seconds_for_form_state_sync_(kDefaultDelaySecondsForFormStateSync) {
[email protected]3a453fa2008-08-15 18:46:34195#ifdef CHROME_PERSONALIZATION
196 personalization_ = Personalization::CreateRendererPersonalization();
197#endif
initial.commit09911bf2008-07-26 23:55:29198}
199
200RenderView::~RenderView() {
[email protected]0aa55312008-10-17 21:53:08201 if (decrement_shared_popup_at_destruction_)
202 shared_popup_counter_->data--;
203
initial.commit09911bf2008-07-26 23:55:29204 // Clear any back-pointers that might still be held by plugins.
205 PluginDelegateList::iterator it = plugin_delegates_.begin();
206 while (it != plugin_delegates_.end()) {
207 (*it)->DropRenderView();
208 it = plugin_delegates_.erase(it);
209 }
210
[email protected]81a34412009-01-05 19:17:24211 render_thread_->RemoveFilter(debug_message_handler_);
[email protected]b75b7d072009-04-06 13:47:00212 render_thread_->RemoveFilter(devtools_agent_filter_);
[email protected]3a453fa2008-08-15 18:46:34213
214#ifdef CHROME_PERSONALIZATION
215 Personalization::CleanupRendererPersonalization(personalization_);
216 personalization_ = NULL;
217#endif
initial.commit09911bf2008-07-26 23:55:29218}
219
220/*static*/
[email protected]0aa55312008-10-17 21:53:08221RenderView* RenderView::Create(
[email protected]81a34412009-01-05 19:17:24222 RenderThreadBase* render_thread,
[email protected]18bcc3c2009-01-27 21:39:15223 gfx::NativeViewId parent_hwnd,
[email protected]1c4947f2009-01-15 22:25:11224 base::WaitableEvent* modal_dialog_event,
[email protected]0aa55312008-10-17 21:53:08225 int32 opener_id,
226 const WebPreferences& webkit_prefs,
227 SharedRenderViewCounter* counter,
228 int32 routing_id) {
initial.commit09911bf2008-07-26 23:55:29229 DCHECK(routing_id != MSG_ROUTING_NONE);
[email protected]81a34412009-01-05 19:17:24230 scoped_refptr<RenderView> view = new RenderView(render_thread);
initial.commit09911bf2008-07-26 23:55:29231 view->Init(parent_hwnd,
232 modal_dialog_event,
233 opener_id,
234 webkit_prefs,
[email protected]0aa55312008-10-17 21:53:08235 counter,
initial.commit09911bf2008-07-26 23:55:29236 routing_id); // adds reference
237 return view;
238}
239
240/*static*/
241void RenderView::SetNextPageID(int32 next_page_id) {
242 // This method should only be called during process startup, and the given
243 // page id had better not exceed our current next page id!
244 DCHECK(next_page_id_ == 1);
245 DCHECK(next_page_id >= next_page_id_);
246 next_page_id_ = next_page_id;
247}
248
249void RenderView::PluginDestroyed(WebPluginDelegateProxy* proxy) {
250 PluginDelegateList::iterator it =
251 std::find(plugin_delegates_.begin(), plugin_delegates_.end(), proxy);
252 DCHECK(it != plugin_delegates_.end());
253 plugin_delegates_.erase(it);
254 // If the plugin is deleted, we need to clear our reference in case user
255 // clicks the info bar to install. Unfortunately we are getting
256 // PluginDestroyed in single process mode. However, that is not a huge
257 // concern.
[email protected]6c8afae52009-01-22 02:24:57258#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29259 if (proxy == first_default_plugin_)
260 first_default_plugin_ = NULL;
[email protected]6c8afae52009-01-22 02:24:57261#else
262 // TODO(port): because of the headers that we aren't including, the compiler
263 // has only seen a forward decl, not the subclass relation. Thus it doesn't
264 // know that the two pointer types compared above are comparable. Once we
265 // port and include the headers this problem should go away.
266 NOTIMPLEMENTED();
267#endif
initial.commit09911bf2008-07-26 23:55:29268}
269
[email protected]690a99c2009-01-06 16:48:45270void RenderView::PluginCrashed(const FilePath& plugin_path) {
initial.commit09911bf2008-07-26 23:55:29271 Send(new ViewHostMsg_CrashedPlugin(routing_id_, plugin_path));
272}
273
274
275void RenderView::JSOutOfMemory() {
276 Send(new ViewHostMsg_JSOutOfMemory(routing_id_));
277}
278
[email protected]18bcc3c2009-01-27 21:39:15279void RenderView::Init(gfx::NativeViewId parent_hwnd,
[email protected]1c4947f2009-01-15 22:25:11280 base::WaitableEvent* modal_dialog_event,
initial.commit09911bf2008-07-26 23:55:29281 int32 opener_id,
282 const WebPreferences& webkit_prefs,
[email protected]0aa55312008-10-17 21:53:08283 SharedRenderViewCounter* counter,
initial.commit09911bf2008-07-26 23:55:29284 int32 routing_id) {
285 DCHECK(!webview());
286
287 if (opener_id != MSG_ROUTING_NONE)
288 opener_id_ = opener_id;
289
[email protected]0aa55312008-10-17 21:53:08290 if (counter) {
291 shared_popup_counter_ = counter;
292 shared_popup_counter_->data++;
293 decrement_shared_popup_at_destruction_ = true;
294 } else {
295 shared_popup_counter_ = new SharedRenderViewCounter(0);
296 decrement_shared_popup_at_destruction_ = false;
297 }
298
[email protected]b75b7d072009-04-06 13:47:00299 devtools_agent_.reset(new DevToolsAgent(routing_id, this));
300 devtools_agent_filter_ = new DevToolsAgentFilter();
[email protected]c5b3b5e2009-02-13 06:41:11301 webwidget_ = WebView::Create(this, webkit_prefs);
initial.commit09911bf2008-07-26 23:55:29302
[email protected]2e417c82009-04-02 22:30:26303#if defined(OS_LINUX)
304 // We have to enable ourselves as the editor delegate on linux so we can copy
305 // text selections to the X clipboard.
306 webview()->SetUseEditorDelegate(true);
307#endif
308
initial.commit09911bf2008-07-26 23:55:29309 // Don't let WebCore keep a B/F list - we have our own.
310 // We let it keep 1 entry because FrameLoader::goToItem expects an item in the
311 // backForwardList, which is used only in ASSERTs.
312 webview()->SetBackForwardListSize(1);
313
314 routing_id_ = routing_id;
[email protected]81a34412009-01-05 19:17:24315 render_thread_->AddRoute(routing_id_, this);
initial.commit09911bf2008-07-26 23:55:29316 // Take a reference on behalf of the RenderThread. This will be balanced
317 // when we receive ViewMsg_Close.
318 AddRef();
319
320 // If this is a popup, we must wait for the CreatingNew_ACK message before
321 // completing initialization. Otherwise, we can finish it now.
322 if (opener_id == MSG_ROUTING_NONE) {
323 did_show_ = true;
324 CompleteInit(parent_hwnd);
325 }
326
327 host_window_ = parent_hwnd;
[email protected]1c4947f2009-01-15 22:25:11328 modal_dialog_event_.reset(modal_dialog_event);
initial.commit09911bf2008-07-26 23:55:29329
[email protected]bb975362009-01-21 01:00:22330 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
[email protected]81e63782009-02-27 19:35:09331 if (command_line.HasSwitch(switches::kDomAutomationController))
332 enabled_bindings_ |= BindingsPolicy::DOM_AUTOMATION;
initial.commit09911bf2008-07-26 23:55:29333 disable_popup_blocking_ =
334 command_line.HasSwitch(switches::kDisablePopupBlocking);
335
336 debug_message_handler_ = new DebugMessageHandler(this);
[email protected]81a34412009-01-05 19:17:24337 render_thread_->AddFilter(debug_message_handler_);
[email protected]b75b7d072009-04-06 13:47:00338 render_thread_->AddFilter(devtools_agent_filter_);
initial.commit09911bf2008-07-26 23:55:29339}
340
341void RenderView::OnMessageReceived(const IPC::Message& message) {
[email protected]f8b6b6f2009-03-10 16:48:26342 WebFrame* main_frame = webview() ? webview()->GetMainFrame() : NULL;
343 renderer_logging::ScopedActiveRenderingURLSetter url_setter(
344 main_frame ? main_frame->GetURL() : GURL());
[email protected]f8b6b6f2009-03-10 16:48:26345
[email protected]b2abac72009-02-26 12:39:28346 // If this is developer tools renderer intercept tools messages first.
[email protected]e4ac5df2009-03-17 15:33:11347 if (devtools_client_.get() && devtools_client_->OnMessageReceived(message))
[email protected]b2abac72009-02-26 12:39:28348 return;
[email protected]b75b7d072009-04-06 13:47:00349 if (devtools_agent_->OnMessageReceived(message))
350 return;
[email protected]b2abac72009-02-26 12:39:28351
initial.commit09911bf2008-07-26 23:55:29352 IPC_BEGIN_MESSAGE_MAP(RenderView, message)
initial.commit09911bf2008-07-26 23:55:29353 IPC_MESSAGE_HANDLER(ViewMsg_CaptureThumbnail, SendThumbnail)
initial.commit09911bf2008-07-26 23:55:29354 IPC_MESSAGE_HANDLER(ViewMsg_PrintPages, OnPrintPages)
355 IPC_MESSAGE_HANDLER(ViewMsg_Navigate, OnNavigate)
356 IPC_MESSAGE_HANDLER(ViewMsg_Stop, OnStop)
357 IPC_MESSAGE_HANDLER(ViewMsg_LoadAlternateHTMLText, OnLoadAlternateHTMLText)
358 IPC_MESSAGE_HANDLER(ViewMsg_StopFinding, OnStopFinding)
359 IPC_MESSAGE_HANDLER(ViewMsg_Undo, OnUndo)
360 IPC_MESSAGE_HANDLER(ViewMsg_Redo, OnRedo)
361 IPC_MESSAGE_HANDLER(ViewMsg_Cut, OnCut)
362 IPC_MESSAGE_HANDLER(ViewMsg_Copy, OnCopy)
363 IPC_MESSAGE_HANDLER(ViewMsg_Paste, OnPaste)
364 IPC_MESSAGE_HANDLER(ViewMsg_Replace, OnReplace)
[email protected]bbbd545c2008-12-15 20:18:04365 IPC_MESSAGE_HANDLER(ViewMsg_ToggleSpellCheck, OnToggleSpellCheck)
initial.commit09911bf2008-07-26 23:55:29366 IPC_MESSAGE_HANDLER(ViewMsg_Delete, OnDelete)
367 IPC_MESSAGE_HANDLER(ViewMsg_SelectAll, OnSelectAll)
368 IPC_MESSAGE_HANDLER(ViewMsg_CopyImageAt, OnCopyImageAt)
369 IPC_MESSAGE_HANDLER(ViewMsg_Find, OnFind)
[email protected]630e26b2008-10-14 22:55:17370 IPC_MESSAGE_HANDLER(ViewMsg_Zoom, OnZoom)
[email protected]ea8c7452009-04-02 20:47:06371 IPC_MESSAGE_HANDLER(ViewMsg_InsertText, OnInsertText)
initial.commit09911bf2008-07-26 23:55:29372 IPC_MESSAGE_HANDLER(ViewMsg_SetPageEncoding, OnSetPageEncoding)
373 IPC_MESSAGE_HANDLER(ViewMsg_InspectElement, OnInspectElement)
374 IPC_MESSAGE_HANDLER(ViewMsg_ShowJavaScriptConsole, OnShowJavaScriptConsole)
[email protected]b2abac72009-02-26 12:39:28375 IPC_MESSAGE_HANDLER(ViewMsg_SetupDevToolsClient, OnSetupDevToolsClient)
initial.commit09911bf2008-07-26 23:55:29376 IPC_MESSAGE_HANDLER(ViewMsg_DownloadImage, OnDownloadImage)
377 IPC_MESSAGE_HANDLER(ViewMsg_ScriptEvalRequest, OnScriptEvalRequest)
[email protected]1810e132009-03-24 23:35:48378 IPC_MESSAGE_HANDLER(ViewMsg_CSSInsertRequest, OnCSSInsertRequest)
initial.commit09911bf2008-07-26 23:55:29379 IPC_MESSAGE_HANDLER(ViewMsg_AddMessageToConsole, OnAddMessageToConsole)
380 IPC_MESSAGE_HANDLER(ViewMsg_DebugAttach, OnDebugAttach)
[email protected]88010e082008-08-29 11:07:40381 IPC_MESSAGE_HANDLER(ViewMsg_DebugDetach, OnDebugDetach)
initial.commit09911bf2008-07-26 23:55:29382 IPC_MESSAGE_HANDLER(ViewMsg_ReservePageIDRange, OnReservePageIDRange)
383 IPC_MESSAGE_HANDLER(ViewMsg_UploadFile, OnUploadFileRequest)
384 IPC_MESSAGE_HANDLER(ViewMsg_FormFill, OnFormFill)
385 IPC_MESSAGE_HANDLER(ViewMsg_FillPasswordForm, OnFillPasswordForm)
386 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragEnter, OnDragTargetDragEnter)
387 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragOver, OnDragTargetDragOver)
388 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragLeave, OnDragTargetDragLeave)
389 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDrop, OnDragTargetDrop)
[email protected]18cb2572008-08-21 20:34:45390 IPC_MESSAGE_HANDLER(ViewMsg_AllowBindings, OnAllowBindings)
initial.commit09911bf2008-07-26 23:55:29391 IPC_MESSAGE_HANDLER(ViewMsg_SetDOMUIProperty, OnSetDOMUIProperty)
[email protected]266eb6f2008-09-30 23:56:50392 IPC_MESSAGE_HANDLER(ViewMsg_DragSourceEndedOrMoved,
393 OnDragSourceEndedOrMoved)
initial.commit09911bf2008-07-26 23:55:29394 IPC_MESSAGE_HANDLER(ViewMsg_DragSourceSystemDragEnded,
395 OnDragSourceSystemDragEnded)
396 IPC_MESSAGE_HANDLER(ViewMsg_SetInitialFocus, OnSetInitialFocus)
397 IPC_MESSAGE_HANDLER(ViewMsg_FindReplyACK, OnFindReplyAck)
398 IPC_MESSAGE_HANDLER(ViewMsg_UpdateTargetURL_ACK, OnUpdateTargetURLAck)
399 IPC_MESSAGE_HANDLER(ViewMsg_UpdateWebPreferences, OnUpdateWebPreferences)
400 IPC_MESSAGE_HANDLER(ViewMsg_SetAltErrorPageURL, OnSetAltErrorPageURL)
401 IPC_MESSAGE_HANDLER(ViewMsg_InstallMissingPlugin, OnInstallMissingPlugin)
402 IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse)
403 IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode, OnEnableViewSourceMode)
404 IPC_MESSAGE_HANDLER(ViewMsg_UpdateBackForwardListCount,
405 OnUpdateBackForwardListCount)
406 IPC_MESSAGE_HANDLER(ViewMsg_GetAllSavableResourceLinksForCurrentPage,
407 OnGetAllSavableResourceLinksForCurrentPage)
[email protected]f09c7182009-03-10 12:54:04408 IPC_MESSAGE_HANDLER(
409 ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks,
410 OnGetSerializedHtmlDataForCurrentPageWithLocalLinks)
initial.commit09911bf2008-07-26 23:55:29411 IPC_MESSAGE_HANDLER(ViewMsg_GetApplicationInfo, OnGetApplicationInfo)
[email protected]266eb6f2008-09-30 23:56:50412 IPC_MESSAGE_HANDLER(ViewMsg_GetAccessibilityInfo, OnGetAccessibilityInfo)
413 IPC_MESSAGE_HANDLER(ViewMsg_ClearAccessibilityInfo,
414 OnClearAccessibilityInfo)
initial.commit09911bf2008-07-26 23:55:29415 IPC_MESSAGE_HANDLER(ViewMsg_ShouldClose, OnMsgShouldClose)
416 IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage)
417 IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged)
[email protected]3c17b9c2008-08-26 02:08:00418#ifdef CHROME_PERSONALIZATION
[email protected]1cc879642008-08-26 01:27:35419 IPC_MESSAGE_HANDLER(ViewMsg_PersonalizationEvent, OnPersonalizationEvent)
[email protected]3c17b9c2008-08-26 02:08:00420#endif
[email protected]18cb2572008-08-21 20:34:45421 IPC_MESSAGE_HANDLER(ViewMsg_HandleMessageFromExternalHost,
422 OnMessageFromExternalHost)
[email protected]0aa55312008-10-17 21:53:08423 IPC_MESSAGE_HANDLER(ViewMsg_DisassociateFromPopupCount,
424 OnDisassociateFromPopupCount)
[email protected]0ebf3872008-11-07 21:35:03425 IPC_MESSAGE_HANDLER(ViewMsg_AutofillSuggestions,
426 OnReceivedAutofillSuggestions)
[email protected]634a6f92008-12-01 21:39:31427 IPC_MESSAGE_HANDLER(ViewMsg_PopupNotificationVisiblityChanged,
428 OnPopupNotificationVisiblityChanged)
[email protected]6f56d482009-02-20 05:02:56429 IPC_MESSAGE_HANDLER(ViewMsg_RequestAudioPacket, OnRequestAudioPacket)
430 IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamCreated, OnAudioStreamCreated)
431 IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamStateChanged,
432 OnAudioStreamStateChanged)
433 IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamVolume, OnAudioStreamVolume)
[email protected]30f75e62009-02-25 22:01:00434 IPC_MESSAGE_HANDLER(ViewMsg_MoveOrResizeStarted, OnMoveOrResizeStarted)
[email protected]309d7a282009-03-24 09:18:27435 IPC_MESSAGE_HANDLER(ViewMsg_ExtensionResponse, OnExtensionResponse)
[email protected]2e417c82009-04-02 22:30:26436 IPC_MESSAGE_HANDLER(ViewMsg_RequestSelectionText, OnRequestSelectionText)
[email protected]634a6f92008-12-01 21:39:31437
initial.commit09911bf2008-07-26 23:55:29438 // Have the super handle all other messages.
439 IPC_MESSAGE_UNHANDLED(RenderWidget::OnMessageReceived(message))
440 IPC_END_MESSAGE_MAP()
441}
442
initial.commit09911bf2008-07-26 23:55:29443void RenderView::SendThumbnail() {
444 WebFrame* main_frame = webview()->GetMainFrame();
445 if (!main_frame)
446 return;
447
448 // get the URL for this page
449 GURL url(main_frame->GetURL());
450 if (url.is_empty())
451 return;
452
453 if (size_.IsEmpty())
454 return; // Don't create an empty thumbnail!
455
456 ThumbnailScore score;
457 SkBitmap thumbnail;
[email protected]b6e4bec2008-11-12 01:17:15458 if (!CaptureThumbnail(main_frame, kThumbnailWidth, kThumbnailHeight,
459 &thumbnail, &score))
460 return;
461
initial.commit09911bf2008-07-26 23:55:29462 // send the thumbnail message to the browser process
[email protected]674741932009-02-04 23:44:46463 Send(new ViewHostMsg_Thumbnail(routing_id_, url, score, thumbnail));
initial.commit09911bf2008-07-26 23:55:29464}
465
[email protected]2e417c82009-04-02 22:30:26466void RenderView::OnRequestSelectionText() {
467 Send(new ViewHostMsg_SetSelectionText(routing_id_, selection_text_));
468}
469
initial.commit09911bf2008-07-26 23:55:29470void RenderView::PrintPage(const ViewMsg_PrintPage_Params& params,
[email protected]88a3ecc2009-03-19 17:36:22471 const gfx::Size& canvas_size,
initial.commit09911bf2008-07-26 23:55:29472 WebFrame* frame) {
[email protected]6c8afae52009-01-22 02:24:57473#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29474 // Generate a memory-based EMF file. The EMF will use the current screen's
475 // DPI.
476 gfx::Emf emf;
477
478 emf.CreateDc(NULL, NULL);
479 HDC hdc = emf.hdc();
480 DCHECK(hdc);
[email protected]21f527e2008-12-17 23:29:40481 skia::PlatformDeviceWin::InitializeDC(hdc);
[email protected]0e92fa32009-03-31 20:39:33482 // Since WebKit extends the page width depending on the magical shrink
[email protected]0dea3ea2009-03-31 23:30:59483 // factor we make sure the canvas covers the worst case scenario
[email protected]0e92fa32009-03-31 20:39:33484 // (x2.0 currently). PrintContext will then set the correct clipping region.
485 int size_x = static_cast<int>(canvas_size.width() * params.params.max_shrink);
486 int size_y = static_cast<int>(canvas_size.height() *
487 params.params.max_shrink);
[email protected]88a3ecc2009-03-19 17:36:22488 // Calculate the dpi adjustment.
489 float shrink = static_cast<float>(canvas_size.width()) /
490 params.params.printable_size.width();
initial.commit09911bf2008-07-26 23:55:29491#if 0
492 // TODO(maruel): This code is kept for testing until the 100% GDI drawing
493 // code is stable. maruels use this code's output as a reference when the
494 // GDI drawing code fails.
495
496 // Mix of Skia and GDI based.
[email protected]88a3ecc2009-03-19 17:36:22497 skia::PlatformCanvasWin canvas(size_x, size_y, true);
initial.commit09911bf2008-07-26 23:55:29498 canvas.drawARGB(255, 255, 255, 255, SkPorterDuff::kSrc_Mode);
[email protected]88a3ecc2009-03-19 17:36:22499 float webkit_shrink = frame->PrintPage(params.page_number, &canvas);
500 if (shrink <= 0) {
initial.commit09911bf2008-07-26 23:55:29501 NOTREACHED() << "Printing page " << params.page_number << " failed.";
[email protected]88a3ecc2009-03-19 17:36:22502 } else {
503 // Update the dpi adjustment with the "page shrink" calculated in webkit.
504 shrink /= webkit_shrink;
initial.commit09911bf2008-07-26 23:55:29505 }
506
507 // Create a BMP v4 header that we can serialize.
508 BITMAPV4HEADER bitmap_header;
[email protected]88a3ecc2009-03-19 17:36:22509 gfx::CreateBitmapV4Header(size_x, size_y, &bitmap_header);
initial.commit09911bf2008-07-26 23:55:29510 const SkBitmap& src_bmp = canvas.getDevice()->accessBitmap(true);
511 SkAutoLockPixels src_lock(src_bmp);
512 int retval = StretchDIBits(hdc,
513 0,
514 0,
[email protected]88a3ecc2009-03-19 17:36:22515 size_x, size_y,
initial.commit09911bf2008-07-26 23:55:29516 0, 0,
[email protected]88a3ecc2009-03-19 17:36:22517 size_x, size_y,
initial.commit09911bf2008-07-26 23:55:29518 src_bmp.getPixels(),
519 reinterpret_cast<BITMAPINFO*>(&bitmap_header),
520 DIB_RGB_COLORS,
521 SRCCOPY);
522 DCHECK(retval != GDI_ERROR);
523#else
524 // 100% GDI based.
[email protected]88a3ecc2009-03-19 17:36:22525 skia::VectorCanvas canvas(hdc, size_x, size_y);
526 float webkit_shrink = frame->PrintPage(params.page_number, &canvas);
527 if (shrink <= 0) {
initial.commit09911bf2008-07-26 23:55:29528 NOTREACHED() << "Printing page " << params.page_number << " failed.";
[email protected]88a3ecc2009-03-19 17:36:22529 } else {
530 // Update the dpi adjustment with the "page shrink" calculated in webkit.
531 shrink /= webkit_shrink;
initial.commit09911bf2008-07-26 23:55:29532 }
533#endif
534
535 // Done printing. Close the device context to retrieve the compiled EMF.
536 if (!emf.CloseDc()) {
537 NOTREACHED() << "EMF failed";
538 }
539
540 // Get the size of the compiled EMF.
541 unsigned buf_size = emf.GetDataSize();
542 DCHECK(buf_size > 128);
543 ViewHostMsg_DidPrintPage_Params page_params;
544 page_params.data_size = 0;
545 page_params.emf_data_handle = NULL;
546 page_params.page_number = params.page_number;
547 page_params.document_cookie = params.params.document_cookie;
548 page_params.actual_shrink = shrink;
[email protected]176aa482008-11-14 03:25:15549 base::SharedMemory shared_buf;
initial.commit09911bf2008-07-26 23:55:29550
551 // http://msdn2.microsoft.com/en-us/library/ms535522.aspx
552 // Windows 2000/XP: When a page in a spooled file exceeds approximately 350
553 // MB, it can fail to print and not send an error message.
554 if (buf_size < 350*1024*1024) {
555 // Allocate a shared memory buffer to hold the generated EMF data.
556 if (shared_buf.Create(L"", false, false, buf_size) &&
557 shared_buf.Map(buf_size)) {
558 // Copy the bits into shared memory.
559 if (emf.GetData(shared_buf.memory(), buf_size)) {
560 page_params.emf_data_handle = shared_buf.handle();
561 page_params.data_size = buf_size;
562 } else {
563 NOTREACHED() << "GetData() failed";
564 }
565 shared_buf.Unmap();
566 } else {
567 NOTREACHED() << "Buffer allocation failed";
568 }
569 } else {
570 NOTREACHED() << "Buffer too large: " << buf_size;
571 }
572 emf.CloseEmf();
573 if (Send(new ViewHostMsg_DuplicateSection(routing_id_,
574 page_params.emf_data_handle,
575 &page_params.emf_data_handle))) {
576 Send(new ViewHostMsg_DidPrintPage(routing_id_, page_params));
577 }
[email protected]6c8afae52009-01-22 02:24:57578#else // defined(OS_WIN)
579 // TODO(port) implement printing
580 NOTIMPLEMENTED();
581#endif
initial.commit09911bf2008-07-26 23:55:29582}
583
[email protected]068637222009-01-29 16:58:07584void RenderView::OnPrintPages() {
initial.commit09911bf2008-07-26 23:55:29585 DCHECK(webview());
[email protected]068637222009-01-29 16:58:07586 if (webview()) {
587 // The renderer own the control flow as if it was a window.print() call.
588 ScriptedPrint(webview()->GetMainFrame());
initial.commit09911bf2008-07-26 23:55:29589 }
initial.commit09911bf2008-07-26 23:55:29590}
591
592void RenderView::PrintPages(const ViewMsg_PrintPages_Params& params,
593 WebFrame* frame) {
[email protected]88a3ecc2009-03-19 17:36:22594 int page_count = 0;
595 gfx::Size canvas_size;
596 canvas_size.set_width(
597 printing::ConvertUnit(params.params.printable_size.width(),
598 static_cast<int>(params.params.dpi),
599 params.params.desired_dpi));
600 canvas_size.set_height(
601 printing::ConvertUnit(params.params.printable_size.height(),
602 static_cast<int>(params.params.dpi),
603 params.params.desired_dpi));
604 frame->BeginPrint(canvas_size, &page_count);
initial.commit09911bf2008-07-26 23:55:29605 Send(new ViewHostMsg_DidGetPrintedPagesCount(routing_id_,
606 params.params.document_cookie,
[email protected]88a3ecc2009-03-19 17:36:22607 page_count));
608 if (page_count) {
initial.commit09911bf2008-07-26 23:55:29609 ViewMsg_PrintPage_Params page_params;
610 page_params.params = params.params;
611 if (params.pages.empty()) {
[email protected]88a3ecc2009-03-19 17:36:22612 for (int i = 0; i < page_count; ++i) {
initial.commit09911bf2008-07-26 23:55:29613 page_params.page_number = i;
[email protected]88a3ecc2009-03-19 17:36:22614 PrintPage(page_params, canvas_size, frame);
initial.commit09911bf2008-07-26 23:55:29615 }
616 } else {
617 for (size_t i = 0; i < params.pages.size(); ++i) {
618 page_params.page_number = params.pages[i];
[email protected]88a3ecc2009-03-19 17:36:22619 PrintPage(page_params, canvas_size, frame);
initial.commit09911bf2008-07-26 23:55:29620 }
621 }
622 }
[email protected]88a3ecc2009-03-19 17:36:22623 frame->EndPrint();
initial.commit09911bf2008-07-26 23:55:29624}
625
626void RenderView::CapturePageInfo(int load_id, bool preliminary_capture) {
627 if (load_id != page_id_)
628 return; // this capture call is no longer relevant due to navigation
629 if (load_id == last_indexed_page_id_)
630 return; // we already indexed this page
631
632 if (!webview())
633 return;
634
635 WebFrame* main_frame = webview()->GetMainFrame();
636 if (!main_frame)
637 return;
638
639 // Don't index/capture pages that are in view source mode.
640 if (main_frame->GetInViewSourceMode())
641 return;
642
643 // Don't index/capture pages that failed to load. This only checks the top
644 // level frame so the thumbnail may contain a frame that failed to load.
645 WebDataSource* ds = main_frame->GetDataSource();
646 if (ds && ds->HasUnreachableURL())
647 return;
648
649 if (!preliminary_capture)
650 last_indexed_page_id_ = load_id;
651
652 // get the URL for this page
653 GURL url(main_frame->GetURL());
654 if (url.is_empty())
655 return;
656
657 // full text
658 std::wstring contents;
659 CaptureText(main_frame, &contents);
660 if (contents.size()) {
661 // Send the text to the browser for indexing.
662 Send(new ViewHostMsg_PageContents(url, load_id, contents));
663 }
664
665 // thumbnail
666 SendThumbnail();
667}
668
669void RenderView::CaptureText(WebFrame* frame, std::wstring* contents) {
670 contents->clear();
671 if (!frame)
672 return;
673
[email protected]0faf0bd92008-09-09 20:53:27674 // Don't index any https pages. People generally don't want their bank
675 // accounts, etc. indexed on their computer, especially since some of these
676 // things are not marked cachable.
677 // TODO(brettw) we may want to consider more elaborate heuristics such as
678 // the cachability of the page. We may also want to consider subframes (this
679 // test will still index subframes if the subframe is SSL).
680 if (frame->GetURL().SchemeIsSecure())
681 return;
682
initial.commit09911bf2008-07-26 23:55:29683#ifdef TIME_TEXT_RETRIEVAL
684 double begin = time_util::GetHighResolutionTimeNow();
685#endif
686
687 // get the contents of the frame
688 frame->GetContentAsPlainText(kMaxIndexChars, contents);
689
690#ifdef TIME_TEXT_RETRIEVAL
691 double end = time_util::GetHighResolutionTimeNow();
692 char buf[128];
693 sprintf_s(buf, "%d chars retrieved for indexing in %gms\n",
694 contents.size(), (end - begin)*1000);
695 OutputDebugStringA(buf);
696#endif
697
698 // When the contents are clipped to the maximum, we don't want to have a
699 // partial word indexed at the end that might have been clipped. Therefore,
700 // terminate the string at the last space to ensure no words are clipped.
701 if (contents->size() == kMaxIndexChars) {
702 size_t last_space_index = contents->find_last_of(kWhitespaceWide);
703 if (last_space_index == std::wstring::npos)
704 return; // don't index if we got a huge block of text with no spaces
705 contents->resize(last_space_index);
706 }
707}
708
[email protected]b6e4bec2008-11-12 01:17:15709bool RenderView::CaptureThumbnail(WebFrame* frame,
initial.commit09911bf2008-07-26 23:55:29710 int w,
711 int h,
712 SkBitmap* thumbnail,
713 ThumbnailScore* score) {
714#ifdef TIME_BITMAP_RETRIEVAL
715 double begin = time_util::GetHighResolutionTimeNow();
716#endif
717
[email protected]21f527e2008-12-17 23:29:40718 scoped_ptr<skia::BitmapPlatformDevice> device;
[email protected]b6e4bec2008-11-12 01:17:15719 if (!frame->CaptureImage(&device, true))
720 return false;
721
722 const SkBitmap& src_bmp = device->accessBitmap(false);
initial.commit09911bf2008-07-26 23:55:29723
724 SkRect dest_rect;
725 dest_rect.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
726 float dest_aspect = dest_rect.width() / dest_rect.height();
727
728 // Get the src rect so that we can preserve the aspect ratio while filling
729 // the destination.
730 SkIRect src_rect;
731 if (src_bmp.width() < dest_rect.width() ||
732 src_bmp.height() < dest_rect.height()) {
733 // Source image is smaller: we clip the part of source image within the
734 // dest rect, and then stretch it to fill the dest rect. We don't respect
735 // the aspect ratio in this case.
736 src_rect.set(0, 0, static_cast<S16CPU>(dest_rect.width()),
737 static_cast<S16CPU>(dest_rect.height()));
738 score->good_clipping = false;
739 } else {
740 float src_aspect = static_cast<float>(src_bmp.width()) / src_bmp.height();
741 if (src_aspect > dest_aspect) {
742 // Wider than tall, clip horizontally: we center the smaller thumbnail in
743 // the wider screen.
744 S16CPU new_width = static_cast<S16CPU>(src_bmp.height() * dest_aspect);
745 S16CPU x_offset = (src_bmp.width() - new_width) / 2;
746 src_rect.set(x_offset, 0, new_width + x_offset, src_bmp.height());
747 score->good_clipping = false;
748 } else {
749 src_rect.set(0, 0, src_bmp.width(),
750 static_cast<S16CPU>(src_bmp.width() / dest_aspect));
751 score->good_clipping = true;
752 }
753 }
754
755 score->at_top = (frame->ScrollOffset().height() == 0);
756
757 SkBitmap subset;
[email protected]b6e4bec2008-11-12 01:17:15758 device->accessBitmap(false).extractSubset(&subset, src_rect);
initial.commit09911bf2008-07-26 23:55:29759
760 // Resample the subset that we want to get it the right size.
[email protected]465b34b72008-12-12 20:19:14761 *thumbnail = skia::ImageOperations::Resize(
762 subset, skia::ImageOperations::RESIZE_LANCZOS3, w, h);
initial.commit09911bf2008-07-26 23:55:29763
764 score->boring_score = CalculateBoringScore(thumbnail);
765
766#ifdef TIME_BITMAP_RETRIEVAL
767 double end = time_util::GetHighResolutionTimeNow();
768 char buf[128];
769 sprintf_s(buf, "thumbnail in %gms\n", (end - begin) * 1000);
770 OutputDebugStringA(buf);
771#endif
[email protected]b6e4bec2008-11-12 01:17:15772 return true;
initial.commit09911bf2008-07-26 23:55:29773}
774
775double RenderView::CalculateBoringScore(SkBitmap* bitmap) {
776 int histogram[256] = {0};
777 color_utils::BuildLumaHistogram(bitmap, histogram);
778
779 int color_count = *std::max_element(histogram, histogram + 256);
780 int pixel_count = bitmap->width() * bitmap->height();
781 return static_cast<double>(color_count) / pixel_count;
782}
783
784void RenderView::OnNavigate(const ViewMsg_Navigate_Params& params) {
785 if (!webview())
786 return;
787
[email protected]f8b6b6f2009-03-10 16:48:26788 renderer_logging::ScopedActiveRenderingURLSetter url_setter(params.url);
[email protected]f8b6b6f2009-03-10 16:48:26789
initial.commit09911bf2008-07-26 23:55:29790 AboutHandler::MaybeHandle(params.url);
791
792 bool is_reload = params.reload;
793
794 WebFrame* main_frame = webview()->GetMainFrame();
[email protected]606843fa2008-12-02 19:08:56795 if (is_reload && !main_frame->HasCurrentHistoryState()) {
initial.commit09911bf2008-07-26 23:55:29796 // We cannot reload if we do not have any history state. This happens, for
797 // example, when recovering from a crash. Our workaround here is a bit of
798 // a hack since it means that reload after a crashed tab does not cause an
799 // end-to-end cache validation.
800 is_reload = false;
801 }
802
803 WebRequestCachePolicy cache_policy;
804 if (is_reload) {
805 cache_policy = WebRequestReloadIgnoringCacheData;
806 } else if (params.page_id != -1 || main_frame->GetInViewSourceMode()) {
807 cache_policy = WebRequestReturnCacheDataElseLoad;
808 } else {
809 cache_policy = WebRequestUseProtocolCachePolicy;
810 }
811
812 scoped_ptr<WebRequest> request(WebRequest::Create(params.url));
813 request->SetCachePolicy(cache_policy);
814 request->SetExtraData(new RenderViewExtraRequestData(
[email protected]c20210e62009-04-03 21:39:26815 params.page_id, params.transition, params.request_time));
initial.commit09911bf2008-07-26 23:55:29816
817 // If we are reloading, then WebKit will use the state of the current page.
818 // Otherwise, we give it the state to navigate to.
819 if (!is_reload)
820 request->SetHistoryState(params.state);
821
[email protected]4c6f2c92008-10-28 20:26:15822 if (params.referrer.is_valid()) {
[email protected]8e3c1a72008-11-25 01:13:32823 request->SetHttpHeaderValue("Referer",
824 params.referrer.spec());
[email protected]c0588052008-10-27 23:01:50825 }
826
initial.commit09911bf2008-07-26 23:55:29827 main_frame->LoadRequest(request.get());
828}
829
830// Stop loading the current page
831void RenderView::OnStop() {
832 if (webview())
833 webview()->StopLoading();
834}
835
836void RenderView::OnLoadAlternateHTMLText(const std::string& html_contents,
837 bool new_navigation,
838 const GURL& display_url,
839 const std::string& security_info) {
840 if (!webview())
841 return;
842
843 scoped_ptr<WebRequest> request(WebRequest::Create(
844 GURL(kUnreachableWebDataURL)));
845 request->SetSecurityInfo(security_info);
846
847 webview()->GetMainFrame()->LoadAlternateHTMLString(request.get(),
848 html_contents,
849 display_url,
850 !new_navigation);
851}
852
853void RenderView::OnCopyImageAt(int x, int y) {
854 webview()->CopyImageAt(x, y);
855}
856
857void RenderView::OnInspectElement(int x, int y) {
858 webview()->InspectElement(x, y);
859}
860
861void RenderView::OnShowJavaScriptConsole() {
862 webview()->ShowJavaScriptConsole();
863}
864
[email protected]b2abac72009-02-26 12:39:28865void RenderView::OnSetupDevToolsClient() {
[email protected]e4ac5df2009-03-17 15:33:11866 DCHECK(!devtools_client_.get());
867 devtools_client_.reset(new DevToolsClient(this));
[email protected]b2abac72009-02-26 12:39:28868}
869
initial.commit09911bf2008-07-26 23:55:29870void RenderView::OnStopFinding(bool clear_selection) {
871 WebView* view = webview();
872 if (!view)
873 return;
874
875 if (clear_selection)
876 view->GetFocusedFrame()->ClearSelection();
877
878 WebFrame* frame = view->GetMainFrame();
879 while (frame) {
[email protected]65134c432008-09-26 21:47:20880 frame->StopFinding(clear_selection);
initial.commit09911bf2008-07-26 23:55:29881 frame = view->GetNextFrameAfter(frame, false);
882 }
883}
884
885void RenderView::OnFindReplyAck() {
886 // Check if there is any queued up request waiting to be sent.
887 if (queued_find_reply_message_.get()) {
888 // Send the search result over to the browser process.
889 Send(queued_find_reply_message_.get());
890 queued_find_reply_message_.release();
891 }
892}
893
894void RenderView::OnUpdateTargetURLAck() {
895 // Check if there is a targeturl waiting to be sent.
896 if (target_url_status_ == TARGET_PENDING) {
897 Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_,
898 pending_target_url_));
899 }
900
901 target_url_status_ = TARGET_NONE;
902}
903
904void RenderView::OnUndo() {
905 if (!webview())
906 return;
907
908 webview()->GetFocusedFrame()->Undo();
909}
910
911void RenderView::OnRedo() {
912 if (!webview())
913 return;
914
915 webview()->GetFocusedFrame()->Redo();
916}
917
918void RenderView::OnCut() {
919 if (!webview())
920 return;
921
922 webview()->GetFocusedFrame()->Cut();
923}
924
925void RenderView::OnCopy() {
926 if (!webview())
927 return;
928
929 webview()->GetFocusedFrame()->Copy();
930}
931
932void RenderView::OnPaste() {
933 if (!webview())
934 return;
935
936 webview()->GetFocusedFrame()->Paste();
937}
938
939void RenderView::OnReplace(const std::wstring& text) {
940 if (!webview())
941 return;
942
943 webview()->GetFocusedFrame()->Replace(text);
944}
945
[email protected]bbbd545c2008-12-15 20:18:04946void RenderView::OnToggleSpellCheck() {
947 if (!webview())
948 return;
949
950 webview()->GetFocusedFrame()->ToggleSpellCheck();
951}
952
initial.commit09911bf2008-07-26 23:55:29953void RenderView::OnDelete() {
954 if (!webview())
955 return;
956
957 webview()->GetFocusedFrame()->Delete();
958}
959
960void RenderView::OnSelectAll() {
961 if (!webview())
962 return;
963
964 webview()->GetFocusedFrame()->SelectAll();
965}
966
967void RenderView::OnSetInitialFocus(bool reverse) {
968 if (!webview())
969 return;
970 webview()->SetInitialFocus(reverse);
971}
972
973///////////////////////////////////////////////////////////////////////////////
974
975// Tell the embedding application that the URL of the active page has changed
976void RenderView::UpdateURL(WebFrame* frame) {
977 WebDataSource* ds = frame->GetDataSource();
978 DCHECK(ds);
979
980 const WebRequest& request = ds->GetRequest();
981 const WebRequest& initial_request = ds->GetInitialRequest();
982 const WebResponse& response = ds->GetResponse();
983
984 // We don't hold a reference to the extra data. The request's reference will
985 // be sufficient because we won't modify it during our call. MAY BE NULL.
986 RenderViewExtraRequestData* extra_data =
987 static_cast<RenderViewExtraRequestData*>(request.GetExtraData());
988
989 ViewHostMsg_FrameNavigate_Params params;
[email protected]2e39d2e2009-02-19 18:41:31990 params.http_status_code = response.GetHttpStatusCode();
initial.commit09911bf2008-07-26 23:55:29991 params.is_post = false;
992 params.page_id = page_id_;
[email protected]8a3422c92008-09-24 17:42:42993 params.is_content_filtered = response.IsContentFiltered();
initial.commit09911bf2008-07-26 23:55:29994 if (!request.GetSecurityInfo().empty()) {
995 // SSL state specified in the request takes precedence over the one in the
996 // response.
997 // So far this is only intended for error pages that are not expected to be
998 // over ssl, so we should not get any clash.
999 DCHECK(response.GetSecurityInfo().empty());
1000 params.security_info = request.GetSecurityInfo();
1001 } else {
1002 params.security_info = response.GetSecurityInfo();
1003 }
1004
1005 // Set the URL to be displayed in the browser UI to the user.
1006 if (ds->HasUnreachableURL()) {
1007 params.url = ds->GetUnreachableURL();
1008 } else {
1009 params.url = request.GetURL();
1010 }
1011
1012 params.redirects = ds->GetRedirectChain();
1013 params.should_update_history = !ds->HasUnreachableURL();
1014
1015 const SearchableFormData* searchable_form_data =
1016 frame->GetDataSource()->GetSearchableFormData();
1017 if (searchable_form_data) {
1018 params.searchable_form_url = searchable_form_data->url();
1019 params.searchable_form_element_name = searchable_form_data->element_name();
1020 params.searchable_form_encoding = searchable_form_data->encoding();
1021 }
1022
1023 const PasswordForm* password_form_data =
1024 frame->GetDataSource()->GetPasswordFormData();
1025 if (password_form_data)
1026 params.password_form = *password_form_data;
1027
1028 params.gesture = navigation_gesture_;
1029 navigation_gesture_ = NavigationGestureUnknown;
1030
1031 if (webview()->GetMainFrame() == frame) {
1032 // Top-level navigation.
1033
1034 // Update contents MIME type for main frame.
[email protected]9d806f52009-03-12 22:50:541035 params.contents_mime_type = ds->GetResponse().GetMimeType();
initial.commit09911bf2008-07-26 23:55:291036
1037 // We assume top level navigations initiated by the renderer are link
1038 // clicks.
1039 params.transition = extra_data ?
1040 extra_data->transition_type : PageTransition::LINK;
1041 if (!PageTransition::IsMainFrame(params.transition)) {
1042 // If the main frame does a load, it should not be reported as a subframe
1043 // navigation. This can occur in the following case:
1044 // 1. You're on a site with frames.
1045 // 2. You do a subframe navigation. This is stored with transition type
1046 // MANUAL_SUBFRAME.
1047 // 3. You navigate to some non-frame site, say, google.com.
1048 // 4. You navigate back to the page from step 2. Since it was initially
1049 // MANUAL_SUBFRAME, it will be that same transition type here.
1050 // We don't want that, because any navigation that changes the toplevel
1051 // frame should be tracked as a toplevel navigation (this allows us to
1052 // update the URL bar, etc).
1053 params.transition = PageTransition::LINK;
1054 }
1055
1056 if (params.transition == PageTransition::LINK &&
1057 frame->GetDataSource()->IsFormSubmit()) {
1058 params.transition = PageTransition::FORM_SUBMIT;
1059 }
1060
1061 // If we have a valid consumed client redirect source,
1062 // the page contained a client redirect (meta refresh, document.loc...),
1063 // so we set the referrer and transition to match.
1064 if (completed_client_redirect_src_.is_valid()) {
[email protected]77e09a92008-08-01 18:11:041065 DCHECK(completed_client_redirect_src_ == params.redirects[0]);
initial.commit09911bf2008-07-26 23:55:291066 params.referrer = completed_client_redirect_src_;
1067 params.transition = static_cast<PageTransition::Type>(
1068 params.transition | PageTransition::CLIENT_REDIRECT);
1069 } else {
1070 // Bug 654101: the referrer will be empty on https->http transitions. It
1071 // would be nice if we could get the real referrer from somewhere.
1072 params.referrer = GURL(initial_request.GetHttpReferrer());
1073 }
1074
[email protected]8e3c1a72008-11-25 01:13:321075 std::string method = request.GetHttpMethod();
1076 if (method == "POST")
initial.commit09911bf2008-07-26 23:55:291077 params.is_post = true;
1078
1079 Send(new ViewHostMsg_FrameNavigate(routing_id_, params));
1080 } else {
1081 // Subframe navigation: the type depends on whether this navigation
1082 // generated a new session history entry. When they do generate a session
1083 // history entry, it means the user initiated the navigation and we should
1084 // mark it as such. This test checks if this is the first time UpdateURL
1085 // has been called since WillNavigateToURL was called to initiate the load.
1086 if (page_id_ > last_page_id_sent_to_browser_)
1087 params.transition = PageTransition::MANUAL_SUBFRAME;
1088 else
1089 params.transition = PageTransition::AUTO_SUBFRAME;
1090
1091 // The browser should never initiate a subframe navigation.
1092 DCHECK(!extra_data);
1093 Send(new ViewHostMsg_FrameNavigate(routing_id_, params));
1094 }
1095
1096 last_page_id_sent_to_browser_ =
1097 std::max(last_page_id_sent_to_browser_, page_id_);
1098
1099 // If we end up reusing this WebRequest (for example, due to a #ref click),
1100 // we don't want the transition type to persist.
1101 if (extra_data)
1102 extra_data->transition_type = PageTransition::LINK; // Just clear it.
[email protected]266eb6f2008-09-30 23:56:501103
[email protected]6c8afae52009-01-22 02:24:571104#if defined(OS_WIN)
[email protected]6a983b42009-03-20 20:12:251105 if (web_accessibility_manager_.get()) {
[email protected]be645db2009-02-06 20:36:331106 // Clear accessibility info cache.
[email protected]6a983b42009-03-20 20:12:251107 web_accessibility_manager_->ClearAccObjMap(-1, true);
[email protected]266eb6f2008-09-30 23:56:501108 }
[email protected]6c8afae52009-01-22 02:24:571109#else
[email protected]7d926f92009-03-03 14:26:541110 // TODO(port): accessibility not yet implemented. See http://crbug.com/8288.
[email protected]6c8afae52009-01-22 02:24:571111#endif
initial.commit09911bf2008-07-26 23:55:291112}
1113
1114// Tell the embedding application that the title of the active page has changed
1115void RenderView::UpdateTitle(WebFrame* frame, const std::wstring& title) {
1116 // Ignore all but top level navigations...
1117 if (webview()->GetMainFrame() == frame)
1118 Send(new ViewHostMsg_UpdateTitle(routing_id_, page_id_, title));
1119}
1120
1121void RenderView::UpdateEncoding(WebFrame* frame,
[email protected]e38f40152008-09-12 23:08:301122 const std::wstring& encoding_name) {
initial.commit09911bf2008-07-26 23:55:291123 // Only update main frame's encoding_name.
1124 if (webview()->GetMainFrame() == frame &&
1125 last_encoding_name_ != encoding_name) {
[email protected]e38f40152008-09-12 23:08:301126 // Save the encoding name for later comparing.
initial.commit09911bf2008-07-26 23:55:291127 last_encoding_name_ = encoding_name;
1128
[email protected]e38f40152008-09-12 23:08:301129 Send(new ViewHostMsg_UpdateEncoding(routing_id_, last_encoding_name_));
initial.commit09911bf2008-07-26 23:55:291130 }
1131}
1132
[email protected]f4d34b52008-11-24 23:05:011133// Sends the previous session history state to the browser so it will be saved
1134// before we navigate to a new page. This must be called *before* the page ID
1135// has been updated so we know what it was.
initial.commit09911bf2008-07-26 23:55:291136void RenderView::UpdateSessionHistory(WebFrame* frame) {
1137 // If we have a valid page ID at this point, then it corresponds to the page
1138 // we are navigating away from. Otherwise, this is the first navigation, so
1139 // there is no past session history to record.
1140 if (page_id_ == -1)
1141 return;
1142
initial.commit09911bf2008-07-26 23:55:291143 std::string state;
[email protected]606843fa2008-12-02 19:08:561144 if (!webview()->GetMainFrame()->GetPreviousHistoryState(&state))
initial.commit09911bf2008-07-26 23:55:291145 return;
[email protected]606843fa2008-12-02 19:08:561146 Send(new ViewHostMsg_UpdateState(routing_id_, page_id_, state));
initial.commit09911bf2008-07-26 23:55:291147}
1148
1149///////////////////////////////////////////////////////////////////////////////
1150// WebViewDelegate
1151
1152void RenderView::DidStartLoading(WebView* webview) {
1153 if (is_loading_) {
1154 DLOG(WARNING) << "DidStartLoading called while loading";
1155 return;
1156 }
1157
1158 is_loading_ = true;
1159 // Clear the pointer so that we can assign it only when there is an unknown
1160 // plugin on a page.
1161 first_default_plugin_ = NULL;
1162
1163 Send(new ViewHostMsg_DidStartLoading(routing_id_, page_id_));
1164}
1165
1166void RenderView::DidStopLoading(WebView* webview) {
1167 if (!is_loading_) {
1168 DLOG(WARNING) << "DidStopLoading called while not loading";
1169 return;
1170 }
1171
1172 is_loading_ = false;
1173
1174 // NOTE: For now we're doing the safest thing, and sending out notification
1175 // when done loading. This currently isn't an issue as the favicon is only
1176 // displayed when done loading. Ideally we would send notification when
1177 // finished parsing the head, but webkit doesn't support that yet.
1178 // The feed discovery code would also benefit from access to the head.
1179 GURL favicon_url(webview->GetMainFrame()->GetFavIconURL());
1180 if (!favicon_url.is_empty())
1181 Send(new ViewHostMsg_UpdateFavIconURL(routing_id_, page_id_, favicon_url));
1182
[email protected]4604d1f42009-03-13 21:52:321183 // Update the list of available feeds.
1184 UpdateFeedList(webview->GetMainFrame()->GetFeedList());
1185
initial.commit09911bf2008-07-26 23:55:291186 AddGURLSearchProvider(webview->GetMainFrame()->GetOSDDURL(),
1187 true); // autodetected
1188
1189 Send(new ViewHostMsg_DidStopLoading(routing_id_, page_id_));
1190
1191 MessageLoop::current()->PostDelayedTask(FROM_HERE,
1192 method_factory_.NewRunnableMethod(&RenderView::CapturePageInfo, page_id_,
1193 false),
1194 kDelayForCaptureMs);
1195
1196 // The page is loaded. Try to process the file we need to upload if any.
1197 ProcessPendingUpload();
1198
1199 // Since the page is done loading, we are sure we don't need to try
1200 // again.
1201 ResetPendingUpload();
1202}
1203
1204void RenderView::DidStartProvisionalLoadForFrame(
1205 WebView* webview,
1206 WebFrame* frame,
1207 NavigationGesture gesture) {
[email protected]77e09a92008-08-01 18:11:041208 if (webview->GetMainFrame() == frame) {
initial.commit09911bf2008-07-26 23:55:291209 navigation_gesture_ = gesture;
[email protected]266eb6f2008-09-30 23:56:501210
[email protected]77e09a92008-08-01 18:11:041211 // Make sure redirect tracking state is clear for the new load.
1212 completed_client_redirect_src_ = GURL();
1213 }
initial.commit09911bf2008-07-26 23:55:291214
[email protected]c20210e62009-04-03 21:39:261215 WebDataSource* ds = frame->GetProvisionalDataSource();
1216 if (ds) {
1217 const WebRequest& req = ds->GetRequest();
1218 RenderViewExtraRequestData* extra_data =
1219 static_cast<RenderViewExtraRequestData*>(req.GetExtraData());
1220 if (extra_data) {
1221 ds->SetRequestTime(extra_data->request_time);
1222 }
1223 }
initial.commit09911bf2008-07-26 23:55:291224 Send(new ViewHostMsg_DidStartProvisionalLoadForFrame(
1225 routing_id_, webview->GetMainFrame() == frame,
1226 frame->GetProvisionalDataSource()->GetRequest().GetURL()));
1227}
1228
1229bool RenderView::DidLoadResourceFromMemoryCache(WebView* webview,
1230 const WebRequest& request,
1231 const WebResponse& response,
1232 WebFrame* frame) {
1233 // Let the browser know we loaded a resource from the memory cache. This
1234 // message is needed to display the correct SSL indicators.
1235 Send(new ViewHostMsg_DidLoadResourceFromMemoryCache(routing_id_,
[email protected]ffc45862009-03-17 06:11:081236 request.GetURL(), frame->GetSecurityOrigin(),
1237 frame->GetTop()->GetSecurityOrigin(),
1238 response.GetSecurityInfo()));
initial.commit09911bf2008-07-26 23:55:291239
1240 return false;
1241}
1242
1243void RenderView::DidReceiveProvisionalLoadServerRedirect(WebView* webview,
1244 WebFrame* frame) {
1245 if (frame == webview->GetMainFrame()) {
1246 // Received a redirect on the main frame.
1247 WebDataSource* data_source =
1248 webview->GetMainFrame()->GetProvisionalDataSource();
1249 if (!data_source) {
1250 // Should only be invoked when we have a data source.
1251 NOTREACHED();
1252 return;
1253 }
1254 const std::vector<GURL>& redirects = data_source->GetRedirectChain();
1255 if (redirects.size() >= 2) {
1256 Send(new ViewHostMsg_DidRedirectProvisionalLoad(
1257 routing_id_, page_id_, redirects[redirects.size() - 2],
1258 redirects[redirects.size() - 1]));
1259 }
1260 }
1261}
1262
1263void RenderView::DidFailProvisionalLoadWithError(WebView* webview,
1264 const WebError& error,
1265 WebFrame* frame) {
1266 // Notify the browser that we failed a provisional load with an error.
1267 //
1268 // Note: It is important this notification occur before DidStopLoading so the
1269 // SSL manager can react to the provisional load failure before being
1270 // notified the load stopped.
1271 //
1272 WebDataSource* ds = frame->GetProvisionalDataSource();
1273 DCHECK(ds);
1274
1275 const WebRequest& failed_request = ds->GetRequest();
1276
1277 bool show_repost_interstitial =
1278 (error.GetErrorCode() == net::ERR_CACHE_MISS &&
1279 LowerCaseEqualsASCII(failed_request.GetHttpMethod(), "post"));
1280 Send(new ViewHostMsg_DidFailProvisionalLoadWithError(
1281 routing_id_, frame == webview->GetMainFrame(),
1282 error.GetErrorCode(), error.GetFailedURL(),
1283 show_repost_interstitial));
1284
initial.commit09911bf2008-07-26 23:55:291285 // Don't display an error page if this is simply a cancelled load. Aside
1286 // from being dumb, WebCore doesn't expect it and it will cause a crash.
1287 if (error.GetErrorCode() == net::ERR_ABORTED)
1288 return;
1289
1290 // If this is a failed back/forward/reload navigation, then we need to do a
1291 // 'replace' load. This is necessary to avoid messing up session history.
1292 // Otherwise, we do a normal load, which simulates a 'go' navigation as far
1293 // as session history is concerned.
1294 RenderViewExtraRequestData* extra_data =
1295 static_cast<RenderViewExtraRequestData*>(failed_request.GetExtraData());
1296 bool replace = extra_data && !extra_data->is_new_navigation();
1297
[email protected]5df266ac2008-10-15 19:50:131298 // Use the alternate error page service if this is a DNS failure or
1299 // connection failure. ERR_CONNECTION_FAILED can be dropped once we no longer
1300 // use winhttp.
1301 int ec = error.GetErrorCode();
1302 if (ec == net::ERR_NAME_NOT_RESOLVED ||
1303 ec == net::ERR_CONNECTION_FAILED ||
1304 ec == net::ERR_CONNECTION_REFUSED ||
1305 ec == net::ERR_ADDRESS_UNREACHABLE ||
1306 ec == net::ERR_TIMED_OUT) {
1307 const GURL& failed_url = error.GetFailedURL();
1308 const GURL& error_page_url = GetAlternateErrorPageURL(failed_url,
1309 ec == net::ERR_NAME_NOT_RESOLVED ? WebViewDelegate::DNS_ERROR
1310 : WebViewDelegate::CONNECTION_ERROR);
1311 if (error_page_url.is_valid()) {
1312 // Ask the WebFrame to fetch the alternate error page for us.
1313 frame->LoadAlternateHTMLErrorPage(&failed_request, error, error_page_url,
1314 replace, GURL(kUnreachableWebDataURL));
1315 return;
1316 }
initial.commit09911bf2008-07-26 23:55:291317 }
[email protected]5df266ac2008-10-15 19:50:131318
[email protected]be645db2009-02-06 20:36:331319 // Fallback to a local error page.
[email protected]5df266ac2008-10-15 19:50:131320 LoadNavigationErrorPage(frame, &failed_request, error, std::string(),
1321 replace);
initial.commit09911bf2008-07-26 23:55:291322}
1323
1324void RenderView::LoadNavigationErrorPage(WebFrame* frame,
1325 const WebRequest* failed_request,
1326 const WebError& error,
1327 const std::string& html,
1328 bool replace) {
1329 const GURL& failed_url = error.GetFailedURL();
1330
1331 std::string alt_html;
1332 if (html.empty()) {
1333 // Use a local error page.
1334 int resource_id;
1335 DictionaryValue error_strings;
1336 if (error.GetErrorCode() == net::ERR_CACHE_MISS &&
1337 LowerCaseEqualsASCII(failed_request->GetHttpMethod(), "post")) {
1338 GetFormRepostErrorValues(failed_url, &error_strings);
1339 resource_id = IDR_ERROR_NO_DETAILS_HTML;
1340 } else {
1341 GetLocalizedErrorValues(error, &error_strings);
1342 resource_id = IDR_NET_ERROR_HTML;
1343 }
[email protected]8e50b602009-03-03 22:59:431344 error_strings.SetString(L"textdirection",
1345 (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) ?
1346 L"rtl" : L"ltr");
initial.commit09911bf2008-07-26 23:55:291347
1348 alt_html = GetAltHTMLForTemplate(error_strings, resource_id);
1349 } else {
1350 alt_html = html;
1351 }
1352
1353 // Use a data: URL as the site URL to prevent against XSS attacks.
1354 scoped_ptr<WebRequest> request(failed_request->Clone());
1355 request->SetURL(GURL(kUnreachableWebDataURL));
1356
1357 frame->LoadAlternateHTMLString(request.get(), alt_html, failed_url,
1358 replace);
1359}
1360
1361void RenderView::DidCommitLoadForFrame(WebView *webview, WebFrame* frame,
1362 bool is_new_navigation) {
1363 const WebRequest& request =
1364 webview->GetMainFrame()->GetDataSource()->GetRequest();
1365 RenderViewExtraRequestData* extra_data =
1366 static_cast<RenderViewExtraRequestData*>(request.GetExtraData());
1367
1368 if (is_new_navigation) {
1369 // When we perform a new navigation, we need to update the previous session
1370 // history entry with state for the page we are leaving.
1371 UpdateSessionHistory(frame);
1372
1373 // We bump our Page ID to correspond with the new session history entry.
1374 page_id_ = next_page_id_++;
1375
1376 MessageLoop::current()->PostDelayedTask(FROM_HERE,
1377 method_factory_.NewRunnableMethod(&RenderView::CapturePageInfo,
1378 page_id_, true),
1379 kDelayForForcedCaptureMs);
1380 } else {
1381 // Inspect the extra_data on the main frame (set in our Navigate method) to
1382 // see if the navigation corresponds to a session history navigation...
1383 // Note: |frame| may or may not be the toplevel frame, but for the case
1384 // of capturing session history, the first committed frame suffices. We
1385 // keep track of whether we've seen this commit before so that only capture
1386 // session history once per navigation.
[email protected]f4d34b52008-11-24 23:05:011387 //
1388 // Note that we need to check if the page ID changed. In the case of a
1389 // reload, the page ID doesn't change, and UpdateSessionHistory gets the
1390 // previous URL and the current page ID, which would be wrong.
initial.commit09911bf2008-07-26 23:55:291391 if (extra_data && !extra_data->is_new_navigation() &&
[email protected]f4d34b52008-11-24 23:05:011392 !extra_data->request_committed &&
1393 page_id_ != extra_data->pending_page_id()) {
initial.commit09911bf2008-07-26 23:55:291394 // This is a successful session history navigation!
1395 UpdateSessionHistory(frame);
initial.commit09911bf2008-07-26 23:55:291396 page_id_ = extra_data->pending_page_id();
1397 }
1398 }
1399
1400 // Remember that we've already processed this request, so we don't update
1401 // the session history again. We do this regardless of whether this is
1402 // a session history navigation, because if we attempted a session history
1403 // navigation without valid HistoryItem state, WebCore will think it is a
1404 // new navigation.
1405 if (extra_data)
1406 extra_data->request_committed = true;
1407
1408 UpdateURL(frame);
1409
1410 // If this committed load was initiated by a client redirect, we're
1411 // at the last stop now, so clear it.
1412 completed_client_redirect_src_ = GURL();
1413
1414 // Check whether we have new encoding name.
1415 UpdateEncoding(frame, webview->GetMainFrameEncodingName());
1416}
1417
1418void RenderView::DidReceiveTitle(WebView* webview,
1419 const std::wstring& title,
1420 WebFrame* frame) {
1421 UpdateTitle(frame, title);
1422
1423 // Also check whether we have new encoding name.
1424 UpdateEncoding(frame, webview->GetMainFrameEncodingName());
1425}
1426
1427void RenderView::DidFinishLoadForFrame(WebView* webview, WebFrame* frame) {
[email protected]c20210e62009-04-03 21:39:261428 if (webview->GetMainFrame() == frame) {
1429 const GURL& url = frame->GetURL();
1430 if (url.SchemeIs("http") || url.SchemeIs("https"))
1431 DumpLoadHistograms();
1432 }
initial.commit09911bf2008-07-26 23:55:291433}
1434
1435void RenderView::DidFailLoadWithError(WebView* webview,
1436 const WebError& error,
1437 WebFrame* frame) {
1438}
1439
1440void RenderView::DidFinishDocumentLoadForFrame(WebView* webview,
1441 WebFrame* frame) {
1442 // Check whether we have new encoding name.
1443 UpdateEncoding(frame, webview->GetMainFrameEncodingName());
[email protected]1e0f70402008-10-16 23:57:471444
[email protected]8930d472009-02-21 08:05:281445 if (RenderThread::current()) // Will be NULL during unit tests.
1446 RenderThread::current()->user_script_slave()->InjectScripts(
[email protected]0afe8272009-02-14 04:15:161447 frame, UserScript::DOCUMENT_END);
initial.commit09911bf2008-07-26 23:55:291448}
1449
1450void RenderView::DidHandleOnloadEventsForFrame(WebView* webview,
1451 WebFrame* frame) {
1452}
1453
1454void RenderView::DidChangeLocationWithinPageForFrame(WebView* webview,
1455 WebFrame* frame,
1456 bool is_new_navigation) {
1457 DidCommitLoadForFrame(webview, frame, is_new_navigation);
[email protected]9d806f52009-03-12 22:50:541458 const string16& title =
[email protected]de56f3782008-10-01 22:31:351459 webview->GetMainFrame()->GetDataSource()->GetPageTitle();
[email protected]9d806f52009-03-12 22:50:541460 UpdateTitle(frame, UTF16ToWideHack(title));
initial.commit09911bf2008-07-26 23:55:291461}
1462
1463void RenderView::DidReceiveIconForFrame(WebView* webview,
1464 WebFrame* frame) {
1465}
1466
1467void RenderView::WillPerformClientRedirect(WebView* webview,
1468 WebFrame* frame,
1469 const GURL& src_url,
1470 const GURL& dest_url,
1471 unsigned int delay_seconds,
1472 unsigned int fire_date) {
1473}
1474
1475void RenderView::DidCancelClientRedirect(WebView* webview,
1476 WebFrame* frame) {
1477}
1478
[email protected]309d7a282009-03-24 09:18:271479void RenderView::WillCloseFrame(WebView* view, WebFrame* frame) {
1480 // Remove all the pending extension callbacks for this frame.
1481 if (pending_extension_callbacks_.IsEmpty())
1482 return;
1483
1484 std::vector<int> orphaned_callbacks;
1485 for (IDMap<WebFrame>::const_iterator iter =
1486 pending_extension_callbacks_.begin();
1487 iter != pending_extension_callbacks_.end(); ++iter) {
1488 if (iter->second == frame)
1489 orphaned_callbacks.push_back(iter->first);
1490 }
1491
1492 for (std::vector<int>::const_iterator iter = orphaned_callbacks.begin();
1493 iter != orphaned_callbacks.end(); ++iter) {
1494 pending_extension_callbacks_.Remove(*iter);
1495 }
1496}
1497
initial.commit09911bf2008-07-26 23:55:291498void RenderView::DidCompleteClientRedirect(WebView* webview,
1499 WebFrame* frame,
1500 const GURL& source) {
1501 if (webview->GetMainFrame() == frame)
1502 completed_client_redirect_src_ = source;
1503}
1504
[email protected]5b35a6b2009-03-16 19:58:081505void RenderView::WillSendRequest(WebView* webview,
1506 uint32 identifier,
1507 WebRequest* request) {
1508 request->SetRequestorID(routing_id_);
1509}
1510
initial.commit09911bf2008-07-26 23:55:291511void RenderView::BindDOMAutomationController(WebFrame* webframe) {
1512 dom_automation_controller_.set_message_sender(this);
1513 dom_automation_controller_.set_routing_id(routing_id_);
1514 dom_automation_controller_.BindToJavascript(webframe,
1515 L"domAutomationController");
1516}
1517
1518void RenderView::WindowObjectCleared(WebFrame* webframe) {
1519 external_js_object_.set_render_view(this);
1520 external_js_object_.BindToJavascript(webframe, L"external");
[email protected]81e63782009-02-27 19:35:091521 if (BindingsPolicy::is_dom_automation_enabled(enabled_bindings_))
initial.commit09911bf2008-07-26 23:55:291522 BindDOMAutomationController(webframe);
[email protected]81e63782009-02-27 19:35:091523 if (BindingsPolicy::is_dom_ui_enabled(enabled_bindings_)) {
initial.commit09911bf2008-07-26 23:55:291524 dom_ui_bindings_.set_message_sender(this);
1525 dom_ui_bindings_.set_routing_id(routing_id_);
1526 dom_ui_bindings_.BindToJavascript(webframe, L"chrome");
1527 }
[email protected]81e63782009-02-27 19:35:091528 if (BindingsPolicy::is_external_host_enabled(enabled_bindings_)) {
[email protected]18cb2572008-08-21 20:34:451529 external_host_bindings_.set_message_sender(this);
1530 external_host_bindings_.set_routing_id(routing_id_);
1531 external_host_bindings_.BindToJavascript(webframe, L"externalHost");
1532 }
[email protected]9a2051d2008-08-15 20:12:421533
[email protected]3a453fa2008-08-15 18:46:341534#ifdef CHROME_PERSONALIZATION
1535 Personalization::ConfigureRendererPersonalization(personalization_, this,
1536 routing_id_, webframe);
1537#endif
initial.commit09911bf2008-07-26 23:55:291538}
1539
[email protected]0afe8272009-02-14 04:15:161540void RenderView::DocumentElementAvailable(WebFrame* frame) {
[email protected]8930d472009-02-21 08:05:281541 if (RenderThread::current()) // Will be NULL during unit tests.
1542 RenderThread::current()->user_script_slave()->InjectScripts(
[email protected]0afe8272009-02-14 04:15:161543 frame, UserScript::DOCUMENT_START);
1544}
1545
initial.commit09911bf2008-07-26 23:55:291546WindowOpenDisposition RenderView::DispositionForNavigationAction(
1547 WebView* webview,
1548 WebFrame* frame,
1549 const WebRequest* request,
1550 WebNavigationType type,
1551 WindowOpenDisposition disposition,
1552 bool is_redirect) {
1553 // Webkit is asking whether to navigate to a new URL.
1554 // This is fine normally, except if we're showing UI from one security
1555 // context and they're trying to navigate to a different context.
1556 const GURL& url = request->GetURL();
1557 // We only care about navigations that are within the current tab (as opposed
1558 // to, for example, opening a new window).
1559 // But we sometimes navigate to about:blank to clear a tab, and we want to
1560 // still allow that.
[email protected]6de74452009-02-25 18:04:591561 if (disposition == CURRENT_TAB && !(url.SchemeIs(chrome::kAboutScheme))) {
initial.commit09911bf2008-07-26 23:55:291562 // GetExtraData is NULL when we did not issue the request ourselves (see
1563 // OnNavigate), and so such a request may correspond to a link-click,
1564 // script, or drag-n-drop initiated navigation.
1565 if (frame == webview->GetMainFrame() && !request->GetExtraData()) {
1566 // When we received such unsolicited navigations, we sometimes want to
1567 // punt them up to the browser to handle.
[email protected]81e63782009-02-27 19:35:091568 if (BindingsPolicy::is_dom_ui_enabled(enabled_bindings_) ||
initial.commit09911bf2008-07-26 23:55:291569 frame->GetInViewSourceMode() ||
[email protected]6de74452009-02-25 18:04:591570 url.SchemeIs(chrome::kViewSourceScheme)) {
[email protected]c0588052008-10-27 23:01:501571 OpenURL(webview, url, GURL(), disposition);
initial.commit09911bf2008-07-26 23:55:291572 return IGNORE_ACTION; // Suppress the load here.
[email protected]50b691c2008-10-31 19:08:351573 } else if (url.SchemeIs(kBackForwardNavigationScheme)) {
1574 std::string offset_str = url.ExtractFileName();
1575 int offset;
1576 if (StringToInt(offset_str, &offset)) {
[email protected]0c0383772008-11-04 00:48:311577 GoToEntryAtOffset(offset);
[email protected]50b691c2008-10-31 19:08:351578 return IGNORE_ACTION; // The browser process handles this one.
1579 }
initial.commit09911bf2008-07-26 23:55:291580 }
1581 }
1582 }
1583
1584 // Detect when a page is "forking" a new tab that can be safely rendered in
1585 // its own process. This is done by sites like Gmail that try to open links
1586 // in new windows without script connections back to the original page. We
1587 // treat such cases as browser navigations (in which we will create a new
1588 // renderer for a cross-site navigation), rather than WebKit navigations.
1589 //
1590 // We use the following heuristic to decide whether to fork a new page in its
1591 // own process:
1592 // The parent page must open a new tab to about:blank, set the new tab's
1593 // window.opener to null, and then redirect the tab to a cross-site URL using
1594 // JavaScript.
1595 bool is_fork =
1596 // Must start from a tab showing about:blank, which is later redirected.
[email protected]6aad4bd2009-02-26 22:55:171597 frame->GetURL() == GURL("about:blank") &&
initial.commit09911bf2008-07-26 23:55:291598 // Must be the first real navigation of the tab.
1599 GetHistoryBackListCount() < 1 &&
1600 GetHistoryForwardListCount() < 1 &&
1601 // The parent page must have set the child's window.opener to null before
1602 // redirecting to the desired URL.
1603 frame->GetOpener() == NULL &&
1604 // Must be a top-level frame.
1605 frame->GetParent() == NULL &&
1606 // Must not have issued the request from this page. GetExtraData is NULL
1607 // when the navigation is being done by something outside the page.
1608 !request->GetExtraData() &&
1609 // Must be targeted at the current tab.
1610 disposition == CURRENT_TAB &&
1611 // Must be a JavaScript navigation, which appears as "other".
1612 type == WebNavigationTypeOther;
1613 if (is_fork) {
1614 // Open the URL via the browser, not via WebKit.
[email protected]c0588052008-10-27 23:01:501615 OpenURL(webview, url, GURL(), disposition);
initial.commit09911bf2008-07-26 23:55:291616 return IGNORE_ACTION;
1617 }
1618
1619 return disposition;
1620}
1621
[email protected]a455d3812009-03-05 20:18:071622void RenderView::RunJavaScriptAlert(WebFrame* webframe,
initial.commit09911bf2008-07-26 23:55:291623 const std::wstring& message) {
[email protected]2e4bdcdc2009-03-27 23:07:301624 RunJavaScriptMessage(MessageBox::kIsJavascriptAlert,
initial.commit09911bf2008-07-26 23:55:291625 message,
1626 std::wstring(),
[email protected]a455d3812009-03-05 20:18:071627 webframe->GetURL(),
initial.commit09911bf2008-07-26 23:55:291628 NULL);
1629}
1630
[email protected]a455d3812009-03-05 20:18:071631bool RenderView::RunJavaScriptConfirm(WebFrame* webframe,
initial.commit09911bf2008-07-26 23:55:291632 const std::wstring& message) {
[email protected]2e4bdcdc2009-03-27 23:07:301633 return RunJavaScriptMessage(MessageBox::kIsJavascriptConfirm,
initial.commit09911bf2008-07-26 23:55:291634 message,
1635 std::wstring(),
[email protected]a455d3812009-03-05 20:18:071636 webframe->GetURL(),
initial.commit09911bf2008-07-26 23:55:291637 NULL);
1638}
1639
[email protected]a455d3812009-03-05 20:18:071640bool RenderView::RunJavaScriptPrompt(WebFrame* webframe,
initial.commit09911bf2008-07-26 23:55:291641 const std::wstring& message,
1642 const std::wstring& default_value,
1643 std::wstring* result) {
[email protected]2e4bdcdc2009-03-27 23:07:301644 return RunJavaScriptMessage(MessageBox::kIsJavascriptPrompt,
initial.commit09911bf2008-07-26 23:55:291645 message,
1646 default_value,
[email protected]a455d3812009-03-05 20:18:071647 webframe->GetURL(),
initial.commit09911bf2008-07-26 23:55:291648 result);
1649}
1650
1651bool RenderView::RunJavaScriptMessage(int type,
1652 const std::wstring& message,
1653 const std::wstring& default_value,
[email protected]a455d3812009-03-05 20:18:071654 const GURL& frame_url,
initial.commit09911bf2008-07-26 23:55:291655 std::wstring* result) {
1656 bool success = false;
1657 std::wstring result_temp;
1658 if (!result)
1659 result = &result_temp;
1660 IPC::SyncMessage* msg = new ViewHostMsg_RunJavaScriptMessage(
[email protected]a455d3812009-03-05 20:18:071661 routing_id_, message, default_value, frame_url, type, &success, result);
initial.commit09911bf2008-07-26 23:55:291662
[email protected]1c4947f2009-01-15 22:25:111663 msg->set_pump_messages_event(modal_dialog_event_.get());
initial.commit09911bf2008-07-26 23:55:291664 Send(msg);
1665
1666 return success;
1667}
1668
1669void RenderView::AddGURLSearchProvider(const GURL& osd_url, bool autodetected) {
1670 if (!osd_url.is_empty())
1671 Send(new ViewHostMsg_PageHasOSDD(routing_id_, page_id_, osd_url,
1672 autodetected));
1673}
1674
[email protected]4604d1f42009-03-13 21:52:321675void RenderView::UpdateFeedList(scoped_refptr<FeedList> feedlist) {
1676 ViewHostMsg_UpdateFeedList_Params params;
1677 params.page_id = page_id_;
1678 params.feedlist = feedlist;
1679 Send(new ViewHostMsg_UpdateFeedList(routing_id_, params));
1680}
1681
[email protected]a455d3812009-03-05 20:18:071682bool RenderView::RunBeforeUnloadConfirm(WebFrame* webframe,
initial.commit09911bf2008-07-26 23:55:291683 const std::wstring& message) {
1684 bool success = false;
1685 // This is an ignored return value, but is included so we can accept the same
1686 // response as RunJavaScriptMessage.
1687 std::wstring ignored_result;
1688 IPC::SyncMessage* msg = new ViewHostMsg_RunBeforeUnloadConfirm(
[email protected]a455d3812009-03-05 20:18:071689 routing_id_, webframe->GetURL(), message, &success, &ignored_result);
initial.commit09911bf2008-07-26 23:55:291690
[email protected]1c4947f2009-01-15 22:25:111691 msg->set_pump_messages_event(modal_dialog_event_.get());
initial.commit09911bf2008-07-26 23:55:291692 Send(msg);
1693
1694 return success;
1695}
1696
[email protected]0578a502008-11-10 19:34:431697void RenderView::EnableSuddenTermination() {
1698 Send(new ViewHostMsg_UnloadListenerChanged(routing_id_, false));
1699}
1700
1701void RenderView::DisableSuddenTermination() {
1702 Send(new ViewHostMsg_UnloadListenerChanged(routing_id_, true));
initial.commit09911bf2008-07-26 23:55:291703}
1704
[email protected]0ebf3872008-11-07 21:35:031705void RenderView::QueryFormFieldAutofill(const std::wstring& field_name,
1706 const std::wstring& text,
1707 int64 node_id) {
1708 static int message_id_counter = 0;
1709 form_field_autofill_request_id_ = message_id_counter++;
1710 Send(new ViewHostMsg_QueryFormFieldAutofill(routing_id_,
1711 field_name, text,
1712 node_id,
1713 form_field_autofill_request_id_));
1714}
1715
[email protected]4d2b6fb2009-03-20 22:28:171716void RenderView::RemoveStoredAutofillEntry(const std::wstring& name,
1717 const std::wstring& value) {
1718 Send(new ViewHostMsg_RemoveAutofillEntry(routing_id_, name, value));
1719}
1720
[email protected]0ebf3872008-11-07 21:35:031721void RenderView::OnReceivedAutofillSuggestions(
1722 int64 node_id,
1723 int request_id,
[email protected]8d0f15c2008-11-11 01:01:091724 const std::vector<std::wstring>& suggestions,
[email protected]0ebf3872008-11-07 21:35:031725 int default_suggestion_index) {
1726 if (!webview() || request_id != form_field_autofill_request_id_)
1727 return;
1728
1729 webview()->AutofillSuggestionsForNode(node_id, suggestions,
1730 default_suggestion_index);
1731}
1732
[email protected]634a6f92008-12-01 21:39:311733void RenderView::OnPopupNotificationVisiblityChanged(bool visible) {
1734 popup_notification_visible_ = visible;
1735}
1736
initial.commit09911bf2008-07-26 23:55:291737void RenderView::ShowModalHTMLDialog(const GURL& url, int width, int height,
1738 const std::string& json_arguments,
1739 std::string* json_retval) {
1740 IPC::SyncMessage* msg = new ViewHostMsg_ShowModalHTMLDialog(
1741 routing_id_, url, width, height, json_arguments, json_retval);
1742
[email protected]1c4947f2009-01-15 22:25:111743 msg->set_pump_messages_event(modal_dialog_event_.get());
initial.commit09911bf2008-07-26 23:55:291744 Send(msg);
1745}
1746
1747uint32 RenderView::GetCPBrowsingContext() {
1748 uint32 context = 0;
1749 Send(new ViewHostMsg_GetCPBrowsingContext(&context));
1750 return context;
1751}
1752
1753// Tell the browser to display a destination link.
1754void RenderView::UpdateTargetURL(WebView* webview, const GURL& url) {
1755 if (url != target_url_) {
1756 if (target_url_status_ == TARGET_INFLIGHT ||
1757 target_url_status_ == TARGET_PENDING) {
1758 // If we have a request in-flight, save the URL to be sent when we
1759 // receive an ACK to the in-flight request. We can happily overwrite
1760 // any existing pending sends.
1761 pending_target_url_ = url;
1762 target_url_status_ = TARGET_PENDING;
1763 } else {
1764 Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_, url));
1765 target_url_ = url;
1766 target_url_status_ = TARGET_INFLIGHT;
1767 }
1768 }
1769}
1770
[email protected]b62d1a8c2009-01-13 23:54:571771void RenderView::RunFileChooser(bool multi_select,
1772 const std::wstring& title,
1773 const std::wstring& default_filename,
1774 const std::wstring& filter,
initial.commit09911bf2008-07-26 23:55:291775 WebFileChooserCallback* file_chooser) {
1776 if (file_chooser_.get()) {
1777 // TODO(brettw): bug 1235154: This should be a synchronous message to deal
1778 // with the fact that web pages can programatically trigger this. With the
1779 // asnychronous messages, we can get an additional call when one is pending,
1780 // which this test is for. For now, we just ignore the additional file
1781 // chooser request. WebKit doesn't do anything to expect the callback, so
1782 // we can just ignore calling it.
1783 delete file_chooser;
1784 return;
1785 }
1786 file_chooser_.reset(file_chooser);
[email protected]b62d1a8c2009-01-13 23:54:571787 Send(new ViewHostMsg_RunFileChooser(routing_id_, multi_select, title,
1788 default_filename, filter));
initial.commit09911bf2008-07-26 23:55:291789}
1790
1791void RenderView::AddMessageToConsole(WebView* webview,
1792 const std::wstring& message,
1793 unsigned int line_no,
1794 const std::wstring& source_id) {
1795 Send(new ViewHostMsg_AddMessageToConsole(routing_id_, message,
1796 static_cast<int32>(line_no),
1797 source_id));
1798}
1799
1800void RenderView::AddSearchProvider(const std::string& url) {
1801 AddGURLSearchProvider(GURL(url),
1802 false); // not autodetected
1803}
1804
1805void RenderView::DebuggerOutput(const std::wstring& out) {
1806 Send(new ViewHostMsg_DebuggerOutput(routing_id_, out));
1807}
1808
1809WebView* RenderView::CreateWebView(WebView* webview, bool user_gesture) {
[email protected]0aa55312008-10-17 21:53:081810 // Check to make sure we aren't overloading on popups.
1811 if (shared_popup_counter_->data > kMaximumNumberOfUnacknowledgedPopups)
1812 return NULL;
1813
[email protected]634a6f92008-12-01 21:39:311814 // This window can't be closed from a window.close() call until we receive a
1815 // message from the Browser process explicitly allowing it.
1816 popup_notification_visible_ = true;
1817
initial.commit09911bf2008-07-26 23:55:291818 int32 routing_id = MSG_ROUTING_NONE;
[email protected]6c8afae52009-01-22 02:24:571819
[email protected]18bcc3c2009-01-27 21:39:151820 ModalDialogEvent modal_dialog_event;
[email protected]6c8afae52009-01-22 02:24:571821 render_thread_->Send(
[email protected]15787f8f2008-10-17 15:29:031822 new ViewHostMsg_CreateWindow(routing_id_, user_gesture, &routing_id,
1823 &modal_dialog_event));
initial.commit09911bf2008-07-26 23:55:291824 if (routing_id == MSG_ROUTING_NONE) {
initial.commit09911bf2008-07-26 23:55:291825 return NULL;
1826 }
1827
1828 // The WebView holds a reference to this new RenderView
1829 const WebPreferences& prefs = webview->GetPreferences();
[email protected]6c8afae52009-01-22 02:24:571830 base::WaitableEvent* waitable_event = new base::WaitableEvent
1831#if defined(OS_WIN)
[email protected]18bcc3c2009-01-27 21:39:151832 (modal_dialog_event.event);
[email protected]6c8afae52009-01-22 02:24:571833#else
1834 (true, false);
1835#endif
[email protected]81a34412009-01-05 19:17:241836 RenderView* view = RenderView::Create(render_thread_,
[email protected]1c4947f2009-01-15 22:25:111837 NULL, waitable_event, routing_id_,
[email protected]0aa55312008-10-17 21:53:081838 prefs, shared_popup_counter_,
1839 routing_id);
initial.commit09911bf2008-07-26 23:55:291840 view->set_opened_by_user_gesture(user_gesture);
1841
1842 // Copy over the alternate error page URL so we can have alt error pages in
1843 // the new render view (we don't need the browser to send the URL back down).
1844 view->alternate_error_page_url_ = alternate_error_page_url_;
1845
1846 return view->webview();
1847}
1848
[email protected]0ebf3872008-11-07 21:35:031849WebWidget* RenderView::CreatePopupWidget(WebView* webview,
[email protected]cfd727f2009-01-09 20:21:111850 bool activatable) {
[email protected]8085dbc82008-09-26 22:53:441851 RenderWidget* widget = RenderWidget::Create(routing_id_,
[email protected]81a34412009-01-05 19:17:241852 render_thread_,
[email protected]cfd727f2009-01-09 20:21:111853 activatable);
initial.commit09911bf2008-07-26 23:55:291854 return widget->webwidget();
1855}
1856
1857WebPluginDelegate* RenderView::CreatePluginDelegate(
1858 WebView* webview,
1859 const GURL& url,
1860 const std::string& mime_type,
1861 const std::string& clsid,
1862 std::string* actual_mime_type) {
[email protected]6c8afae52009-01-22 02:24:571863#if defined(OS_WIN)
[email protected]88a1fb47a2009-03-13 00:18:061864 if (RenderProcess::current()->in_process_plugins()) {
[email protected]690a99c2009-01-06 16:48:451865 FilePath path;
[email protected]81a34412009-01-05 19:17:241866 render_thread_->Send(
initial.commit09911bf2008-07-26 23:55:291867 new ViewHostMsg_GetPluginPath(url, mime_type, clsid, &path,
1868 actual_mime_type));
[email protected]690a99c2009-01-06 16:48:451869 if (path.value().empty())
initial.commit09911bf2008-07-26 23:55:291870 return NULL;
1871
1872 std::string mime_type_to_use;
1873 if (actual_mime_type && !actual_mime_type->empty())
1874 mime_type_to_use = *actual_mime_type;
1875 else
1876 mime_type_to_use = mime_type;
1877
[email protected]b94d3322009-02-12 19:49:041878 return WebPluginDelegate::Create(path,
1879 mime_type_to_use,
1880 gfx::NativeViewFromId(host_window_));
initial.commit09911bf2008-07-26 23:55:291881 }
1882
1883 WebPluginDelegateProxy* proxy =
1884 WebPluginDelegateProxy::Create(url, mime_type, clsid, this);
1885 if (!proxy)
1886 return NULL;
1887
1888 // We hold onto the proxy so we can poke it when we are painting. See our
1889 // DidPaint implementation below.
1890 plugin_delegates_.push_back(proxy);
1891
1892 return proxy;
[email protected]6c8afae52009-01-22 02:24:571893#else
1894 // TODO(port): Plugins currently not supported
1895 NOTIMPLEMENTED();
1896 return NULL;
1897#endif
initial.commit09911bf2008-07-26 23:55:291898}
1899
[email protected]ec9212f2008-12-18 21:40:361900webkit_glue::WebMediaPlayerDelegate* RenderView::CreateMediaPlayerDelegate() {
[email protected]be645db2009-02-06 20:36:331901#if defined(OS_WIN)
[email protected]d43ed912009-02-03 04:52:531902 return new WebMediaPlayerDelegateImpl(this);
[email protected]be645db2009-02-06 20:36:331903#else
1904 // TODO(port)
1905 NOTIMPLEMENTED();
1906 return NULL;
1907#endif
[email protected]ec9212f2008-12-18 21:40:361908}
1909
initial.commit09911bf2008-07-26 23:55:291910void RenderView::OnMissingPluginStatus(WebPluginDelegate* delegate,
1911 int status) {
[email protected]6c8afae52009-01-22 02:24:571912#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:291913 if (first_default_plugin_ == NULL) {
1914 // Show the InfoBar for the first available plugin.
1915 if (status == default_plugin::MISSING_PLUGIN_AVAILABLE) {
1916 first_default_plugin_ = delegate;
1917 Send(new ViewHostMsg_MissingPluginStatus(routing_id_, status));
1918 }
1919 } else {
1920 // Closes the InfoBar if user clicks on the plugin (instead of the InfoBar)
1921 // to start the download/install.
1922 if (status == default_plugin::MISSING_PLUGIN_USER_STARTED_DOWNLOAD) {
1923 Send(new ViewHostMsg_MissingPluginStatus(routing_id_, status));
1924 }
1925 }
[email protected]6c8afae52009-01-22 02:24:571926#else
1927 // TODO(port): plugins current not supported
1928 NOTIMPLEMENTED();
1929#endif
initial.commit09911bf2008-07-26 23:55:291930}
1931
[email protected]eb47a132009-03-04 00:39:561932WebWorker* RenderView::CreateWebWorker(WebWorkerClient* client) {
1933#if defined(OS_WIN)
[email protected]fd0995032009-03-24 02:01:111934 return new WebWorkerProxy(client, routing_id_);
[email protected]eb47a132009-03-04 00:39:561935#else
1936 // TODO(port): out of process workers
1937 NOTIMPLEMENTED();
1938 return NULL;
1939#endif
1940}
1941
initial.commit09911bf2008-07-26 23:55:291942void RenderView::OpenURL(WebView* webview, const GURL& url,
[email protected]c0588052008-10-27 23:01:501943 const GURL& referrer,
initial.commit09911bf2008-07-26 23:55:291944 WindowOpenDisposition disposition) {
[email protected]c0588052008-10-27 23:01:501945 Send(new ViewHostMsg_OpenURL(routing_id_, url, referrer, disposition));
initial.commit09911bf2008-07-26 23:55:291946}
1947
[email protected]1d522202009-04-04 01:56:421948void RenderView::DidContentsSizeChange(WebWidget* webwidget,
1949 int new_width,
1950 int new_height) {
1951 // TODO(rafaelw): This is a temporary solution. Only the ExtensionView wants
1952 // this notification at the moment. It isn't clean to test for ExtensionView
1953 // by examining the enabled_bindings. This needs to be generalized as it
1954 // becomes clear what extension toolbars need.
1955 if (BindingsPolicy::is_extension_enabled(enabled_bindings_)) {
1956 int width = webview()->GetMainFrame()->GetContentsPreferredWidth();
1957 Send(new ViewHostMsg_DidContentsPreferredWidthChange(routing_id_, width));
1958 }
1959}
1960
initial.commit09911bf2008-07-26 23:55:291961// We are supposed to get a single call to Show for a newly created RenderView
1962// that was created via RenderView::CreateWebView. So, we wait until this
1963// point to dispatch the ShowView message.
1964//
1965// This method provides us with the information about how to display the newly
1966// created RenderView (i.e., as a constrained popup or as a new tab).
1967//
1968void RenderView::Show(WebWidget* webwidget, WindowOpenDisposition disposition) {
1969 DCHECK(!did_show_) << "received extraneous Show call";
1970 DCHECK(opener_id_ != MSG_ROUTING_NONE);
1971
1972 if (did_show_)
1973 return;
1974 did_show_ = true;
1975
1976 // NOTE: initial_pos_ may still have its default values at this point, but
1977 // that's okay. It'll be ignored if disposition is not NEW_POPUP, or the
1978 // browser process will impose a default position otherwise.
1979 Send(new ViewHostMsg_ShowView(
1980 opener_id_, routing_id_, disposition, initial_pos_,
1981 WasOpenedByUserGestureHelper()));
1982}
1983
[email protected]634a6f92008-12-01 21:39:311984void RenderView::CloseWidgetSoon(WebWidget* webwidget) {
1985 if (popup_notification_visible_ == false)
1986 RenderWidget::CloseWidgetSoon(webwidget);
1987}
1988
initial.commit09911bf2008-07-26 23:55:291989void RenderView::RunModal(WebWidget* webwidget) {
1990 DCHECK(did_show_) << "should already have shown the view";
1991
1992 IPC::SyncMessage* msg = new ViewHostMsg_RunModal(routing_id_);
1993
[email protected]1c4947f2009-01-15 22:25:111994 msg->set_pump_messages_event(modal_dialog_event_.get());
initial.commit09911bf2008-07-26 23:55:291995 Send(msg);
1996}
1997
1998void RenderView::SyncNavigationState() {
1999 if (!webview())
2000 return;
2001
initial.commit09911bf2008-07-26 23:55:292002 std::string state;
[email protected]606843fa2008-12-02 19:08:562003 if (!webview()->GetMainFrame()->GetCurrentHistoryState(&state))
initial.commit09911bf2008-07-26 23:55:292004 return;
[email protected]606843fa2008-12-02 19:08:562005 Send(new ViewHostMsg_UpdateState(routing_id_, page_id_, state));
initial.commit09911bf2008-07-26 23:55:292006}
2007
2008void RenderView::ShowContextMenu(WebView* webview,
[email protected]124646932009-01-28 18:39:022009 ContextNode node,
initial.commit09911bf2008-07-26 23:55:292010 int x,
2011 int y,
2012 const GURL& link_url,
2013 const GURL& image_url,
2014 const GURL& page_url,
2015 const GURL& frame_url,
2016 const std::wstring& selection_text,
2017 const std::wstring& misspelled_word,
[email protected]6aa376b2008-09-23 18:49:522018 int edit_flags,
2019 const std::string& security_info) {
[email protected]e09ba552009-02-05 03:26:292020 ContextMenuParams params;
[email protected]124646932009-01-28 18:39:022021 params.node = node;
initial.commit09911bf2008-07-26 23:55:292022 params.x = x;
2023 params.y = y;
2024 params.image_url = image_url;
2025 params.link_url = link_url;
2026 params.page_url = page_url;
2027 params.frame_url = frame_url;
2028 params.selection_text = selection_text;
2029 params.misspelled_word = misspelled_word;
[email protected]be645db2009-02-06 20:36:332030 params.spellcheck_enabled =
[email protected]bbbd545c2008-12-15 20:18:042031 webview->GetFocusedFrame()->SpellCheckEnabled();
initial.commit09911bf2008-07-26 23:55:292032 params.edit_flags = edit_flags;
[email protected]6aa376b2008-09-23 18:49:522033 params.security_info = security_info;
initial.commit09911bf2008-07-26 23:55:292034 Send(new ViewHostMsg_ContextMenu(routing_id_, params));
2035}
2036
2037void RenderView::StartDragging(WebView* webview, const WebDropData& drop_data) {
2038 Send(new ViewHostMsg_StartDragging(routing_id_, drop_data));
2039}
2040
2041void RenderView::TakeFocus(WebView* webview, bool reverse) {
2042 Send(new ViewHostMsg_TakeFocus(routing_id_, reverse));
2043}
2044
2045void RenderView::DidDownloadImage(int id,
2046 const GURL& image_url,
2047 bool errored,
2048 const SkBitmap& image) {
2049 Send(new ViewHostMsg_DidDownloadImage(routing_id_, id, image_url, errored,
2050 image));
2051}
2052
2053
2054void RenderView::OnDownloadImage(int id,
2055 const GURL& image_url,
2056 int image_size) {
2057 if (!webview()->DownloadImage(id, image_url, image_size))
2058 Send(new ViewHostMsg_DidDownloadImage(routing_id_, id, image_url, true,
2059 SkBitmap()));
2060}
2061
2062void RenderView::OnGetApplicationInfo(int page_id) {
2063 webkit_glue::WebApplicationInfo app_info;
2064 if (page_id == page_id_)
2065 webkit_glue::GetApplicationInfo(webview(), &app_info);
2066
2067 // Prune out any data URLs in the set of icons. The browser process expects
2068 // any icon with a data URL to have originated from a favicon. We don't want
2069 // to decode arbitrary data URLs in the browser process. See
2070 // http://b/issue?id=1162972
2071 for (size_t i = 0; i < app_info.icons.size(); ++i) {
[email protected]6de74452009-02-25 18:04:592072 if (app_info.icons[i].url.SchemeIs(chrome::kDataScheme)) {
initial.commit09911bf2008-07-26 23:55:292073 app_info.icons.erase(app_info.icons.begin() + i);
2074 --i;
2075 }
2076 }
2077
2078 Send(new ViewHostMsg_DidGetApplicationInfo(routing_id_, page_id, app_info));
2079}
2080
2081GURL RenderView::GetAlternateErrorPageURL(const GURL& failedURL,
2082 ErrorPageType error_type) {
2083 if (failedURL.SchemeIsSecure()) {
2084 // If the URL that failed was secure, then the embedding web page was not
2085 // expecting a network attacker to be able to manipulate its contents. As
2086 // we fetch alternate error pages over HTTP, we would be allowing a network
2087 // attacker to manipulate the contents of the response if we tried to use
2088 // the link doctor here.
2089 return GURL::EmptyGURL();
2090 }
2091
2092 // Grab the base URL from the browser process.
2093 if (!alternate_error_page_url_.is_valid())
2094 return GURL::EmptyGURL();
2095
2096 // Strip query params from the failed URL.
2097 GURL::Replacements remove_params;
2098 remove_params.ClearUsername();
2099 remove_params.ClearPassword();
2100 remove_params.ClearQuery();
2101 remove_params.ClearRef();
2102 const GURL url_to_send = failedURL.ReplaceComponents(remove_params);
2103
2104 // Construct the query params to send to link doctor.
2105 std::string params(alternate_error_page_url_.query());
2106 params.append("&url=");
2107 params.append(EscapeQueryParamValue(url_to_send.spec()));
2108 params.append("&sourceid=chrome");
2109 params.append("&error=");
2110 switch (error_type) {
2111 case DNS_ERROR:
2112 params.append("dnserror");
2113 break;
2114
2115 case HTTP_404:
2116 params.append("http404");
2117 break;
2118
[email protected]5df266ac2008-10-15 19:50:132119 case CONNECTION_ERROR:
[email protected]e1f934b2009-01-26 20:41:332120 params.append("connectionfailure");
[email protected]5df266ac2008-10-15 19:50:132121 break;
2122
initial.commit09911bf2008-07-26 23:55:292123 default:
2124 NOTREACHED() << "unknown ErrorPageType";
2125 }
2126
2127 // OK, build the final url to return.
2128 GURL::Replacements link_doctor_params;
2129 link_doctor_params.SetQueryStr(params);
2130 GURL url = alternate_error_page_url_.ReplaceComponents(link_doctor_params);
2131 return url;
2132}
2133
[email protected]4f999132009-03-31 18:08:402134void RenderView::OnFind(const WebKit::WebFindInPageRequest& request) {
initial.commit09911bf2008-07-26 23:55:292135 WebFrame* main_frame = webview()->GetMainFrame();
2136 WebFrame* frame_after_main = webview()->GetNextFrameAfter(main_frame, true);
2137 WebFrame* focused_frame = webview()->GetFocusedFrame();
2138 WebFrame* search_frame = focused_frame; // start searching focused frame.
2139
2140 bool multi_frame = (frame_after_main != main_frame);
2141
2142 // If we have multiple frames, we don't want to wrap the search within the
2143 // frame, so we check here if we only have main_frame in the chain.
2144 bool wrap_within_frame = !multi_frame;
2145
2146 gfx::Rect selection_rect;
2147 bool result = false;
2148
2149 do {
[email protected]884db412008-11-24 23:46:502150 result = search_frame->Find(request, wrap_within_frame, &selection_rect);
initial.commit09911bf2008-07-26 23:55:292151
2152 if (!result) {
2153 // don't leave text selected as you move to the next frame.
2154 search_frame->ClearSelection();
2155
2156 // Find the next frame, but skip the invisible ones.
2157 do {
2158 // What is the next frame to search? (we might be going backwards). Note
2159 // that we specify wrap=true so that search_frame never becomes NULL.
2160 search_frame = request.forward ?
2161 webview()->GetNextFrameAfter(search_frame, true) :
2162 webview()->GetPreviousFrameBefore(search_frame, true);
2163 } while (!search_frame->Visible() && search_frame != focused_frame);
2164
[email protected]884db412008-11-24 23:46:502165 // Make sure selection doesn't affect the search operation in new frame.
initial.commit09911bf2008-07-26 23:55:292166 search_frame->ClearSelection();
2167
2168 // If we have multiple frames and we have wrapped back around to the
2169 // focused frame, we need to search it once more allowing wrap within
2170 // the frame, otherwise it will report 'no match' if the focused frame has
2171 // reported matches, but no frames after the focused_frame contain a
2172 // match for the search word(s).
2173 if (multi_frame && search_frame == focused_frame) {
[email protected]884db412008-11-24 23:46:502174 result = search_frame->Find(request, true, // Force wrapping.
2175 &selection_rect);
initial.commit09911bf2008-07-26 23:55:292176 }
2177 }
2178
2179 // TODO(jcampan): http://b/issue?id=1157486 Remove StoreForFocus call once
2180 // we have the fix for 792423.
2181 search_frame->GetView()->StoreFocusForFrame(search_frame);
2182 webview()->SetFocusedFrame(search_frame);
2183 } while (!result && search_frame != focused_frame);
2184
2185 // Make sure we don't leave any frame focused or the focus won't be restored
2186 // properly in WebViewImpl::SetFocus(). Note that we are talking here about
2187 // focused on the SelectionController, not FocusController.
2188 // webview()->GetFocusedFrame() will still return the last focused frame (as
2189 // it queries the FocusController).
2190 // TODO(jcampan): http://b/issue?id=1157486 Remove next line once we have the
2191 // fix for 792423.
2192 webview()->SetFocusedFrame(NULL);
2193
[email protected]4f999132009-03-31 18:08:402194 if (request.findNext) {
[email protected]4f3dc372009-02-24 00:10:292195 // Force the main_frame to report the actual count.
[email protected]4f999132009-03-31 18:08:402196 main_frame->IncreaseMatchCount(0, request.identifier);
[email protected]4f3dc372009-02-24 00:10:292197 } else {
2198 // If nothing is found, set result to "0 of 0", otherwise, set it to
2199 // "-1 of 1" to indicate that we found at least one item, but we don't know
2200 // yet what is active.
2201 int ordinal = result ? -1 : 0; // -1 here means, we might know more later.
2202 int match_count = result ? 1 : 0; // 1 here means possibly more coming.
initial.commit09911bf2008-07-26 23:55:292203
[email protected]4f3dc372009-02-24 00:10:292204 // If we find no matches then this will be our last status update.
2205 // Otherwise the scoping effort will send more results.
2206 bool final_status_update = !result;
initial.commit09911bf2008-07-26 23:55:292207
[email protected]4f3dc372009-02-24 00:10:292208 // Send the search result over to the browser process.
[email protected]4f999132009-03-31 18:08:402209 Send(new ViewHostMsg_Find_Reply(routing_id_,
2210 request.identifier,
[email protected]4f3dc372009-02-24 00:10:292211 match_count,
2212 selection_rect,
2213 ordinal,
2214 final_status_update));
initial.commit09911bf2008-07-26 23:55:292215
initial.commit09911bf2008-07-26 23:55:292216 // Scoping effort begins, starting with the mainframe.
2217 search_frame = main_frame;
2218
2219 main_frame->ResetMatchCount();
2220
2221 do {
2222 // Cancel all old scoping requests before starting a new one.
2223 search_frame->CancelPendingScopingEffort();
2224
2225 // We don't start another scoping effort unless at least one match has
2226 // been found.
2227 if (result) {
2228 // Start new scoping request. If the scoping function determines that it
2229 // needs to scope, it will defer until later.
2230 search_frame->ScopeStringMatches(request,
2231 true); // reset the tickmarks
2232 }
2233
2234 // Iterate to the next frame. The frame will not necessarily scope, for
2235 // example if it is not visible.
2236 search_frame = webview()->GetNextFrameAfter(search_frame, true);
2237 } while (search_frame != main_frame);
2238 }
2239}
2240
2241void RenderView::ReportFindInPageMatchCount(int count, int request_id,
2242 bool final_update) {
2243 // If we have a message that has been queued up, then we should just replace
2244 // it. The ACK from the browser will make sure it gets sent when the browser
2245 // wants it.
2246 if (queued_find_reply_message_.get()) {
2247 IPC::Message* msg = new ViewHostMsg_Find_Reply(
2248 routing_id_,
2249 request_id,
2250 count,
2251 gfx::Rect(0, 0, 0, 0),
2252 -1, // Don't update active match ordinal.
2253 final_update);
2254 queued_find_reply_message_.reset(msg);
2255 } else {
2256 // Send the search result over to the browser process.
2257 Send(new ViewHostMsg_Find_Reply(
2258 routing_id_,
2259 request_id,
2260 count,
2261 gfx::Rect(0, 0, 0, 0),
2262 -1, // // Don't update active match ordinal.
2263 final_update));
2264 }
2265}
2266
2267void RenderView::ReportFindInPageSelection(int request_id,
2268 int active_match_ordinal,
2269 const gfx::Rect& selection_rect) {
2270 // Send the search result over to the browser process.
2271 Send(new ViewHostMsg_Find_Reply(routing_id_,
2272 request_id,
2273 -1,
2274 selection_rect,
2275 active_match_ordinal,
2276 false));
2277}
2278
2279bool RenderView::WasOpenedByUserGesture(WebView* webview) const {
2280 return WasOpenedByUserGestureHelper();
2281}
2282
2283bool RenderView::WasOpenedByUserGestureHelper() const {
2284 // If pop-up blocking has been disabled, then treat all new windows as if
2285 // they were opened by a user gesture. This will prevent them from being
2286 // blocked. This is a bit of a hack, there should be a more straightforward
2287 // way to disable pop-up blocking.
2288 if (disable_popup_blocking_)
2289 return true;
2290
2291 return opened_by_user_gesture_;
2292}
2293
2294void RenderView::SpellCheck(const std::wstring& word, int& misspell_location,
2295 int& misspell_length) {
2296 Send(new ViewHostMsg_SpellCheck(routing_id_, word, &misspell_location,
2297 &misspell_length));
2298}
2299
2300void RenderView::SetInputMethodState(bool enabled) {
2301 // Save the updated IME status and mark the input focus has been updated.
2302 // The IME status is to be sent to a browser process next time when
2303 // the input caret is rendered.
[email protected]9f23f592008-11-17 08:36:342304 if (!ime_control_busy_) {
2305 ime_control_updated_ = true;
2306 ime_control_new_state_ = enabled;
2307 }
initial.commit09911bf2008-07-26 23:55:292308}
2309
2310void RenderView::ScriptedPrint(WebFrame* frame) {
[email protected]6c8afae52009-01-22 02:24:572311#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:292312 // Retrieve the default print settings to calculate the expected number of
2313 // pages.
2314 ViewMsg_Print_Params default_settings;
2315 IPC::SyncMessage* msg =
2316 new ViewHostMsg_GetDefaultPrintSettings(routing_id_, &default_settings);
2317 if (Send(msg)) {
2318 msg = NULL;
2319 // Continue only if the settings are valid.
2320 if (default_settings.dpi && default_settings.document_cookie) {
[email protected]88a3ecc2009-03-19 17:36:222321 int expected_pages_count = 0;
2322 gfx::Size canvas_size;
2323 canvas_size.set_width(
2324 printing::ConvertUnit(default_settings.printable_size.width(),
2325 static_cast<int>(default_settings.dpi),
2326 default_settings.desired_dpi));
2327 canvas_size.set_height(
2328 printing::ConvertUnit(default_settings.printable_size.height(),
2329 static_cast<int>(default_settings.dpi),
2330 default_settings.desired_dpi));
2331 frame->BeginPrint(canvas_size, &expected_pages_count);
initial.commit09911bf2008-07-26 23:55:292332 DCHECK(expected_pages_count);
[email protected]88a3ecc2009-03-19 17:36:222333 frame->EndPrint();
initial.commit09911bf2008-07-26 23:55:292334
2335 // Ask the browser to show UI to retrieve the final print settings.
2336 ViewMsg_PrintPages_Params print_settings;
2337 // host_window_ may be NULL at this point if the current window is a popup
2338 // and the print() command has been issued from the parent. The receiver
2339 // of this message has to deal with this.
2340 msg = new ViewHostMsg_ScriptedPrint(routing_id_,
2341 host_window_,
2342 default_settings.document_cookie,
2343 expected_pages_count,
2344 &print_settings);
2345 if (Send(msg)) {
2346 msg = NULL;
2347
2348 // If the settings are invalid, early quit.
2349 if (print_settings.params.dpi &&
2350 print_settings.params.document_cookie) {
2351 // Render the printed pages. It will implicitly revert the document to
2352 // display CSS media type.
2353 PrintPages(print_settings, frame);
2354 // All went well.
2355 return;
2356 } else {
2357 // The user cancelled.
2358 }
2359 } else {
2360 // Send() failed.
2361 NOTREACHED();
2362 }
2363 } else {
2364 // The user cancelled.
2365 }
2366 } else {
2367 // Send() failed.
2368 NOTREACHED();
2369 }
2370 // TODO(maruel): bug 1123882 Alert the user that printing failed.
[email protected]6c8afae52009-01-22 02:24:572371#else // defined(OS_WIN)
2372 // TODO(port): print not implemented
2373 NOTIMPLEMENTED();
2374#endif
initial.commit09911bf2008-07-26 23:55:292375}
2376
2377void RenderView::WebInspectorOpened(int num_resources) {
2378 Send(new ViewHostMsg_InspectElement_Reply(routing_id_, num_resources));
2379}
2380
2381void RenderView::UserMetricsRecordAction(const std::wstring& action) {
2382 Send(new ViewHostMsg_UserMetricsRecordAction(routing_id_, action));
2383}
2384
2385void RenderView::DnsPrefetch(const std::vector<std::string>& host_names) {
2386 Send(new ViewHostMsg_DnsPrefetch(host_names));
2387}
2388
[email protected]630e26b2008-10-14 22:55:172389void RenderView::OnZoom(int function) {
2390 static const bool kZoomIsTextOnly = false;
2391 switch (function) {
2392 case PageZoom::SMALLER:
2393 webview()->ZoomOut(kZoomIsTextOnly);
initial.commit09911bf2008-07-26 23:55:292394 break;
[email protected]630e26b2008-10-14 22:55:172395 case PageZoom::STANDARD:
2396 webview()->ResetZoom();
initial.commit09911bf2008-07-26 23:55:292397 break;
[email protected]630e26b2008-10-14 22:55:172398 case PageZoom::LARGER:
2399 webview()->ZoomIn(kZoomIsTextOnly);
initial.commit09911bf2008-07-26 23:55:292400 break;
2401 default:
2402 NOTREACHED();
2403 }
2404}
2405
[email protected]ea8c7452009-04-02 20:47:062406void RenderView::OnInsertText(const string16& text) {
2407 webview()->InsertText(text);
2408}
2409
[email protected]e38f40152008-09-12 23:08:302410void RenderView::OnSetPageEncoding(const std::wstring& encoding_name) {
initial.commit09911bf2008-07-26 23:55:292411 webview()->SetPageEncoding(encoding_name);
2412}
2413
2414void RenderView::OnPasswordFormsSeen(WebView* webview,
2415 const std::vector<PasswordForm>& forms) {
2416 Send(new ViewHostMsg_PasswordFormsSeen(routing_id_, forms));
2417}
2418
[email protected]8d0f15c2008-11-11 01:01:092419void RenderView::OnAutofillFormSubmitted(WebView* webview,
2420 const AutofillForm& form) {
2421 Send(new ViewHostMsg_AutofillFormSubmitted(routing_id_, form));
2422}
2423
initial.commit09911bf2008-07-26 23:55:292424WebHistoryItem* RenderView::GetHistoryEntryAtOffset(int offset) {
[email protected]50b691c2008-10-31 19:08:352425 // Our history list is kept in the browser process on the UI thread. Since
2426 // we can't make a sync IPC call to that thread without risking deadlock,
2427 // we use a trick: construct a fake history item of the form:
2428 // history://go/OFFSET
2429 // When WebCore tells us to navigate to it, we tell the browser process to
2430 // do a back/forward navigation instead.
2431
2432 GURL url(StringPrintf("%s://go/%d", kBackForwardNavigationScheme, offset));
2433 history_navigation_item_ = WebHistoryItem::Create(url, L"", "", NULL);
2434 return history_navigation_item_.get();
initial.commit09911bf2008-07-26 23:55:292435}
2436
[email protected]0c0383772008-11-04 00:48:312437void RenderView::GoToEntryAtOffset(int offset) {
[email protected]f46aff62008-10-16 07:58:052438 history_back_list_count_ += offset;
2439 history_forward_list_count_ -= offset;
2440
initial.commit09911bf2008-07-26 23:55:292441 Send(new ViewHostMsg_GoToEntryAtOffset(routing_id_, offset));
2442}
2443
2444int RenderView::GetHistoryBackListCount() {
2445 return history_back_list_count_;
2446}
2447
2448int RenderView::GetHistoryForwardListCount() {
2449 return history_forward_list_count_;
2450}
2451
2452void RenderView::OnNavStateChanged(WebView* webview) {
[email protected]81a34412009-01-05 19:17:242453 if (!nav_state_sync_timer_.IsRunning()) {
2454 nav_state_sync_timer_.Start(
2455 TimeDelta::FromSeconds(delay_seconds_for_form_state_sync_), this,
2456 &RenderView::SyncNavigationState);
2457 }
initial.commit09911bf2008-07-26 23:55:292458}
2459
2460void RenderView::SetTooltipText(WebView* webview,
2461 const std::wstring& tooltip_text) {
2462 Send(new ViewHostMsg_SetTooltipText(routing_id_, tooltip_text));
2463}
2464
[email protected]2e417c82009-04-02 22:30:262465void RenderView::DidChangeSelection(bool is_empty_selection) {
2466#if defined(OS_LINUX)
2467 if (!is_empty_selection) {
2468 // TODO(estade): find a way to incrementally update the selection text.
2469 selection_text_ = webview()->GetMainFrame()->GetSelection(false);
2470 Send(new ViewHostMsg_SelectionChanged(routing_id_));
2471 }
2472#endif
2473}
2474
2475
initial.commit09911bf2008-07-26 23:55:292476void RenderView::DownloadUrl(const GURL& url, const GURL& referrer) {
2477 Send(new ViewHostMsg_DownloadUrl(routing_id_, url, referrer));
2478}
2479
[email protected]611cad42009-03-16 18:51:342480WebDevToolsAgentDelegate* RenderView::GetWebDevToolsAgentDelegate() {
[email protected]b75b7d072009-04-06 13:47:002481 return devtools_agent_.get();
[email protected]611cad42009-03-16 18:51:342482}
2483
[email protected]ea8c7452009-04-02 20:47:062484void RenderView::PasteFromSelectionClipboard() {
2485 Send(new ViewHostMsg_PasteFromSelectionClipboard(routing_id_));
2486}
2487
initial.commit09911bf2008-07-26 23:55:292488WebFrame* RenderView::GetChildFrame(const std::wstring& frame_xpath) const {
2489 WebFrame* web_frame;
2490 if (frame_xpath.empty()) {
2491 web_frame = webview()->GetMainFrame();
2492 } else {
2493 web_frame = webview()->GetMainFrame()->GetChildFrame(frame_xpath);
2494 }
2495
2496 return web_frame;
2497}
2498
[email protected]f29acf52008-11-03 20:08:332499void RenderView::EvaluateScript(const std::wstring& frame_xpath,
2500 const std::wstring& script) {
initial.commit09911bf2008-07-26 23:55:292501 WebFrame* web_frame = GetChildFrame(frame_xpath);
2502 if (!web_frame)
2503 return;
2504
[email protected]4f999132009-03-31 18:08:402505 web_frame->ExecuteScript(WebScriptSource(WideToUTF16Hack(script)));
initial.commit09911bf2008-07-26 23:55:292506}
2507
[email protected]1810e132009-03-24 23:35:482508void RenderView::InsertCSS(const std::wstring& frame_xpath,
2509 const std::string& css) {
2510 WebFrame* web_frame = GetChildFrame(frame_xpath);
2511 if (!web_frame)
2512 return;
2513
2514 web_frame->InsertCSSStyles(css);
2515}
2516
initial.commit09911bf2008-07-26 23:55:292517void RenderView::OnScriptEvalRequest(const std::wstring& frame_xpath,
2518 const std::wstring& jscript) {
[email protected]f29acf52008-11-03 20:08:332519 EvaluateScript(frame_xpath, jscript);
initial.commit09911bf2008-07-26 23:55:292520}
2521
[email protected]1810e132009-03-24 23:35:482522void RenderView::OnCSSInsertRequest(const std::wstring& frame_xpath,
2523 const std::string& css) {
2524 InsertCSS(frame_xpath, css);
2525}
2526
initial.commit09911bf2008-07-26 23:55:292527void RenderView::OnAddMessageToConsole(const std::wstring& frame_xpath,
[email protected]0dea3ea2009-03-31 23:30:592528 const WebConsoleMessage& message) {
initial.commit09911bf2008-07-26 23:55:292529 WebFrame* web_frame = GetChildFrame(frame_xpath);
[email protected]0dea3ea2009-03-31 23:30:592530 if (web_frame)
2531 web_frame->AddMessageToConsole(message);
initial.commit09911bf2008-07-26 23:55:292532}
2533
[email protected]6c8afae52009-01-22 02:24:572534#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:292535void RenderView::OnDebugAttach() {
initial.commit09911bf2008-07-26 23:55:292536 Send(new ViewHostMsg_DidDebugAttach(routing_id_));
2537 // Tell the plugin host to stop accepting messages in order to avoid
2538 // hangs while the renderer is paused.
2539 // TODO(1243929): It might be an improvement to add more plumbing to do this
2540 // when the renderer is actually paused vs. just the debugger being attached.
2541 PluginChannelHost::SetListening(false);
2542}
2543
2544void RenderView::OnDebugDetach() {
2545 // Tell the plugin host to start accepting plugin messages again.
2546 PluginChannelHost::SetListening(true);
2547}
[email protected]6c8afae52009-01-22 02:24:572548#else // defined(OS_WIN)
2549// TODO(port): plugins not yet supported
2550void RenderView::OnDebugAttach() { NOTIMPLEMENTED(); }
2551void RenderView::OnDebugDetach() { NOTIMPLEMENTED(); }
2552#endif
initial.commit09911bf2008-07-26 23:55:292553
[email protected]81e63782009-02-27 19:35:092554void RenderView::OnAllowBindings(int enabled_bindings_flags) {
2555 enabled_bindings_ |= enabled_bindings_flags;
initial.commit09911bf2008-07-26 23:55:292556}
2557
2558void RenderView::OnSetDOMUIProperty(const std::string& name,
2559 const std::string& value) {
[email protected]81e63782009-02-27 19:35:092560 DCHECK(BindingsPolicy::is_dom_ui_enabled(enabled_bindings_));
initial.commit09911bf2008-07-26 23:55:292561 dom_ui_bindings_.SetProperty(name, value);
2562}
2563
2564void RenderView::OnReservePageIDRange(int size_of_range) {
2565 next_page_id_ += size_of_range + 1;
2566}
2567
2568void RenderView::OnDragSourceEndedOrMoved(int client_x,
2569 int client_y,
2570 int screen_x,
2571 int screen_y,
2572 bool ended) {
2573 if (ended)
2574 webview()->DragSourceEndedAt(client_x, client_y, screen_x, screen_y);
2575 else
2576 webview()->DragSourceMovedTo(client_x, client_y, screen_x, screen_y);
2577}
2578
2579void RenderView::OnDragSourceSystemDragEnded() {
2580 webview()->DragSourceSystemDragEnded();
2581}
2582
2583void RenderView::OnUploadFileRequest(const ViewMsg_UploadFile_Params& p) {
2584 webkit_glue::FileUploadData* f = new webkit_glue::FileUploadData;
2585 f->file_path = p.file_path;
2586 f->form_name = p.form;
2587 f->file_name = p.file;
2588 f->submit_name = p.submit;
2589
2590 // Build the other form values map.
2591 if (!p.other_values.empty()) {
2592 std::vector<std::wstring> e;
2593 std::vector<std::wstring> kvp;
2594 std::vector<std::wstring>::iterator i;
2595
2596 SplitString(p.other_values, L'\n', &e);
2597 for (i = e.begin(); i != e.end(); ++i) {
2598 SplitString(*i, L'=', &kvp);
2599 if (kvp.size() == 2)
2600 f->other_form_values[kvp[0]] = kvp[1];
2601 kvp.clear();
2602 }
2603 }
2604
2605 pending_upload_data_.reset(f);
2606 ProcessPendingUpload();
2607}
2608
2609void RenderView::ProcessPendingUpload() {
2610 webkit_glue::FileUploadData* f = pending_upload_data_.get();
2611 if (f && webview() && webkit_glue::FillFormToUploadFile(webview(), *f))
2612 ResetPendingUpload();
2613}
2614
2615void RenderView::ResetPendingUpload() {
2616 pending_upload_data_.reset();
2617}
2618
2619void RenderView::OnFormFill(const FormData& form) {
2620 webkit_glue::FillForm(this->webview(), form);
2621}
2622
2623void RenderView::OnFillPasswordForm(
2624 const PasswordFormDomManager::FillData& form_data) {
2625 webkit_glue::FillPasswordForm(this->webview(), form_data);
2626}
2627
2628void RenderView::OnDragTargetDragEnter(const WebDropData& drop_data,
2629 const gfx::Point& client_pt, const gfx::Point& screen_pt) {
2630 bool is_drop_target = webview()->DragTargetDragEnter(drop_data,
2631 client_pt.x(), client_pt.y(), screen_pt.x(), screen_pt.y());
2632
2633 Send(new ViewHostMsg_UpdateDragCursor(routing_id_, is_drop_target));
2634}
2635
2636void RenderView::OnDragTargetDragOver(const gfx::Point& client_pt,
2637 const gfx::Point& screen_pt) {
2638 bool is_drop_target = webview()->DragTargetDragOver(client_pt.x(),
2639 client_pt.y(), screen_pt.x(), screen_pt.y());
2640
2641 Send(new ViewHostMsg_UpdateDragCursor(routing_id_, is_drop_target));
2642}
2643
2644void RenderView::OnDragTargetDragLeave() {
2645 webview()->DragTargetDragLeave();
2646}
2647
2648void RenderView::OnDragTargetDrop(const gfx::Point& client_pt,
2649 const gfx::Point& screen_pt) {
2650 webview()->DragTargetDrop(client_pt.x(), client_pt.y(), screen_pt.x(),
2651 screen_pt.y());
2652}
2653
2654void RenderView::OnUpdateWebPreferences(const WebPreferences& prefs) {
2655 webview()->SetPreferences(prefs);
2656}
2657
2658void RenderView::OnSetAltErrorPageURL(const GURL& url) {
2659 alternate_error_page_url_ = url;
2660}
2661
2662void RenderView::DidPaint() {
2663 PluginDelegateList::iterator it = plugin_delegates_.begin();
2664 while (it != plugin_delegates_.end()) {
2665 (*it)->FlushGeometryUpdates();
2666 ++it;
2667 }
2668}
2669
2670void RenderView::OnInstallMissingPlugin() {
2671 // This could happen when the first default plugin is deleted.
2672 if (first_default_plugin_ == NULL)
2673 return;
2674 first_default_plugin_->InstallMissingPlugin();
2675}
2676
[email protected]b62d1a8c2009-01-13 23:54:572677void RenderView::OnFileChooserResponse(
[email protected]561abe62009-04-06 18:08:342678 const std::vector<FilePath>& file_names) {
[email protected]8029f5672009-03-20 22:33:362679 // This could happen if we navigated to a different page before the user
2680 // closed the chooser.
2681 if (!file_chooser_.get())
2682 return;
2683
[email protected]b62d1a8c2009-01-13 23:54:572684 file_chooser_->OnFileChoose(file_names);
initial.commit09911bf2008-07-26 23:55:292685 file_chooser_.reset();
2686}
2687
2688void RenderView::OnEnableViewSourceMode() {
2689 if (!webview())
2690 return;
2691 WebFrame* main_frame = webview()->GetMainFrame();
2692 if (!main_frame)
2693 return;
2694
2695 main_frame->SetInViewSourceMode(true);
2696}
2697
2698void RenderView::OnUpdateBackForwardListCount(int back_list_count,
2699 int forward_list_count) {
2700 history_back_list_count_ = back_list_count;
2701 history_forward_list_count_ = forward_list_count;
2702}
2703
[email protected]266eb6f2008-09-30 23:56:502704void RenderView::OnGetAccessibilityInfo(
[email protected]6a983b42009-03-20 20:12:252705 const webkit_glue::WebAccessibility::InParams& in_params,
2706 webkit_glue::WebAccessibility::OutParams* out_params) {
[email protected]6c8afae52009-01-22 02:24:572707#if defined(OS_WIN)
[email protected]6a983b42009-03-20 20:12:252708 if (!web_accessibility_manager_.get()) {
2709 web_accessibility_manager_.reset(
2710 webkit_glue::WebAccessibilityManager::Create());
2711 }
[email protected]266eb6f2008-09-30 23:56:502712
[email protected]6a983b42009-03-20 20:12:252713 if (!web_accessibility_manager_->GetAccObjInfo(webview(), in_params,
2714 out_params)) {
[email protected]266eb6f2008-09-30 23:56:502715 return;
2716 }
[email protected]6c8afae52009-01-22 02:24:572717#else // defined(OS_WIN)
2718 // TODO(port): accessibility not yet implemented
2719 NOTIMPLEMENTED();
2720#endif
[email protected]266eb6f2008-09-30 23:56:502721}
2722
[email protected]6a983b42009-03-20 20:12:252723void RenderView::OnClearAccessibilityInfo(int acc_obj_id, bool clear_all) {
[email protected]6c8afae52009-01-22 02:24:572724#if defined(OS_WIN)
[email protected]6a983b42009-03-20 20:12:252725 if (!web_accessibility_manager_.get()) {
[email protected]266eb6f2008-09-30 23:56:502726 // If accessibility is not activated, ignore clearing message.
2727 return;
2728 }
[email protected]6a983b42009-03-20 20:12:252729 if (!web_accessibility_manager_->ClearAccObjMap(acc_obj_id, clear_all))
[email protected]266eb6f2008-09-30 23:56:502730 return;
[email protected]6c8afae52009-01-22 02:24:572731#else // defined(OS_WIN)
2732 // TODO(port): accessibility not yet implemented
2733 NOTIMPLEMENTED();
2734#endif
[email protected]266eb6f2008-09-30 23:56:502735}
2736
initial.commit09911bf2008-07-26 23:55:292737void RenderView::OnGetAllSavableResourceLinksForCurrentPage(
2738 const GURL& page_url) {
2739 // Prepare list to storage all savable resource links.
2740 std::vector<GURL> resources_list;
2741 std::vector<GURL> referrers_list;
2742 std::vector<GURL> frames_list;
2743 webkit_glue::SavableResourcesResult result(&resources_list,
2744 &referrers_list,
2745 &frames_list);
2746
2747 if (!webkit_glue::GetAllSavableResourceLinksForCurrentPage(webview(),
2748 page_url,
2749 &result)) {
2750 // If something is wrong when collecting all savable resource links,
2751 // send empty list to embedder(browser) to tell it failed.
2752 referrers_list.clear();
2753 resources_list.clear();
2754 frames_list.clear();
2755 }
2756
2757 // Send result of all savable resource links to embedder.
2758 Send(new ViewHostMsg_SendCurrentPageAllSavableResourceLinks(routing_id_,
2759 resources_list,
2760 referrers_list,
2761 frames_list));
2762}
2763
2764void RenderView::OnGetSerializedHtmlDataForCurrentPageWithLocalLinks(
[email protected]f6b48532009-02-12 01:56:322765 const std::vector<GURL>& links,
[email protected]fde6714d12009-02-18 22:39:312766 const std::vector<FilePath>& local_paths,
2767 const FilePath& local_directory_name) {
initial.commit09911bf2008-07-26 23:55:292768 webkit_glue::DomSerializer dom_serializer(webview()->GetMainFrame(),
2769 true,
2770 this,
2771 links,
2772 local_paths,
2773 local_directory_name);
2774 dom_serializer.SerializeDom();
2775}
2776
2777void RenderView::DidSerializeDataForFrame(const GURL& frame_url,
2778 const std::string& data, PageSavingSerializationStatus status) {
2779 Send(new ViewHostMsg_SendSerializedHtmlData(routing_id_,
2780 frame_url, data, static_cast<int32>(status)));
2781}
2782
[email protected]04b4a6c2008-08-02 00:44:472783void RenderView::OnMsgShouldClose() {
initial.commit09911bf2008-07-26 23:55:292784 bool should_close = webview()->ShouldClose();
[email protected]04b4a6c2008-08-02 00:44:472785 Send(new ViewHostMsg_ShouldClose_ACK(routing_id_, should_close));
initial.commit09911bf2008-07-26 23:55:292786}
2787
2788void RenderView::OnClosePage(int new_render_process_host_id,
[email protected]04b4a6c2008-08-02 00:44:472789 int new_request_id) {
initial.commit09911bf2008-07-26 23:55:292790 // TODO(creis): We'd rather use webview()->Close() here, but that currently
2791 // sets the WebView's delegate_ to NULL, preventing any JavaScript dialogs
2792 // in the onunload handler from appearing. For now, we're bypassing that and
2793 // calling the FrameLoader's CloseURL method directly. This should be
2794 // revisited to avoid having two ways to close a page. Having a single way
2795 // to close that can run onunload is also useful for fixing
2796 // http://b/issue?id=753080.
2797 WebFrame* main_frame = webview()->GetMainFrame();
2798 if (main_frame)
2799 main_frame->ClosePage();
2800
2801 Send(new ViewHostMsg_ClosePage_ACK(routing_id_,
2802 new_render_process_host_id,
[email protected]04b4a6c2008-08-02 00:44:472803 new_request_id));
initial.commit09911bf2008-07-26 23:55:292804}
2805
2806void RenderView::OnThemeChanged() {
[email protected]6c8afae52009-01-22 02:24:572807#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:292808 gfx::NativeTheme::instance()->CloseHandles();
2809 gfx::Rect view_rect(0, 0, size_.width(), size_.height());
2810 DidInvalidateRect(webwidget_, view_rect);
[email protected]6c8afae52009-01-22 02:24:572811#else // defined(OS_WIN)
2812 // TODO(port): we don't support theming on non-Windows platforms yet
2813 NOTIMPLEMENTED();
2814#endif
initial.commit09911bf2008-07-26 23:55:292815}
2816
[email protected]f386cca792008-08-26 02:02:182817#ifdef CHROME_PERSONALIZATION
[email protected]1cc879642008-08-26 01:27:352818void RenderView::OnPersonalizationEvent(std::string event_name,
2819 std::string event_args) {
2820 Personalization::HandleViewMsgPersonalizationEvent(personalization_,
2821 webview(),
2822 event_name,
2823 event_args);
2824}
[email protected]f386cca792008-08-26 02:02:182825#endif
[email protected]1cc879642008-08-26 01:27:352826
2827void RenderView::TransitionToCommittedForNewPage() {
[email protected]f386cca792008-08-26 02:02:182828#ifdef CHROME_PERSONALIZATION
[email protected]1cc879642008-08-26 01:27:352829 Personalization::HandleTransitionToCommittedForNewPage(personalization_);
[email protected]f386cca792008-08-26 02:02:182830#endif
[email protected]1cc879642008-08-26 01:27:352831}
2832
[email protected]f46aff62008-10-16 07:58:052833void RenderView::DidAddHistoryItem() {
[email protected]f8901082008-10-31 23:34:032834 // We don't want to update the history length for the start page
2835 // navigation.
2836 WebFrame* main_frame = webview()->GetMainFrame();
2837 DCHECK(main_frame != NULL);
2838
2839 WebDataSource* ds = main_frame->GetDataSource();
2840 DCHECK(ds != NULL);
2841
2842 const WebRequest& request = ds->GetRequest();
2843 RenderViewExtraRequestData* extra_data =
2844 static_cast<RenderViewExtraRequestData*>(request.GetExtraData());
2845
2846 if (extra_data && extra_data->transition_type == PageTransition::START_PAGE)
2847 return;
2848
[email protected]f46aff62008-10-16 07:58:052849 history_back_list_count_++;
2850 history_forward_list_count_ = 0;
2851}
2852
[email protected]28790922009-03-09 19:48:372853void RenderView::OnMessageFromExternalHost(const std::string& message,
2854 const std::string& origin,
2855 const std::string& target) {
[email protected]3ac14a052008-08-15 21:22:152856 if (message.empty())
2857 return;
2858
[email protected]28790922009-03-09 19:48:372859 external_host_bindings_.ForwardMessageFromExternalHost(message, origin,
2860 target);
[email protected]3ac14a052008-08-15 21:22:152861}
2862
[email protected]0aa55312008-10-17 21:53:082863void RenderView::OnDisassociateFromPopupCount() {
2864 if (decrement_shared_popup_at_destruction_)
2865 shared_popup_counter_->data--;
2866 shared_popup_counter_ = new SharedRenderViewCounter(0);
2867 decrement_shared_popup_at_destruction_ = false;
2868}
2869
initial.commit09911bf2008-07-26 23:55:292870std::string RenderView::GetAltHTMLForTemplate(
2871 const DictionaryValue& error_strings, int template_resource_id) const {
2872 const StringPiece template_html(
2873 ResourceBundle::GetSharedInstance().GetRawDataResource(
2874 template_resource_id));
2875
2876 if (template_html.empty()) {
2877 NOTREACHED() << "unable to load template. ID: " << template_resource_id;
2878 return "";
2879 }
2880 // "t" is the id of the templates root node.
2881 return jstemplate_builder::GetTemplateHtml(
2882 template_html, &error_strings, "t");
2883}
[email protected]0e79b9e2009-02-13 04:20:482884
2885MessageLoop* RenderView::GetMessageLoopForIO() {
2886 // Assume that we have only one RenderThread in the process and the owner loop
2887 // of RenderThread is an IO message loop.
[email protected]8930d472009-02-21 08:05:282888 if (RenderThread::current())
2889 return RenderThread::current()->owner_loop();
[email protected]0e79b9e2009-02-13 04:20:482890 return NULL;
2891}
[email protected]6f56d482009-02-20 05:02:562892
2893void RenderView::OnRequestAudioPacket(int stream_id) {
2894 AudioRendererImpl* audio_renderer = audio_renderers_.Lookup(stream_id);
[email protected]4f3dc372009-02-24 00:10:292895 if (!audio_renderer) {
[email protected]6f56d482009-02-20 05:02:562896 NOTREACHED();
2897 return;
2898 }
2899 audio_renderer->OnRequestPacket();
2900}
2901
2902void RenderView::OnAudioStreamCreated(
2903 int stream_id, base::SharedMemoryHandle handle, int length) {
2904 AudioRendererImpl* audio_renderer = audio_renderers_.Lookup(stream_id);
[email protected]4f3dc372009-02-24 00:10:292905 if (!audio_renderer) {
[email protected]6f56d482009-02-20 05:02:562906 NOTREACHED();
2907 return;
2908 }
2909 audio_renderer->OnCreated(handle, length);
2910}
2911
2912void RenderView::OnAudioStreamStateChanged(
2913 int stream_id, AudioOutputStream::State state, int info) {
2914 AudioRendererImpl* audio_renderer = audio_renderers_.Lookup(stream_id);
[email protected]4f3dc372009-02-24 00:10:292915 if (!audio_renderer) {
[email protected]6f56d482009-02-20 05:02:562916 NOTREACHED();
2917 return;
2918 }
2919 audio_renderer->OnStateChanged(state, info);
2920}
2921
2922void RenderView::OnAudioStreamVolume(int stream_id, double left, double right) {
2923 AudioRendererImpl* audio_renderer = audio_renderers_.Lookup(stream_id);
[email protected]4f3dc372009-02-24 00:10:292924 if (!audio_renderer) {
[email protected]6f56d482009-02-20 05:02:562925 NOTREACHED();
2926 return;
2927 }
2928 audio_renderer->OnVolume(left, right);
2929}
2930
[email protected]30f75e62009-02-25 22:01:002931void RenderView::OnMoveOrResizeStarted() {
2932 if (webview())
2933 webview()->HideAutofillPopup();
2934}
2935
[email protected]6f56d482009-02-20 05:02:562936int32 RenderView::CreateAudioStream(AudioRendererImpl* audio_renderer,
2937 AudioManager::Format format, int channels,
2938 int sample_rate, int bits_per_sample,
2939 size_t packet_size) {
[email protected]8db216e2009-03-10 22:40:312940 DCHECK(RenderThread::current()->message_loop() == MessageLoop::current());
[email protected]6f56d482009-02-20 05:02:562941 // Loop through the map and make sure there's no renderer already in the map.
2942 for (IDMap<AudioRendererImpl>::const_iterator iter = audio_renderers_.begin();
2943 iter != audio_renderers_.end(); ++iter) {
2944 DCHECK(iter->second != audio_renderer);
2945 }
2946
2947 // Add to map and send the IPC to browser process.
2948 int32 stream_id = audio_renderers_.Add(audio_renderer);
2949 ViewHostMsg_Audio_CreateStream params;
2950 params.format = format;
2951 params.channels = channels;
2952 params.sample_rate = sample_rate;
2953 params.bits_per_sample = bits_per_sample;
2954 params.packet_size = packet_size;
2955 Send(new ViewHostMsg_CreateAudioStream(routing_id_, stream_id, params));
2956 return stream_id;
2957}
2958
2959void RenderView::StartAudioStream(int stream_id) {
[email protected]8db216e2009-03-10 22:40:312960 DCHECK(RenderThread::current()->message_loop() == MessageLoop::current());
[email protected]6f56d482009-02-20 05:02:562961 DCHECK(audio_renderers_.Lookup(stream_id) != NULL);
2962 Send(new ViewHostMsg_StartAudioStream(routing_id_, stream_id));
2963}
2964
2965void RenderView::CloseAudioStream(int stream_id) {
[email protected]8db216e2009-03-10 22:40:312966 DCHECK(RenderThread::current()->message_loop() == MessageLoop::current());
[email protected]d1f17392009-04-03 23:05:302967 if (audio_renderers_.Lookup(stream_id) != NULL) {
2968 // Remove the entry from the map and send a close message to browser
2969 // process, we won't be getting anything back from browser even if there's
2970 // an error.
2971 audio_renderers_.Remove(stream_id);
2972 Send(new ViewHostMsg_CloseAudioStream(routing_id_, stream_id));
2973 }
[email protected]6f56d482009-02-20 05:02:562974}
2975
[email protected]2ee2329e2009-02-27 23:51:162976void RenderView::NotifyAudioPacketReady(int stream_id, size_t size) {
[email protected]8db216e2009-03-10 22:40:312977 DCHECK(RenderThread::current()->message_loop() == MessageLoop::current());
[email protected]6f56d482009-02-20 05:02:562978 DCHECK(audio_renderers_.Lookup(stream_id) != NULL);
[email protected]2ee2329e2009-02-27 23:51:162979 Send(new ViewHostMsg_NotifyAudioPacketReady(routing_id_, stream_id, size));
[email protected]6f56d482009-02-20 05:02:562980}
2981
2982void RenderView::GetAudioVolume(int stream_id) {
[email protected]8db216e2009-03-10 22:40:312983 DCHECK(RenderThread::current()->message_loop() == MessageLoop::current());
[email protected]6f56d482009-02-20 05:02:562984 DCHECK(audio_renderers_.Lookup(stream_id) != NULL);
2985 Send(new ViewHostMsg_GetAudioVolume(routing_id_, stream_id));
2986}
2987
2988void RenderView::SetAudioVolume(int stream_id, double left, double right) {
[email protected]8db216e2009-03-10 22:40:312989 DCHECK(RenderThread::current()->message_loop() == MessageLoop::current());
[email protected]6f56d482009-02-20 05:02:562990 DCHECK(audio_renderers_.Lookup(stream_id) != NULL);
2991 Send(new ViewHostMsg_SetAudioVolume(routing_id_, stream_id, left, right));
2992}
[email protected]30f75e62009-02-25 22:01:002993
2994void RenderView::OnResize(const gfx::Size& new_size,
2995 const gfx::Rect& resizer_rect) {
2996 if (webview())
2997 webview()->HideAutofillPopup();
2998 RenderWidget::OnResize(new_size, resizer_rect);
2999}
[email protected]0aa477bd2009-03-23 22:21:433000
[email protected]309d7a282009-03-24 09:18:273001void RenderView::SendExtensionRequest(const std::string& name,
3002 const std::string& args,
3003 int callback_id,
3004 WebFrame* callback_frame) {
3005 DCHECK(RenderThread::current()->message_loop() == MessageLoop::current());
3006
3007 if (callback_id != -1) {
3008 DCHECK(callback_frame) << "Callback specified without frame";
3009 pending_extension_callbacks_.AddWithID(callback_frame, callback_id);
3010 }
3011
3012 Send(new ViewHostMsg_ExtensionRequest(routing_id_, name, args, callback_id));
3013}
3014
3015void RenderView::OnExtensionResponse(int callback_id,
3016 const std::string& response) {
3017 WebFrame* web_frame = pending_extension_callbacks_.Lookup(callback_id);
3018 if (!web_frame)
3019 return; // The frame went away.
3020
3021 extensions_v8::ExtensionProcessBindings::ExecuteCallbackInFrame(
3022 web_frame, callback_id, response);
3023 pending_extension_callbacks_.Remove(callback_id);
3024}
[email protected]c20210e62009-04-03 21:39:263025
3026// Dump all load time histograms. We create 2 sets time based histograms,
3027// one that is specific to the navigation type and one that aggregates all
3028// navigation types
3029//
3030// Each set contains 5 histograms measuring various times.
3031// The time points we keep are
3032// request: time document was requested by user
3033// start: time load of document started
3034// finishDoc: main document loaded, before onload()
3035// finish: after onload() and all resources are loaded
3036// finish_document_load_time and finish_load_time.
3037// The times that we histogram are
3038// requestToStart,
3039// startToFinishDoc,
3040// finishDocToFinish,
3041// startToFinish,
3042// requestToFinish,
3043//
3044void RenderView::DumpLoadHistograms() const {
3045 WebFrame* main_frame = webview()->GetMainFrame();
3046 WebDataSource* ds = main_frame->GetDataSource();
3047 WebNavigationType nav_type = ds->GetNavigationType();
3048 Time request_time = ds->GetRequestTime();
3049 Time start_load_time = ds->GetStartLoadTime();
3050 Time finish_document_load_time = ds->GetFinishDocumentLoadTime();
3051 Time finish_load_time = ds->GetFinishLoadTime();
3052 TimeDelta request_to_start = start_load_time - request_time;
3053 TimeDelta start_to_finish_doc = finish_document_load_time - start_load_time;
3054 TimeDelta finish_doc_to_finish = finish_load_time - finish_document_load_time;
3055 TimeDelta start_to_finish = finish_load_time - start_load_time;
3056 TimeDelta request_to_finish = finish_load_time - start_load_time;
3057
3058 UMA_HISTOGRAM_TIMES("Renderer.All.RequestToStart", request_to_start);
3059 UMA_HISTOGRAM_TIMES("Renderer.All.StartToFinishDoc", start_to_finish_doc);
3060 UMA_HISTOGRAM_TIMES("Renderer.All.FinishDocToFinish", finish_doc_to_finish);
3061 UMA_HISTOGRAM_TIMES("Renderer.All.StartToFinish", start_to_finish);
3062 UMA_HISTOGRAM_TIMES("Renderer.All.RequestToFinish", request_to_finish);
3063 switch (nav_type) {
3064 case WebNavigationTypeLinkClicked:
3065 UMA_HISTOGRAM_TIMES(
3066 "Renderer.LinkClicked.RequestToStart", request_to_start);
3067 UMA_HISTOGRAM_TIMES(
3068 "Renderer.LinkClicked.StartToFinishDoc", start_to_finish_doc);
3069 UMA_HISTOGRAM_TIMES(
3070 "Renderer.LinkClicked.FinishDocToFinish", finish_doc_to_finish);
3071 UMA_HISTOGRAM_TIMES(
3072 "Renderer.LinkClicked.RequestToFinish", request_to_finish);
3073 UMA_HISTOGRAM_TIMES(
3074 "Renderer.LinkClicked.StartToFinish", start_to_finish);
3075 break;
3076 case WebNavigationTypeFormSubmitted:
3077 UMA_HISTOGRAM_TIMES(
3078 "Renderer.FormSubmitted.RequestToStart", request_to_start);
3079 UMA_HISTOGRAM_TIMES(
3080 "Renderer.FormSubmitted.StartToFinishDoc", start_to_finish_doc);
3081 UMA_HISTOGRAM_TIMES(
3082 "Renderer.FormSubmitted.FinishDocToFinish", finish_doc_to_finish);
3083 UMA_HISTOGRAM_TIMES(
3084 "Renderer.FormSubmitted.RequestToFinish", request_to_finish);
3085 UMA_HISTOGRAM_TIMES(
3086 "Renderer.FormSubmitted.StartToFinish", start_to_finish);
3087 break;
3088 case WebNavigationTypeBackForward:
3089 UMA_HISTOGRAM_TIMES(
3090 "Renderer.BackForward.RequestToStart", request_to_start);
3091 UMA_HISTOGRAM_TIMES(
3092 "Renderer.BackForward.StartToFinishDoc", start_to_finish_doc);
3093 UMA_HISTOGRAM_TIMES(
3094 "Renderer.BackForward.FinishDocToFinish", finish_doc_to_finish);
3095 UMA_HISTOGRAM_TIMES(
3096 "Renderer.BackForward.RequestToFinish", request_to_finish);
3097 UMA_HISTOGRAM_TIMES(
3098 "Renderer.BackForward.StartToFinish", start_to_finish);
3099 break;
3100 case WebNavigationTypeReload:
3101 UMA_HISTOGRAM_TIMES(
3102 "Renderer.Reload.RequestToStart", request_to_start);
3103 UMA_HISTOGRAM_TIMES(
3104 "Renderer.Reload.StartToFinishDoc", start_to_finish_doc);
3105 UMA_HISTOGRAM_TIMES(
3106 "Renderer.Reload.FinishDocToFinish", finish_doc_to_finish);
3107 UMA_HISTOGRAM_TIMES(
3108 "Renderer.Reload.RequestToFinish", request_to_finish);
3109 UMA_HISTOGRAM_TIMES(
3110 "Renderer.Reload.StartToFinish", start_to_finish);
3111 break;
3112 case WebNavigationTypeFormResubmitted:
3113 UMA_HISTOGRAM_TIMES(
3114 "Renderer.FormResubmitted.RequestToStart", request_to_start);
3115 UMA_HISTOGRAM_TIMES(
3116 "Renderer.FormResubmitted.StartToFinishDoc", start_to_finish_doc);
3117 UMA_HISTOGRAM_TIMES(
3118 "Renderer.FormResubmitted.FinishDocToFinish", finish_doc_to_finish);
3119 UMA_HISTOGRAM_TIMES(
3120 "Renderer.FormResubmitted.RequestToFinish", request_to_finish);
3121 UMA_HISTOGRAM_TIMES(
3122 "Renderer.FormResubmitted.StartToFinish", start_to_finish);
3123 break;
3124 case WebNavigationTypeOther:
3125 UMA_HISTOGRAM_TIMES(
3126 "Renderer.Other.RequestToStart", request_to_start);
3127 UMA_HISTOGRAM_TIMES(
3128 "Renderer.Other.StartToFinishDoc", start_to_finish_doc);
3129 UMA_HISTOGRAM_TIMES(
3130 "Renderer.Other.FinishDocToFinish", finish_doc_to_finish);
3131 UMA_HISTOGRAM_TIMES(
3132 "Renderer.Other.RequestToFinish", request_to_finish);
3133 UMA_HISTOGRAM_TIMES(
3134 "Renderer.Other.StartToFinish", start_to_finish);
3135 break;
3136 }
3137}