Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: chrome/browser/renderer_host/render_view_host.cc

Issue 6532073: Move core pieces of browser\renderer_host to src\content. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 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.
4
5 #include "chrome/browser/renderer_host/render_view_host.h"
6
7 #include <string>
8 #include <utility>
9 #include <vector>
10
11 #include "base/command_line.h"
12 #include "base/i18n/rtl.h"
13 #include "base/json/json_reader.h"
14 #include "base/string_util.h"
15 #include "base/time.h"
16 #include "base/utf_string_conversions.h"
17 #include "base/values.h"
18 #include "chrome/browser/child_process_security_policy.h"
19 #include "chrome/browser/cross_site_request_manager.h"
20 #include "chrome/browser/debugger/devtools_manager.h"
21 #include "chrome/browser/dom_operation_notification_details.h"
22 #include "chrome/browser/extensions/extension_message_service.h"
23 #include "chrome/browser/in_process_webkit/session_storage_namespace.h"
24 #include "chrome/browser/metrics/user_metrics.h"
25 #include "chrome/browser/net/predictor_api.h"
26 #include "chrome/browser/profiles/profile.h"
27 #include "chrome/browser/renderer_host/render_process_host.h"
28 #include "chrome/browser/renderer_host/render_view_host_delegate.h"
29 #include "chrome/browser/renderer_host/render_widget_host.h"
30 #include "chrome/browser/renderer_host/render_widget_host_view.h"
31 #include "chrome/browser/renderer_host/site_instance.h"
32 #include "chrome/common/bindings_policy.h"
33 #include "chrome/common/chrome_constants.h"
34 #include "chrome/common/chrome_switches.h"
35 #include "chrome/common/native_web_keyboard_event.h"
36 #include "chrome/common/net/url_request_context_getter.h"
37 #include "chrome/common/notification_details.h"
38 #include "chrome/common/notification_service.h"
39 #include "chrome/common/notification_type.h"
40 #include "chrome/common/render_messages.h"
41 #include "chrome/common/render_messages_params.h"
42 #include "chrome/common/result_codes.h"
43 #include "chrome/common/thumbnail_score.h"
44 #include "chrome/common/translate_errors.h"
45 #include "chrome/common/url_constants.h"
46 #include "chrome/common/web_apps.h"
47 #include "net/base/net_util.h"
48 #include "printing/native_metafile.h"
49 #include "third_party/skia/include/core/SkBitmap.h"
50 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFindOptions.h"
51 #include "ui/gfx/native_widget_types.h"
52 #include "webkit/glue/context_menu.h"
53 #include "webkit/glue/webaccessibility.h"
54 #include "webkit/glue/webdropdata.h"
55
56 using base::TimeDelta;
57 using WebKit::WebConsoleMessage;
58 using WebKit::WebDragOperation;
59 using WebKit::WebDragOperationNone;
60 using WebKit::WebDragOperationsMask;
61 using WebKit::WebFindOptions;
62 using WebKit::WebInputEvent;
63 using WebKit::WebMediaPlayerAction;
64 using WebKit::WebTextDirection;
65
66 namespace {
67
68 // Delay to wait on closing the tab for a beforeunload/unload handler to fire.
69 const int kUnloadTimeoutMS = 1000;
70
71 } // namespace
72
73 ///////////////////////////////////////////////////////////////////////////////
74 // RenderViewHost, public:
75
76 // static
77 RenderViewHost* RenderViewHost::FromID(int render_process_id,
78 int render_view_id) {
79 RenderProcessHost* process = RenderProcessHost::FromID(render_process_id);
80 if (!process)
81 return NULL;
82 RenderWidgetHost* widget = static_cast<RenderWidgetHost*>(
83 process->GetListenerByID(render_view_id));
84 if (!widget || !widget->IsRenderView())
85 return NULL;
86 return static_cast<RenderViewHost*>(widget);
87 }
88
89 RenderViewHost::RenderViewHost(SiteInstance* instance,
90 RenderViewHostDelegate* delegate,
91 int routing_id,
92 SessionStorageNamespace* session_storage)
93 : RenderWidgetHost(instance->GetProcess(), routing_id),
94 instance_(instance),
95 delegate_(delegate),
96 waiting_for_drag_context_response_(false),
97 enabled_bindings_(0),
98 pending_request_id_(0),
99 navigations_suspended_(false),
100 suspended_nav_message_(NULL),
101 run_modal_reply_msg_(NULL),
102 is_waiting_for_beforeunload_ack_(false),
103 is_waiting_for_unload_ack_(false),
104 unload_ack_is_for_cross_site_transition_(false),
105 are_javascript_messages_suppressed_(false),
106 sudden_termination_allowed_(false),
107 session_storage_namespace_(session_storage),
108 is_extension_process_(false),
109 save_accessibility_tree_for_testing_(false),
110 render_view_termination_status_(base::TERMINATION_STATUS_STILL_RUNNING) {
111 if (!session_storage_namespace_) {
112 session_storage_namespace_ =
113 new SessionStorageNamespace(process()->profile());
114 }
115
116 DCHECK(instance_);
117 DCHECK(delegate_);
118 }
119
120 RenderViewHost::~RenderViewHost() {
121 delegate()->RenderViewDeleted(this);
122
123 // Be sure to clean up any leftover state from cross-site requests.
124 CrossSiteRequestManager::GetInstance()->SetHasPendingCrossSiteRequest(
125 process()->id(), routing_id(), false);
126 }
127
128 bool RenderViewHost::CreateRenderView(const string16& frame_name) {
129 DCHECK(!IsRenderViewLive()) << "Creating view twice";
130
131 // The process may (if we're sharing a process with another host that already
132 // initialized it) or may not (we have our own process or the old process
133 // crashed) have been initialized. Calling Init multiple times will be
134 // ignored, so this is safe.
135 if (!process()->Init(renderer_accessible(), is_extension_process_))
136 return false;
137 DCHECK(process()->HasConnection());
138 DCHECK(process()->profile());
139
140 if (BindingsPolicy::is_web_ui_enabled(enabled_bindings_)) {
141 ChildProcessSecurityPolicy::GetInstance()->GrantWebUIBindings(
142 process()->id());
143 }
144
145 if (BindingsPolicy::is_extension_enabled(enabled_bindings_)) {
146 ChildProcessSecurityPolicy::GetInstance()->GrantExtensionBindings(
147 process()->id());
148
149 // Extensions may have permission to access chrome:// URLs.
150 ChildProcessSecurityPolicy::GetInstance()->GrantScheme(
151 process()->id(), chrome::kChromeUIScheme);
152 }
153
154 renderer_initialized_ = true;
155
156 ViewMsg_New_Params params;
157 params.parent_window = GetNativeViewId();
158 params.renderer_preferences =
159 delegate_->GetRendererPrefs(process()->profile());
160 params.web_preferences = delegate_->GetWebkitPrefs();
161 params.view_id = routing_id();
162 params.session_storage_namespace_id = session_storage_namespace_->id();
163 params.frame_name = frame_name;
164 Send(new ViewMsg_New(params));
165
166 // Set the alternate error page, which is profile specific, in the renderer.
167 GURL url = delegate_->GetAlternateErrorPageURL();
168 SetAlternateErrorPageURL(url);
169
170 // If it's enabled, tell the renderer to set up the Javascript bindings for
171 // sending messages back to the browser.
172 Send(new ViewMsg_AllowBindings(routing_id(), enabled_bindings_));
173 UpdateBrowserWindowId(delegate_->GetBrowserWindowID());
174 Send(new ViewMsg_NotifyRenderViewType(routing_id(),
175 delegate_->GetRenderViewType()));
176 // Let our delegate know that we created a RenderView.
177 delegate_->RenderViewCreated(this);
178 process()->ViewCreated();
179
180 return true;
181 }
182
183 bool RenderViewHost::IsRenderViewLive() const {
184 return process()->HasConnection() && renderer_initialized_;
185 }
186
187 void RenderViewHost::SyncRendererPrefs() {
188 Send(new ViewMsg_SetRendererPrefs(routing_id(),
189 delegate_->GetRendererPrefs(
190 process()->profile())));
191 }
192
193 void RenderViewHost::Navigate(const ViewMsg_Navigate_Params& params) {
194 ChildProcessSecurityPolicy::GetInstance()->GrantRequestURL(
195 process()->id(), params.url);
196
197 ViewMsg_Navigate* nav_message = new ViewMsg_Navigate(routing_id(), params);
198
199 // Only send the message if we aren't suspended at the start of a cross-site
200 // request.
201 if (navigations_suspended_) {
202 // Shouldn't be possible to have a second navigation while suspended, since
203 // navigations will only be suspended during a cross-site request. If a
204 // second navigation occurs, TabContents will cancel this pending RVH
205 // create a new pending RVH.
206 DCHECK(!suspended_nav_message_.get());
207 suspended_nav_message_.reset(nav_message);
208 } else {
209 // Unset this, otherwise if true and the hang monitor fires we'll
210 // incorrectly close the tab.
211 is_waiting_for_unload_ack_ = false;
212
213 Send(nav_message);
214
215 // Force the throbber to start. We do this because WebKit's "started
216 // loading" message will be received asynchronously from the UI of the
217 // browser. But we want to keep the throbber in sync with what's happening
218 // in the UI. For example, we want to start throbbing immediately when the
219 // user naivgates even if the renderer is delayed. There is also an issue
220 // with the throbber starting because the WebUI (which controls whether the
221 // favicon is displayed) happens synchronously. If the start loading
222 // messages was asynchronous, then the default favicon would flash in.
223 //
224 // WebKit doesn't send throb notifications for JavaScript URLs, so we
225 // don't want to either.
226 if (!params.url.SchemeIs(chrome::kJavaScriptScheme))
227 delegate_->DidStartLoading();
228 }
229 const GURL& url = params.url;
230 if (!delegate_->IsExternalTabContainer() &&
231 (url.SchemeIs("http") || url.SchemeIs("https")))
232 chrome_browser_net::PreconnectUrlAndSubresources(url);
233 }
234
235 void RenderViewHost::NavigateToURL(const GURL& url) {
236 ViewMsg_Navigate_Params params;
237 params.page_id = -1;
238 params.url = url;
239 params.transition = PageTransition::LINK;
240 params.navigation_type = ViewMsg_Navigate_Params::NORMAL;
241 Navigate(params);
242 }
243
244 void RenderViewHost::SetNavigationsSuspended(bool suspend) {
245 // This should only be called to toggle the state.
246 DCHECK(navigations_suspended_ != suspend);
247
248 navigations_suspended_ = suspend;
249 if (!suspend && suspended_nav_message_.get()) {
250 // There's a navigation message waiting to be sent. Now that we're not
251 // suspended anymore, resume navigation by sending it.
252 Send(suspended_nav_message_.release());
253 }
254 }
255
256 void RenderViewHost::FirePageBeforeUnload(bool for_cross_site_transition) {
257 if (!IsRenderViewLive()) {
258 // This RenderViewHost doesn't have a live renderer, so just skip running
259 // the onbeforeunload handler.
260 is_waiting_for_beforeunload_ack_ = true; // Checked by OnMsgShouldCloseACK.
261 unload_ack_is_for_cross_site_transition_ = for_cross_site_transition;
262 OnMsgShouldCloseACK(true);
263 return;
264 }
265
266 // This may be called more than once (if the user clicks the tab close button
267 // several times, or if she clicks the tab close button then the browser close
268 // button), and we only send the message once.
269 if (is_waiting_for_beforeunload_ack_) {
270 // Some of our close messages could be for the tab, others for cross-site
271 // transitions. We always want to think it's for closing the tab if any
272 // of the messages were, since otherwise it might be impossible to close
273 // (if there was a cross-site "close" request pending when the user clicked
274 // the close button). We want to keep the "for cross site" flag only if
275 // both the old and the new ones are also for cross site.
276 unload_ack_is_for_cross_site_transition_ =
277 unload_ack_is_for_cross_site_transition_ && for_cross_site_transition;
278 } else {
279 // Start the hang monitor in case the renderer hangs in the beforeunload
280 // handler.
281 is_waiting_for_beforeunload_ack_ = true;
282 unload_ack_is_for_cross_site_transition_ = for_cross_site_transition;
283 StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
284 Send(new ViewMsg_ShouldClose(routing_id()));
285 }
286 }
287
288 void RenderViewHost::ClosePage(bool for_cross_site_transition,
289 int new_render_process_host_id,
290 int new_request_id) {
291 // In most cases, this will not be set to false afterward. Either the tab
292 // will be closed, or a pending RenderViewHost will replace this one.
293 is_waiting_for_unload_ack_ = true;
294 // Start the hang monitor in case the renderer hangs in the unload handler.
295 StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
296
297 ViewMsg_ClosePage_Params params;
298 params.closing_process_id = process()->id();
299 params.closing_route_id = routing_id();
300 params.for_cross_site_transition = for_cross_site_transition;
301 params.new_render_process_host_id = new_render_process_host_id;
302 params.new_request_id = new_request_id;
303 if (IsRenderViewLive()) {
304 NotificationService::current()->Notify(
305 NotificationType::RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW,
306 Source<RenderViewHost>(this),
307 NotificationService::NoDetails());
308
309 Send(new ViewMsg_ClosePage(routing_id(), params));
310 } else {
311 // This RenderViewHost doesn't have a live renderer, so just skip closing
312 // the page. We must notify the ResourceDispatcherHost on the IO thread,
313 // which we will do through the RenderProcessHost's widget helper.
314 process()->CrossSiteClosePageACK(params);
315 }
316 }
317
318 void RenderViewHost::ClosePageIgnoringUnloadEvents() {
319 StopHangMonitorTimeout();
320 is_waiting_for_beforeunload_ack_ = false;
321 is_waiting_for_unload_ack_ = false;
322
323 sudden_termination_allowed_ = true;
324 delegate_->Close(this);
325 }
326
327 void RenderViewHost::SetHasPendingCrossSiteRequest(bool has_pending_request,
328 int request_id) {
329 CrossSiteRequestManager::GetInstance()->SetHasPendingCrossSiteRequest(
330 process()->id(), routing_id(), has_pending_request);
331 pending_request_id_ = request_id;
332 }
333
334 int RenderViewHost::GetPendingRequestId() {
335 return pending_request_id_;
336 }
337
338 RenderViewHost::CommandState RenderViewHost::GetStateForCommand(
339 RenderViewCommand command) const {
340 if (command != RENDER_VIEW_COMMAND_TOGGLE_SPELL_CHECK)
341 LOG(DFATAL) << "Unknown command " << command;
342
343 std::map<RenderViewCommand, CommandState>::const_iterator it =
344 command_states_.find(command);
345 if (it == command_states_.end()) {
346 CommandState state;
347 state.is_enabled = false;
348 state.checked_state = RENDER_VIEW_COMMAND_CHECKED_STATE_UNCHECKED;
349 return state;
350 }
351 return it->second;
352 }
353
354 void RenderViewHost::Stop() {
355 Send(new ViewMsg_Stop(routing_id()));
356 }
357
358 void RenderViewHost::ReloadFrame() {
359 Send(new ViewMsg_ReloadFrame(routing_id()));
360 }
361
362 bool RenderViewHost::PrintPages() {
363 return Send(new ViewMsg_PrintPages(routing_id()));
364 }
365
366 bool RenderViewHost::PrintPreview() {
367 return Send(new ViewMsg_PrintPreview(routing_id()));
368 }
369
370 void RenderViewHost::PrintingDone(int document_cookie, bool success) {
371 Send(new ViewMsg_PrintingDone(routing_id(), document_cookie, success));
372 }
373
374 void RenderViewHost::StartFinding(int request_id,
375 const string16& search_text,
376 bool forward,
377 bool match_case,
378 bool find_next) {
379 if (search_text.empty())
380 return;
381
382 WebFindOptions options;
383 options.forward = forward;
384 options.matchCase = match_case;
385 options.findNext = find_next;
386 Send(new ViewMsg_Find(routing_id(), request_id, search_text, options));
387
388 // This call is asynchronous and returns immediately.
389 // The result of the search is sent as a notification message by the renderer.
390 }
391
392 void RenderViewHost::StopFinding(
393 FindBarController::SelectionAction selection_action) {
394 ViewMsg_StopFinding_Params params;
395
396 switch (selection_action) {
397 case FindBarController::kClearSelection:
398 params.action = ViewMsg_StopFinding_Params::kClearSelection;
399 break;
400 case FindBarController::kKeepSelection:
401 params.action = ViewMsg_StopFinding_Params::kKeepSelection;
402 break;
403 case FindBarController::kActivateSelection:
404 params.action = ViewMsg_StopFinding_Params::kActivateSelection;
405 break;
406 default:
407 NOTREACHED();
408 params.action = ViewMsg_StopFinding_Params::kKeepSelection;
409 }
410 Send(new ViewMsg_StopFinding(routing_id(), params));
411 }
412
413 void RenderViewHost::Zoom(PageZoom::Function function) {
414 Send(new ViewMsg_Zoom(routing_id(), function));
415 }
416
417 void RenderViewHost::SetZoomLevel(double zoom_level) {
418 Send(new ViewMsg_SetZoomLevel(routing_id(), zoom_level));
419 }
420
421 void RenderViewHost::SetPageEncoding(const std::string& encoding_name) {
422 Send(new ViewMsg_SetPageEncoding(routing_id(), encoding_name));
423 }
424
425 void RenderViewHost::ResetPageEncodingToDefault() {
426 Send(new ViewMsg_ResetPageEncodingToDefault(routing_id()));
427 }
428
429 void RenderViewHost::SetAlternateErrorPageURL(const GURL& url) {
430 Send(new ViewMsg_SetAltErrorPageURL(routing_id(), url));
431 }
432
433 void RenderViewHost::DragTargetDragEnter(
434 const WebDropData& drop_data,
435 const gfx::Point& client_pt,
436 const gfx::Point& screen_pt,
437 WebDragOperationsMask operations_allowed) {
438 // Grant the renderer the ability to load the drop_data.
439 ChildProcessSecurityPolicy* policy =
440 ChildProcessSecurityPolicy::GetInstance();
441 policy->GrantRequestURL(process()->id(), drop_data.url);
442 for (std::vector<string16>::const_iterator iter(drop_data.filenames.begin());
443 iter != drop_data.filenames.end(); ++iter) {
444 FilePath path = FilePath::FromWStringHack(UTF16ToWideHack(*iter));
445 policy->GrantRequestURL(process()->id(),
446 net::FilePathToFileURL(path));
447 policy->GrantReadFile(process()->id(), path);
448 }
449 Send(new ViewMsg_DragTargetDragEnter(routing_id(), drop_data, client_pt,
450 screen_pt, operations_allowed));
451 }
452
453 void RenderViewHost::DragTargetDragOver(
454 const gfx::Point& client_pt, const gfx::Point& screen_pt,
455 WebDragOperationsMask operations_allowed) {
456 Send(new ViewMsg_DragTargetDragOver(routing_id(), client_pt, screen_pt,
457 operations_allowed));
458 }
459
460 void RenderViewHost::DragTargetDragLeave() {
461 Send(new ViewMsg_DragTargetDragLeave(routing_id()));
462 }
463
464 void RenderViewHost::DragTargetDrop(
465 const gfx::Point& client_pt, const gfx::Point& screen_pt) {
466 Send(new ViewMsg_DragTargetDrop(routing_id(), client_pt, screen_pt));
467 }
468
469 void RenderViewHost::ReservePageIDRange(int size) {
470 Send(new ViewMsg_ReservePageIDRange(routing_id(), size));
471 }
472
473 void RenderViewHost::ExecuteJavascriptInWebFrame(
474 const string16& frame_xpath,
475 const string16& jscript) {
476 Send(new ViewMsg_ScriptEvalRequest(routing_id(), frame_xpath, jscript,
477 0, false));
478 }
479
480 int RenderViewHost::ExecuteJavascriptInWebFrameNotifyResult(
481 const string16& frame_xpath,
482 const string16& jscript) {
483 static int next_id = 1;
484 Send(new ViewMsg_ScriptEvalRequest(routing_id(), frame_xpath, jscript,
485 next_id, true));
486 return next_id++;
487 }
488
489 void RenderViewHost::InsertCSSInWebFrame(
490 const std::wstring& frame_xpath,
491 const std::string& css,
492 const std::string& id) {
493 Send(new ViewMsg_CSSInsertRequest(routing_id(), frame_xpath, css, id));
494 }
495
496 void RenderViewHost::AddMessageToConsole(
497 const string16& frame_xpath,
498 const string16& message,
499 const WebConsoleMessage::Level& level) {
500 Send(new ViewMsg_AddMessageToConsole(
501 routing_id(), frame_xpath, message, level));
502 }
503
504 void RenderViewHost::Undo() {
505 Send(new ViewMsg_Undo(routing_id()));
506 }
507
508 void RenderViewHost::Redo() {
509 Send(new ViewMsg_Redo(routing_id()));
510 }
511
512 void RenderViewHost::Cut() {
513 Send(new ViewMsg_Cut(routing_id()));
514 }
515
516 void RenderViewHost::Copy() {
517 Send(new ViewMsg_Copy(routing_id()));
518 }
519
520 void RenderViewHost::CopyToFindPboard() {
521 #if defined(OS_MACOSX)
522 // Windows/Linux don't have the concept of a find pasteboard.
523 Send(new ViewMsg_CopyToFindPboard(routing_id()));
524 #endif
525 }
526
527 void RenderViewHost::Paste() {
528 Send(new ViewMsg_Paste(routing_id()));
529 }
530
531 void RenderViewHost::ToggleSpellCheck() {
532 Send(new ViewMsg_ToggleSpellCheck(routing_id()));
533 }
534
535 void RenderViewHost::Delete() {
536 Send(new ViewMsg_Delete(routing_id()));
537 }
538
539 void RenderViewHost::SelectAll() {
540 Send(new ViewMsg_SelectAll(routing_id()));
541 }
542
543 void RenderViewHost::ToggleSpellPanel(bool is_currently_visible) {
544 Send(new ViewMsg_ToggleSpellPanel(routing_id(), is_currently_visible));
545 }
546
547 int RenderViewHost::DownloadFavIcon(const GURL& url, int image_size) {
548 if (!url.is_valid()) {
549 NOTREACHED();
550 return 0;
551 }
552 static int next_id = 1;
553 int id = next_id++;
554 Send(new ViewMsg_DownloadFavIcon(routing_id(), id, url, image_size));
555 return id;
556 }
557
558 void RenderViewHost::GetApplicationInfo(int32 page_id) {
559 Send(new ViewMsg_GetApplicationInfo(routing_id(), page_id));
560 }
561
562 void RenderViewHost::CaptureThumbnail() {
563 Send(new ViewMsg_CaptureThumbnail(routing_id()));
564 }
565
566 void RenderViewHost::CaptureSnapshot() {
567 Send(new ViewMsg_CaptureSnapshot(routing_id()));
568 }
569
570 void RenderViewHost::JavaScriptMessageBoxClosed(IPC::Message* reply_msg,
571 bool success,
572 const std::wstring& prompt) {
573 process()->set_ignore_input_events(false);
574 bool is_waiting =
575 is_waiting_for_beforeunload_ack_ || is_waiting_for_unload_ack_;
576 if (is_waiting)
577 StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
578
579 ViewHostMsg_RunJavaScriptMessage::WriteReplyParams(reply_msg,
580 success, prompt);
581 Send(reply_msg);
582
583 // If we are waiting for an unload or beforeunload ack and the user has
584 // suppressed messages, kill the tab immediately; a page that's spamming
585 // alerts in onbeforeunload is presumably malicious, so there's no point in
586 // continuing to run its script and dragging out the process.
587 // This must be done after sending the reply since RenderView can't close
588 // correctly while waiting for a response.
589 if (is_waiting && are_javascript_messages_suppressed_)
590 delegate_->RendererUnresponsive(this, is_waiting);
591 }
592
593 void RenderViewHost::ModalHTMLDialogClosed(IPC::Message* reply_msg,
594 const std::string& json_retval) {
595 if (is_waiting_for_beforeunload_ack_ || is_waiting_for_unload_ack_)
596 StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
597
598 ViewHostMsg_ShowModalHTMLDialog::WriteReplyParams(reply_msg, json_retval);
599 Send(reply_msg);
600 }
601
602 void RenderViewHost::CopyImageAt(int x, int y) {
603 Send(new ViewMsg_CopyImageAt(routing_id(), x, y));
604 }
605
606 void RenderViewHost::DragSourceEndedAt(
607 int client_x, int client_y, int screen_x, int screen_y,
608 WebDragOperation operation) {
609 Send(new ViewMsg_DragSourceEndedOrMoved(
610 routing_id(),
611 gfx::Point(client_x, client_y),
612 gfx::Point(screen_x, screen_y),
613 true, operation));
614 }
615
616 void RenderViewHost::DragSourceMovedTo(
617 int client_x, int client_y, int screen_x, int screen_y) {
618 Send(new ViewMsg_DragSourceEndedOrMoved(
619 routing_id(),
620 gfx::Point(client_x, client_y),
621 gfx::Point(screen_x, screen_y),
622 false, WebDragOperationNone));
623 }
624
625 void RenderViewHost::DragSourceSystemDragEnded() {
626 Send(new ViewMsg_DragSourceSystemDragEnded(routing_id()));
627 }
628
629 void RenderViewHost::AllowBindings(int bindings_flags) {
630 DCHECK(!renderer_initialized_);
631 enabled_bindings_ |= bindings_flags;
632 }
633
634 void RenderViewHost::SetWebUIProperty(const std::string& name,
635 const std::string& value) {
636 DCHECK(BindingsPolicy::is_web_ui_enabled(enabled_bindings_));
637 Send(new ViewMsg_SetWebUIProperty(routing_id(), name, value));
638 }
639
640 void RenderViewHost::GotFocus() {
641 RenderWidgetHost::GotFocus(); // Notifies the renderer it got focus.
642
643 RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
644 if (view)
645 view->GotFocus();
646 }
647
648 void RenderViewHost::LostCapture() {
649 RenderWidgetHost::LostCapture();
650
651 RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
652 if (view)
653 view->LostCapture();
654 }
655
656 void RenderViewHost::SetInitialFocus(bool reverse) {
657 Send(new ViewMsg_SetInitialFocus(routing_id(), reverse));
658 }
659
660 void RenderViewHost::ClearFocusedNode() {
661 Send(new ViewMsg_ClearFocusedNode(routing_id()));
662 }
663
664 void RenderViewHost::ScrollFocusedEditableNodeIntoView() {
665 Send(new ViewMsg_ScrollFocusedEditableNodeIntoView(routing_id()));
666 }
667
668 void RenderViewHost::UpdateWebPreferences(const WebPreferences& prefs) {
669 Send(new ViewMsg_UpdateWebPreferences(routing_id(), prefs));
670 }
671
672 void RenderViewHost::InstallMissingPlugin() {
673 Send(new ViewMsg_InstallMissingPlugin(routing_id()));
674 }
675
676 void RenderViewHost::LoadBlockedPlugins() {
677 Send(new ViewMsg_LoadBlockedPlugins(routing_id()));
678 }
679
680 void RenderViewHost::FilesSelectedInChooser(
681 const std::vector<FilePath>& files) {
682 // Grant the security access requested to the given files.
683 for (std::vector<FilePath>::const_iterator file = files.begin();
684 file != files.end(); ++file) {
685 ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(
686 process()->id(), *file);
687 }
688 Send(new ViewMsg_RunFileChooserResponse(routing_id(), files));
689 }
690
691 void RenderViewHost::LoadStateChanged(const GURL& url,
692 net::LoadState load_state,
693 uint64 upload_position,
694 uint64 upload_size) {
695 delegate_->LoadStateChanged(url, load_state, upload_position, upload_size);
696 }
697
698 bool RenderViewHost::SuddenTerminationAllowed() const {
699 return sudden_termination_allowed_ || process()->sudden_termination_allowed();
700 }
701
702 ///////////////////////////////////////////////////////////////////////////////
703 // RenderViewHost, IPC message handlers:
704
705 bool RenderViewHost::OnMessageReceived(const IPC::Message& msg) {
706 #if defined(OS_WIN)
707 // On Windows there's a potential deadlock with sync messsages going in
708 // a circle from browser -> plugin -> renderer -> browser.
709 // On Linux we can avoid this by avoiding sync messages from browser->plugin.
710 // On Mac we avoid this by not supporting windowed plugins.
711 if (msg.is_sync() && !msg.is_caller_pumping_messages()) {
712 // NOTE: IF YOU HIT THIS ASSERT, THE SOLUTION IS ALMOST NEVER TO RUN A
713 // NESTED MESSAGE LOOP IN THE RENDERER!!!
714 // That introduces reentrancy which causes hard to track bugs. You should
715 // find a way to either turn this into an asynchronous message, or one
716 // that can be answered on the IO thread.
717 NOTREACHED() << "Can't send sync messages to UI thread without pumping "
718 "messages in the renderer or else deadlocks can occur if the page "
719 "has windowed plugins! (message type " << msg.type() << ")";
720 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg);
721 reply->set_reply_error();
722 Send(reply);
723 return true;
724 }
725 #endif
726
727 if (delegate_->OnMessageReceived(msg))
728 return true;
729
730 bool handled = true;
731 bool msg_is_ok = true;
732 IPC_BEGIN_MESSAGE_MAP_EX(RenderViewHost, msg, msg_is_ok)
733 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowView, OnMsgShowView)
734 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnMsgShowWidget)
735 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowFullscreenWidget,
736 OnMsgShowFullscreenWidget)
737 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_RunModal, OnMsgRunModal)
738 IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewReady, OnMsgRenderViewReady)
739 IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewGone, OnMsgRenderViewGone)
740 IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_FrameNavigate, OnMsgNavigate(msg))
741 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateState, OnMsgUpdateState)
742 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateTitle, OnMsgUpdateTitle)
743 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateEncoding, OnMsgUpdateEncoding)
744 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateTargetURL, OnMsgUpdateTargetURL)
745 IPC_MESSAGE_HANDLER(ViewHostMsg_Thumbnail, OnMsgThumbnail)
746 IPC_MESSAGE_HANDLER(ViewHostMsg_Snapshot, OnMsgScreenshot)
747 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateInspectorSetting,
748 OnUpdateInspectorSetting)
749 IPC_MESSAGE_HANDLER(ViewHostMsg_Close, OnMsgClose)
750 IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove, OnMsgRequestMove)
751 IPC_MESSAGE_HANDLER(ViewHostMsg_DidStartLoading, OnMsgDidStartLoading)
752 IPC_MESSAGE_HANDLER(ViewHostMsg_DidStopLoading, OnMsgDidStopLoading)
753 IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeLoadProgress,
754 OnMsgDidChangeLoadProgress)
755 IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentAvailableInMainFrame,
756 OnMsgDocumentAvailableInMainFrame)
757 IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentOnLoadCompletedInMainFrame,
758 OnMsgDocumentOnLoadCompletedInMainFrame)
759 IPC_MESSAGE_HANDLER(ViewMsg_ExecuteCodeFinished,
760 OnExecuteCodeFinished)
761 IPC_MESSAGE_HANDLER(ViewHostMsg_ContextMenu, OnMsgContextMenu)
762 IPC_MESSAGE_HANDLER(ViewHostMsg_OpenURL, OnMsgOpenURL)
763 IPC_MESSAGE_HANDLER(ViewHostMsg_DidContentsPreferredSizeChange,
764 OnMsgDidContentsPreferredSizeChange)
765 IPC_MESSAGE_HANDLER(ViewHostMsg_DomOperationResponse,
766 OnMsgDomOperationResponse)
767 IPC_MESSAGE_HANDLER(ViewHostMsg_WebUISend, OnMsgWebUISend)
768 IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardMessageToExternalHost,
769 OnMsgForwardMessageToExternalHost)
770 IPC_MESSAGE_HANDLER(ViewHostMsg_SetTooltipText, OnMsgSetTooltipText)
771 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_RunJavaScriptMessage,
772 OnMsgRunJavaScriptMessage)
773 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_RunBeforeUnloadConfirm,
774 OnMsgRunBeforeUnloadConfirm)
775 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ShowModalHTMLDialog,
776 OnMsgShowModalHTMLDialog)
777 IPC_MESSAGE_HANDLER(ViewHostMsg_StartDragging, OnMsgStartDragging)
778 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateDragCursor, OnUpdateDragCursor)
779 IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
780 IPC_MESSAGE_HANDLER(ViewHostMsg_AddMessageToConsole, OnAddMessageToConsole)
781 IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardToDevToolsAgent,
782 OnForwardToDevToolsAgent)
783 IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardToDevToolsClient,
784 OnForwardToDevToolsClient)
785 IPC_MESSAGE_HANDLER(ViewHostMsg_ActivateDevToolsWindow,
786 OnActivateDevToolsWindow)
787 IPC_MESSAGE_HANDLER(ViewHostMsg_CloseDevToolsWindow,
788 OnCloseDevToolsWindow)
789 IPC_MESSAGE_HANDLER(ViewHostMsg_RequestDockDevToolsWindow,
790 OnRequestDockDevToolsWindow)
791 IPC_MESSAGE_HANDLER(ViewHostMsg_RequestUndockDevToolsWindow,
792 OnRequestUndockDevToolsWindow)
793 IPC_MESSAGE_HANDLER(ViewHostMsg_DevToolsRuntimePropertyChanged,
794 OnDevToolsRuntimePropertyChanged)
795 IPC_MESSAGE_HANDLER(ViewHostMsg_ShouldClose_ACK, OnMsgShouldCloseACK)
796 IPC_MESSAGE_HANDLER(ViewHostMsg_ExtensionRequest, OnExtensionRequest)
797 IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionChanged, OnMsgSelectionChanged)
798 IPC_MESSAGE_HANDLER(ViewHostMsg_ExtensionPostMessage,
799 OnExtensionPostMessage)
800 IPC_MESSAGE_HANDLER(ViewHostMsg_AccessibilityNotifications,
801 OnAccessibilityNotifications)
802 IPC_MESSAGE_HANDLER(ViewHostMsg_OnCSSInserted, OnCSSInserted)
803 IPC_MESSAGE_HANDLER(ViewHostMsg_ContentBlocked, OnContentBlocked)
804 IPC_MESSAGE_HANDLER(ViewHostMsg_AppCacheAccessed, OnAppCacheAccessed)
805 IPC_MESSAGE_HANDLER(ViewHostMsg_WebDatabaseAccessed, OnWebDatabaseAccessed)
806 IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeChanged, OnMsgFocusedNodeChanged)
807 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateZoomLimits, OnUpdateZoomLimits)
808 IPC_MESSAGE_HANDLER(ViewHostMsg_ScriptEvalResponse, OnScriptEvalResponse)
809 #if defined(OS_MACOSX)
810 IPC_MESSAGE_HANDLER(ViewHostMsg_ShowPopup, OnMsgShowPopup)
811 #endif
812 IPC_MESSAGE_HANDLER(ViewHostMsg_CommandStateChanged,
813 OnCommandStateChanged)
814 // Have the super handle all other messages.
815 IPC_MESSAGE_UNHANDLED(handled = RenderWidgetHost::OnMessageReceived(msg))
816 IPC_END_MESSAGE_MAP_EX()
817
818 if (!msg_is_ok) {
819 // The message had a handler, but its de-serialization failed.
820 // Kill the renderer.
821 UserMetrics::RecordAction(UserMetricsAction("BadMessageTerminate_RVH"));
822 process()->ReceivedBadMessage();
823 }
824
825 return handled;
826 }
827
828 void RenderViewHost::Shutdown() {
829 // If we are being run modally (see RunModal), then we need to cleanup.
830 if (run_modal_reply_msg_) {
831 Send(run_modal_reply_msg_);
832 run_modal_reply_msg_ = NULL;
833 }
834
835 DevToolsManager* devtools_manager = DevToolsManager::GetInstance();
836 if (devtools_manager) // NULL in tests
837 devtools_manager->UnregisterDevToolsClientHostFor(this);
838
839 RenderWidgetHost::Shutdown();
840 }
841
842 bool RenderViewHost::IsRenderView() const {
843 return true;
844 }
845
846 void RenderViewHost::CreateNewWindow(
847 int route_id,
848 const ViewHostMsg_CreateWindow_Params& params) {
849 RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
850 if (!view)
851 return;
852
853 view->CreateNewWindow(route_id, params);
854 }
855
856 void RenderViewHost::CreateNewWidget(int route_id,
857 WebKit::WebPopupType popup_type) {
858 RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
859 if (view)
860 view->CreateNewWidget(route_id, popup_type);
861 }
862
863 void RenderViewHost::CreateNewFullscreenWidget(int route_id) {
864 RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
865 if (view)
866 view->CreateNewFullscreenWidget(route_id);
867 }
868
869 void RenderViewHost::OnMsgShowView(int route_id,
870 WindowOpenDisposition disposition,
871 const gfx::Rect& initial_pos,
872 bool user_gesture) {
873 RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
874 if (view) {
875 view->ShowCreatedWindow(route_id, disposition, initial_pos, user_gesture);
876 Send(new ViewMsg_Move_ACK(route_id));
877 }
878 }
879
880 void RenderViewHost::OnMsgShowWidget(int route_id,
881 const gfx::Rect& initial_pos) {
882 RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
883 if (view) {
884 view->ShowCreatedWidget(route_id, initial_pos);
885 Send(new ViewMsg_Move_ACK(route_id));
886 }
887 }
888
889 void RenderViewHost::OnMsgShowFullscreenWidget(int route_id) {
890 RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
891 if (view) {
892 view->ShowCreatedFullscreenWidget(route_id);
893 Send(new ViewMsg_Move_ACK(route_id));
894 }
895 }
896
897 void RenderViewHost::OnMsgRunModal(IPC::Message* reply_msg) {
898 DCHECK(!run_modal_reply_msg_);
899 run_modal_reply_msg_ = reply_msg;
900
901 // TODO(darin): Bug 1107929: Need to inform our delegate to show this view in
902 // an app-modal fashion.
903 }
904
905 void RenderViewHost::OnMsgRenderViewReady() {
906 render_view_termination_status_ = base::TERMINATION_STATUS_STILL_RUNNING;
907 WasResized();
908 delegate_->RenderViewReady(this);
909 }
910
911 void RenderViewHost::OnMsgRenderViewGone(int status, int exit_code) {
912 // Keep the termination status so we can get at it later when we
913 // need to know why it died.
914 render_view_termination_status_ =
915 static_cast<base::TerminationStatus>(status);
916
917 // Our base class RenderWidgetHost needs to reset some stuff.
918 RendererExited(render_view_termination_status_, exit_code);
919
920 delegate_->RenderViewGone(this,
921 static_cast<base::TerminationStatus>(status),
922 exit_code);
923 }
924
925 // Called when the renderer navigates. For every frame loaded, we'll get this
926 // notification containing parameters identifying the navigation.
927 //
928 // Subframes are identified by the page transition type. For subframes loaded
929 // as part of a wider page load, the page_id will be the same as for the top
930 // level frame. If the user explicitly requests a subframe navigation, we will
931 // get a new page_id because we need to create a new navigation entry for that
932 // action.
933 void RenderViewHost::OnMsgNavigate(const IPC::Message& msg) {
934 // Read the parameters out of the IPC message directly to avoid making another
935 // copy when we filter the URLs.
936 void* iter = NULL;
937 ViewHostMsg_FrameNavigate_Params validated_params;
938 if (!IPC::ParamTraits<ViewHostMsg_FrameNavigate_Params>::
939 Read(&msg, &iter, &validated_params))
940 return;
941
942 // If we're waiting for a beforeunload ack from this renderer and we receive
943 // a Navigate message from the main frame, then the renderer was navigating
944 // before it received the request. If it is during a cross-site navigation,
945 // then we should forget about the beforeunload, because the navigation will
946 // now be canceled. (If it is instead during an attempt to close the page,
947 // we should be sure to keep waiting for the ack, which the new page will
948 // send.)
949 //
950 // If we did not clear this state, an unresponsiveness timer might think we
951 // are waiting for an ack but are not in a cross-site navigation, and would
952 // close the tab. TODO(creis): That timer code should be refactored to only
953 // close the tab if we explicitly know the user tried to close the tab, and
954 // not just check for the absence of a cross-site navigation. Once that's
955 // fixed, this check can go away.
956 if (is_waiting_for_beforeunload_ack_ &&
957 unload_ack_is_for_cross_site_transition_ &&
958 PageTransition::IsMainFrame(validated_params.transition)) {
959 is_waiting_for_beforeunload_ack_ = false;
960 StopHangMonitorTimeout();
961 }
962
963 // If we're waiting for an unload ack from this renderer and we receive a
964 // Navigate message, then the renderer was navigating before it received the
965 // unload request. It will either respond to the unload request soon or our
966 // timer will expire. Either way, we should ignore this message, because we
967 // have already committed to closing this renderer.
968 if (is_waiting_for_unload_ack_)
969 return;
970
971 const int renderer_id = process()->id();
972 ChildProcessSecurityPolicy* policy =
973 ChildProcessSecurityPolicy::GetInstance();
974 // Without this check, an evil renderer can trick the browser into creating
975 // a navigation entry for a banned URL. If the user clicks the back button
976 // followed by the forward button (or clicks reload, or round-trips through
977 // session restore, etc), we'll think that the browser commanded the
978 // renderer to load the URL and grant the renderer the privileges to request
979 // the URL. To prevent this attack, we block the renderer from inserting
980 // banned URLs into the navigation controller in the first place.
981 FilterURL(policy, renderer_id, &validated_params.url);
982 FilterURL(policy, renderer_id, &validated_params.referrer);
983 for (std::vector<GURL>::iterator it(validated_params.redirects.begin());
984 it != validated_params.redirects.end(); ++it) {
985 FilterURL(policy, renderer_id, &(*it));
986 }
987 FilterURL(policy, renderer_id, &validated_params.searchable_form_url);
988 FilterURL(policy, renderer_id, &validated_params.password_form.origin);
989 FilterURL(policy, renderer_id, &validated_params.password_form.action);
990
991 delegate_->DidNavigate(this, validated_params);
992 }
993
994 void RenderViewHost::OnMsgUpdateState(int32 page_id,
995 const std::string& state) {
996 delegate_->UpdateState(this, page_id, state);
997 }
998
999 void RenderViewHost::OnMsgUpdateTitle(int32 page_id,
1000 const std::wstring& title) {
1001 if (title.length() > chrome::kMaxTitleChars) {
1002 NOTREACHED() << "Renderer sent too many characters in title.";
1003 return;
1004 }
1005 delegate_->UpdateTitle(this, page_id, title);
1006 }
1007
1008 void RenderViewHost::OnMsgUpdateEncoding(const std::string& encoding_name) {
1009 delegate_->UpdateEncoding(this, encoding_name);
1010 }
1011
1012 void RenderViewHost::OnMsgUpdateTargetURL(int32 page_id,
1013 const GURL& url) {
1014 delegate_->UpdateTargetURL(page_id, url);
1015
1016 // Send a notification back to the renderer that we are ready to
1017 // receive more target urls.
1018 Send(new ViewMsg_UpdateTargetURL_ACK(routing_id()));
1019 }
1020
1021 void RenderViewHost::OnMsgThumbnail(const GURL& url,
1022 const ThumbnailScore& score,
1023 const SkBitmap& bitmap) {
1024 delegate_->UpdateThumbnail(url, bitmap, score);
1025 }
1026
1027 void RenderViewHost::OnMsgScreenshot(const SkBitmap& bitmap) {
1028 NotificationService::current()->Notify(
1029 NotificationType::TAB_SNAPSHOT_TAKEN,
1030 Source<RenderViewHost>(this),
1031 Details<const SkBitmap>(&bitmap));
1032 }
1033
1034 void RenderViewHost::OnUpdateInspectorSetting(
1035 const std::string& key, const std::string& value) {
1036 delegate_->UpdateInspectorSetting(key, value);
1037 }
1038
1039 void RenderViewHost::OnMsgClose() {
1040 // If the renderer is telling us to close, it has already run the unload
1041 // events, and we can take the fast path.
1042 ClosePageIgnoringUnloadEvents();
1043 }
1044
1045 void RenderViewHost::OnMsgRequestMove(const gfx::Rect& pos) {
1046 delegate_->RequestMove(pos);
1047 Send(new ViewMsg_Move_ACK(routing_id()));
1048 }
1049
1050 void RenderViewHost::OnMsgDidStartLoading() {
1051 delegate_->DidStartLoading();
1052 }
1053
1054 void RenderViewHost::OnMsgDidStopLoading() {
1055 delegate_->DidStopLoading();
1056 }
1057
1058 void RenderViewHost::OnMsgDidChangeLoadProgress(double load_progress) {
1059 delegate_->DidChangeLoadProgress(load_progress);
1060 }
1061
1062 void RenderViewHost::OnMsgDocumentAvailableInMainFrame() {
1063 delegate_->DocumentAvailableInMainFrame(this);
1064 }
1065
1066 void RenderViewHost::OnMsgDocumentOnLoadCompletedInMainFrame(int32 page_id) {
1067 delegate_->DocumentOnLoadCompletedInMainFrame(this, page_id);
1068 }
1069
1070 void RenderViewHost::OnExecuteCodeFinished(int request_id, bool success) {
1071 std::pair<int, bool> result_details(request_id, success);
1072 NotificationService::current()->Notify(
1073 NotificationType::TAB_CODE_EXECUTED,
1074 NotificationService::AllSources(),
1075 Details<std::pair<int, bool> >(&result_details));
1076 }
1077
1078 void RenderViewHost::OnMsgContextMenu(const ContextMenuParams& params) {
1079 RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
1080 if (!view)
1081 return;
1082
1083 // Validate the URLs in |params|. If the renderer can't request the URLs
1084 // directly, don't show them in the context menu.
1085 ContextMenuParams validated_params(params);
1086 int renderer_id = process()->id();
1087 ChildProcessSecurityPolicy* policy =
1088 ChildProcessSecurityPolicy::GetInstance();
1089
1090 // We don't validate |unfiltered_link_url| so that this field can be used
1091 // when users want to copy the original link URL.
1092 FilterURL(policy, renderer_id, &validated_params.link_url);
1093 FilterURL(policy, renderer_id, &validated_params.src_url);
1094 FilterURL(policy, renderer_id, &validated_params.page_url);
1095 FilterURL(policy, renderer_id, &validated_params.frame_url);
1096
1097 view->ShowContextMenu(validated_params);
1098 }
1099
1100 void RenderViewHost::OnMsgOpenURL(const GURL& url,
1101 const GURL& referrer,
1102 WindowOpenDisposition disposition) {
1103 GURL validated_url(url);
1104 FilterURL(ChildProcessSecurityPolicy::GetInstance(),
1105 process()->id(), &validated_url);
1106
1107 delegate_->RequestOpenURL(validated_url, referrer, disposition);
1108 }
1109
1110 void RenderViewHost::OnMsgDidContentsPreferredSizeChange(
1111 const gfx::Size& new_size) {
1112 RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
1113 if (!view)
1114 return;
1115 view->UpdatePreferredSize(new_size);
1116 }
1117
1118 void RenderViewHost::OnMsgDomOperationResponse(
1119 const std::string& json_string, int automation_id) {
1120 delegate_->DomOperationResponse(json_string, automation_id);
1121
1122 // We also fire a notification for more loosely-coupled use cases.
1123 DomOperationNotificationDetails details(json_string, automation_id);
1124 NotificationService::current()->Notify(
1125 NotificationType::DOM_OPERATION_RESPONSE, Source<RenderViewHost>(this),
1126 Details<DomOperationNotificationDetails>(&details));
1127 }
1128
1129 void RenderViewHost::OnMsgWebUISend(
1130 const GURL& source_url, const std::string& message,
1131 const std::string& content) {
1132 if (!ChildProcessSecurityPolicy::GetInstance()->
1133 HasWebUIBindings(process()->id())) {
1134 NOTREACHED() << "Blocked unauthorized use of WebUIBindings.";
1135 return;
1136 }
1137
1138 scoped_ptr<Value> value;
1139 if (!content.empty()) {
1140 value.reset(base::JSONReader::Read(content, false));
1141 if (!value.get() || !value->IsType(Value::TYPE_LIST)) {
1142 // The page sent us something that we didn't understand.
1143 // This probably indicates a programming error.
1144 NOTREACHED() << "Invalid JSON argument in OnMsgWebUISend.";
1145 return;
1146 }
1147 }
1148
1149 ViewHostMsg_DomMessage_Params params;
1150 params.name = message;
1151 if (value.get())
1152 params.arguments.Swap(static_cast<ListValue*>(value.get()));
1153 params.source_url = source_url;
1154 // WebUI doesn't use these values yet.
1155 // TODO(aa): When WebUI is ported to ExtensionFunctionDispatcher, send real
1156 // values here.
1157 params.request_id = -1;
1158 params.has_callback = false;
1159 params.user_gesture = false;
1160 delegate_->ProcessWebUIMessage(params);
1161 }
1162
1163 void RenderViewHost::OnMsgForwardMessageToExternalHost(
1164 const std::string& message, const std::string& origin,
1165 const std::string& target) {
1166 delegate_->ProcessExternalHostMessage(message, origin, target);
1167 }
1168
1169 void RenderViewHost::DisassociateFromPopupCount() {
1170 Send(new ViewMsg_DisassociateFromPopupCount(routing_id()));
1171 }
1172
1173 void RenderViewHost::AllowScriptToClose(bool script_can_close) {
1174 Send(new ViewMsg_AllowScriptToClose(routing_id(), script_can_close));
1175 }
1176
1177 void RenderViewHost::OnMsgSetTooltipText(
1178 const std::wstring& tooltip_text,
1179 WebTextDirection text_direction_hint) {
1180 // First, add directionality marks around tooltip text if necessary.
1181 // A naive solution would be to simply always wrap the text. However, on
1182 // windows, Unicode directional embedding characters can't be displayed on
1183 // systems that lack RTL fonts and are instead displayed as empty squares.
1184 //
1185 // To get around this we only wrap the string when we deem it necessary i.e.
1186 // when the locale direction is different than the tooltip direction hint.
1187 //
1188 // Currently, we use element's directionality as the tooltip direction hint.
1189 // An alternate solution would be to set the overall directionality based on
1190 // trying to detect the directionality from the tooltip text rather than the
1191 // element direction. One could argue that would be a preferable solution
1192 // but we use the current approach to match Fx & IE's behavior.
1193 std::wstring wrapped_tooltip_text = tooltip_text;
1194 if (!tooltip_text.empty()) {
1195 if (text_direction_hint == WebKit::WebTextDirectionLeftToRight) {
1196 // Force the tooltip to have LTR directionality.
1197 wrapped_tooltip_text = UTF16ToWide(
1198 base::i18n::GetDisplayStringInLTRDirectionality(
1199 WideToUTF16(wrapped_tooltip_text)));
1200 } else if (text_direction_hint == WebKit::WebTextDirectionRightToLeft &&
1201 !base::i18n::IsRTL()) {
1202 // Force the tooltip to have RTL directionality.
1203 base::i18n::WrapStringWithRTLFormatting(&wrapped_tooltip_text);
1204 }
1205 }
1206 if (view())
1207 view()->SetTooltipText(wrapped_tooltip_text);
1208 }
1209
1210 void RenderViewHost::OnMsgSelectionChanged(const std::string& text) {
1211 if (view())
1212 view()->SelectionChanged(text);
1213 }
1214
1215 void RenderViewHost::OnMsgRunJavaScriptMessage(
1216 const std::wstring& message,
1217 const std::wstring& default_prompt,
1218 const GURL& frame_url,
1219 const int flags,
1220 IPC::Message* reply_msg) {
1221 // While a JS message dialog is showing, tabs in the same process shouldn't
1222 // process input events.
1223 process()->set_ignore_input_events(true);
1224 StopHangMonitorTimeout();
1225 delegate_->RunJavaScriptMessage(message, default_prompt, frame_url, flags,
1226 reply_msg,
1227 &are_javascript_messages_suppressed_);
1228 }
1229
1230 void RenderViewHost::OnMsgRunBeforeUnloadConfirm(const GURL& frame_url,
1231 const std::wstring& message,
1232 IPC::Message* reply_msg) {
1233 // While a JS before unload dialog is showing, tabs in the same process
1234 // shouldn't process input events.
1235 process()->set_ignore_input_events(true);
1236 StopHangMonitorTimeout();
1237 delegate_->RunBeforeUnloadConfirm(message, reply_msg);
1238 }
1239
1240 void RenderViewHost::OnMsgShowModalHTMLDialog(
1241 const GURL& url, int width, int height, const std::string& json_arguments,
1242 IPC::Message* reply_msg) {
1243 StopHangMonitorTimeout();
1244 delegate_->ShowModalHTMLDialog(url, width, height, json_arguments, reply_msg);
1245 }
1246
1247 void RenderViewHost::MediaPlayerActionAt(const gfx::Point& location,
1248 const WebMediaPlayerAction& action) {
1249 // TODO(ajwong): Which thread should run this? Does it matter?
1250 Send(new ViewMsg_MediaPlayerActionAt(routing_id(), location, action));
1251 }
1252
1253 void RenderViewHost::ContextMenuClosed(
1254 const webkit_glue::CustomContextMenuContext& custom_context) {
1255 Send(new ViewMsg_ContextMenuClosed(routing_id(), custom_context));
1256 }
1257
1258 void RenderViewHost::PrintNodeUnderContextMenu() {
1259 Send(new ViewMsg_PrintNodeUnderContextMenu(routing_id()));
1260 }
1261
1262 void RenderViewHost::PrintForPrintPreview() {
1263 Send(new ViewMsg_PrintForPrintPreview(routing_id()));
1264 }
1265
1266 void RenderViewHost::OnMsgStartDragging(
1267 const WebDropData& drop_data,
1268 WebDragOperationsMask drag_operations_mask,
1269 const SkBitmap& image,
1270 const gfx::Point& image_offset) {
1271 RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
1272 if (view)
1273 view->StartDragging(drop_data, drag_operations_mask, image, image_offset);
1274 }
1275
1276 void RenderViewHost::OnUpdateDragCursor(WebDragOperation current_op) {
1277 RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
1278 if (view)
1279 view->UpdateDragCursor(current_op);
1280 }
1281
1282 void RenderViewHost::OnTakeFocus(bool reverse) {
1283 RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
1284 if (view)
1285 view->TakeFocus(reverse);
1286 }
1287
1288 void RenderViewHost::OnAddMessageToConsole(const std::wstring& message,
1289 int32 line_no,
1290 const std::wstring& source_id) {
1291 std::wstring msg = StringPrintf(L"\"%ls,\" source: %ls (%d)", message.c_str(),
1292 source_id.c_str(), line_no);
1293 logging::LogMessage("CONSOLE", 0).stream() << msg;
1294 }
1295
1296 void RenderViewHost::OnForwardToDevToolsAgent(const IPC::Message& message) {
1297 DevToolsManager::GetInstance()->ForwardToDevToolsAgent(this, message);
1298 }
1299
1300 void RenderViewHost::OnForwardToDevToolsClient(const IPC::Message& message) {
1301 DevToolsManager::GetInstance()->ForwardToDevToolsClient(this, message);
1302 }
1303
1304 void RenderViewHost::OnActivateDevToolsWindow() {
1305 DevToolsManager::GetInstance()->ActivateWindow(this);
1306 }
1307
1308 void RenderViewHost::OnCloseDevToolsWindow() {
1309 DevToolsManager::GetInstance()->CloseWindow(this);
1310 }
1311
1312 void RenderViewHost::OnRequestDockDevToolsWindow() {
1313 DevToolsManager::GetInstance()->RequestDockWindow(this);
1314 }
1315
1316 void RenderViewHost::OnRequestUndockDevToolsWindow() {
1317 DevToolsManager::GetInstance()->RequestUndockWindow(this);
1318 }
1319
1320 void RenderViewHost::OnDevToolsRuntimePropertyChanged(
1321 const std::string& name,
1322 const std::string& value) {
1323 DevToolsManager::GetInstance()->
1324 RuntimePropertyChanged(this, name, value);
1325 }
1326
1327 bool RenderViewHost::PreHandleKeyboardEvent(
1328 const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) {
1329 RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
1330 return view && view->PreHandleKeyboardEvent(event, is_keyboard_shortcut);
1331 }
1332
1333 void RenderViewHost::UnhandledKeyboardEvent(
1334 const NativeWebKeyboardEvent& event) {
1335 RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
1336 if (view)
1337 view->HandleKeyboardEvent(event);
1338 }
1339
1340 void RenderViewHost::OnUserGesture() {
1341 delegate_->OnUserGesture();
1342 }
1343
1344 void RenderViewHost::GetMalwareDOMDetails() {
1345 Send(new ViewMsg_GetMalwareDOMDetails(routing_id()));
1346 }
1347
1348 void RenderViewHost::GetAllSavableResourceLinksForCurrentPage(
1349 const GURL& page_url) {
1350 Send(new ViewMsg_GetAllSavableResourceLinksForCurrentPage(routing_id(),
1351 page_url));
1352 }
1353
1354 void RenderViewHost::GetSerializedHtmlDataForCurrentPageWithLocalLinks(
1355 const std::vector<GURL>& links,
1356 const std::vector<FilePath>& local_paths,
1357 const FilePath& local_directory_name) {
1358 Send(new ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks(
1359 routing_id(), links, local_paths, local_directory_name));
1360 }
1361
1362 void RenderViewHost::OnMsgShouldCloseACK(bool proceed) {
1363 StopHangMonitorTimeout();
1364 // If this renderer navigated while the beforeunload request was in flight, we
1365 // may have cleared this state in OnMsgNavigate, in which case we can ignore
1366 // this message.
1367 if (!is_waiting_for_beforeunload_ack_)
1368 return;
1369
1370 is_waiting_for_beforeunload_ack_ = false;
1371
1372 RenderViewHostDelegate::RendererManagement* management_delegate =
1373 delegate_->GetRendererManagementDelegate();
1374 if (management_delegate) {
1375 management_delegate->ShouldClosePage(
1376 unload_ack_is_for_cross_site_transition_, proceed);
1377 }
1378 }
1379
1380 void RenderViewHost::WindowMoveOrResizeStarted() {
1381 Send(new ViewMsg_MoveOrResizeStarted(routing_id()));
1382 }
1383
1384 void RenderViewHost::NotifyRendererUnresponsive() {
1385 delegate_->RendererUnresponsive(
1386 this, is_waiting_for_beforeunload_ack_ || is_waiting_for_unload_ack_);
1387 }
1388
1389 void RenderViewHost::NotifyRendererResponsive() {
1390 delegate_->RendererResponsive(this);
1391 }
1392
1393 void RenderViewHost::OnMsgFocusedNodeChanged(bool is_editable_node) {
1394 delegate_->FocusedNodeChanged(is_editable_node);
1395 }
1396
1397 void RenderViewHost::OnMsgFocus() {
1398 RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
1399 if (view)
1400 view->Activate();
1401 }
1402
1403 void RenderViewHost::OnMsgBlur() {
1404 RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
1405 if (view)
1406 view->Deactivate();
1407 }
1408
1409 void RenderViewHost::ForwardMouseEvent(
1410 const WebKit::WebMouseEvent& mouse_event) {
1411
1412 // We make a copy of the mouse event because
1413 // RenderWidgetHost::ForwardMouseEvent will delete |mouse_event|.
1414 WebKit::WebMouseEvent event_copy(mouse_event);
1415 RenderWidgetHost::ForwardMouseEvent(event_copy);
1416
1417 RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
1418 if (view) {
1419 switch (event_copy.type) {
1420 case WebInputEvent::MouseMove:
1421 view->HandleMouseMove();
1422 break;
1423 case WebInputEvent::MouseLeave:
1424 view->HandleMouseLeave();
1425 break;
1426 case WebInputEvent::MouseDown:
1427 view->HandleMouseDown();
1428 break;
1429 case WebInputEvent::MouseWheel:
1430 if (ignore_input_events() && delegate_)
1431 delegate_->OnIgnoredUIEvent();
1432 break;
1433 case WebInputEvent::MouseUp:
1434 view->HandleMouseUp();
1435 default:
1436 // For now, we don't care about the rest.
1437 break;
1438 }
1439 }
1440 }
1441
1442 void RenderViewHost::OnMouseActivate() {
1443 RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
1444 if (view)
1445 view->HandleMouseActivate();
1446 }
1447
1448 void RenderViewHost::ForwardKeyboardEvent(
1449 const NativeWebKeyboardEvent& key_event) {
1450 if (ignore_input_events()) {
1451 if (key_event.type == WebInputEvent::RawKeyDown && delegate_)
1452 delegate_->OnIgnoredUIEvent();
1453 return;
1454 }
1455 RenderWidgetHost::ForwardKeyboardEvent(key_event);
1456 }
1457
1458 void RenderViewHost::ForwardEditCommand(const std::string& name,
1459 const std::string& value) {
1460 IPC::Message* message = new ViewMsg_ExecuteEditCommand(routing_id(),
1461 name,
1462 value);
1463 Send(message);
1464 }
1465
1466 void RenderViewHost::ForwardEditCommandsForNextKeyEvent(
1467 const EditCommands& edit_commands) {
1468 IPC::Message* message = new ViewMsg_SetEditCommandsForNextKeyEvent(
1469 routing_id(), edit_commands);
1470 Send(message);
1471 }
1472
1473 void RenderViewHost::ForwardMessageFromExternalHost(const std::string& message,
1474 const std::string& origin,
1475 const std::string& target) {
1476 Send(new ViewMsg_HandleMessageFromExternalHost(routing_id(), message, origin,
1477 target));
1478 }
1479
1480 void RenderViewHost::OnExtensionRequest(
1481 const ViewHostMsg_DomMessage_Params& params) {
1482 if (!ChildProcessSecurityPolicy::GetInstance()->
1483 HasExtensionBindings(process()->id())) {
1484 // This can happen if someone uses window.open() to open an extension URL
1485 // from a non-extension context.
1486 BlockExtensionRequest(params.request_id);
1487 return;
1488 }
1489
1490 delegate_->ProcessWebUIMessage(params);
1491 }
1492
1493 void RenderViewHost::SendExtensionResponse(int request_id, bool success,
1494 const std::string& response,
1495 const std::string& error) {
1496 Send(new ViewMsg_ExtensionResponse(routing_id(), request_id, success,
1497 response, error));
1498 }
1499
1500 void RenderViewHost::BlockExtensionRequest(int request_id) {
1501 SendExtensionResponse(request_id, false, "",
1502 "Access to extension API denied.");
1503 }
1504
1505 void RenderViewHost::UpdateBrowserWindowId(int window_id) {
1506 Send(new ViewMsg_UpdateBrowserWindowId(routing_id(), window_id));
1507 }
1508
1509 void RenderViewHost::PerformCustomContextMenuAction(
1510 const webkit_glue::CustomContextMenuContext& custom_context,
1511 unsigned action) {
1512 Send(new ViewMsg_CustomContextMenuAction(routing_id(),
1513 custom_context,
1514 action));
1515 }
1516
1517 void RenderViewHost::SendContentSettings(const GURL& url,
1518 const ContentSettings& settings) {
1519 Send(new ViewMsg_SetContentSettingsForCurrentURL(url, settings));
1520 }
1521
1522 void RenderViewHost::EnablePreferredSizeChangedMode(int flags) {
1523 Send(new ViewMsg_EnablePreferredSizeChangedMode(routing_id(), flags));
1524 }
1525
1526 #if defined(OS_MACOSX)
1527 void RenderViewHost::DidSelectPopupMenuItem(int selected_index) {
1528 Send(new ViewMsg_SelectPopupMenuItem(routing_id(), selected_index));
1529 }
1530
1531 void RenderViewHost::DidCancelPopupMenu() {
1532 Send(new ViewMsg_SelectPopupMenuItem(routing_id(), -1));
1533 }
1534 #endif
1535
1536 void RenderViewHost::SearchBoxChange(const string16& value,
1537 bool verbatim,
1538 int selection_start,
1539 int selection_end) {
1540 Send(new ViewMsg_SearchBoxChange(
1541 routing_id(), value, verbatim, selection_start, selection_end));
1542 }
1543
1544 void RenderViewHost::SearchBoxSubmit(const string16& value,
1545 bool verbatim) {
1546 Send(new ViewMsg_SearchBoxSubmit(routing_id(), value, verbatim));
1547 }
1548
1549 void RenderViewHost::SearchBoxCancel() {
1550 Send(new ViewMsg_SearchBoxCancel(routing_id()));
1551 }
1552
1553 void RenderViewHost::SearchBoxResize(const gfx::Rect& search_box_bounds) {
1554 Send(new ViewMsg_SearchBoxResize(routing_id(), search_box_bounds));
1555 }
1556
1557 void RenderViewHost::DetermineIfPageSupportsInstant(const string16& value,
1558 bool verbatim,
1559 int selection_start,
1560 int selection_end) {
1561 Send(new ViewMsg_DetermineIfPageSupportsInstant(
1562 routing_id(), value, verbatim, selection_start, selection_end));
1563 }
1564
1565 void RenderViewHost::FilterURL(ChildProcessSecurityPolicy* policy,
1566 int renderer_id,
1567 GURL* url) {
1568 if (!url->is_valid())
1569 return; // We don't need to block invalid URLs.
1570
1571 if (url->SchemeIs(chrome::kAboutScheme)) {
1572 // The renderer treats all URLs in the about: scheme as being about:blank.
1573 // Canonicalize about: URLs to about:blank.
1574 *url = GURL(chrome::kAboutBlankURL);
1575 }
1576
1577 if (!policy->CanRequestURL(renderer_id, *url)) {
1578 // If this renderer is not permitted to request this URL, we invalidate the
1579 // URL. This prevents us from storing the blocked URL and becoming confused
1580 // later.
1581 VLOG(1) << "Blocked URL " << url->spec();
1582 *url = GURL();
1583 }
1584 }
1585
1586 void RenderViewHost::JavaScriptStressTestControl(int cmd, int param) {
1587 Send(new ViewMsg_JavaScriptStressTestControl(routing_id(), cmd, param));
1588 }
1589
1590 void RenderViewHost::OnExtensionPostMessage(
1591 int port_id, const std::string& message) {
1592 if (process()->profile()->GetExtensionMessageService()) {
1593 process()->profile()->GetExtensionMessageService()->
1594 PostMessageFromRenderer(port_id, message);
1595 }
1596 }
1597
1598 void RenderViewHost::OnAccessibilityNotifications(
1599 const std::vector<ViewHostMsg_AccessibilityNotification_Params>& params) {
1600 if (view())
1601 view()->OnAccessibilityNotifications(params);
1602
1603 if (params.size() > 0) {
1604 for (unsigned i = 0; i < params.size(); i++) {
1605 const ViewHostMsg_AccessibilityNotification_Params& param = params[i];
1606
1607 if (param.notification_type ==
1608 ViewHostMsg_AccessibilityNotification_Params::
1609 NOTIFICATION_TYPE_LOAD_COMPLETE) {
1610 // TODO(ctguil): Remove when mac processes OnAccessibilityNotifications.
1611 if (view())
1612 view()->UpdateAccessibilityTree(param.acc_obj);
1613
1614 if (save_accessibility_tree_for_testing_)
1615 accessibility_tree_ = param.acc_obj;
1616 }
1617 }
1618
1619 NotificationService::current()->Notify(
1620 NotificationType::RENDER_VIEW_HOST_ACCESSIBILITY_TREE_UPDATED,
1621 Source<RenderViewHost>(this),
1622 NotificationService::NoDetails());
1623 }
1624
1625 AccessibilityNotificationsAck();
1626 }
1627
1628 void RenderViewHost::OnCSSInserted() {
1629 delegate_->DidInsertCSS();
1630 }
1631
1632 void RenderViewHost::OnContentBlocked(ContentSettingsType type,
1633 const std::string& resource_identifier) {
1634 RenderViewHostDelegate::ContentSettings* content_settings_delegate =
1635 delegate_->GetContentSettingsDelegate();
1636 if (content_settings_delegate)
1637 content_settings_delegate->OnContentBlocked(type, resource_identifier);
1638 }
1639
1640 void RenderViewHost::OnAppCacheAccessed(const GURL& manifest_url,
1641 bool blocked_by_policy) {
1642 RenderViewHostDelegate::ContentSettings* content_settings_delegate =
1643 delegate_->GetContentSettingsDelegate();
1644 if (content_settings_delegate)
1645 content_settings_delegate->OnAppCacheAccessed(manifest_url,
1646 blocked_by_policy);
1647 }
1648
1649 void RenderViewHost::OnWebDatabaseAccessed(const GURL& url,
1650 const string16& name,
1651 const string16& display_name,
1652 unsigned long estimated_size,
1653 bool blocked_by_policy) {
1654 RenderViewHostDelegate::ContentSettings* content_settings_delegate =
1655 delegate_->GetContentSettingsDelegate();
1656 if (content_settings_delegate)
1657 content_settings_delegate->OnWebDatabaseAccessed(
1658 url, name, display_name, estimated_size, blocked_by_policy);
1659 }
1660
1661 void RenderViewHost::OnUpdateZoomLimits(int minimum_percent,
1662 int maximum_percent,
1663 bool remember) {
1664 delegate_->UpdateZoomLimits(minimum_percent, maximum_percent, remember);
1665 }
1666
1667 void RenderViewHost::OnScriptEvalResponse(int id, const ListValue& result) {
1668 Value* result_value;
1669 result.Get(0, &result_value);
1670 std::pair<int, Value*> details(id, result_value);
1671 NotificationService::current()->Notify(
1672 NotificationType::EXECUTE_JAVASCRIPT_RESULT,
1673 Source<RenderViewHost>(this),
1674 Details<std::pair<int, Value*> >(&details));
1675 }
1676
1677 #if defined(OS_MACOSX)
1678 void RenderViewHost::OnMsgShowPopup(
1679 const ViewHostMsg_ShowPopup_Params& params) {
1680 RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
1681 if (view) {
1682 view->ShowPopupMenu(params.bounds,
1683 params.item_height,
1684 params.item_font_size,
1685 params.selected_item,
1686 params.popup_items,
1687 params.right_aligned);
1688 }
1689 }
1690 #endif
1691
1692 void RenderViewHost::OnCommandStateChanged(int command,
1693 bool is_enabled,
1694 int checked_state) {
1695 if (command != RENDER_VIEW_COMMAND_TOGGLE_SPELL_CHECK) {
1696 LOG(DFATAL) << "Unknown command " << command;
1697 return;
1698 }
1699
1700 if (checked_state != RENDER_VIEW_COMMAND_CHECKED_STATE_UNCHECKED &&
1701 checked_state != RENDER_VIEW_COMMAND_CHECKED_STATE_CHECKED &&
1702 checked_state != RENDER_VIEW_COMMAND_CHECKED_STATE_MIXED) {
1703 LOG(DFATAL) << "Invalid checked state " << checked_state;
1704 return;
1705 }
1706
1707 CommandState state;
1708 state.is_enabled = is_enabled;
1709 state.checked_state =
1710 static_cast<RenderViewCommandCheckedState>(checked_state);
1711 command_states_[static_cast<RenderViewCommand>(command)] = state;
1712 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698