1 // Copyright 2013 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.
5 #include "chrome/browser/guestview/webview/webview_guest.h"
7 #include "base/command_line.h"
8 #include "base/strings/stringprintf.h"
9 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/extensions/api/web_request/web_request_api.h"
11 #include "chrome/browser/extensions/extension_renderer_state.h"
12 #include "chrome/browser/extensions/extension_web_contents_observer.h"
13 #include "chrome/browser/extensions/script_executor.h"
14 #include "chrome/browser/favicon/favicon_tab_helper.h"
15 #include "chrome/browser/guestview/guestview_constants.h"
16 #include "chrome/browser/guestview/webview/webview_constants.h"
17 #include "chrome/browser/guestview/webview/webview_permission_types.h"
18 #include "chrome/common/chrome_version_info.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/browser/native_web_keyboard_event.h"
21 #include "content/public/browser/navigation_entry.h"
22 #include "content/public/browser/notification_details.h"
23 #include "content/public/browser/notification_service.h"
24 #include "content/public/browser/notification_source.h"
25 #include "content/public/browser/notification_types.h"
26 #include "content/public/browser/render_process_host.h"
27 #include "content/public/browser/resource_request_details.h"
28 #include "content/public/browser/site_instance.h"
29 #include "content/public/browser/storage_partition.h"
30 #include "content/public/browser/user_metrics.h"
31 #include "content/public/browser/web_contents.h"
32 #include "content/public/common/content_switches.h"
33 #include "content/public/common/page_zoom.h"
34 #include "content/public/common/result_codes.h"
35 #include "extensions/common/constants.h"
36 #include "net/base/net_errors.h"
38 #if defined(ENABLE_PLUGINS)
39 #include "chrome/browser/guestview/webview/plugin_permission_helper.h"
42 #if defined(OS_CHROMEOS)
43 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
46 using base::UserMetricsAction;
47 using content::WebContents;
51 static std::string TerminationStatusToString(base::TerminationStatus status) {
53 case base::TERMINATION_STATUS_NORMAL_TERMINATION:
55 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
56 case base::TERMINATION_STATUS_STILL_RUNNING:
58 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
60 case base::TERMINATION_STATUS_PROCESS_CRASHED:
61 #if defined(OS_ANDROID)
62 case base::TERMINATION_STATUS_OOM_PROTECTED:
65 case base::TERMINATION_STATUS_MAX_ENUM:
68 NOTREACHED() << "Unknown Termination Status.";
72 static std::string PermissionTypeToString(BrowserPluginPermissionType type) {
74 case BROWSER_PLUGIN_PERMISSION_TYPE_DOWNLOAD:
75 return webview::kPermissionTypeDownload;
76 case BROWSER_PLUGIN_PERMISSION_TYPE_GEOLOCATION:
77 return webview::kPermissionTypeGeolocation;
78 case BROWSER_PLUGIN_PERMISSION_TYPE_MEDIA:
79 return webview::kPermissionTypeMedia;
80 case BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW:
81 return webview::kPermissionTypeNewWindow;
82 case BROWSER_PLUGIN_PERMISSION_TYPE_POINTER_LOCK:
83 return webview::kPermissionTypePointerLock;
84 case BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG:
85 return webview::kPermissionTypeDialog;
86 case BROWSER_PLUGIN_PERMISSION_TYPE_UNKNOWN:
90 WebViewPermissionType webview = static_cast<WebViewPermissionType>(type);
92 case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
93 return webview::kPermissionTypeLoadPlugin;
101 void RemoveWebViewEventListenersOnIOThread(
103 const std::string& extension_id,
104 int embedder_process_id,
105 int view_instance_id) {
106 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
107 ExtensionWebRequestEventRouter::GetInstance()->RemoveWebViewEventListeners(
114 void AttachWebViewHelpers(WebContents* contents) {
115 FaviconTabHelper::CreateForWebContents(contents);
116 extensions::ExtensionWebContentsObserver::CreateForWebContents(contents);
117 #if defined(ENABLE_PLUGINS)
118 PluginPermissionHelper::CreateForWebContents(contents);
124 WebViewGuest::WebViewGuest(WebContents* guest_web_contents,
125 const std::string& extension_id)
126 : GuestView(guest_web_contents, extension_id),
127 WebContentsObserver(guest_web_contents),
128 script_executor_(new extensions::ScriptExecutor(guest_web_contents,
129 &script_observers_)),
130 next_permission_request_id_(0),
131 is_overriding_user_agent_(false),
132 pending_reload_on_attachment_(false),
134 chromevox_injected_(false) {
135 notification_registrar_.Add(
136 this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
137 content::Source<WebContents>(guest_web_contents));
139 notification_registrar_.Add(
140 this, content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
141 content::Source<WebContents>(guest_web_contents));
143 #if defined(OS_CHROMEOS)
144 notification_registrar_.Add(this,
145 chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK,
146 content::NotificationService::AllSources());
149 AttachWebViewHelpers(guest_web_contents);
153 WebViewGuest* WebViewGuest::From(int embedder_process_id,
154 int guest_instance_id) {
155 GuestView* guest = GuestView::From(embedder_process_id, guest_instance_id);
158 return guest->AsWebView();
162 WebViewGuest* WebViewGuest::FromWebContents(WebContents* contents) {
163 GuestView* guest = GuestView::FromWebContents(contents);
164 return guest ? guest->AsWebView() : NULL;
168 void WebViewGuest::RecordUserInitiatedUMA(const PermissionResponseInfo& info,
171 // Note that |allow| == true means the embedder explicitly allowed the
172 // request. For some requests they might still fail. An example of such
173 // scenario would be: an embedder allows geolocation request but doesn't
174 // have geolocation access on its own.
175 switch (info.permission_type) {
176 case BROWSER_PLUGIN_PERMISSION_TYPE_DOWNLOAD:
177 content::RecordAction(
178 UserMetricsAction("BrowserPlugin.PermissionAllow.Download"));
180 case BROWSER_PLUGIN_PERMISSION_TYPE_GEOLOCATION:
181 content::RecordAction(
182 UserMetricsAction("BrowserPlugin.PermissionAllow.Geolocation"));
184 case BROWSER_PLUGIN_PERMISSION_TYPE_MEDIA:
185 content::RecordAction(
186 UserMetricsAction("BrowserPlugin.PermissionAllow.Media"));
188 case BROWSER_PLUGIN_PERMISSION_TYPE_POINTER_LOCK:
189 content::RecordAction(
190 UserMetricsAction("BrowserPlugin.PermissionAllow.PointerLock"));
192 case BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW:
193 content::RecordAction(
194 UserMetricsAction("BrowserPlugin.PermissionAllow.NewWindow"));
196 case BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG:
197 content::RecordAction(
198 UserMetricsAction("BrowserPlugin.PermissionAllow.JSDialog"));
200 case BROWSER_PLUGIN_PERMISSION_TYPE_UNKNOWN:
203 WebViewPermissionType webview_permission_type =
204 static_cast<WebViewPermissionType>(info.permission_type);
205 switch (webview_permission_type) {
206 case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
207 content::RecordAction(
208 UserMetricsAction("WebView.Guest.PermissionAllow.PluginLoad"));
216 switch (info.permission_type) {
217 case BROWSER_PLUGIN_PERMISSION_TYPE_DOWNLOAD:
218 content::RecordAction(
219 UserMetricsAction("BrowserPlugin.PermissionDeny.Download"));
221 case BROWSER_PLUGIN_PERMISSION_TYPE_GEOLOCATION:
222 content::RecordAction(
223 UserMetricsAction("BrowserPlugin.PermissionDeny.Geolocation"));
225 case BROWSER_PLUGIN_PERMISSION_TYPE_MEDIA:
226 content::RecordAction(
227 UserMetricsAction("BrowserPlugin.PermissionDeny.Media"));
229 case BROWSER_PLUGIN_PERMISSION_TYPE_POINTER_LOCK:
230 content::RecordAction(
231 UserMetricsAction("BrowserPlugin.PermissionDeny.PointerLock"));
233 case BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW:
234 content::RecordAction(
235 UserMetricsAction("BrowserPlugin.PermissionDeny.NewWindow"));
237 case BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG:
238 content::RecordAction(
239 UserMetricsAction("BrowserPlugin.PermissionDeny.JSDialog"));
241 case BROWSER_PLUGIN_PERMISSION_TYPE_UNKNOWN:
244 WebViewPermissionType webview_permission_type =
245 static_cast<WebViewPermissionType>(info.permission_type);
246 switch (webview_permission_type) {
247 case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
248 content::RecordAction(
249 UserMetricsAction("WebView.Guest.PermissionDeny.PluginLoad"));
259 void WebViewGuest::Attach(WebContents* embedder_web_contents,
260 const base::DictionaryValue& args) {
261 std::string user_agent_override;
262 if (args.GetString(webview::kParameterUserAgentOverride,
263 &user_agent_override)) {
264 SetUserAgentOverride(user_agent_override);
266 SetUserAgentOverride("");
269 GuestView::Attach(embedder_web_contents, args);
271 AddWebViewToExtensionRendererState();
274 GuestView::Type WebViewGuest::GetViewType() const {
275 return GuestView::WEBVIEW;
278 WebViewGuest* WebViewGuest::AsWebView() {
282 AdViewGuest* WebViewGuest::AsAdView() {
286 void WebViewGuest::AddMessageToConsole(int32 level,
287 const base::string16& message,
289 const base::string16& source_id) {
290 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
291 // Log levels are from base/logging.h: LogSeverity.
292 args->SetInteger(webview::kLevel, level);
293 args->SetString(webview::kMessage, message);
294 args->SetInteger(webview::kLine, line_no);
295 args->SetString(webview::kSourceId, source_id);
297 new GuestView::Event(webview::kEventConsoleMessage, args.Pass()));
300 void WebViewGuest::Close() {
301 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
302 DispatchEvent(new GuestView::Event(webview::kEventClose, args.Pass()));
305 void WebViewGuest::DidAttach() {
306 if (pending_reload_on_attachment_) {
307 pending_reload_on_attachment_ = false;
308 guest_web_contents()->GetController().Reload(false);
312 void WebViewGuest::EmbedderDestroyed() {
313 // TODO(fsamuel): WebRequest event listeners for <webview> should survive
314 // reparenting of a <webview> within a single embedder. Right now, we keep
315 // around the browser state for the listener for the lifetime of the embedder.
316 // Ideally, the lifetime of the listeners should match the lifetime of the
317 // <webview> DOM node. Once http://crbug.com/156219 is resolved we can move
318 // the call to RemoveWebViewEventListenersOnIOThread back to
319 // WebViewGuest::WebContentsDestroyed.
320 content::BrowserThread::PostTask(
321 content::BrowserThread::IO,
324 &RemoveWebViewEventListenersOnIOThread,
325 browser_context(), extension_id(),
326 embedder_render_process_id(),
327 view_instance_id()));
330 void WebViewGuest::GuestProcessGone(base::TerminationStatus status) {
331 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
332 args->SetInteger(webview::kProcessId,
333 guest_web_contents()->GetRenderProcessHost()->GetID());
334 args->SetString(webview::kReason, TerminationStatusToString(status));
336 new GuestView::Event(webview::kEventExit, args.Pass()));
339 bool WebViewGuest::HandleKeyboardEvent(
340 const content::NativeWebKeyboardEvent& event) {
341 if (event.type != blink::WebInputEvent::RawKeyDown)
344 #if defined(OS_MACOSX)
345 if (event.modifiers != blink::WebInputEvent::MetaKey)
348 if (event.windowsKeyCode == ui::VKEY_OEM_4) {
353 if (event.windowsKeyCode == ui::VKEY_OEM_6) {
358 if (event.windowsKeyCode == ui::VKEY_BROWSER_BACK) {
363 if (event.windowsKeyCode == ui::VKEY_BROWSER_FORWARD) {
371 bool WebViewGuest::IsDragAndDropEnabled() {
372 #if defined(OS_CHROMEOS)
375 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
376 if (channel != chrome::VersionInfo::CHANNEL_STABLE &&
377 channel != chrome::VersionInfo::CHANNEL_BETA) {
378 // Drag and drop is enabled in canary and dev channel.
382 return CommandLine::ForCurrentProcess()->HasSwitch(
383 switches::kEnableBrowserPluginDragDrop);
387 bool WebViewGuest::IsOverridingUserAgent() const {
388 return is_overriding_user_agent_;
391 void WebViewGuest::LoadProgressed(double progress) {
392 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
393 args->SetString(guestview::kUrl, guest_web_contents()->GetURL().spec());
394 args->SetDouble(webview::kProgress, progress);
395 DispatchEvent(new GuestView::Event(webview::kEventLoadProgress, args.Pass()));
398 void WebViewGuest::LoadAbort(bool is_top_level,
400 const std::string& error_type) {
401 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
402 args->SetBoolean(guestview::kIsTopLevel, is_top_level);
403 args->SetString(guestview::kUrl, url.possibly_invalid_spec());
404 args->SetString(guestview::kReason, error_type);
405 DispatchEvent(new GuestView::Event(webview::kEventLoadAbort, args.Pass()));
408 // TODO(fsamuel): Find a reliable way to test the 'responsive' and
409 // 'unresponsive' events.
410 void WebViewGuest::RendererResponsive() {
411 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
412 args->SetInteger(webview::kProcessId,
413 guest_web_contents()->GetRenderProcessHost()->GetID());
414 DispatchEvent(new GuestView::Event(webview::kEventResponsive, args.Pass()));
417 void WebViewGuest::RendererUnresponsive() {
418 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
419 args->SetInteger(webview::kProcessId,
420 guest_web_contents()->GetRenderProcessHost()->GetID());
421 DispatchEvent(new GuestView::Event(webview::kEventUnresponsive, args.Pass()));
424 bool WebViewGuest::RequestPermission(
425 BrowserPluginPermissionType permission_type,
426 const base::DictionaryValue& request_info,
427 const PermissionResponseCallback& callback,
428 bool allowed_by_default) {
429 // If there are too many pending permission requests then reject this request.
430 if (pending_permission_requests_.size() >=
431 webview::kMaxOutstandingPermissionRequests) {
432 callback.Run(false, std::string());
436 int request_id = next_permission_request_id_++;
437 pending_permission_requests_[request_id] =
438 PermissionResponseInfo(callback, permission_type, allowed_by_default);
439 scoped_ptr<base::DictionaryValue> args(request_info.DeepCopy());
440 args->SetInteger(webview::kRequestId, request_id);
441 switch (permission_type) {
442 case BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW: {
443 DispatchEvent(new GuestView::Event(webview::kEventNewWindow,
447 case BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG: {
448 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
449 if (channel > chrome::VersionInfo::CHANNEL_DEV) {
450 // 'dialog' API is not available in stable/beta.
451 callback.Run(false, std::string());
454 DispatchEvent(new GuestView::Event(webview::kEventDialog,
459 args->SetString(webview::kPermission,
460 PermissionTypeToString(permission_type));
461 DispatchEvent(new GuestView::Event(webview::kEventPermissionRequest,
469 void WebViewGuest::Observe(int type,
470 const content::NotificationSource& source,
471 const content::NotificationDetails& details) {
473 case content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME: {
474 DCHECK_EQ(content::Source<WebContents>(source).ptr(),
475 guest_web_contents());
476 if (content::Source<WebContents>(source).ptr() == guest_web_contents())
480 case content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT: {
481 DCHECK_EQ(content::Source<WebContents>(source).ptr(),
482 guest_web_contents());
483 content::ResourceRedirectDetails* resource_redirect_details =
484 content::Details<content::ResourceRedirectDetails>(details).ptr();
486 resource_redirect_details->resource_type == ResourceType::MAIN_FRAME;
487 LoadRedirect(resource_redirect_details->url,
488 resource_redirect_details->new_url,
492 #if defined(OS_CHROMEOS)
493 case chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK:
494 InjectChromeVoxIfNeeded(guest_web_contents()->GetRenderViewHost());
498 NOTREACHED() << "Unexpected notification sent.";
503 void WebViewGuest::SetZoom(double zoom_factor) {
504 double zoom_level = content::ZoomFactorToZoomLevel(zoom_factor);
505 guest_web_contents()->SetZoomLevel(zoom_level);
507 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
508 args->SetDouble(webview::kOldZoomFactor, current_zoom_factor_);
509 args->SetDouble(webview::kNewZoomFactor, zoom_factor);
510 DispatchEvent(new GuestView::Event(webview::kEventZoomChange, args.Pass()));
512 current_zoom_factor_ = zoom_factor;
515 double WebViewGuest::GetZoom() {
516 return current_zoom_factor_;
519 void WebViewGuest::Go(int relative_index) {
520 guest_web_contents()->GetController().GoToOffset(relative_index);
523 void WebViewGuest::Reload() {
524 // TODO(fsamuel): Don't check for repost because we don't want to show
525 // Chromium's repost warning. We might want to implement a separate API
526 // for registering a callback if a repost is about to happen.
527 guest_web_contents()->GetController().Reload(false);
530 WebViewGuest::SetPermissionResult WebViewGuest::SetPermission(
532 PermissionResponseAction action,
533 const std::string& user_input) {
534 RequestMap::iterator request_itr =
535 pending_permission_requests_.find(request_id);
537 if (request_itr == pending_permission_requests_.end())
538 return SET_PERMISSION_INVALID;
540 const PermissionResponseInfo& info = request_itr->second;
541 bool allow = (action == ALLOW) ||
542 ((action == DEFAULT) && info.allowed_by_default);
544 info.callback.Run(allow, user_input);
546 // Only record user initiated (i.e. non-default) actions.
547 if (action != DEFAULT)
548 RecordUserInitiatedUMA(info, allow);
550 pending_permission_requests_.erase(request_itr);
552 return allow ? SET_PERMISSION_ALLOWED : SET_PERMISSION_DENIED;
555 void WebViewGuest::SetUserAgentOverride(
556 const std::string& user_agent_override) {
557 is_overriding_user_agent_ = !user_agent_override.empty();
558 if (is_overriding_user_agent_) {
559 content::RecordAction(UserMetricsAction("WebView.Guest.OverrideUA"));
561 guest_web_contents()->SetUserAgentOverride(user_agent_override);
564 void WebViewGuest::Stop() {
565 guest_web_contents()->Stop();
568 void WebViewGuest::Terminate() {
569 content::RecordAction(UserMetricsAction("WebView.Guest.Terminate"));
570 base::ProcessHandle process_handle =
571 guest_web_contents()->GetRenderProcessHost()->GetHandle();
573 base::KillProcess(process_handle, content::RESULT_CODE_KILLED, false);
576 bool WebViewGuest::ClearData(const base::Time remove_since,
578 const base::Closure& callback) {
579 content::RecordAction(UserMetricsAction("WebView.Guest.ClearData"));
580 content::StoragePartition* partition =
581 content::BrowserContext::GetStoragePartition(
582 guest_web_contents()->GetBrowserContext(),
583 guest_web_contents()->GetSiteInstance());
588 partition->ClearData(
590 content::StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
592 content::StoragePartition::OriginMatcherFunction(),
599 WebViewGuest::~WebViewGuest() {
602 void WebViewGuest::DidCommitProvisionalLoadForFrame(
604 const base::string16& frame_unique_name,
607 content::PageTransition transition_type,
608 content::RenderViewHost* render_view_host) {
609 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
610 args->SetString(guestview::kUrl, url.spec());
611 args->SetBoolean(guestview::kIsTopLevel, is_main_frame);
612 args->SetInteger(webview::kInternalCurrentEntryIndex,
613 guest_web_contents()->GetController().GetCurrentEntryIndex());
614 args->SetInteger(webview::kInternalEntryCount,
615 guest_web_contents()->GetController().GetEntryCount());
616 args->SetInteger(webview::kInternalProcessId,
617 guest_web_contents()->GetRenderProcessHost()->GetID());
618 DispatchEvent(new GuestView::Event(webview::kEventLoadCommit, args.Pass()));
620 // Update the current zoom factor for the new page.
621 current_zoom_factor_ = content::ZoomLevelToZoomFactor(
622 guest_web_contents()->GetZoomLevel());
625 chromevox_injected_ = false;
626 main_frame_id_ = frame_id;
630 void WebViewGuest::DidFailProvisionalLoad(
632 const base::string16& frame_unique_name,
634 const GURL& validated_url,
636 const base::string16& error_description,
637 content::RenderViewHost* render_view_host) {
638 // Translate the |error_code| into an error string.
639 std::string error_type;
640 base::RemoveChars(net::ErrorToString(error_code), "net::", &error_type);
641 LoadAbort(is_main_frame, validated_url, error_type);
644 void WebViewGuest::DidStartProvisionalLoadForFrame(
646 int64 parent_frame_id,
648 const GURL& validated_url,
650 bool is_iframe_srcdoc,
651 content::RenderViewHost* render_view_host) {
652 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
653 args->SetString(guestview::kUrl, validated_url.spec());
654 args->SetBoolean(guestview::kIsTopLevel, is_main_frame);
655 DispatchEvent(new GuestView::Event(webview::kEventLoadStart, args.Pass()));
658 void WebViewGuest::DocumentLoadedInFrame(
660 content::RenderViewHost* render_view_host) {
661 if (frame_id == main_frame_id_)
662 InjectChromeVoxIfNeeded(render_view_host);
665 void WebViewGuest::DidStopLoading(content::RenderViewHost* render_view_host) {
666 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
667 DispatchEvent(new GuestView::Event(webview::kEventLoadStop, args.Pass()));
670 void WebViewGuest::WebContentsDestroyed(WebContents* web_contents) {
671 RemoveWebViewFromExtensionRendererState(web_contents);
674 void WebViewGuest::UserAgentOverrideSet(const std::string& user_agent) {
675 content::NavigationController& controller =
676 guest_web_contents()->GetController();
677 content::NavigationEntry* entry = controller.GetVisibleEntry();
680 entry->SetIsOverridingUserAgent(!user_agent.empty());
682 // We cannot reload now because all resource loads are suspended until
684 pending_reload_on_attachment_ = true;
687 guest_web_contents()->GetController().Reload(false);
690 void WebViewGuest::LoadHandlerCalled() {
691 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
692 DispatchEvent(new GuestView::Event(webview::kEventContentLoad, args.Pass()));
695 void WebViewGuest::LoadRedirect(const GURL& old_url,
698 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
699 args->SetBoolean(guestview::kIsTopLevel, is_top_level);
700 args->SetString(webview::kNewURL, new_url.spec());
701 args->SetString(webview::kOldURL, old_url.spec());
702 DispatchEvent(new GuestView::Event(webview::kEventLoadRedirect, args.Pass()));
705 void WebViewGuest::AddWebViewToExtensionRendererState() {
706 const GURL& site_url = guest_web_contents()->GetSiteInstance()->GetSiteURL();
707 std::string partition_domain;
708 std::string partition_id;
710 if (!GetGuestPartitionConfigForSite(
711 site_url, &partition_domain, &partition_id, &in_memory)) {
715 DCHECK(extension_id() == partition_domain);
717 ExtensionRendererState::WebViewInfo webview_info;
718 webview_info.embedder_process_id = embedder_render_process_id();
719 webview_info.instance_id = view_instance_id();
720 webview_info.partition_id = partition_id;
721 webview_info.extension_id = extension_id();
723 content::BrowserThread::PostTask(
724 content::BrowserThread::IO, FROM_HERE,
726 &ExtensionRendererState::AddWebView,
727 base::Unretained(ExtensionRendererState::GetInstance()),
728 guest_web_contents()->GetRenderProcessHost()->GetID(),
729 guest_web_contents()->GetRoutingID(),
734 void WebViewGuest::RemoveWebViewFromExtensionRendererState(
735 WebContents* web_contents) {
736 content::BrowserThread::PostTask(
737 content::BrowserThread::IO, FROM_HERE,
739 &ExtensionRendererState::RemoveWebView,
740 base::Unretained(ExtensionRendererState::GetInstance()),
741 web_contents->GetRenderProcessHost()->GetID(),
742 web_contents->GetRoutingID()));
745 GURL WebViewGuest::ResolveURL(const std::string& src) {
746 if (extension_id().empty()) {
751 GURL default_url(base::StringPrintf("%s://%s/",
752 extensions::kExtensionScheme,
753 extension_id().c_str()));
754 return default_url.Resolve(src);
757 void WebViewGuest::SizeChanged(const gfx::Size& old_size,
758 const gfx::Size& new_size) {
759 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
760 args->SetInteger(webview::kOldHeight, old_size.height());
761 args->SetInteger(webview::kOldWidth, old_size.width());
762 args->SetInteger(webview::kNewHeight, new_size.height());
763 args->SetInteger(webview::kNewWidth, new_size.width());
764 DispatchEvent(new GuestView::Event(webview::kEventSizeChanged, args.Pass()));
767 void WebViewGuest::InjectChromeVoxIfNeeded(
768 content::RenderViewHost* render_view_host) {
769 #if defined(OS_CHROMEOS)
770 if (!chromevox_injected_) {
771 chromeos::AccessibilityManager* manager =
772 chromeos::AccessibilityManager::Get();
773 if (manager && manager->IsSpokenFeedbackEnabled()) {
774 manager->InjectChromeVox(render_view_host);
775 chromevox_injected_ = true;
781 WebViewGuest::PermissionResponseInfo::PermissionResponseInfo()
782 : permission_type(BROWSER_PLUGIN_PERMISSION_TYPE_UNKNOWN),
783 allowed_by_default(false) {
786 WebViewGuest::PermissionResponseInfo::PermissionResponseInfo(
787 const PermissionResponseCallback& callback,
788 BrowserPluginPermissionType permission_type,
789 bool allowed_by_default)
790 : callback(callback),
791 permission_type(permission_type),
792 allowed_by_default(allowed_by_default) {
795 WebViewGuest::PermissionResponseInfo::~PermissionResponseInfo() {