blob: 7c85b653ab5e83b68a98e95b55cdd97a249c4993 [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]8a2820a2008-10-09 21:58:0512#include "base/gfx/gdi_util.h"
initial.commit09911bf2008-07-26 23:55:2913#include "base/gfx/native_theme.h"
initial.commit09911bf2008-07-26 23:55:2914#include "base/gfx/png_encoder.h"
15#include "base/string_piece.h"
16#include "base/string_util.h"
17#include "chrome/app/theme/theme_resources.h"
18#include "chrome/common/chrome_switches.h"
19#include "chrome/common/gfx/emf.h"
20#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]630e26b2008-10-14 22:55:1724#include "chrome/common/page_zoom.h"
initial.commit09911bf2008-07-26 23:55:2925#include "chrome/common/resource_bundle.h"
initial.commit09911bf2008-07-26 23:55:2926#include "chrome/common/thumbnail_score.h"
[email protected]173de1b2008-08-15 18:36:4627#include "chrome/common/chrome_plugin_lib.h"
initial.commit09911bf2008-07-26 23:55:2928#include "chrome/renderer/about_handler.h"
[email protected]173de1b2008-08-15 18:36:4629#include "chrome/renderer/chrome_plugin_host.h"
initial.commit09911bf2008-07-26 23:55:2930#include "chrome/renderer/debug_message_handler.h"
31#include "chrome/renderer/localized_error.h"
32#include "chrome/renderer/renderer_resources.h"
[email protected]0938d3c2009-01-09 20:37:3533#include "chrome/renderer/user_script_slave.h"
initial.commit09911bf2008-07-26 23:55:2934#include "chrome/renderer/visitedlink_slave.h"
[email protected]ec9212f2008-12-18 21:40:3635#include "chrome/renderer/webmediaplayer_delegate_impl.h"
initial.commit09911bf2008-07-26 23:55:2936#include "chrome/renderer/webplugin_delegate_proxy.h"
37#include "chrome/views/message_box_view.h"
38#include "net/base/escape.h"
39#include "net/base/net_errors.h"
[email protected]c399a8a2008-11-22 19:38:0040#include "skia/ext/bitmap_platform_device.h"
[email protected]83c9e6552008-12-03 16:22:1041#include "skia/ext/image_operations.h"
[email protected]c399a8a2008-11-22 19:38:0042#include "skia/ext/vector_canvas.h"
initial.commit09911bf2008-07-26 23:55:2943#include "webkit/default_plugin/default_plugin_shared.h"
44#include "webkit/glue/dom_operations.h"
45#include "webkit/glue/dom_serializer.h"
46#include "webkit/glue/password_form.h"
47#include "webkit/glue/plugins/plugin_list.h"
48#include "webkit/glue/searchable_form_data.h"
49#include "webkit/glue/webdatasource.h"
50#include "webkit/glue/webdropdata.h"
51#include "webkit/glue/weberror.h"
52#include "webkit/glue/webframe.h"
53#include "webkit/glue/webhistoryitem.h"
54#include "webkit/glue/webinputevent.h"
55#include "webkit/glue/webkit_glue.h"
56#include "webkit/glue/webpreferences.h"
57#include "webkit/glue/webresponse.h"
58#include "webkit/glue/weburlrequest.h"
59#include "webkit/glue/webview.h"
60#include "webkit/glue/plugins/webplugin_delegate_impl.h"
[email protected]ae615162008-12-03 01:11:5861//#include "webkit/port/platform/graphics/PlatformContextSkia.h"
initial.commit09911bf2008-07-26 23:55:2962
63#include "generated_resources.h"
64
[email protected]e1acf6f2008-10-27 20:43:3365using base::TimeDelta;
66
initial.commit09911bf2008-07-26 23:55:2967//-----------------------------------------------------------------------------
68
69// define to write the time necessary for thumbnail/DOM text retrieval,
70// respectively, into the system debug log
71// #define TIME_BITMAP_RETRIEVAL
72// #define TIME_TEXT_RETRIEVAL
73
74// maximum number of characters in the document to index, any text beyond this
75// point will be clipped
76static const int kMaxIndexChars = 65535;
77
78// Size of the thumbnails that we'll generate
79static const int kThumbnailWidth = 196;
80static const int kThumbnailHeight = 136;
81
82// Delay in milliseconds that we'll wait before capturing the page contents
83// and thumbnail.
84static const int kDelayForCaptureMs = 500;
85
86// Typically, we capture the page data once the page is loaded.
87// Sometimes, the page never finishes to load, preventing the page capture
88// To workaround this problem, we always perform a capture after the following
89// delay.
90static const int kDelayForForcedCaptureMs = 6000;
91
[email protected]81a34412009-01-05 19:17:2492// The default value for RenderView.delay_seconds_for_form_state_sync_, see
93// that variable for more.
94const int kDefaultDelaySecondsForFormStateSync = 5;
initial.commit09911bf2008-07-26 23:55:2995
96// The next available page ID to use. This ensures that the page IDs are
97// globally unique in the renderer.
98static int32 next_page_id_ = 1;
99
[email protected]0aa55312008-10-17 21:53:08100// The maximum number of popups that can be spawned from one page.
101static const int kMaximumNumberOfUnacknowledgedPopups = 25;
102
initial.commit09911bf2008-07-26 23:55:29103static const char* const kUnreachableWebDataURL =
[email protected]76a010b2008-12-07 23:48:03104 "chrome://chromewebdata/";
initial.commit09911bf2008-07-26 23:55:29105
[email protected]50b691c2008-10-31 19:08:35106static const char* const kBackForwardNavigationScheme = "history";
107
initial.commit09911bf2008-07-26 23:55:29108namespace {
109
110// Associated with browser-initiated navigations to hold tracking data.
111class RenderViewExtraRequestData : public WebRequest::ExtraData {
112 public:
113 RenderViewExtraRequestData(int32 pending_page_id,
114 PageTransition::Type transition,
115 const GURL& url)
116 : pending_page_id_(pending_page_id),
117 transition_type(transition),
118 request_committed(false) {
119 }
120
121 // Contains the page_id for this navigation or -1 if there is none yet.
122 int32 pending_page_id() const { return pending_page_id_; }
123
124 // Is this a new navigation?
125 bool is_new_navigation() const { return pending_page_id_ == -1; }
126
127 // Contains the transition type that the browser specified when it
128 // initiated the load.
129 PageTransition::Type transition_type;
130
131 // True if we have already processed the "DidCommitLoad" event for this
132 // request. Used by session history.
133 bool request_committed;
134
135 private:
136 int32 pending_page_id_;
137
138 DISALLOW_EVIL_CONSTRUCTORS(RenderViewExtraRequestData);
139};
140
141} // namespace
142
143///////////////////////////////////////////////////////////////////////////////
144
[email protected]81a34412009-01-05 19:17:24145RenderView::RenderView(RenderThreadBase* render_thread)
146 : RenderWidget(render_thread, true),
[email protected]e75cb49e2009-01-05 23:13:21147 enable_dom_automation_(false),
148 enable_dom_ui_bindings_(false),
149 enable_external_host_bindings_(false),
150 target_url_status_(TARGET_NONE),
[email protected]81a34412009-01-05 19:17:24151 is_loading_(false),
[email protected]e75cb49e2009-01-05 23:13:21152 navigation_gesture_(NavigationGestureUnknown),
[email protected]81a34412009-01-05 19:17:24153 page_id_(-1),
154 last_page_id_sent_to_browser_(-1),
155 last_indexed_page_id_(-1),
[email protected]81a34412009-01-05 19:17:24156 opened_by_user_gesture_(true),
[email protected]e75cb49e2009-01-05 23:13:21157 method_factory_(this),
[email protected]81a34412009-01-05 19:17:24158 first_default_plugin_(NULL),
[email protected]e75cb49e2009-01-05 23:13:21159 printed_document_width_(0),
[email protected]81a34412009-01-05 19:17:24160 history_back_list_count_(0),
161 history_forward_list_count_(0),
162 disable_popup_blocking_(false),
163 has_unload_listener_(false),
164 decrement_shared_popup_at_destruction_(false),
[email protected]0938d3c2009-01-09 20:37:35165 user_scripts_enabled_(false),
[email protected]81a34412009-01-05 19:17:24166 waiting_for_create_window_ack_(false),
167 form_field_autofill_request_id_(0),
168 popup_notification_visible_(false),
169 delay_seconds_for_form_state_sync_(kDefaultDelaySecondsForFormStateSync) {
initial.commit09911bf2008-07-26 23:55:29170 resource_dispatcher_ = new ResourceDispatcher(this);
[email protected]3a453fa2008-08-15 18:46:34171#ifdef CHROME_PERSONALIZATION
172 personalization_ = Personalization::CreateRendererPersonalization();
173#endif
initial.commit09911bf2008-07-26 23:55:29174}
175
176RenderView::~RenderView() {
[email protected]0aa55312008-10-17 21:53:08177 if (decrement_shared_popup_at_destruction_)
178 shared_popup_counter_->data--;
179
initial.commit09911bf2008-07-26 23:55:29180 resource_dispatcher_->ClearMessageSender();
181 // Clear any back-pointers that might still be held by plugins.
182 PluginDelegateList::iterator it = plugin_delegates_.begin();
183 while (it != plugin_delegates_.end()) {
184 (*it)->DropRenderView();
185 it = plugin_delegates_.erase(it);
186 }
187
[email protected]81a34412009-01-05 19:17:24188 render_thread_->RemoveFilter(debug_message_handler_);
[email protected]3a453fa2008-08-15 18:46:34189
190#ifdef CHROME_PERSONALIZATION
191 Personalization::CleanupRendererPersonalization(personalization_);
192 personalization_ = NULL;
193#endif
initial.commit09911bf2008-07-26 23:55:29194}
195
196/*static*/
[email protected]0aa55312008-10-17 21:53:08197RenderView* RenderView::Create(
[email protected]81a34412009-01-05 19:17:24198 RenderThreadBase* render_thread,
[email protected]0aa55312008-10-17 21:53:08199 HWND parent_hwnd,
[email protected]1c4947f2009-01-15 22:25:11200 base::WaitableEvent* modal_dialog_event,
[email protected]0aa55312008-10-17 21:53:08201 int32 opener_id,
202 const WebPreferences& webkit_prefs,
203 SharedRenderViewCounter* counter,
204 int32 routing_id) {
initial.commit09911bf2008-07-26 23:55:29205 DCHECK(routing_id != MSG_ROUTING_NONE);
[email protected]81a34412009-01-05 19:17:24206 scoped_refptr<RenderView> view = new RenderView(render_thread);
initial.commit09911bf2008-07-26 23:55:29207 view->Init(parent_hwnd,
208 modal_dialog_event,
209 opener_id,
210 webkit_prefs,
[email protected]0aa55312008-10-17 21:53:08211 counter,
initial.commit09911bf2008-07-26 23:55:29212 routing_id); // adds reference
213 return view;
214}
215
216/*static*/
217void RenderView::SetNextPageID(int32 next_page_id) {
218 // This method should only be called during process startup, and the given
219 // page id had better not exceed our current next page id!
220 DCHECK(next_page_id_ == 1);
221 DCHECK(next_page_id >= next_page_id_);
222 next_page_id_ = next_page_id;
223}
224
225void RenderView::PluginDestroyed(WebPluginDelegateProxy* proxy) {
226 PluginDelegateList::iterator it =
227 std::find(plugin_delegates_.begin(), plugin_delegates_.end(), proxy);
228 DCHECK(it != plugin_delegates_.end());
229 plugin_delegates_.erase(it);
230 // If the plugin is deleted, we need to clear our reference in case user
231 // clicks the info bar to install. Unfortunately we are getting
232 // PluginDestroyed in single process mode. However, that is not a huge
233 // concern.
234 if (proxy == first_default_plugin_)
235 first_default_plugin_ = NULL;
236}
237
[email protected]690a99c2009-01-06 16:48:45238void RenderView::PluginCrashed(const FilePath& plugin_path) {
initial.commit09911bf2008-07-26 23:55:29239 Send(new ViewHostMsg_CrashedPlugin(routing_id_, plugin_path));
240}
241
242
243void RenderView::JSOutOfMemory() {
244 Send(new ViewHostMsg_JSOutOfMemory(routing_id_));
245}
246
247void RenderView::Init(HWND parent_hwnd,
[email protected]1c4947f2009-01-15 22:25:11248 base::WaitableEvent* modal_dialog_event,
initial.commit09911bf2008-07-26 23:55:29249 int32 opener_id,
250 const WebPreferences& webkit_prefs,
[email protected]0aa55312008-10-17 21:53:08251 SharedRenderViewCounter* counter,
initial.commit09911bf2008-07-26 23:55:29252 int32 routing_id) {
253 DCHECK(!webview());
254
255 if (opener_id != MSG_ROUTING_NONE)
256 opener_id_ = opener_id;
257
[email protected]0aa55312008-10-17 21:53:08258 if (counter) {
259 shared_popup_counter_ = counter;
260 shared_popup_counter_->data++;
261 decrement_shared_popup_at_destruction_ = true;
262 } else {
263 shared_popup_counter_ = new SharedRenderViewCounter(0);
264 decrement_shared_popup_at_destruction_ = false;
265 }
266
initial.commit09911bf2008-07-26 23:55:29267 // Avoid a leak here by not assigning, since WebView::Create addrefs for us.
268 WebWidget* view = WebView::Create(this, webkit_prefs);
269 webwidget_.swap(&view);
270
271 // Don't let WebCore keep a B/F list - we have our own.
272 // We let it keep 1 entry because FrameLoader::goToItem expects an item in the
273 // backForwardList, which is used only in ASSERTs.
274 webview()->SetBackForwardListSize(1);
275
276 routing_id_ = routing_id;
[email protected]81a34412009-01-05 19:17:24277 render_thread_->AddRoute(routing_id_, this);
initial.commit09911bf2008-07-26 23:55:29278 // Take a reference on behalf of the RenderThread. This will be balanced
279 // when we receive ViewMsg_Close.
280 AddRef();
281
282 // If this is a popup, we must wait for the CreatingNew_ACK message before
283 // completing initialization. Otherwise, we can finish it now.
284 if (opener_id == MSG_ROUTING_NONE) {
285 did_show_ = true;
286 CompleteInit(parent_hwnd);
287 }
288
289 host_window_ = parent_hwnd;
[email protected]1c4947f2009-01-15 22:25:11290 modal_dialog_event_.reset(modal_dialog_event);
initial.commit09911bf2008-07-26 23:55:29291
292 CommandLine command_line;
293 enable_dom_automation_ =
294 command_line.HasSwitch(switches::kDomAutomationController);
295 disable_popup_blocking_ =
296 command_line.HasSwitch(switches::kDisablePopupBlocking);
[email protected]0938d3c2009-01-09 20:37:35297 user_scripts_enabled_ =
298 command_line.HasSwitch(switches::kEnableUserScripts);
initial.commit09911bf2008-07-26 23:55:29299
300 debug_message_handler_ = new DebugMessageHandler(this);
[email protected]81a34412009-01-05 19:17:24301 render_thread_->AddFilter(debug_message_handler_);
initial.commit09911bf2008-07-26 23:55:29302}
303
304void RenderView::OnMessageReceived(const IPC::Message& message) {
[email protected]06828b92008-10-20 21:25:46305 // If the current RenderView instance represents a popup, then we
306 // need to wait for ViewMsg_CreatingNew_ACK to be sent by the browser.
307 // As part of this ack we also receive the browser window handle, which
308 // parents any plugins instantiated in this RenderView instance.
309 // Plugins can be instantiated only when we receive the parent window
310 // handle as they are child windows.
311 if (waiting_for_create_window_ack_ &&
312 resource_dispatcher_->IsResourceMessage(message)) {
313 queued_resource_messages_.push(new IPC::Message(message));
314 return;
315 }
316
initial.commit09911bf2008-07-26 23:55:29317 // Let the resource dispatcher intercept resource messages first.
318 if (resource_dispatcher_->OnMessageReceived(message))
319 return;
[email protected]06828b92008-10-20 21:25:46320
initial.commit09911bf2008-07-26 23:55:29321 IPC_BEGIN_MESSAGE_MAP(RenderView, message)
322 IPC_MESSAGE_HANDLER(ViewMsg_CreatingNew_ACK, OnCreatingNewAck)
323 IPC_MESSAGE_HANDLER(ViewMsg_CaptureThumbnail, SendThumbnail)
324 IPC_MESSAGE_HANDLER(ViewMsg_GetPrintedPagesCount, OnGetPrintedPagesCount)
325 IPC_MESSAGE_HANDLER(ViewMsg_PrintPages, OnPrintPages)
326 IPC_MESSAGE_HANDLER(ViewMsg_Navigate, OnNavigate)
327 IPC_MESSAGE_HANDLER(ViewMsg_Stop, OnStop)
328 IPC_MESSAGE_HANDLER(ViewMsg_LoadAlternateHTMLText, OnLoadAlternateHTMLText)
329 IPC_MESSAGE_HANDLER(ViewMsg_StopFinding, OnStopFinding)
330 IPC_MESSAGE_HANDLER(ViewMsg_Undo, OnUndo)
331 IPC_MESSAGE_HANDLER(ViewMsg_Redo, OnRedo)
332 IPC_MESSAGE_HANDLER(ViewMsg_Cut, OnCut)
333 IPC_MESSAGE_HANDLER(ViewMsg_Copy, OnCopy)
334 IPC_MESSAGE_HANDLER(ViewMsg_Paste, OnPaste)
335 IPC_MESSAGE_HANDLER(ViewMsg_Replace, OnReplace)
[email protected]bbbd545c2008-12-15 20:18:04336 IPC_MESSAGE_HANDLER(ViewMsg_ToggleSpellCheck, OnToggleSpellCheck)
initial.commit09911bf2008-07-26 23:55:29337 IPC_MESSAGE_HANDLER(ViewMsg_Delete, OnDelete)
338 IPC_MESSAGE_HANDLER(ViewMsg_SelectAll, OnSelectAll)
339 IPC_MESSAGE_HANDLER(ViewMsg_CopyImageAt, OnCopyImageAt)
340 IPC_MESSAGE_HANDLER(ViewMsg_Find, OnFind)
[email protected]630e26b2008-10-14 22:55:17341 IPC_MESSAGE_HANDLER(ViewMsg_Zoom, OnZoom)
initial.commit09911bf2008-07-26 23:55:29342 IPC_MESSAGE_HANDLER(ViewMsg_SetPageEncoding, OnSetPageEncoding)
343 IPC_MESSAGE_HANDLER(ViewMsg_InspectElement, OnInspectElement)
344 IPC_MESSAGE_HANDLER(ViewMsg_ShowJavaScriptConsole, OnShowJavaScriptConsole)
345 IPC_MESSAGE_HANDLER(ViewMsg_DownloadImage, OnDownloadImage)
346 IPC_MESSAGE_HANDLER(ViewMsg_ScriptEvalRequest, OnScriptEvalRequest)
347 IPC_MESSAGE_HANDLER(ViewMsg_AddMessageToConsole, OnAddMessageToConsole)
348 IPC_MESSAGE_HANDLER(ViewMsg_DebugAttach, OnDebugAttach)
[email protected]88010e082008-08-29 11:07:40349 IPC_MESSAGE_HANDLER(ViewMsg_DebugDetach, OnDebugDetach)
initial.commit09911bf2008-07-26 23:55:29350 IPC_MESSAGE_HANDLER(ViewMsg_ReservePageIDRange, OnReservePageIDRange)
351 IPC_MESSAGE_HANDLER(ViewMsg_UploadFile, OnUploadFileRequest)
352 IPC_MESSAGE_HANDLER(ViewMsg_FormFill, OnFormFill)
353 IPC_MESSAGE_HANDLER(ViewMsg_FillPasswordForm, OnFillPasswordForm)
354 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragEnter, OnDragTargetDragEnter)
355 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragOver, OnDragTargetDragOver)
356 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDragLeave, OnDragTargetDragLeave)
357 IPC_MESSAGE_HANDLER(ViewMsg_DragTargetDrop, OnDragTargetDrop)
358 IPC_MESSAGE_HANDLER(ViewMsg_AllowDomAutomationBindings,
359 OnAllowDomAutomationBindings)
[email protected]18cb2572008-08-21 20:34:45360 IPC_MESSAGE_HANDLER(ViewMsg_AllowBindings, OnAllowBindings)
initial.commit09911bf2008-07-26 23:55:29361 IPC_MESSAGE_HANDLER(ViewMsg_SetDOMUIProperty, OnSetDOMUIProperty)
[email protected]266eb6f2008-09-30 23:56:50362 IPC_MESSAGE_HANDLER(ViewMsg_DragSourceEndedOrMoved,
363 OnDragSourceEndedOrMoved)
initial.commit09911bf2008-07-26 23:55:29364 IPC_MESSAGE_HANDLER(ViewMsg_DragSourceSystemDragEnded,
365 OnDragSourceSystemDragEnded)
366 IPC_MESSAGE_HANDLER(ViewMsg_SetInitialFocus, OnSetInitialFocus)
367 IPC_MESSAGE_HANDLER(ViewMsg_FindReplyACK, OnFindReplyAck)
368 IPC_MESSAGE_HANDLER(ViewMsg_UpdateTargetURL_ACK, OnUpdateTargetURLAck)
369 IPC_MESSAGE_HANDLER(ViewMsg_UpdateWebPreferences, OnUpdateWebPreferences)
370 IPC_MESSAGE_HANDLER(ViewMsg_SetAltErrorPageURL, OnSetAltErrorPageURL)
371 IPC_MESSAGE_HANDLER(ViewMsg_InstallMissingPlugin, OnInstallMissingPlugin)
372 IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse)
373 IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode, OnEnableViewSourceMode)
374 IPC_MESSAGE_HANDLER(ViewMsg_UpdateBackForwardListCount,
375 OnUpdateBackForwardListCount)
376 IPC_MESSAGE_HANDLER(ViewMsg_GetAllSavableResourceLinksForCurrentPage,
377 OnGetAllSavableResourceLinksForCurrentPage)
378 IPC_MESSAGE_HANDLER(ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks,
379 OnGetSerializedHtmlDataForCurrentPageWithLocalLinks)
380 IPC_MESSAGE_HANDLER(ViewMsg_GetApplicationInfo, OnGetApplicationInfo)
[email protected]266eb6f2008-09-30 23:56:50381 IPC_MESSAGE_HANDLER(ViewMsg_GetAccessibilityInfo, OnGetAccessibilityInfo)
382 IPC_MESSAGE_HANDLER(ViewMsg_ClearAccessibilityInfo,
383 OnClearAccessibilityInfo)
initial.commit09911bf2008-07-26 23:55:29384 IPC_MESSAGE_HANDLER(ViewMsg_ShouldClose, OnMsgShouldClose)
385 IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage)
386 IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged)
[email protected]3c17b9c2008-08-26 02:08:00387#ifdef CHROME_PERSONALIZATION
[email protected]1cc879642008-08-26 01:27:35388 IPC_MESSAGE_HANDLER(ViewMsg_PersonalizationEvent, OnPersonalizationEvent)
[email protected]3c17b9c2008-08-26 02:08:00389#endif
[email protected]18cb2572008-08-21 20:34:45390 IPC_MESSAGE_HANDLER(ViewMsg_HandleMessageFromExternalHost,
391 OnMessageFromExternalHost)
[email protected]0aa55312008-10-17 21:53:08392 IPC_MESSAGE_HANDLER(ViewMsg_DisassociateFromPopupCount,
393 OnDisassociateFromPopupCount)
[email protected]0ebf3872008-11-07 21:35:03394 IPC_MESSAGE_HANDLER(ViewMsg_AutofillSuggestions,
395 OnReceivedAutofillSuggestions)
[email protected]634a6f92008-12-01 21:39:31396 IPC_MESSAGE_HANDLER(ViewMsg_PopupNotificationVisiblityChanged,
397 OnPopupNotificationVisiblityChanged)
398
initial.commit09911bf2008-07-26 23:55:29399 // Have the super handle all other messages.
400 IPC_MESSAGE_UNHANDLED(RenderWidget::OnMessageReceived(message))
401 IPC_END_MESSAGE_MAP()
402}
403
404// Got a response from the browser after the renderer decided to create a new
405// view.
406void RenderView::OnCreatingNewAck(HWND parent) {
407 CompleteInit(parent);
[email protected]06828b92008-10-20 21:25:46408
409 waiting_for_create_window_ack_ = false;
410
411 while (!queued_resource_messages_.empty()) {
412 IPC::Message* queued_msg = queued_resource_messages_.front();
413 queued_resource_messages_.pop();
414 resource_dispatcher_->OnMessageReceived(*queued_msg);
415 delete queued_msg;
416 }
initial.commit09911bf2008-07-26 23:55:29417}
418
419void RenderView::SendThumbnail() {
420 WebFrame* main_frame = webview()->GetMainFrame();
421 if (!main_frame)
422 return;
423
424 // get the URL for this page
425 GURL url(main_frame->GetURL());
426 if (url.is_empty())
427 return;
428
429 if (size_.IsEmpty())
430 return; // Don't create an empty thumbnail!
431
432 ThumbnailScore score;
433 SkBitmap thumbnail;
[email protected]b6e4bec2008-11-12 01:17:15434 if (!CaptureThumbnail(main_frame, kThumbnailWidth, kThumbnailHeight,
435 &thumbnail, &score))
436 return;
437
initial.commit09911bf2008-07-26 23:55:29438 // send the thumbnail message to the browser process
439 IPC::Message* thumbnail_msg = new IPC::Message(routing_id_,
440 ViewHostMsg_Thumbnail::ID, IPC::Message::PRIORITY_NORMAL);
441 IPC::ParamTraits<GURL>::Write(thumbnail_msg, url);
442 IPC::ParamTraits<ThumbnailScore>::Write(thumbnail_msg, score);
443 IPC::ParamTraits<SkBitmap>::Write(thumbnail_msg, thumbnail);
444 Send(thumbnail_msg);
445}
446
447int RenderView::SwitchFrameToPrintMediaType(const ViewMsg_Print_Params& params,
448 WebFrame* frame) {
449 float ratio = static_cast<float>(params.desired_dpi / params.dpi);
450 float paper_width = params.printable_size.width() * ratio;
451 float paper_height = params.printable_size.height() * ratio;
452 float minLayoutWidth = static_cast<float>(paper_width * params.min_shrink);
453 float maxLayoutWidth = static_cast<float>(paper_width * params.max_shrink);
454
455 // Safari uses: 765 & 1224. Margins aren't exactly the same either.
456 // Scale = 2.222 for MDI printer.
457 int pages;
458 if (!frame->SetPrintingMode(true,
459 minLayoutWidth,
460 maxLayoutWidth,
461 &printed_document_width_)) {
462 NOTREACHED();
463 pages = 0;
464 } else {
[email protected]98c74f82008-12-01 14:34:42465 DCHECK_GT(printed_document_width_, 0);
initial.commit09911bf2008-07-26 23:55:29466 // Force to recalculate the height, otherwise it reuse the current window
467 // height as the default.
468 float effective_shrink = printed_document_width_ / paper_width;
469 gfx::Size page_size(printed_document_width_,
470 static_cast<int>(paper_height * effective_shrink) - 1);
471 WebView* view = frame->GetView();
472 if (view) {
473 // Hack around an issue where if the current view height is higher than
474 // the page height, empty pages will be printed even if the bottom of the
475 // web page is empty.
476 printing_view_size_ = view->GetSize();
477 view->Resize(page_size);
478 view->Layout();
479 }
480 pages = frame->ComputePageRects(params.printable_size);
481 DCHECK(pages);
482 }
483 return pages;
484}
485
486void RenderView::SwitchFrameToDisplayMediaType(WebFrame* frame) {
487 // Set the layout back to "normal" document; i.e. CSS media type = "screen".
488 frame->SetPrintingMode(false, 0, 0, NULL);
489 WebView* view = frame->GetView();
490 if (view) {
491 // Restore from the hack described at SwitchFrameToPrintMediaType().
492 view->Resize(printing_view_size_);
493 view->Layout();
494 printing_view_size_.SetSize(0, 0);
495 }
496 printed_document_width_ = 0;
497}
498
499void RenderView::OnPrintPage(const ViewMsg_PrintPage_Params& params) {
500 DCHECK(webview());
501 if (webview())
502 PrintPage(params, webview()->GetMainFrame());
503}
504
505void RenderView::PrintPage(const ViewMsg_PrintPage_Params& params,
506 WebFrame* frame) {
507 if (printed_document_width_ <= 0) {
508 NOTREACHED();
509 return;
510 }
511
512 // Generate a memory-based EMF file. The EMF will use the current screen's
513 // DPI.
514 gfx::Emf emf;
515
516 emf.CreateDc(NULL, NULL);
517 HDC hdc = emf.hdc();
518 DCHECK(hdc);
[email protected]21f527e2008-12-17 23:29:40519 skia::PlatformDeviceWin::InitializeDC(hdc);
initial.commit09911bf2008-07-26 23:55:29520
521 gfx::Rect rect;
522 frame->GetPageRect(params.page_number, &rect);
523 DCHECK(rect.height());
524 DCHECK(rect.width());
525 double shrink = static_cast<double>(printed_document_width_) /
526 params.params.printable_size.width();
527 // This check would fire each time the page would get truncated on the
528 // right. This is not worth a DCHECK() but should be looked into, for
529 // example, wouldn't be worth trying in landscape?
530 // DCHECK_LE(rect.width(), printed_document_width_);
531
532 // Buffer one page at a time.
533 int src_size_x = printed_document_width_;
534 int src_size_y =
535 static_cast<int>(ceil(params.params.printable_size.height() *
536 shrink));
537#if 0
538 // TODO(maruel): This code is kept for testing until the 100% GDI drawing
539 // code is stable. maruels use this code's output as a reference when the
540 // GDI drawing code fails.
541
542 // Mix of Skia and GDI based.
[email protected]21f527e2008-12-17 23:29:40543 skia::PlatformCanvasWin canvas(src_size_x, src_size_y, true);
initial.commit09911bf2008-07-26 23:55:29544 canvas.drawARGB(255, 255, 255, 255, SkPorterDuff::kSrc_Mode);
545 PlatformContextSkia context(&canvas);
546 if (!frame->SpoolPage(params.page_number, &context)) {
547 NOTREACHED() << "Printing page " << params.page_number << " failed.";
548 return;
549 }
550
551 // Create a BMP v4 header that we can serialize.
552 BITMAPV4HEADER bitmap_header;
553 gfx::CreateBitmapV4Header(src_size_x, src_size_y, &bitmap_header);
554 const SkBitmap& src_bmp = canvas.getDevice()->accessBitmap(true);
555 SkAutoLockPixels src_lock(src_bmp);
556 int retval = StretchDIBits(hdc,
557 0,
558 0,
559 src_size_x, src_size_y,
560 0, 0,
561 src_size_x, src_size_y,
562 src_bmp.getPixels(),
563 reinterpret_cast<BITMAPINFO*>(&bitmap_header),
564 DIB_RGB_COLORS,
565 SRCCOPY);
566 DCHECK(retval != GDI_ERROR);
567#else
568 // 100% GDI based.
[email protected]21f527e2008-12-17 23:29:40569 skia::VectorCanvas canvas(hdc, src_size_x, src_size_y);
initial.commit09911bf2008-07-26 23:55:29570 // Set the clipping region to be sure to not overflow.
571 SkRect clip_rect;
572 clip_rect.set(0, 0, SkIntToScalar(src_size_x), SkIntToScalar(src_size_y));
573 canvas.clipRect(clip_rect);
[email protected]99c72202008-10-31 03:49:49574 if (!frame->SpoolPage(params.page_number, &canvas)) {
initial.commit09911bf2008-07-26 23:55:29575 NOTREACHED() << "Printing page " << params.page_number << " failed.";
576 return;
577 }
578#endif
579
580 // Done printing. Close the device context to retrieve the compiled EMF.
581 if (!emf.CloseDc()) {
582 NOTREACHED() << "EMF failed";
583 }
584
585 // Get the size of the compiled EMF.
586 unsigned buf_size = emf.GetDataSize();
587 DCHECK(buf_size > 128);
588 ViewHostMsg_DidPrintPage_Params page_params;
589 page_params.data_size = 0;
590 page_params.emf_data_handle = NULL;
591 page_params.page_number = params.page_number;
592 page_params.document_cookie = params.params.document_cookie;
593 page_params.actual_shrink = shrink;
[email protected]176aa482008-11-14 03:25:15594 base::SharedMemory shared_buf;
initial.commit09911bf2008-07-26 23:55:29595
596 // http://msdn2.microsoft.com/en-us/library/ms535522.aspx
597 // Windows 2000/XP: When a page in a spooled file exceeds approximately 350
598 // MB, it can fail to print and not send an error message.
599 if (buf_size < 350*1024*1024) {
600 // Allocate a shared memory buffer to hold the generated EMF data.
601 if (shared_buf.Create(L"", false, false, buf_size) &&
602 shared_buf.Map(buf_size)) {
603 // Copy the bits into shared memory.
604 if (emf.GetData(shared_buf.memory(), buf_size)) {
605 page_params.emf_data_handle = shared_buf.handle();
606 page_params.data_size = buf_size;
607 } else {
608 NOTREACHED() << "GetData() failed";
609 }
610 shared_buf.Unmap();
611 } else {
612 NOTREACHED() << "Buffer allocation failed";
613 }
614 } else {
615 NOTREACHED() << "Buffer too large: " << buf_size;
616 }
617 emf.CloseEmf();
618 if (Send(new ViewHostMsg_DuplicateSection(routing_id_,
619 page_params.emf_data_handle,
620 &page_params.emf_data_handle))) {
621 Send(new ViewHostMsg_DidPrintPage(routing_id_, page_params));
622 }
623}
624
625void RenderView::OnGetPrintedPagesCount(const ViewMsg_Print_Params& params) {
626 DCHECK(webview());
627 if (!webview()) {
628 Send(new ViewHostMsg_DidGetPrintedPagesCount(routing_id_,
629 params.document_cookie,
630 0));
631 return;
632 }
633 WebFrame* frame = webview()->GetMainFrame();
634 int expected_pages = SwitchFrameToPrintMediaType(params, frame);
635 Send(new ViewHostMsg_DidGetPrintedPagesCount(routing_id_,
636 params.document_cookie,
637 expected_pages));
638 SwitchFrameToDisplayMediaType(frame);
639}
640
641void RenderView::OnPrintPages(const ViewMsg_PrintPages_Params& params) {
642 DCHECK(webview());
643 if (webview())
644 PrintPages(params, webview()->GetMainFrame());
645}
646
647void RenderView::PrintPages(const ViewMsg_PrintPages_Params& params,
648 WebFrame* frame) {
649 int pages = SwitchFrameToPrintMediaType(params.params, frame);
650 Send(new ViewHostMsg_DidGetPrintedPagesCount(routing_id_,
651 params.params.document_cookie,
652 pages));
653 if (pages) {
654 ViewMsg_PrintPage_Params page_params;
655 page_params.params = params.params;
656 if (params.pages.empty()) {
657 for (int i = 0; i < pages; ++i) {
658 page_params.page_number = i;
659 PrintPage(page_params, frame);
660 }
661 } else {
662 for (size_t i = 0; i < params.pages.size(); ++i) {
663 page_params.page_number = params.pages[i];
664 PrintPage(page_params, frame);
665 }
666 }
667 }
668 SwitchFrameToDisplayMediaType(frame);
669}
670
671void RenderView::CapturePageInfo(int load_id, bool preliminary_capture) {
672 if (load_id != page_id_)
673 return; // this capture call is no longer relevant due to navigation
674 if (load_id == last_indexed_page_id_)
675 return; // we already indexed this page
676
677 if (!webview())
678 return;
679
680 WebFrame* main_frame = webview()->GetMainFrame();
681 if (!main_frame)
682 return;
683
684 // Don't index/capture pages that are in view source mode.
685 if (main_frame->GetInViewSourceMode())
686 return;
687
688 // Don't index/capture pages that failed to load. This only checks the top
689 // level frame so the thumbnail may contain a frame that failed to load.
690 WebDataSource* ds = main_frame->GetDataSource();
691 if (ds && ds->HasUnreachableURL())
692 return;
693
694 if (!preliminary_capture)
695 last_indexed_page_id_ = load_id;
696
697 // get the URL for this page
698 GURL url(main_frame->GetURL());
699 if (url.is_empty())
700 return;
701
702 // full text
703 std::wstring contents;
704 CaptureText(main_frame, &contents);
705 if (contents.size()) {
706 // Send the text to the browser for indexing.
707 Send(new ViewHostMsg_PageContents(url, load_id, contents));
708 }
709
710 // thumbnail
711 SendThumbnail();
712}
713
714void RenderView::CaptureText(WebFrame* frame, std::wstring* contents) {
715 contents->clear();
716 if (!frame)
717 return;
718
[email protected]0faf0bd92008-09-09 20:53:27719 // Don't index any https pages. People generally don't want their bank
720 // accounts, etc. indexed on their computer, especially since some of these
721 // things are not marked cachable.
722 // TODO(brettw) we may want to consider more elaborate heuristics such as
723 // the cachability of the page. We may also want to consider subframes (this
724 // test will still index subframes if the subframe is SSL).
725 if (frame->GetURL().SchemeIsSecure())
726 return;
727
initial.commit09911bf2008-07-26 23:55:29728#ifdef TIME_TEXT_RETRIEVAL
729 double begin = time_util::GetHighResolutionTimeNow();
730#endif
731
732 // get the contents of the frame
733 frame->GetContentAsPlainText(kMaxIndexChars, contents);
734
735#ifdef TIME_TEXT_RETRIEVAL
736 double end = time_util::GetHighResolutionTimeNow();
737 char buf[128];
738 sprintf_s(buf, "%d chars retrieved for indexing in %gms\n",
739 contents.size(), (end - begin)*1000);
740 OutputDebugStringA(buf);
741#endif
742
743 // When the contents are clipped to the maximum, we don't want to have a
744 // partial word indexed at the end that might have been clipped. Therefore,
745 // terminate the string at the last space to ensure no words are clipped.
746 if (contents->size() == kMaxIndexChars) {
747 size_t last_space_index = contents->find_last_of(kWhitespaceWide);
748 if (last_space_index == std::wstring::npos)
749 return; // don't index if we got a huge block of text with no spaces
750 contents->resize(last_space_index);
751 }
752}
753
[email protected]b6e4bec2008-11-12 01:17:15754bool RenderView::CaptureThumbnail(WebFrame* frame,
initial.commit09911bf2008-07-26 23:55:29755 int w,
756 int h,
757 SkBitmap* thumbnail,
758 ThumbnailScore* score) {
759#ifdef TIME_BITMAP_RETRIEVAL
760 double begin = time_util::GetHighResolutionTimeNow();
761#endif
762
[email protected]21f527e2008-12-17 23:29:40763 scoped_ptr<skia::BitmapPlatformDevice> device;
[email protected]b6e4bec2008-11-12 01:17:15764 if (!frame->CaptureImage(&device, true))
765 return false;
766
767 const SkBitmap& src_bmp = device->accessBitmap(false);
initial.commit09911bf2008-07-26 23:55:29768
769 SkRect dest_rect;
770 dest_rect.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
771 float dest_aspect = dest_rect.width() / dest_rect.height();
772
773 // Get the src rect so that we can preserve the aspect ratio while filling
774 // the destination.
775 SkIRect src_rect;
776 if (src_bmp.width() < dest_rect.width() ||
777 src_bmp.height() < dest_rect.height()) {
778 // Source image is smaller: we clip the part of source image within the
779 // dest rect, and then stretch it to fill the dest rect. We don't respect
780 // the aspect ratio in this case.
781 src_rect.set(0, 0, static_cast<S16CPU>(dest_rect.width()),
782 static_cast<S16CPU>(dest_rect.height()));
783 score->good_clipping = false;
784 } else {
785 float src_aspect = static_cast<float>(src_bmp.width()) / src_bmp.height();
786 if (src_aspect > dest_aspect) {
787 // Wider than tall, clip horizontally: we center the smaller thumbnail in
788 // the wider screen.
789 S16CPU new_width = static_cast<S16CPU>(src_bmp.height() * dest_aspect);
790 S16CPU x_offset = (src_bmp.width() - new_width) / 2;
791 src_rect.set(x_offset, 0, new_width + x_offset, src_bmp.height());
792 score->good_clipping = false;
793 } else {
794 src_rect.set(0, 0, src_bmp.width(),
795 static_cast<S16CPU>(src_bmp.width() / dest_aspect));
796 score->good_clipping = true;
797 }
798 }
799
800 score->at_top = (frame->ScrollOffset().height() == 0);
801
802 SkBitmap subset;
[email protected]b6e4bec2008-11-12 01:17:15803 device->accessBitmap(false).extractSubset(&subset, src_rect);
initial.commit09911bf2008-07-26 23:55:29804
805 // Resample the subset that we want to get it the right size.
[email protected]465b34b72008-12-12 20:19:14806 *thumbnail = skia::ImageOperations::Resize(
807 subset, skia::ImageOperations::RESIZE_LANCZOS3, w, h);
initial.commit09911bf2008-07-26 23:55:29808
809 score->boring_score = CalculateBoringScore(thumbnail);
810
811#ifdef TIME_BITMAP_RETRIEVAL
812 double end = time_util::GetHighResolutionTimeNow();
813 char buf[128];
814 sprintf_s(buf, "thumbnail in %gms\n", (end - begin) * 1000);
815 OutputDebugStringA(buf);
816#endif
[email protected]b6e4bec2008-11-12 01:17:15817 return true;
initial.commit09911bf2008-07-26 23:55:29818}
819
820double RenderView::CalculateBoringScore(SkBitmap* bitmap) {
821 int histogram[256] = {0};
822 color_utils::BuildLumaHistogram(bitmap, histogram);
823
824 int color_count = *std::max_element(histogram, histogram + 256);
825 int pixel_count = bitmap->width() * bitmap->height();
826 return static_cast<double>(color_count) / pixel_count;
827}
828
829void RenderView::OnNavigate(const ViewMsg_Navigate_Params& params) {
830 if (!webview())
831 return;
832
833 AboutHandler::MaybeHandle(params.url);
834
835 bool is_reload = params.reload;
836
837 WebFrame* main_frame = webview()->GetMainFrame();
[email protected]606843fa2008-12-02 19:08:56838 if (is_reload && !main_frame->HasCurrentHistoryState()) {
initial.commit09911bf2008-07-26 23:55:29839 // We cannot reload if we do not have any history state. This happens, for
840 // example, when recovering from a crash. Our workaround here is a bit of
841 // a hack since it means that reload after a crashed tab does not cause an
842 // end-to-end cache validation.
843 is_reload = false;
844 }
845
846 WebRequestCachePolicy cache_policy;
847 if (is_reload) {
848 cache_policy = WebRequestReloadIgnoringCacheData;
849 } else if (params.page_id != -1 || main_frame->GetInViewSourceMode()) {
850 cache_policy = WebRequestReturnCacheDataElseLoad;
851 } else {
852 cache_policy = WebRequestUseProtocolCachePolicy;
853 }
854
855 scoped_ptr<WebRequest> request(WebRequest::Create(params.url));
856 request->SetCachePolicy(cache_policy);
857 request->SetExtraData(new RenderViewExtraRequestData(
858 params.page_id, params.transition, params.url));
859
860 // If we are reloading, then WebKit will use the state of the current page.
861 // Otherwise, we give it the state to navigate to.
862 if (!is_reload)
863 request->SetHistoryState(params.state);
864
[email protected]4c6f2c92008-10-28 20:26:15865 if (params.referrer.is_valid()) {
[email protected]8e3c1a72008-11-25 01:13:32866 request->SetHttpHeaderValue("Referer",
867 params.referrer.spec());
[email protected]c0588052008-10-27 23:01:50868 }
869
initial.commit09911bf2008-07-26 23:55:29870 main_frame->LoadRequest(request.get());
871}
872
873// Stop loading the current page
874void RenderView::OnStop() {
875 if (webview())
876 webview()->StopLoading();
877}
878
879void RenderView::OnLoadAlternateHTMLText(const std::string& html_contents,
880 bool new_navigation,
881 const GURL& display_url,
882 const std::string& security_info) {
883 if (!webview())
884 return;
885
886 scoped_ptr<WebRequest> request(WebRequest::Create(
887 GURL(kUnreachableWebDataURL)));
888 request->SetSecurityInfo(security_info);
889
890 webview()->GetMainFrame()->LoadAlternateHTMLString(request.get(),
891 html_contents,
892 display_url,
893 !new_navigation);
894}
895
896void RenderView::OnCopyImageAt(int x, int y) {
897 webview()->CopyImageAt(x, y);
898}
899
900void RenderView::OnInspectElement(int x, int y) {
901 webview()->InspectElement(x, y);
902}
903
904void RenderView::OnShowJavaScriptConsole() {
905 webview()->ShowJavaScriptConsole();
906}
907
908void RenderView::OnStopFinding(bool clear_selection) {
909 WebView* view = webview();
910 if (!view)
911 return;
912
913 if (clear_selection)
914 view->GetFocusedFrame()->ClearSelection();
915
916 WebFrame* frame = view->GetMainFrame();
917 while (frame) {
[email protected]65134c432008-09-26 21:47:20918 frame->StopFinding(clear_selection);
initial.commit09911bf2008-07-26 23:55:29919 frame = view->GetNextFrameAfter(frame, false);
920 }
921}
922
923void RenderView::OnFindReplyAck() {
924 // Check if there is any queued up request waiting to be sent.
925 if (queued_find_reply_message_.get()) {
926 // Send the search result over to the browser process.
927 Send(queued_find_reply_message_.get());
928 queued_find_reply_message_.release();
929 }
930}
931
932void RenderView::OnUpdateTargetURLAck() {
933 // Check if there is a targeturl waiting to be sent.
934 if (target_url_status_ == TARGET_PENDING) {
935 Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_,
936 pending_target_url_));
937 }
938
939 target_url_status_ = TARGET_NONE;
940}
941
942void RenderView::OnUndo() {
943 if (!webview())
944 return;
945
946 webview()->GetFocusedFrame()->Undo();
947}
948
949void RenderView::OnRedo() {
950 if (!webview())
951 return;
952
953 webview()->GetFocusedFrame()->Redo();
954}
955
956void RenderView::OnCut() {
957 if (!webview())
958 return;
959
960 webview()->GetFocusedFrame()->Cut();
961}
962
963void RenderView::OnCopy() {
964 if (!webview())
965 return;
966
967 webview()->GetFocusedFrame()->Copy();
968}
969
970void RenderView::OnPaste() {
971 if (!webview())
972 return;
973
974 webview()->GetFocusedFrame()->Paste();
975}
976
977void RenderView::OnReplace(const std::wstring& text) {
978 if (!webview())
979 return;
980
981 webview()->GetFocusedFrame()->Replace(text);
982}
983
[email protected]bbbd545c2008-12-15 20:18:04984void RenderView::OnToggleSpellCheck() {
985 if (!webview())
986 return;
987
988 webview()->GetFocusedFrame()->ToggleSpellCheck();
989}
990
initial.commit09911bf2008-07-26 23:55:29991void RenderView::OnDelete() {
992 if (!webview())
993 return;
994
995 webview()->GetFocusedFrame()->Delete();
996}
997
998void RenderView::OnSelectAll() {
999 if (!webview())
1000 return;
1001
1002 webview()->GetFocusedFrame()->SelectAll();
1003}
1004
1005void RenderView::OnSetInitialFocus(bool reverse) {
1006 if (!webview())
1007 return;
1008 webview()->SetInitialFocus(reverse);
1009}
1010
1011///////////////////////////////////////////////////////////////////////////////
1012
1013// Tell the embedding application that the URL of the active page has changed
1014void RenderView::UpdateURL(WebFrame* frame) {
1015 WebDataSource* ds = frame->GetDataSource();
1016 DCHECK(ds);
1017
1018 const WebRequest& request = ds->GetRequest();
1019 const WebRequest& initial_request = ds->GetInitialRequest();
1020 const WebResponse& response = ds->GetResponse();
1021
1022 // We don't hold a reference to the extra data. The request's reference will
1023 // be sufficient because we won't modify it during our call. MAY BE NULL.
1024 RenderViewExtraRequestData* extra_data =
1025 static_cast<RenderViewExtraRequestData*>(request.GetExtraData());
1026
1027 ViewHostMsg_FrameNavigate_Params params;
1028 params.is_post = false;
1029 params.page_id = page_id_;
[email protected]8a3422c92008-09-24 17:42:421030 params.is_content_filtered = response.IsContentFiltered();
initial.commit09911bf2008-07-26 23:55:291031 if (!request.GetSecurityInfo().empty()) {
1032 // SSL state specified in the request takes precedence over the one in the
1033 // response.
1034 // So far this is only intended for error pages that are not expected to be
1035 // over ssl, so we should not get any clash.
1036 DCHECK(response.GetSecurityInfo().empty());
1037 params.security_info = request.GetSecurityInfo();
1038 } else {
1039 params.security_info = response.GetSecurityInfo();
1040 }
1041
1042 // Set the URL to be displayed in the browser UI to the user.
1043 if (ds->HasUnreachableURL()) {
1044 params.url = ds->GetUnreachableURL();
1045 } else {
1046 params.url = request.GetURL();
1047 }
1048
1049 params.redirects = ds->GetRedirectChain();
1050 params.should_update_history = !ds->HasUnreachableURL();
1051
1052 const SearchableFormData* searchable_form_data =
1053 frame->GetDataSource()->GetSearchableFormData();
1054 if (searchable_form_data) {
1055 params.searchable_form_url = searchable_form_data->url();
1056 params.searchable_form_element_name = searchable_form_data->element_name();
1057 params.searchable_form_encoding = searchable_form_data->encoding();
1058 }
1059
1060 const PasswordForm* password_form_data =
1061 frame->GetDataSource()->GetPasswordFormData();
1062 if (password_form_data)
1063 params.password_form = *password_form_data;
1064
1065 params.gesture = navigation_gesture_;
1066 navigation_gesture_ = NavigationGestureUnknown;
1067
1068 if (webview()->GetMainFrame() == frame) {
1069 // Top-level navigation.
1070
1071 // Update contents MIME type for main frame.
1072 std::wstring mime_type = ds->GetResponseMimeType();
1073 params.contents_mime_type = WideToASCII(mime_type);
1074
1075 // We assume top level navigations initiated by the renderer are link
1076 // clicks.
1077 params.transition = extra_data ?
1078 extra_data->transition_type : PageTransition::LINK;
1079 if (!PageTransition::IsMainFrame(params.transition)) {
1080 // If the main frame does a load, it should not be reported as a subframe
1081 // navigation. This can occur in the following case:
1082 // 1. You're on a site with frames.
1083 // 2. You do a subframe navigation. This is stored with transition type
1084 // MANUAL_SUBFRAME.
1085 // 3. You navigate to some non-frame site, say, google.com.
1086 // 4. You navigate back to the page from step 2. Since it was initially
1087 // MANUAL_SUBFRAME, it will be that same transition type here.
1088 // We don't want that, because any navigation that changes the toplevel
1089 // frame should be tracked as a toplevel navigation (this allows us to
1090 // update the URL bar, etc).
1091 params.transition = PageTransition::LINK;
1092 }
1093
1094 if (params.transition == PageTransition::LINK &&
1095 frame->GetDataSource()->IsFormSubmit()) {
1096 params.transition = PageTransition::FORM_SUBMIT;
1097 }
1098
1099 // If we have a valid consumed client redirect source,
1100 // the page contained a client redirect (meta refresh, document.loc...),
1101 // so we set the referrer and transition to match.
1102 if (completed_client_redirect_src_.is_valid()) {
[email protected]77e09a92008-08-01 18:11:041103 DCHECK(completed_client_redirect_src_ == params.redirects[0]);
initial.commit09911bf2008-07-26 23:55:291104 params.referrer = completed_client_redirect_src_;
1105 params.transition = static_cast<PageTransition::Type>(
1106 params.transition | PageTransition::CLIENT_REDIRECT);
1107 } else {
1108 // Bug 654101: the referrer will be empty on https->http transitions. It
1109 // would be nice if we could get the real referrer from somewhere.
1110 params.referrer = GURL(initial_request.GetHttpReferrer());
1111 }
1112
[email protected]8e3c1a72008-11-25 01:13:321113 std::string method = request.GetHttpMethod();
1114 if (method == "POST")
initial.commit09911bf2008-07-26 23:55:291115 params.is_post = true;
1116
1117 Send(new ViewHostMsg_FrameNavigate(routing_id_, params));
1118 } else {
1119 // Subframe navigation: the type depends on whether this navigation
1120 // generated a new session history entry. When they do generate a session
1121 // history entry, it means the user initiated the navigation and we should
1122 // mark it as such. This test checks if this is the first time UpdateURL
1123 // has been called since WillNavigateToURL was called to initiate the load.
1124 if (page_id_ > last_page_id_sent_to_browser_)
1125 params.transition = PageTransition::MANUAL_SUBFRAME;
1126 else
1127 params.transition = PageTransition::AUTO_SUBFRAME;
1128
1129 // The browser should never initiate a subframe navigation.
1130 DCHECK(!extra_data);
1131 Send(new ViewHostMsg_FrameNavigate(routing_id_, params));
1132 }
1133
1134 last_page_id_sent_to_browser_ =
1135 std::max(last_page_id_sent_to_browser_, page_id_);
1136
1137 // If we end up reusing this WebRequest (for example, due to a #ref click),
1138 // we don't want the transition type to persist.
1139 if (extra_data)
1140 extra_data->transition_type = PageTransition::LINK; // Just clear it.
[email protected]266eb6f2008-09-30 23:56:501141
1142 if (glue_accessibility_.get()) {
1143 // Clear accessibility info cache.
1144 glue_accessibility_->ClearIAccessibleMap(-1, true);
1145 }
initial.commit09911bf2008-07-26 23:55:291146}
1147
1148// Tell the embedding application that the title of the active page has changed
1149void RenderView::UpdateTitle(WebFrame* frame, const std::wstring& title) {
1150 // Ignore all but top level navigations...
1151 if (webview()->GetMainFrame() == frame)
1152 Send(new ViewHostMsg_UpdateTitle(routing_id_, page_id_, title));
1153}
1154
1155void RenderView::UpdateEncoding(WebFrame* frame,
[email protected]e38f40152008-09-12 23:08:301156 const std::wstring& encoding_name) {
initial.commit09911bf2008-07-26 23:55:291157 // Only update main frame's encoding_name.
1158 if (webview()->GetMainFrame() == frame &&
1159 last_encoding_name_ != encoding_name) {
[email protected]e38f40152008-09-12 23:08:301160 // Save the encoding name for later comparing.
initial.commit09911bf2008-07-26 23:55:291161 last_encoding_name_ = encoding_name;
1162
[email protected]e38f40152008-09-12 23:08:301163 Send(new ViewHostMsg_UpdateEncoding(routing_id_, last_encoding_name_));
initial.commit09911bf2008-07-26 23:55:291164 }
1165}
1166
[email protected]f4d34b52008-11-24 23:05:011167// Sends the previous session history state to the browser so it will be saved
1168// before we navigate to a new page. This must be called *before* the page ID
1169// has been updated so we know what it was.
initial.commit09911bf2008-07-26 23:55:291170void RenderView::UpdateSessionHistory(WebFrame* frame) {
1171 // If we have a valid page ID at this point, then it corresponds to the page
1172 // we are navigating away from. Otherwise, this is the first navigation, so
1173 // there is no past session history to record.
1174 if (page_id_ == -1)
1175 return;
1176
initial.commit09911bf2008-07-26 23:55:291177 std::string state;
[email protected]606843fa2008-12-02 19:08:561178 if (!webview()->GetMainFrame()->GetPreviousHistoryState(&state))
initial.commit09911bf2008-07-26 23:55:291179 return;
[email protected]606843fa2008-12-02 19:08:561180 Send(new ViewHostMsg_UpdateState(routing_id_, page_id_, state));
initial.commit09911bf2008-07-26 23:55:291181}
1182
1183///////////////////////////////////////////////////////////////////////////////
1184// WebViewDelegate
1185
1186void RenderView::DidStartLoading(WebView* webview) {
1187 if (is_loading_) {
1188 DLOG(WARNING) << "DidStartLoading called while loading";
1189 return;
1190 }
1191
1192 is_loading_ = true;
1193 // Clear the pointer so that we can assign it only when there is an unknown
1194 // plugin on a page.
1195 first_default_plugin_ = NULL;
1196
1197 Send(new ViewHostMsg_DidStartLoading(routing_id_, page_id_));
1198}
1199
1200void RenderView::DidStopLoading(WebView* webview) {
1201 if (!is_loading_) {
1202 DLOG(WARNING) << "DidStopLoading called while not loading";
1203 return;
1204 }
1205
1206 is_loading_ = false;
1207
1208 // NOTE: For now we're doing the safest thing, and sending out notification
1209 // when done loading. This currently isn't an issue as the favicon is only
1210 // displayed when done loading. Ideally we would send notification when
1211 // finished parsing the head, but webkit doesn't support that yet.
1212 // The feed discovery code would also benefit from access to the head.
1213 GURL favicon_url(webview->GetMainFrame()->GetFavIconURL());
1214 if (!favicon_url.is_empty())
1215 Send(new ViewHostMsg_UpdateFavIconURL(routing_id_, page_id_, favicon_url));
1216
1217 AddGURLSearchProvider(webview->GetMainFrame()->GetOSDDURL(),
1218 true); // autodetected
1219
1220 Send(new ViewHostMsg_DidStopLoading(routing_id_, page_id_));
1221
1222 MessageLoop::current()->PostDelayedTask(FROM_HERE,
1223 method_factory_.NewRunnableMethod(&RenderView::CapturePageInfo, page_id_,
1224 false),
1225 kDelayForCaptureMs);
1226
1227 // The page is loaded. Try to process the file we need to upload if any.
1228 ProcessPendingUpload();
1229
1230 // Since the page is done loading, we are sure we don't need to try
1231 // again.
1232 ResetPendingUpload();
1233}
1234
1235void RenderView::DidStartProvisionalLoadForFrame(
1236 WebView* webview,
1237 WebFrame* frame,
1238 NavigationGesture gesture) {
[email protected]77e09a92008-08-01 18:11:041239 if (webview->GetMainFrame() == frame) {
initial.commit09911bf2008-07-26 23:55:291240 navigation_gesture_ = gesture;
[email protected]266eb6f2008-09-30 23:56:501241
[email protected]77e09a92008-08-01 18:11:041242 // Make sure redirect tracking state is clear for the new load.
1243 completed_client_redirect_src_ = GURL();
1244 }
initial.commit09911bf2008-07-26 23:55:291245
1246 Send(new ViewHostMsg_DidStartProvisionalLoadForFrame(
1247 routing_id_, webview->GetMainFrame() == frame,
1248 frame->GetProvisionalDataSource()->GetRequest().GetURL()));
1249}
1250
1251bool RenderView::DidLoadResourceFromMemoryCache(WebView* webview,
1252 const WebRequest& request,
1253 const WebResponse& response,
1254 WebFrame* frame) {
1255 // Let the browser know we loaded a resource from the memory cache. This
1256 // message is needed to display the correct SSL indicators.
1257 Send(new ViewHostMsg_DidLoadResourceFromMemoryCache(routing_id_,
1258 request.GetURL(), response.GetSecurityInfo()));
1259
1260 return false;
1261}
1262
1263void RenderView::DidReceiveProvisionalLoadServerRedirect(WebView* webview,
1264 WebFrame* frame) {
1265 if (frame == webview->GetMainFrame()) {
1266 // Received a redirect on the main frame.
1267 WebDataSource* data_source =
1268 webview->GetMainFrame()->GetProvisionalDataSource();
1269 if (!data_source) {
1270 // Should only be invoked when we have a data source.
1271 NOTREACHED();
1272 return;
1273 }
1274 const std::vector<GURL>& redirects = data_source->GetRedirectChain();
1275 if (redirects.size() >= 2) {
1276 Send(new ViewHostMsg_DidRedirectProvisionalLoad(
1277 routing_id_, page_id_, redirects[redirects.size() - 2],
1278 redirects[redirects.size() - 1]));
1279 }
1280 }
1281}
1282
1283void RenderView::DidFailProvisionalLoadWithError(WebView* webview,
1284 const WebError& error,
1285 WebFrame* frame) {
1286 // Notify the browser that we failed a provisional load with an error.
1287 //
1288 // Note: It is important this notification occur before DidStopLoading so the
1289 // SSL manager can react to the provisional load failure before being
1290 // notified the load stopped.
1291 //
1292 WebDataSource* ds = frame->GetProvisionalDataSource();
1293 DCHECK(ds);
1294
1295 const WebRequest& failed_request = ds->GetRequest();
1296
1297 bool show_repost_interstitial =
1298 (error.GetErrorCode() == net::ERR_CACHE_MISS &&
1299 LowerCaseEqualsASCII(failed_request.GetHttpMethod(), "post"));
1300 Send(new ViewHostMsg_DidFailProvisionalLoadWithError(
1301 routing_id_, frame == webview->GetMainFrame(),
1302 error.GetErrorCode(), error.GetFailedURL(),
1303 show_repost_interstitial));
1304
initial.commit09911bf2008-07-26 23:55:291305 // Don't display an error page if this is simply a cancelled load. Aside
1306 // from being dumb, WebCore doesn't expect it and it will cause a crash.
1307 if (error.GetErrorCode() == net::ERR_ABORTED)
1308 return;
1309
1310 // If this is a failed back/forward/reload navigation, then we need to do a
1311 // 'replace' load. This is necessary to avoid messing up session history.
1312 // Otherwise, we do a normal load, which simulates a 'go' navigation as far
1313 // as session history is concerned.
1314 RenderViewExtraRequestData* extra_data =
1315 static_cast<RenderViewExtraRequestData*>(failed_request.GetExtraData());
1316 bool replace = extra_data && !extra_data->is_new_navigation();
1317
[email protected]5df266ac2008-10-15 19:50:131318 // Use the alternate error page service if this is a DNS failure or
1319 // connection failure. ERR_CONNECTION_FAILED can be dropped once we no longer
1320 // use winhttp.
1321 int ec = error.GetErrorCode();
1322 if (ec == net::ERR_NAME_NOT_RESOLVED ||
1323 ec == net::ERR_CONNECTION_FAILED ||
1324 ec == net::ERR_CONNECTION_REFUSED ||
1325 ec == net::ERR_ADDRESS_UNREACHABLE ||
1326 ec == net::ERR_TIMED_OUT) {
1327 const GURL& failed_url = error.GetFailedURL();
1328 const GURL& error_page_url = GetAlternateErrorPageURL(failed_url,
1329 ec == net::ERR_NAME_NOT_RESOLVED ? WebViewDelegate::DNS_ERROR
1330 : WebViewDelegate::CONNECTION_ERROR);
1331 if (error_page_url.is_valid()) {
1332 // Ask the WebFrame to fetch the alternate error page for us.
1333 frame->LoadAlternateHTMLErrorPage(&failed_request, error, error_page_url,
1334 replace, GURL(kUnreachableWebDataURL));
1335 return;
1336 }
initial.commit09911bf2008-07-26 23:55:291337 }
[email protected]5df266ac2008-10-15 19:50:131338
1339 // Fallback to a local error page.
1340 LoadNavigationErrorPage(frame, &failed_request, error, std::string(),
1341 replace);
initial.commit09911bf2008-07-26 23:55:291342}
1343
1344void RenderView::LoadNavigationErrorPage(WebFrame* frame,
1345 const WebRequest* failed_request,
1346 const WebError& error,
1347 const std::string& html,
1348 bool replace) {
1349 const GURL& failed_url = error.GetFailedURL();
1350
1351 std::string alt_html;
1352 if (html.empty()) {
1353 // Use a local error page.
1354 int resource_id;
1355 DictionaryValue error_strings;
1356 if (error.GetErrorCode() == net::ERR_CACHE_MISS &&
1357 LowerCaseEqualsASCII(failed_request->GetHttpMethod(), "post")) {
1358 GetFormRepostErrorValues(failed_url, &error_strings);
1359 resource_id = IDR_ERROR_NO_DETAILS_HTML;
1360 } else {
1361 GetLocalizedErrorValues(error, &error_strings);
1362 resource_id = IDR_NET_ERROR_HTML;
1363 }
1364 error_strings.SetString(L"textdirection",
1365 (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) ?
1366 L"rtl" : L"ltr");
1367
1368 alt_html = GetAltHTMLForTemplate(error_strings, resource_id);
1369 } else {
1370 alt_html = html;
1371 }
1372
1373 // Use a data: URL as the site URL to prevent against XSS attacks.
1374 scoped_ptr<WebRequest> request(failed_request->Clone());
1375 request->SetURL(GURL(kUnreachableWebDataURL));
1376
1377 frame->LoadAlternateHTMLString(request.get(), alt_html, failed_url,
1378 replace);
1379}
1380
1381void RenderView::DidCommitLoadForFrame(WebView *webview, WebFrame* frame,
1382 bool is_new_navigation) {
1383 const WebRequest& request =
1384 webview->GetMainFrame()->GetDataSource()->GetRequest();
1385 RenderViewExtraRequestData* extra_data =
1386 static_cast<RenderViewExtraRequestData*>(request.GetExtraData());
1387
1388 if (is_new_navigation) {
1389 // When we perform a new navigation, we need to update the previous session
1390 // history entry with state for the page we are leaving.
1391 UpdateSessionHistory(frame);
1392
1393 // We bump our Page ID to correspond with the new session history entry.
1394 page_id_ = next_page_id_++;
1395
1396 MessageLoop::current()->PostDelayedTask(FROM_HERE,
1397 method_factory_.NewRunnableMethod(&RenderView::CapturePageInfo,
1398 page_id_, true),
1399 kDelayForForcedCaptureMs);
1400 } else {
1401 // Inspect the extra_data on the main frame (set in our Navigate method) to
1402 // see if the navigation corresponds to a session history navigation...
1403 // Note: |frame| may or may not be the toplevel frame, but for the case
1404 // of capturing session history, the first committed frame suffices. We
1405 // keep track of whether we've seen this commit before so that only capture
1406 // session history once per navigation.
[email protected]f4d34b52008-11-24 23:05:011407 //
1408 // Note that we need to check if the page ID changed. In the case of a
1409 // reload, the page ID doesn't change, and UpdateSessionHistory gets the
1410 // previous URL and the current page ID, which would be wrong.
initial.commit09911bf2008-07-26 23:55:291411 if (extra_data && !extra_data->is_new_navigation() &&
[email protected]f4d34b52008-11-24 23:05:011412 !extra_data->request_committed &&
1413 page_id_ != extra_data->pending_page_id()) {
initial.commit09911bf2008-07-26 23:55:291414 // This is a successful session history navigation!
1415 UpdateSessionHistory(frame);
initial.commit09911bf2008-07-26 23:55:291416 page_id_ = extra_data->pending_page_id();
1417 }
1418 }
1419
1420 // Remember that we've already processed this request, so we don't update
1421 // the session history again. We do this regardless of whether this is
1422 // a session history navigation, because if we attempted a session history
1423 // navigation without valid HistoryItem state, WebCore will think it is a
1424 // new navigation.
1425 if (extra_data)
1426 extra_data->request_committed = true;
1427
1428 UpdateURL(frame);
1429
1430 // If this committed load was initiated by a client redirect, we're
1431 // at the last stop now, so clear it.
1432 completed_client_redirect_src_ = GURL();
1433
1434 // Check whether we have new encoding name.
1435 UpdateEncoding(frame, webview->GetMainFrameEncodingName());
1436}
1437
1438void RenderView::DidReceiveTitle(WebView* webview,
1439 const std::wstring& title,
1440 WebFrame* frame) {
1441 UpdateTitle(frame, title);
1442
1443 // Also check whether we have new encoding name.
1444 UpdateEncoding(frame, webview->GetMainFrameEncodingName());
1445}
1446
1447void RenderView::DidFinishLoadForFrame(WebView* webview, WebFrame* frame) {
1448}
1449
1450void RenderView::DidFailLoadWithError(WebView* webview,
1451 const WebError& error,
1452 WebFrame* frame) {
1453}
1454
1455void RenderView::DidFinishDocumentLoadForFrame(WebView* webview,
1456 WebFrame* frame) {
1457 // Check whether we have new encoding name.
1458 UpdateEncoding(frame, webview->GetMainFrameEncodingName());
[email protected]1e0f70402008-10-16 23:57:471459
[email protected]0938d3c2009-01-09 20:37:351460 // Inject any user scripts. Do not inject into chrome UI pages, but do inject
1461 // into any other document.
1462 if (user_scripts_enabled_) {
[email protected]1e0f70402008-10-16 23:57:471463 const GURL &gurl = frame->GetURL();
[email protected]81a34412009-01-05 19:17:241464 if (g_render_thread && // Will be NULL when testing.
1465 (gurl.SchemeIs("file") ||
1466 gurl.SchemeIs("http") ||
1467 gurl.SchemeIs("https"))) {
[email protected]0938d3c2009-01-09 20:37:351468 g_render_thread->user_script_slave()->InjectScripts(frame);
[email protected]1e0f70402008-10-16 23:57:471469 }
1470 }
initial.commit09911bf2008-07-26 23:55:291471}
1472
1473void RenderView::DidHandleOnloadEventsForFrame(WebView* webview,
1474 WebFrame* frame) {
1475}
1476
1477void RenderView::DidChangeLocationWithinPageForFrame(WebView* webview,
1478 WebFrame* frame,
1479 bool is_new_navigation) {
1480 DidCommitLoadForFrame(webview, frame, is_new_navigation);
[email protected]de56f3782008-10-01 22:31:351481 const std::wstring& title =
1482 webview->GetMainFrame()->GetDataSource()->GetPageTitle();
1483 UpdateTitle(frame, title);
initial.commit09911bf2008-07-26 23:55:291484}
1485
1486void RenderView::DidReceiveIconForFrame(WebView* webview,
1487 WebFrame* frame) {
1488}
1489
1490void RenderView::WillPerformClientRedirect(WebView* webview,
1491 WebFrame* frame,
1492 const GURL& src_url,
1493 const GURL& dest_url,
1494 unsigned int delay_seconds,
1495 unsigned int fire_date) {
1496}
1497
1498void RenderView::DidCancelClientRedirect(WebView* webview,
1499 WebFrame* frame) {
1500}
1501
1502void RenderView::DidCompleteClientRedirect(WebView* webview,
1503 WebFrame* frame,
1504 const GURL& source) {
1505 if (webview->GetMainFrame() == frame)
1506 completed_client_redirect_src_ = source;
1507}
1508
1509void RenderView::BindDOMAutomationController(WebFrame* webframe) {
1510 dom_automation_controller_.set_message_sender(this);
1511 dom_automation_controller_.set_routing_id(routing_id_);
1512 dom_automation_controller_.BindToJavascript(webframe,
1513 L"domAutomationController");
1514}
1515
1516void RenderView::WindowObjectCleared(WebFrame* webframe) {
1517 external_js_object_.set_render_view(this);
1518 external_js_object_.BindToJavascript(webframe, L"external");
1519 if (enable_dom_automation_)
1520 BindDOMAutomationController(webframe);
1521 if (enable_dom_ui_bindings_) {
1522 dom_ui_bindings_.set_message_sender(this);
1523 dom_ui_bindings_.set_routing_id(routing_id_);
1524 dom_ui_bindings_.BindToJavascript(webframe, L"chrome");
1525 }
[email protected]18cb2572008-08-21 20:34:451526 if (enable_external_host_bindings_) {
1527 external_host_bindings_.set_message_sender(this);
1528 external_host_bindings_.set_routing_id(routing_id_);
1529 external_host_bindings_.BindToJavascript(webframe, L"externalHost");
1530 }
[email protected]9a2051d2008-08-15 20:12:421531
[email protected]3a453fa2008-08-15 18:46:341532#ifdef CHROME_PERSONALIZATION
1533 Personalization::ConfigureRendererPersonalization(personalization_, this,
1534 routing_id_, webframe);
1535#endif
initial.commit09911bf2008-07-26 23:55:291536}
1537
1538WindowOpenDisposition RenderView::DispositionForNavigationAction(
1539 WebView* webview,
1540 WebFrame* frame,
1541 const WebRequest* request,
1542 WebNavigationType type,
1543 WindowOpenDisposition disposition,
1544 bool is_redirect) {
1545 // Webkit is asking whether to navigate to a new URL.
1546 // This is fine normally, except if we're showing UI from one security
1547 // context and they're trying to navigate to a different context.
1548 const GURL& url = request->GetURL();
1549 // We only care about navigations that are within the current tab (as opposed
1550 // to, for example, opening a new window).
1551 // But we sometimes navigate to about:blank to clear a tab, and we want to
1552 // still allow that.
1553 if (disposition == CURRENT_TAB && !(url.SchemeIs("about"))) {
1554 // GetExtraData is NULL when we did not issue the request ourselves (see
1555 // OnNavigate), and so such a request may correspond to a link-click,
1556 // script, or drag-n-drop initiated navigation.
1557 if (frame == webview->GetMainFrame() && !request->GetExtraData()) {
1558 // When we received such unsolicited navigations, we sometimes want to
1559 // punt them up to the browser to handle.
1560 if (enable_dom_ui_bindings_ ||
1561 frame->GetInViewSourceMode() ||
1562 url.SchemeIs("view-source")) {
[email protected]c0588052008-10-27 23:01:501563 OpenURL(webview, url, GURL(), disposition);
initial.commit09911bf2008-07-26 23:55:291564 return IGNORE_ACTION; // Suppress the load here.
[email protected]50b691c2008-10-31 19:08:351565 } else if (url.SchemeIs(kBackForwardNavigationScheme)) {
1566 std::string offset_str = url.ExtractFileName();
1567 int offset;
1568 if (StringToInt(offset_str, &offset)) {
[email protected]0c0383772008-11-04 00:48:311569 GoToEntryAtOffset(offset);
[email protected]50b691c2008-10-31 19:08:351570 return IGNORE_ACTION; // The browser process handles this one.
1571 }
initial.commit09911bf2008-07-26 23:55:291572 }
1573 }
1574 }
1575
1576 // Detect when a page is "forking" a new tab that can be safely rendered in
1577 // its own process. This is done by sites like Gmail that try to open links
1578 // in new windows without script connections back to the original page. We
1579 // treat such cases as browser navigations (in which we will create a new
1580 // renderer for a cross-site navigation), rather than WebKit navigations.
1581 //
1582 // We use the following heuristic to decide whether to fork a new page in its
1583 // own process:
1584 // The parent page must open a new tab to about:blank, set the new tab's
1585 // window.opener to null, and then redirect the tab to a cross-site URL using
1586 // JavaScript.
1587 bool is_fork =
1588 // Must start from a tab showing about:blank, which is later redirected.
1589 frame->GetURL() == GURL("about:blank") &&
1590 // Must be the first real navigation of the tab.
1591 GetHistoryBackListCount() < 1 &&
1592 GetHistoryForwardListCount() < 1 &&
1593 // The parent page must have set the child's window.opener to null before
1594 // redirecting to the desired URL.
1595 frame->GetOpener() == NULL &&
1596 // Must be a top-level frame.
1597 frame->GetParent() == NULL &&
1598 // Must not have issued the request from this page. GetExtraData is NULL
1599 // when the navigation is being done by something outside the page.
1600 !request->GetExtraData() &&
1601 // Must be targeted at the current tab.
1602 disposition == CURRENT_TAB &&
1603 // Must be a JavaScript navigation, which appears as "other".
1604 type == WebNavigationTypeOther;
1605 if (is_fork) {
1606 // Open the URL via the browser, not via WebKit.
[email protected]c0588052008-10-27 23:01:501607 OpenURL(webview, url, GURL(), disposition);
initial.commit09911bf2008-07-26 23:55:291608 return IGNORE_ACTION;
1609 }
1610
1611 return disposition;
1612}
1613
1614void RenderView::RunJavaScriptAlert(WebView* webview,
1615 const std::wstring& message) {
1616 RunJavaScriptMessage(MessageBoxView::kIsJavascriptAlert,
1617 message,
1618 std::wstring(),
1619 NULL);
1620}
1621
1622bool RenderView::RunJavaScriptConfirm(WebView* webview,
1623 const std::wstring& message) {
1624 return RunJavaScriptMessage(MessageBoxView::kIsJavascriptConfirm,
1625 message,
1626 std::wstring(),
1627 NULL);
1628}
1629
1630bool RenderView::RunJavaScriptPrompt(WebView* webview,
1631 const std::wstring& message,
1632 const std::wstring& default_value,
1633 std::wstring* result) {
1634 return RunJavaScriptMessage(MessageBoxView::kIsJavascriptPrompt,
1635 message,
1636 default_value,
1637 result);
1638}
1639
1640bool RenderView::RunJavaScriptMessage(int type,
1641 const std::wstring& message,
1642 const std::wstring& default_value,
1643 std::wstring* result) {
1644 bool success = false;
1645 std::wstring result_temp;
1646 if (!result)
1647 result = &result_temp;
1648 IPC::SyncMessage* msg = new ViewHostMsg_RunJavaScriptMessage(
1649 routing_id_, message, default_value, type, &success, result);
1650
[email protected]1c4947f2009-01-15 22:25:111651 msg->set_pump_messages_event(modal_dialog_event_.get());
initial.commit09911bf2008-07-26 23:55:291652 Send(msg);
1653
1654 return success;
1655}
1656
1657void RenderView::AddGURLSearchProvider(const GURL& osd_url, bool autodetected) {
1658 if (!osd_url.is_empty())
1659 Send(new ViewHostMsg_PageHasOSDD(routing_id_, page_id_, osd_url,
1660 autodetected));
1661}
1662
1663bool RenderView::RunBeforeUnloadConfirm(WebView* webview,
1664 const std::wstring& message) {
1665 bool success = false;
1666 // This is an ignored return value, but is included so we can accept the same
1667 // response as RunJavaScriptMessage.
1668 std::wstring ignored_result;
1669 IPC::SyncMessage* msg = new ViewHostMsg_RunBeforeUnloadConfirm(
1670 routing_id_, message, &success, &ignored_result);
1671
[email protected]1c4947f2009-01-15 22:25:111672 msg->set_pump_messages_event(modal_dialog_event_.get());
initial.commit09911bf2008-07-26 23:55:291673 Send(msg);
1674
1675 return success;
1676}
1677
[email protected]0578a502008-11-10 19:34:431678void RenderView::EnableSuddenTermination() {
1679 Send(new ViewHostMsg_UnloadListenerChanged(routing_id_, false));
1680}
1681
1682void RenderView::DisableSuddenTermination() {
1683 Send(new ViewHostMsg_UnloadListenerChanged(routing_id_, true));
initial.commit09911bf2008-07-26 23:55:291684}
1685
[email protected]0ebf3872008-11-07 21:35:031686void RenderView::QueryFormFieldAutofill(const std::wstring& field_name,
1687 const std::wstring& text,
1688 int64 node_id) {
1689 static int message_id_counter = 0;
1690 form_field_autofill_request_id_ = message_id_counter++;
1691 Send(new ViewHostMsg_QueryFormFieldAutofill(routing_id_,
1692 field_name, text,
1693 node_id,
1694 form_field_autofill_request_id_));
1695}
1696
1697void RenderView::OnReceivedAutofillSuggestions(
1698 int64 node_id,
1699 int request_id,
[email protected]8d0f15c2008-11-11 01:01:091700 const std::vector<std::wstring>& suggestions,
[email protected]0ebf3872008-11-07 21:35:031701 int default_suggestion_index) {
1702 if (!webview() || request_id != form_field_autofill_request_id_)
1703 return;
1704
1705 webview()->AutofillSuggestionsForNode(node_id, suggestions,
1706 default_suggestion_index);
1707}
1708
[email protected]634a6f92008-12-01 21:39:311709void RenderView::OnPopupNotificationVisiblityChanged(bool visible) {
1710 popup_notification_visible_ = visible;
1711}
1712
initial.commit09911bf2008-07-26 23:55:291713void RenderView::ShowModalHTMLDialog(const GURL& url, int width, int height,
1714 const std::string& json_arguments,
1715 std::string* json_retval) {
1716 IPC::SyncMessage* msg = new ViewHostMsg_ShowModalHTMLDialog(
1717 routing_id_, url, width, height, json_arguments, json_retval);
1718
[email protected]1c4947f2009-01-15 22:25:111719 msg->set_pump_messages_event(modal_dialog_event_.get());
initial.commit09911bf2008-07-26 23:55:291720 Send(msg);
1721}
1722
1723uint32 RenderView::GetCPBrowsingContext() {
1724 uint32 context = 0;
1725 Send(new ViewHostMsg_GetCPBrowsingContext(&context));
1726 return context;
1727}
1728
1729// Tell the browser to display a destination link.
1730void RenderView::UpdateTargetURL(WebView* webview, const GURL& url) {
1731 if (url != target_url_) {
1732 if (target_url_status_ == TARGET_INFLIGHT ||
1733 target_url_status_ == TARGET_PENDING) {
1734 // If we have a request in-flight, save the URL to be sent when we
1735 // receive an ACK to the in-flight request. We can happily overwrite
1736 // any existing pending sends.
1737 pending_target_url_ = url;
1738 target_url_status_ = TARGET_PENDING;
1739 } else {
1740 Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_, url));
1741 target_url_ = url;
1742 target_url_status_ = TARGET_INFLIGHT;
1743 }
1744 }
1745}
1746
[email protected]b62d1a8c2009-01-13 23:54:571747void RenderView::RunFileChooser(bool multi_select,
1748 const std::wstring& title,
1749 const std::wstring& default_filename,
1750 const std::wstring& filter,
initial.commit09911bf2008-07-26 23:55:291751 WebFileChooserCallback* file_chooser) {
1752 if (file_chooser_.get()) {
1753 // TODO(brettw): bug 1235154: This should be a synchronous message to deal
1754 // with the fact that web pages can programatically trigger this. With the
1755 // asnychronous messages, we can get an additional call when one is pending,
1756 // which this test is for. For now, we just ignore the additional file
1757 // chooser request. WebKit doesn't do anything to expect the callback, so
1758 // we can just ignore calling it.
1759 delete file_chooser;
1760 return;
1761 }
1762 file_chooser_.reset(file_chooser);
[email protected]b62d1a8c2009-01-13 23:54:571763 Send(new ViewHostMsg_RunFileChooser(routing_id_, multi_select, title,
1764 default_filename, filter));
initial.commit09911bf2008-07-26 23:55:291765}
1766
1767void RenderView::AddMessageToConsole(WebView* webview,
1768 const std::wstring& message,
1769 unsigned int line_no,
1770 const std::wstring& source_id) {
1771 Send(new ViewHostMsg_AddMessageToConsole(routing_id_, message,
1772 static_cast<int32>(line_no),
1773 source_id));
1774}
1775
1776void RenderView::AddSearchProvider(const std::string& url) {
1777 AddGURLSearchProvider(GURL(url),
1778 false); // not autodetected
1779}
1780
1781void RenderView::DebuggerOutput(const std::wstring& out) {
1782 Send(new ViewHostMsg_DebuggerOutput(routing_id_, out));
1783}
1784
1785WebView* RenderView::CreateWebView(WebView* webview, bool user_gesture) {
[email protected]0aa55312008-10-17 21:53:081786 // Check to make sure we aren't overloading on popups.
1787 if (shared_popup_counter_->data > kMaximumNumberOfUnacknowledgedPopups)
1788 return NULL;
1789
[email protected]634a6f92008-12-01 21:39:311790 // This window can't be closed from a window.close() call until we receive a
1791 // message from the Browser process explicitly allowing it.
1792 popup_notification_visible_ = true;
1793
initial.commit09911bf2008-07-26 23:55:291794 int32 routing_id = MSG_ROUTING_NONE;
[email protected]1829fcc2008-09-29 23:52:321795 HANDLE modal_dialog_event = NULL;
[email protected]81a34412009-01-05 19:17:241796 bool result = render_thread_->Send(
[email protected]15787f8f2008-10-17 15:29:031797 new ViewHostMsg_CreateWindow(routing_id_, user_gesture, &routing_id,
1798 &modal_dialog_event));
initial.commit09911bf2008-07-26 23:55:291799 if (routing_id == MSG_ROUTING_NONE) {
1800 DCHECK(modal_dialog_event == NULL);
1801 return NULL;
1802 }
1803
1804 // The WebView holds a reference to this new RenderView
1805 const WebPreferences& prefs = webview->GetPreferences();
[email protected]1c4947f2009-01-15 22:25:111806 base::WaitableEvent* waitable_event =
1807 new base::WaitableEvent(modal_dialog_event);
[email protected]81a34412009-01-05 19:17:241808 RenderView* view = RenderView::Create(render_thread_,
[email protected]1c4947f2009-01-15 22:25:111809 NULL, waitable_event, routing_id_,
[email protected]0aa55312008-10-17 21:53:081810 prefs, shared_popup_counter_,
1811 routing_id);
initial.commit09911bf2008-07-26 23:55:291812 view->set_opened_by_user_gesture(user_gesture);
[email protected]06828b92008-10-20 21:25:461813 view->set_waiting_for_create_window_ack(true);
initial.commit09911bf2008-07-26 23:55:291814
1815 // Copy over the alternate error page URL so we can have alt error pages in
1816 // the new render view (we don't need the browser to send the URL back down).
1817 view->alternate_error_page_url_ = alternate_error_page_url_;
1818
1819 return view->webview();
1820}
1821
[email protected]0ebf3872008-11-07 21:35:031822WebWidget* RenderView::CreatePopupWidget(WebView* webview,
[email protected]cfd727f2009-01-09 20:21:111823 bool activatable) {
[email protected]8085dbc82008-09-26 22:53:441824 RenderWidget* widget = RenderWidget::Create(routing_id_,
[email protected]81a34412009-01-05 19:17:241825 render_thread_,
[email protected]cfd727f2009-01-09 20:21:111826 activatable);
initial.commit09911bf2008-07-26 23:55:291827 return widget->webwidget();
1828}
1829
[email protected]173de1b2008-08-15 18:36:461830static bool ShouldLoadPluginInProcess(const std::string& mime_type,
1831 bool* is_gears) {
1832 if (RenderProcess::ShouldLoadPluginsInProcess())
1833 return true;
1834
1835 if (mime_type == "application/x-googlegears") {
1836 *is_gears = true;
1837 CommandLine cmd;
1838 return cmd.HasSwitch(switches::kGearsInRenderer);
1839 }
1840
1841 return false;
1842}
1843
initial.commit09911bf2008-07-26 23:55:291844WebPluginDelegate* RenderView::CreatePluginDelegate(
1845 WebView* webview,
1846 const GURL& url,
1847 const std::string& mime_type,
1848 const std::string& clsid,
1849 std::string* actual_mime_type) {
[email protected]173de1b2008-08-15 18:36:461850 bool is_gears = false;
1851 if (ShouldLoadPluginInProcess(mime_type, &is_gears)) {
[email protected]690a99c2009-01-06 16:48:451852 FilePath path;
[email protected]81a34412009-01-05 19:17:241853 render_thread_->Send(
initial.commit09911bf2008-07-26 23:55:291854 new ViewHostMsg_GetPluginPath(url, mime_type, clsid, &path,
1855 actual_mime_type));
[email protected]690a99c2009-01-06 16:48:451856 if (path.value().empty())
initial.commit09911bf2008-07-26 23:55:291857 return NULL;
1858
1859 std::string mime_type_to_use;
1860 if (actual_mime_type && !actual_mime_type->empty())
1861 mime_type_to_use = *actual_mime_type;
1862 else
1863 mime_type_to_use = mime_type;
1864
[email protected]173de1b2008-08-15 18:36:461865 if (is_gears)
1866 ChromePluginLib::Create(path, GetCPBrowserFuncsForRenderer());
[email protected]690a99c2009-01-06 16:48:451867 return WebPluginDelegateImpl::Create(path,
1868 mime_type_to_use, host_window_);
initial.commit09911bf2008-07-26 23:55:291869 }
1870
1871 WebPluginDelegateProxy* proxy =
1872 WebPluginDelegateProxy::Create(url, mime_type, clsid, this);
1873 if (!proxy)
1874 return NULL;
1875
1876 // We hold onto the proxy so we can poke it when we are painting. See our
1877 // DidPaint implementation below.
1878 plugin_delegates_.push_back(proxy);
1879
1880 return proxy;
1881}
1882
[email protected]ec9212f2008-12-18 21:40:361883webkit_glue::WebMediaPlayerDelegate* RenderView::CreateMediaPlayerDelegate() {
1884 return new WebMediaPlayerDelegateImpl();
1885}
1886
initial.commit09911bf2008-07-26 23:55:291887void RenderView::OnMissingPluginStatus(WebPluginDelegate* delegate,
1888 int status) {
1889 if (first_default_plugin_ == NULL) {
1890 // Show the InfoBar for the first available plugin.
1891 if (status == default_plugin::MISSING_PLUGIN_AVAILABLE) {
1892 first_default_plugin_ = delegate;
1893 Send(new ViewHostMsg_MissingPluginStatus(routing_id_, status));
1894 }
1895 } else {
1896 // Closes the InfoBar if user clicks on the plugin (instead of the InfoBar)
1897 // to start the download/install.
1898 if (status == default_plugin::MISSING_PLUGIN_USER_STARTED_DOWNLOAD) {
1899 Send(new ViewHostMsg_MissingPluginStatus(routing_id_, status));
1900 }
1901 }
1902}
1903
1904void RenderView::OpenURL(WebView* webview, const GURL& url,
[email protected]c0588052008-10-27 23:01:501905 const GURL& referrer,
initial.commit09911bf2008-07-26 23:55:291906 WindowOpenDisposition disposition) {
[email protected]c0588052008-10-27 23:01:501907 Send(new ViewHostMsg_OpenURL(routing_id_, url, referrer, disposition));
initial.commit09911bf2008-07-26 23:55:291908}
1909
1910// We are supposed to get a single call to Show for a newly created RenderView
1911// that was created via RenderView::CreateWebView. So, we wait until this
1912// point to dispatch the ShowView message.
1913//
1914// This method provides us with the information about how to display the newly
1915// created RenderView (i.e., as a constrained popup or as a new tab).
1916//
1917void RenderView::Show(WebWidget* webwidget, WindowOpenDisposition disposition) {
1918 DCHECK(!did_show_) << "received extraneous Show call";
1919 DCHECK(opener_id_ != MSG_ROUTING_NONE);
1920
1921 if (did_show_)
1922 return;
1923 did_show_ = true;
1924
1925 // NOTE: initial_pos_ may still have its default values at this point, but
1926 // that's okay. It'll be ignored if disposition is not NEW_POPUP, or the
1927 // browser process will impose a default position otherwise.
1928 Send(new ViewHostMsg_ShowView(
1929 opener_id_, routing_id_, disposition, initial_pos_,
1930 WasOpenedByUserGestureHelper()));
1931}
1932
[email protected]634a6f92008-12-01 21:39:311933void RenderView::CloseWidgetSoon(WebWidget* webwidget) {
1934 if (popup_notification_visible_ == false)
1935 RenderWidget::CloseWidgetSoon(webwidget);
1936}
1937
initial.commit09911bf2008-07-26 23:55:291938void RenderView::RunModal(WebWidget* webwidget) {
1939 DCHECK(did_show_) << "should already have shown the view";
1940
1941 IPC::SyncMessage* msg = new ViewHostMsg_RunModal(routing_id_);
1942
[email protected]1c4947f2009-01-15 22:25:111943 msg->set_pump_messages_event(modal_dialog_event_.get());
initial.commit09911bf2008-07-26 23:55:291944 Send(msg);
1945}
1946
1947void RenderView::SyncNavigationState() {
1948 if (!webview())
1949 return;
1950
initial.commit09911bf2008-07-26 23:55:291951 std::string state;
[email protected]606843fa2008-12-02 19:08:561952 if (!webview()->GetMainFrame()->GetCurrentHistoryState(&state))
initial.commit09911bf2008-07-26 23:55:291953 return;
[email protected]606843fa2008-12-02 19:08:561954 Send(new ViewHostMsg_UpdateState(routing_id_, page_id_, state));
initial.commit09911bf2008-07-26 23:55:291955}
1956
1957void RenderView::ShowContextMenu(WebView* webview,
1958 ContextNode::Type type,
1959 int x,
1960 int y,
1961 const GURL& link_url,
1962 const GURL& image_url,
1963 const GURL& page_url,
1964 const GURL& frame_url,
1965 const std::wstring& selection_text,
1966 const std::wstring& misspelled_word,
[email protected]6aa376b2008-09-23 18:49:521967 int edit_flags,
1968 const std::string& security_info) {
initial.commit09911bf2008-07-26 23:55:291969 ViewHostMsg_ContextMenu_Params params;
1970 params.type = type;
1971 params.x = x;
1972 params.y = y;
1973 params.image_url = image_url;
1974 params.link_url = link_url;
1975 params.page_url = page_url;
1976 params.frame_url = frame_url;
1977 params.selection_text = selection_text;
1978 params.misspelled_word = misspelled_word;
[email protected]bbbd545c2008-12-15 20:18:041979 params.spellcheck_enabled =
1980 webview->GetFocusedFrame()->SpellCheckEnabled();
initial.commit09911bf2008-07-26 23:55:291981 params.edit_flags = edit_flags;
[email protected]6aa376b2008-09-23 18:49:521982 params.security_info = security_info;
initial.commit09911bf2008-07-26 23:55:291983 Send(new ViewHostMsg_ContextMenu(routing_id_, params));
1984}
1985
1986void RenderView::StartDragging(WebView* webview, const WebDropData& drop_data) {
1987 Send(new ViewHostMsg_StartDragging(routing_id_, drop_data));
1988}
1989
1990void RenderView::TakeFocus(WebView* webview, bool reverse) {
1991 Send(new ViewHostMsg_TakeFocus(routing_id_, reverse));
1992}
1993
1994void RenderView::DidDownloadImage(int id,
1995 const GURL& image_url,
1996 bool errored,
1997 const SkBitmap& image) {
1998 Send(new ViewHostMsg_DidDownloadImage(routing_id_, id, image_url, errored,
1999 image));
2000}
2001
2002
2003void RenderView::OnDownloadImage(int id,
2004 const GURL& image_url,
2005 int image_size) {
2006 if (!webview()->DownloadImage(id, image_url, image_size))
2007 Send(new ViewHostMsg_DidDownloadImage(routing_id_, id, image_url, true,
2008 SkBitmap()));
2009}
2010
2011void RenderView::OnGetApplicationInfo(int page_id) {
2012 webkit_glue::WebApplicationInfo app_info;
2013 if (page_id == page_id_)
2014 webkit_glue::GetApplicationInfo(webview(), &app_info);
2015
2016 // Prune out any data URLs in the set of icons. The browser process expects
2017 // any icon with a data URL to have originated from a favicon. We don't want
2018 // to decode arbitrary data URLs in the browser process. See
2019 // http://b/issue?id=1162972
2020 for (size_t i = 0; i < app_info.icons.size(); ++i) {
2021 if (app_info.icons[i].url.SchemeIs("data")) {
2022 app_info.icons.erase(app_info.icons.begin() + i);
2023 --i;
2024 }
2025 }
2026
2027 Send(new ViewHostMsg_DidGetApplicationInfo(routing_id_, page_id, app_info));
2028}
2029
2030GURL RenderView::GetAlternateErrorPageURL(const GURL& failedURL,
2031 ErrorPageType error_type) {
2032 if (failedURL.SchemeIsSecure()) {
2033 // If the URL that failed was secure, then the embedding web page was not
2034 // expecting a network attacker to be able to manipulate its contents. As
2035 // we fetch alternate error pages over HTTP, we would be allowing a network
2036 // attacker to manipulate the contents of the response if we tried to use
2037 // the link doctor here.
2038 return GURL::EmptyGURL();
2039 }
2040
2041 // Grab the base URL from the browser process.
2042 if (!alternate_error_page_url_.is_valid())
2043 return GURL::EmptyGURL();
2044
2045 // Strip query params from the failed URL.
2046 GURL::Replacements remove_params;
2047 remove_params.ClearUsername();
2048 remove_params.ClearPassword();
2049 remove_params.ClearQuery();
2050 remove_params.ClearRef();
2051 const GURL url_to_send = failedURL.ReplaceComponents(remove_params);
2052
2053 // Construct the query params to send to link doctor.
2054 std::string params(alternate_error_page_url_.query());
2055 params.append("&url=");
2056 params.append(EscapeQueryParamValue(url_to_send.spec()));
2057 params.append("&sourceid=chrome");
2058 params.append("&error=");
2059 switch (error_type) {
2060 case DNS_ERROR:
2061 params.append("dnserror");
2062 break;
2063
2064 case HTTP_404:
2065 params.append("http404");
2066 break;
2067
[email protected]5df266ac2008-10-15 19:50:132068 case CONNECTION_ERROR:
2069 params.append("connectionerror");
2070 break;
2071
initial.commit09911bf2008-07-26 23:55:292072 default:
2073 NOTREACHED() << "unknown ErrorPageType";
2074 }
2075
2076 // OK, build the final url to return.
2077 GURL::Replacements link_doctor_params;
2078 link_doctor_params.SetQueryStr(params);
2079 GURL url = alternate_error_page_url_.ReplaceComponents(link_doctor_params);
2080 return url;
2081}
2082
2083void RenderView::OnFind(const FindInPageRequest& request) {
2084 WebFrame* main_frame = webview()->GetMainFrame();
2085 WebFrame* frame_after_main = webview()->GetNextFrameAfter(main_frame, true);
2086 WebFrame* focused_frame = webview()->GetFocusedFrame();
2087 WebFrame* search_frame = focused_frame; // start searching focused frame.
2088
2089 bool multi_frame = (frame_after_main != main_frame);
2090
2091 // If we have multiple frames, we don't want to wrap the search within the
2092 // frame, so we check here if we only have main_frame in the chain.
2093 bool wrap_within_frame = !multi_frame;
2094
2095 gfx::Rect selection_rect;
2096 bool result = false;
2097
2098 do {
[email protected]884db412008-11-24 23:46:502099 result = search_frame->Find(request, wrap_within_frame, &selection_rect);
initial.commit09911bf2008-07-26 23:55:292100
2101 if (!result) {
2102 // don't leave text selected as you move to the next frame.
2103 search_frame->ClearSelection();
2104
2105 // Find the next frame, but skip the invisible ones.
2106 do {
2107 // What is the next frame to search? (we might be going backwards). Note
2108 // that we specify wrap=true so that search_frame never becomes NULL.
2109 search_frame = request.forward ?
2110 webview()->GetNextFrameAfter(search_frame, true) :
2111 webview()->GetPreviousFrameBefore(search_frame, true);
2112 } while (!search_frame->Visible() && search_frame != focused_frame);
2113
[email protected]884db412008-11-24 23:46:502114 // Make sure selection doesn't affect the search operation in new frame.
initial.commit09911bf2008-07-26 23:55:292115 search_frame->ClearSelection();
2116
2117 // If we have multiple frames and we have wrapped back around to the
2118 // focused frame, we need to search it once more allowing wrap within
2119 // the frame, otherwise it will report 'no match' if the focused frame has
2120 // reported matches, but no frames after the focused_frame contain a
2121 // match for the search word(s).
2122 if (multi_frame && search_frame == focused_frame) {
[email protected]884db412008-11-24 23:46:502123 result = search_frame->Find(request, true, // Force wrapping.
2124 &selection_rect);
initial.commit09911bf2008-07-26 23:55:292125 }
2126 }
2127
2128 // TODO(jcampan): http://b/issue?id=1157486 Remove StoreForFocus call once
2129 // we have the fix for 792423.
2130 search_frame->GetView()->StoreFocusForFrame(search_frame);
2131 webview()->SetFocusedFrame(search_frame);
2132 } while (!result && search_frame != focused_frame);
2133
2134 // Make sure we don't leave any frame focused or the focus won't be restored
2135 // properly in WebViewImpl::SetFocus(). Note that we are talking here about
2136 // focused on the SelectionController, not FocusController.
2137 // webview()->GetFocusedFrame() will still return the last focused frame (as
2138 // it queries the FocusController).
2139 // TODO(jcampan): http://b/issue?id=1157486 Remove next line once we have the
2140 // fix for 792423.
2141 webview()->SetFocusedFrame(NULL);
2142
2143 // We send back word that we found some matches, because we don't want to lag
2144 // when notifying the user that we found something. At this point we only know
2145 // that we found 1 match, but the scoping effort will tell us more. However,
2146 // if this is a FindNext request, the scoping effort is already under way, or
2147 // done already, so we have partial results. In that case we set it to -1 so
2148 // that it gets ignored by the FindInPageController.
2149 int match_count = result ? 1 : 0; // 1 here means possibly more coming.
2150 if (request.find_next)
2151 match_count = -1;
2152
2153 // If we find no matches (or if this is Find Next) then this will be our last
2154 // status update. Otherwise the scoping effort will send more results.
2155 bool final_status_update = !result || request.find_next;
2156
2157 // Send the search result over to the browser process.
2158 Send(new ViewHostMsg_Find_Reply(routing_id_, request.request_id,
2159 match_count,
2160 selection_rect,
2161 -1, // Don't update active match ordinal.
2162 final_status_update));
2163
2164 if (!request.find_next) {
2165 // Scoping effort begins, starting with the mainframe.
2166 search_frame = main_frame;
2167
2168 main_frame->ResetMatchCount();
2169
2170 do {
2171 // Cancel all old scoping requests before starting a new one.
2172 search_frame->CancelPendingScopingEffort();
2173
2174 // We don't start another scoping effort unless at least one match has
2175 // been found.
2176 if (result) {
2177 // Start new scoping request. If the scoping function determines that it
2178 // needs to scope, it will defer until later.
2179 search_frame->ScopeStringMatches(request,
2180 true); // reset the tickmarks
2181 }
2182
2183 // Iterate to the next frame. The frame will not necessarily scope, for
2184 // example if it is not visible.
2185 search_frame = webview()->GetNextFrameAfter(search_frame, true);
2186 } while (search_frame != main_frame);
2187 }
2188}
2189
2190void RenderView::ReportFindInPageMatchCount(int count, int request_id,
2191 bool final_update) {
2192 // If we have a message that has been queued up, then we should just replace
2193 // it. The ACK from the browser will make sure it gets sent when the browser
2194 // wants it.
2195 if (queued_find_reply_message_.get()) {
2196 IPC::Message* msg = new ViewHostMsg_Find_Reply(
2197 routing_id_,
2198 request_id,
2199 count,
2200 gfx::Rect(0, 0, 0, 0),
2201 -1, // Don't update active match ordinal.
2202 final_update);
2203 queued_find_reply_message_.reset(msg);
2204 } else {
2205 // Send the search result over to the browser process.
2206 Send(new ViewHostMsg_Find_Reply(
2207 routing_id_,
2208 request_id,
2209 count,
2210 gfx::Rect(0, 0, 0, 0),
2211 -1, // // Don't update active match ordinal.
2212 final_update));
2213 }
2214}
2215
2216void RenderView::ReportFindInPageSelection(int request_id,
2217 int active_match_ordinal,
2218 const gfx::Rect& selection_rect) {
2219 // Send the search result over to the browser process.
2220 Send(new ViewHostMsg_Find_Reply(routing_id_,
2221 request_id,
2222 -1,
2223 selection_rect,
2224 active_match_ordinal,
2225 false));
2226}
2227
2228bool RenderView::WasOpenedByUserGesture(WebView* webview) const {
2229 return WasOpenedByUserGestureHelper();
2230}
2231
2232bool RenderView::WasOpenedByUserGestureHelper() const {
2233 // If pop-up blocking has been disabled, then treat all new windows as if
2234 // they were opened by a user gesture. This will prevent them from being
2235 // blocked. This is a bit of a hack, there should be a more straightforward
2236 // way to disable pop-up blocking.
2237 if (disable_popup_blocking_)
2238 return true;
2239
2240 return opened_by_user_gesture_;
2241}
2242
2243void RenderView::SpellCheck(const std::wstring& word, int& misspell_location,
2244 int& misspell_length) {
2245 Send(new ViewHostMsg_SpellCheck(routing_id_, word, &misspell_location,
2246 &misspell_length));
2247}
2248
2249void RenderView::SetInputMethodState(bool enabled) {
2250 // Save the updated IME status and mark the input focus has been updated.
2251 // The IME status is to be sent to a browser process next time when
2252 // the input caret is rendered.
[email protected]9f23f592008-11-17 08:36:342253 if (!ime_control_busy_) {
2254 ime_control_updated_ = true;
2255 ime_control_new_state_ = enabled;
2256 }
initial.commit09911bf2008-07-26 23:55:292257}
2258
2259void RenderView::ScriptedPrint(WebFrame* frame) {
2260 // Retrieve the default print settings to calculate the expected number of
2261 // pages.
2262 ViewMsg_Print_Params default_settings;
2263 IPC::SyncMessage* msg =
2264 new ViewHostMsg_GetDefaultPrintSettings(routing_id_, &default_settings);
2265 if (Send(msg)) {
2266 msg = NULL;
2267 // Continue only if the settings are valid.
2268 if (default_settings.dpi && default_settings.document_cookie) {
2269 int expected_pages_count = SwitchFrameToPrintMediaType(default_settings,
2270 frame);
2271 DCHECK(expected_pages_count);
2272 SwitchFrameToDisplayMediaType(frame);
2273
2274 // Ask the browser to show UI to retrieve the final print settings.
2275 ViewMsg_PrintPages_Params print_settings;
2276 // host_window_ may be NULL at this point if the current window is a popup
2277 // and the print() command has been issued from the parent. The receiver
2278 // of this message has to deal with this.
2279 msg = new ViewHostMsg_ScriptedPrint(routing_id_,
2280 host_window_,
2281 default_settings.document_cookie,
2282 expected_pages_count,
2283 &print_settings);
2284 if (Send(msg)) {
2285 msg = NULL;
2286
2287 // If the settings are invalid, early quit.
2288 if (print_settings.params.dpi &&
2289 print_settings.params.document_cookie) {
2290 // Render the printed pages. It will implicitly revert the document to
2291 // display CSS media type.
2292 PrintPages(print_settings, frame);
2293 // All went well.
2294 return;
2295 } else {
2296 // The user cancelled.
2297 }
2298 } else {
2299 // Send() failed.
2300 NOTREACHED();
2301 }
2302 } else {
2303 // The user cancelled.
2304 }
2305 } else {
2306 // Send() failed.
2307 NOTREACHED();
2308 }
2309 // TODO(maruel): bug 1123882 Alert the user that printing failed.
2310}
2311
2312void RenderView::WebInspectorOpened(int num_resources) {
2313 Send(new ViewHostMsg_InspectElement_Reply(routing_id_, num_resources));
2314}
2315
2316void RenderView::UserMetricsRecordAction(const std::wstring& action) {
2317 Send(new ViewHostMsg_UserMetricsRecordAction(routing_id_, action));
2318}
2319
2320void RenderView::DnsPrefetch(const std::vector<std::string>& host_names) {
2321 Send(new ViewHostMsg_DnsPrefetch(host_names));
2322}
2323
[email protected]630e26b2008-10-14 22:55:172324void RenderView::OnZoom(int function) {
2325 static const bool kZoomIsTextOnly = false;
2326 switch (function) {
2327 case PageZoom::SMALLER:
2328 webview()->ZoomOut(kZoomIsTextOnly);
initial.commit09911bf2008-07-26 23:55:292329 break;
[email protected]630e26b2008-10-14 22:55:172330 case PageZoom::STANDARD:
2331 webview()->ResetZoom();
initial.commit09911bf2008-07-26 23:55:292332 break;
[email protected]630e26b2008-10-14 22:55:172333 case PageZoom::LARGER:
2334 webview()->ZoomIn(kZoomIsTextOnly);
initial.commit09911bf2008-07-26 23:55:292335 break;
2336 default:
2337 NOTREACHED();
2338 }
2339}
2340
[email protected]e38f40152008-09-12 23:08:302341void RenderView::OnSetPageEncoding(const std::wstring& encoding_name) {
initial.commit09911bf2008-07-26 23:55:292342 webview()->SetPageEncoding(encoding_name);
2343}
2344
2345void RenderView::OnPasswordFormsSeen(WebView* webview,
2346 const std::vector<PasswordForm>& forms) {
2347 Send(new ViewHostMsg_PasswordFormsSeen(routing_id_, forms));
2348}
2349
[email protected]8d0f15c2008-11-11 01:01:092350void RenderView::OnAutofillFormSubmitted(WebView* webview,
2351 const AutofillForm& form) {
2352 Send(new ViewHostMsg_AutofillFormSubmitted(routing_id_, form));
2353}
2354
initial.commit09911bf2008-07-26 23:55:292355WebHistoryItem* RenderView::GetHistoryEntryAtOffset(int offset) {
[email protected]50b691c2008-10-31 19:08:352356 // Our history list is kept in the browser process on the UI thread. Since
2357 // we can't make a sync IPC call to that thread without risking deadlock,
2358 // we use a trick: construct a fake history item of the form:
2359 // history://go/OFFSET
2360 // When WebCore tells us to navigate to it, we tell the browser process to
2361 // do a back/forward navigation instead.
2362
2363 GURL url(StringPrintf("%s://go/%d", kBackForwardNavigationScheme, offset));
2364 history_navigation_item_ = WebHistoryItem::Create(url, L"", "", NULL);
2365 return history_navigation_item_.get();
initial.commit09911bf2008-07-26 23:55:292366}
2367
[email protected]0c0383772008-11-04 00:48:312368void RenderView::GoToEntryAtOffset(int offset) {
[email protected]f46aff62008-10-16 07:58:052369 history_back_list_count_ += offset;
2370 history_forward_list_count_ -= offset;
2371
initial.commit09911bf2008-07-26 23:55:292372 Send(new ViewHostMsg_GoToEntryAtOffset(routing_id_, offset));
2373}
2374
2375int RenderView::GetHistoryBackListCount() {
2376 return history_back_list_count_;
2377}
2378
2379int RenderView::GetHistoryForwardListCount() {
2380 return history_forward_list_count_;
2381}
2382
2383void RenderView::OnNavStateChanged(WebView* webview) {
[email protected]81a34412009-01-05 19:17:242384 if (!nav_state_sync_timer_.IsRunning()) {
2385 nav_state_sync_timer_.Start(
2386 TimeDelta::FromSeconds(delay_seconds_for_form_state_sync_), this,
2387 &RenderView::SyncNavigationState);
2388 }
initial.commit09911bf2008-07-26 23:55:292389}
2390
2391void RenderView::SetTooltipText(WebView* webview,
2392 const std::wstring& tooltip_text) {
2393 Send(new ViewHostMsg_SetTooltipText(routing_id_, tooltip_text));
2394}
2395
2396void RenderView::DownloadUrl(const GURL& url, const GURL& referrer) {
2397 Send(new ViewHostMsg_DownloadUrl(routing_id_, url, referrer));
2398}
2399
2400WebFrame* RenderView::GetChildFrame(const std::wstring& frame_xpath) const {
2401 WebFrame* web_frame;
2402 if (frame_xpath.empty()) {
2403 web_frame = webview()->GetMainFrame();
2404 } else {
2405 web_frame = webview()->GetMainFrame()->GetChildFrame(frame_xpath);
2406 }
2407
2408 return web_frame;
2409}
2410
[email protected]f29acf52008-11-03 20:08:332411void RenderView::EvaluateScript(const std::wstring& frame_xpath,
2412 const std::wstring& script) {
initial.commit09911bf2008-07-26 23:55:292413 WebFrame* web_frame = GetChildFrame(frame_xpath);
2414 if (!web_frame)
2415 return;
2416
[email protected]f8ca6e92008-11-27 00:50:162417 web_frame->ExecuteJavaScript(WideToUTF8(script), GURL());
initial.commit09911bf2008-07-26 23:55:292418}
2419
2420void RenderView::OnScriptEvalRequest(const std::wstring& frame_xpath,
2421 const std::wstring& jscript) {
[email protected]f29acf52008-11-03 20:08:332422 EvaluateScript(frame_xpath, jscript);
initial.commit09911bf2008-07-26 23:55:292423}
2424
2425void RenderView::OnAddMessageToConsole(const std::wstring& frame_xpath,
2426 const std::wstring& msg,
2427 ConsoleMessageLevel level) {
2428 WebFrame* web_frame = GetChildFrame(frame_xpath);
2429 if (!web_frame)
2430 return;
2431
2432 web_frame->AddMessageToConsole(msg, level);
2433}
2434
2435void RenderView::OnDebugAttach() {
initial.commit09911bf2008-07-26 23:55:292436 Send(new ViewHostMsg_DidDebugAttach(routing_id_));
2437 // Tell the plugin host to stop accepting messages in order to avoid
2438 // hangs while the renderer is paused.
2439 // TODO(1243929): It might be an improvement to add more plumbing to do this
2440 // when the renderer is actually paused vs. just the debugger being attached.
2441 PluginChannelHost::SetListening(false);
2442}
2443
2444void RenderView::OnDebugDetach() {
2445 // Tell the plugin host to start accepting plugin messages again.
2446 PluginChannelHost::SetListening(true);
2447}
2448
2449void RenderView::OnAllowDomAutomationBindings(bool allow_bindings) {
2450 enable_dom_automation_ = allow_bindings;
2451}
2452
[email protected]18cb2572008-08-21 20:34:452453void RenderView::OnAllowBindings(bool enable_dom_ui_bindings,
[email protected]266eb6f2008-09-30 23:56:502454 bool enable_external_host_bindings) {
[email protected]18cb2572008-08-21 20:34:452455 enable_dom_ui_bindings_ = enable_dom_ui_bindings;
2456 enable_external_host_bindings_ = enable_external_host_bindings;
initial.commit09911bf2008-07-26 23:55:292457}
2458
2459void RenderView::OnSetDOMUIProperty(const std::string& name,
2460 const std::string& value) {
2461 DCHECK(enable_dom_ui_bindings_);
2462 dom_ui_bindings_.SetProperty(name, value);
2463}
2464
2465void RenderView::OnReservePageIDRange(int size_of_range) {
2466 next_page_id_ += size_of_range + 1;
2467}
2468
2469void RenderView::OnDragSourceEndedOrMoved(int client_x,
2470 int client_y,
2471 int screen_x,
2472 int screen_y,
2473 bool ended) {
2474 if (ended)
2475 webview()->DragSourceEndedAt(client_x, client_y, screen_x, screen_y);
2476 else
2477 webview()->DragSourceMovedTo(client_x, client_y, screen_x, screen_y);
2478}
2479
2480void RenderView::OnDragSourceSystemDragEnded() {
2481 webview()->DragSourceSystemDragEnded();
2482}
2483
2484void RenderView::OnUploadFileRequest(const ViewMsg_UploadFile_Params& p) {
2485 webkit_glue::FileUploadData* f = new webkit_glue::FileUploadData;
2486 f->file_path = p.file_path;
2487 f->form_name = p.form;
2488 f->file_name = p.file;
2489 f->submit_name = p.submit;
2490
2491 // Build the other form values map.
2492 if (!p.other_values.empty()) {
2493 std::vector<std::wstring> e;
2494 std::vector<std::wstring> kvp;
2495 std::vector<std::wstring>::iterator i;
2496
2497 SplitString(p.other_values, L'\n', &e);
2498 for (i = e.begin(); i != e.end(); ++i) {
2499 SplitString(*i, L'=', &kvp);
2500 if (kvp.size() == 2)
2501 f->other_form_values[kvp[0]] = kvp[1];
2502 kvp.clear();
2503 }
2504 }
2505
2506 pending_upload_data_.reset(f);
2507 ProcessPendingUpload();
2508}
2509
2510void RenderView::ProcessPendingUpload() {
2511 webkit_glue::FileUploadData* f = pending_upload_data_.get();
2512 if (f && webview() && webkit_glue::FillFormToUploadFile(webview(), *f))
2513 ResetPendingUpload();
2514}
2515
2516void RenderView::ResetPendingUpload() {
2517 pending_upload_data_.reset();
2518}
2519
2520void RenderView::OnFormFill(const FormData& form) {
2521 webkit_glue::FillForm(this->webview(), form);
2522}
2523
2524void RenderView::OnFillPasswordForm(
2525 const PasswordFormDomManager::FillData& form_data) {
2526 webkit_glue::FillPasswordForm(this->webview(), form_data);
2527}
2528
2529void RenderView::OnDragTargetDragEnter(const WebDropData& drop_data,
2530 const gfx::Point& client_pt, const gfx::Point& screen_pt) {
2531 bool is_drop_target = webview()->DragTargetDragEnter(drop_data,
2532 client_pt.x(), client_pt.y(), screen_pt.x(), screen_pt.y());
2533
2534 Send(new ViewHostMsg_UpdateDragCursor(routing_id_, is_drop_target));
2535}
2536
2537void RenderView::OnDragTargetDragOver(const gfx::Point& client_pt,
2538 const gfx::Point& screen_pt) {
2539 bool is_drop_target = webview()->DragTargetDragOver(client_pt.x(),
2540 client_pt.y(), screen_pt.x(), screen_pt.y());
2541
2542 Send(new ViewHostMsg_UpdateDragCursor(routing_id_, is_drop_target));
2543}
2544
2545void RenderView::OnDragTargetDragLeave() {
2546 webview()->DragTargetDragLeave();
2547}
2548
2549void RenderView::OnDragTargetDrop(const gfx::Point& client_pt,
2550 const gfx::Point& screen_pt) {
2551 webview()->DragTargetDrop(client_pt.x(), client_pt.y(), screen_pt.x(),
2552 screen_pt.y());
2553}
2554
2555void RenderView::OnUpdateWebPreferences(const WebPreferences& prefs) {
2556 webview()->SetPreferences(prefs);
2557}
2558
2559void RenderView::OnSetAltErrorPageURL(const GURL& url) {
2560 alternate_error_page_url_ = url;
2561}
2562
2563void RenderView::DidPaint() {
2564 PluginDelegateList::iterator it = plugin_delegates_.begin();
2565 while (it != plugin_delegates_.end()) {
2566 (*it)->FlushGeometryUpdates();
2567 ++it;
2568 }
2569}
2570
2571void RenderView::OnInstallMissingPlugin() {
2572 // This could happen when the first default plugin is deleted.
2573 if (first_default_plugin_ == NULL)
2574 return;
2575 first_default_plugin_->InstallMissingPlugin();
2576}
2577
[email protected]b62d1a8c2009-01-13 23:54:572578void RenderView::OnFileChooserResponse(
2579 const std::vector<std::wstring>& file_names) {
2580 file_chooser_->OnFileChoose(file_names);
initial.commit09911bf2008-07-26 23:55:292581 file_chooser_.reset();
2582}
2583
2584void RenderView::OnEnableViewSourceMode() {
2585 if (!webview())
2586 return;
2587 WebFrame* main_frame = webview()->GetMainFrame();
2588 if (!main_frame)
2589 return;
2590
2591 main_frame->SetInViewSourceMode(true);
2592}
2593
2594void RenderView::OnUpdateBackForwardListCount(int back_list_count,
2595 int forward_list_count) {
2596 history_back_list_count_ = back_list_count;
2597 history_forward_list_count_ = forward_list_count;
2598}
2599
[email protected]266eb6f2008-09-30 23:56:502600void RenderView::OnGetAccessibilityInfo(
2601 const ViewMsg_Accessibility_In_Params& in_params,
2602 ViewHostMsg_Accessibility_Out_Params* out_params) {
2603
2604 if (!glue_accessibility_.get())
2605 glue_accessibility_.reset(new GlueAccessibility());
2606
2607 if (!glue_accessibility_->
2608 GetAccessibilityInfo(webview(), in_params, out_params)) {
2609 return;
2610 }
2611}
2612
2613void RenderView::OnClearAccessibilityInfo(int iaccessible_id, bool clear_all) {
2614 if (!glue_accessibility_.get()) {
2615 // If accessibility is not activated, ignore clearing message.
2616 return;
2617 }
2618
2619 if (!glue_accessibility_->ClearIAccessibleMap(iaccessible_id, clear_all))
2620 return;
2621}
2622
initial.commit09911bf2008-07-26 23:55:292623void RenderView::OnGetAllSavableResourceLinksForCurrentPage(
2624 const GURL& page_url) {
2625 // Prepare list to storage all savable resource links.
2626 std::vector<GURL> resources_list;
2627 std::vector<GURL> referrers_list;
2628 std::vector<GURL> frames_list;
2629 webkit_glue::SavableResourcesResult result(&resources_list,
2630 &referrers_list,
2631 &frames_list);
2632
2633 if (!webkit_glue::GetAllSavableResourceLinksForCurrentPage(webview(),
2634 page_url,
2635 &result)) {
2636 // If something is wrong when collecting all savable resource links,
2637 // send empty list to embedder(browser) to tell it failed.
2638 referrers_list.clear();
2639 resources_list.clear();
2640 frames_list.clear();
2641 }
2642
2643 // Send result of all savable resource links to embedder.
2644 Send(new ViewHostMsg_SendCurrentPageAllSavableResourceLinks(routing_id_,
2645 resources_list,
2646 referrers_list,
2647 frames_list));
2648}
2649
2650void RenderView::OnGetSerializedHtmlDataForCurrentPageWithLocalLinks(
2651 const std::vector<std::wstring>& links,
2652 const std::vector<std::wstring>& local_paths,
2653 const std::wstring& local_directory_name) {
2654 webkit_glue::DomSerializer dom_serializer(webview()->GetMainFrame(),
2655 true,
2656 this,
2657 links,
2658 local_paths,
2659 local_directory_name);
2660 dom_serializer.SerializeDom();
2661}
2662
2663void RenderView::DidSerializeDataForFrame(const GURL& frame_url,
2664 const std::string& data, PageSavingSerializationStatus status) {
2665 Send(new ViewHostMsg_SendSerializedHtmlData(routing_id_,
2666 frame_url, data, static_cast<int32>(status)));
2667}
2668
[email protected]04b4a6c2008-08-02 00:44:472669void RenderView::OnMsgShouldClose() {
initial.commit09911bf2008-07-26 23:55:292670 bool should_close = webview()->ShouldClose();
[email protected]04b4a6c2008-08-02 00:44:472671 Send(new ViewHostMsg_ShouldClose_ACK(routing_id_, should_close));
initial.commit09911bf2008-07-26 23:55:292672}
2673
2674void RenderView::OnClosePage(int new_render_process_host_id,
[email protected]04b4a6c2008-08-02 00:44:472675 int new_request_id) {
initial.commit09911bf2008-07-26 23:55:292676 // TODO(creis): We'd rather use webview()->Close() here, but that currently
2677 // sets the WebView's delegate_ to NULL, preventing any JavaScript dialogs
2678 // in the onunload handler from appearing. For now, we're bypassing that and
2679 // calling the FrameLoader's CloseURL method directly. This should be
2680 // revisited to avoid having two ways to close a page. Having a single way
2681 // to close that can run onunload is also useful for fixing
2682 // http://b/issue?id=753080.
2683 WebFrame* main_frame = webview()->GetMainFrame();
2684 if (main_frame)
2685 main_frame->ClosePage();
2686
2687 Send(new ViewHostMsg_ClosePage_ACK(routing_id_,
2688 new_render_process_host_id,
[email protected]04b4a6c2008-08-02 00:44:472689 new_request_id));
initial.commit09911bf2008-07-26 23:55:292690}
2691
2692void RenderView::OnThemeChanged() {
2693 gfx::NativeTheme::instance()->CloseHandles();
2694 gfx::Rect view_rect(0, 0, size_.width(), size_.height());
2695 DidInvalidateRect(webwidget_, view_rect);
2696}
2697
[email protected]f386cca792008-08-26 02:02:182698#ifdef CHROME_PERSONALIZATION
[email protected]1cc879642008-08-26 01:27:352699void RenderView::OnPersonalizationEvent(std::string event_name,
2700 std::string event_args) {
2701 Personalization::HandleViewMsgPersonalizationEvent(personalization_,
2702 webview(),
2703 event_name,
2704 event_args);
2705}
[email protected]f386cca792008-08-26 02:02:182706#endif
[email protected]1cc879642008-08-26 01:27:352707
2708void RenderView::TransitionToCommittedForNewPage() {
[email protected]f386cca792008-08-26 02:02:182709#ifdef CHROME_PERSONALIZATION
[email protected]1cc879642008-08-26 01:27:352710 Personalization::HandleTransitionToCommittedForNewPage(personalization_);
[email protected]f386cca792008-08-26 02:02:182711#endif
[email protected]1cc879642008-08-26 01:27:352712}
2713
[email protected]f46aff62008-10-16 07:58:052714void RenderView::DidAddHistoryItem() {
[email protected]f8901082008-10-31 23:34:032715 // We don't want to update the history length for the start page
2716 // navigation.
2717 WebFrame* main_frame = webview()->GetMainFrame();
2718 DCHECK(main_frame != NULL);
2719
2720 WebDataSource* ds = main_frame->GetDataSource();
2721 DCHECK(ds != NULL);
2722
2723 const WebRequest& request = ds->GetRequest();
2724 RenderViewExtraRequestData* extra_data =
2725 static_cast<RenderViewExtraRequestData*>(request.GetExtraData());
2726
2727 if (extra_data && extra_data->transition_type == PageTransition::START_PAGE)
2728 return;
2729
[email protected]f46aff62008-10-16 07:58:052730 history_back_list_count_++;
2731 history_forward_list_count_ = 0;
2732}
2733
[email protected]18cb2572008-08-21 20:34:452734void RenderView::OnMessageFromExternalHost(
2735 const std::string& target, const std::string& message) {
[email protected]3ac14a052008-08-15 21:22:152736 if (message.empty())
2737 return;
2738
2739 WebFrame* main_frame = webview()->GetMainFrame();
2740 if (!main_frame)
2741 return;
2742
2743 std::string script = "javascript:";
2744 script += target;
2745 script += "(";
2746 script += "'";
2747 script += message;
2748 script += "'";
2749 script += ");void(0);";
2750
2751 GURL script_url(script);
2752 scoped_ptr<WebRequest> request(WebRequest::Create(script_url));
2753 // TODO(iyengar)
2754 // Need a mechanism to send results back.
2755 main_frame->LoadRequest(request.get());
2756}
2757
[email protected]0aa55312008-10-17 21:53:082758void RenderView::OnDisassociateFromPopupCount() {
2759 if (decrement_shared_popup_at_destruction_)
2760 shared_popup_counter_->data--;
2761 shared_popup_counter_ = new SharedRenderViewCounter(0);
2762 decrement_shared_popup_at_destruction_ = false;
2763}
2764
initial.commit09911bf2008-07-26 23:55:292765std::string RenderView::GetAltHTMLForTemplate(
2766 const DictionaryValue& error_strings, int template_resource_id) const {
2767 const StringPiece template_html(
2768 ResourceBundle::GetSharedInstance().GetRawDataResource(
2769 template_resource_id));
2770
2771 if (template_html.empty()) {
2772 NOTREACHED() << "unable to load template. ID: " << template_resource_id;
2773 return "";
2774 }
2775 // "t" is the id of the templates root node.
2776 return jstemplate_builder::GetTemplateHtml(
2777 template_html, &error_strings, "t");
2778}