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/extensions/api/web_request/web_request_api.h"
10 #include "chrome/browser/extensions/extension_renderer_state.h"
11 #include "chrome/browser/extensions/extension_web_contents_observer.h"
12 #include "chrome/browser/extensions/script_executor.h"
13 #include "chrome/browser/favicon/favicon_tab_helper.h"
14 #include "chrome/browser/guestview/guestview_constants.h"
15 #include "chrome/browser/guestview/webview/webview_constants.h"
16 #include "chrome/browser/guestview/webview/webview_permission_types.h"
17 #include "chrome/common/chrome_version_info.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/native_web_keyboard_event.h"
20 #include "content/public/browser/navigation_entry.h"
21 #include "content/public/browser/notification_details.h"
22 #include "content/public/browser/notification_source.h"
23 #include "content/public/browser/notification_types.h"
24 #include "content/public/browser/render_process_host.h"
25 #include "content/public/browser/resource_request_details.h"
26 #include "content/public/browser/site_instance.h"
27 #include "content/public/browser/storage_partition.h"
28 #include "content/public/browser/user_metrics.h"
29 #include "content/public/browser/web_contents.h"
30 #include "content/public/common/content_switches.h"
31 #include "content/public/common/result_codes.h"
32 #include "extensions/common/constants.h"
33 #include "net/base/net_errors.h"
35 #if defined(ENABLE_PLUGINS)
36 #include "chrome/browser/guestview/webview/plugin_permission_helper.h"
39 using base::UserMetricsAction
;
40 using content::WebContents
;
44 static std::string
TerminationStatusToString(base::TerminationStatus status
) {
46 case base::TERMINATION_STATUS_NORMAL_TERMINATION
:
48 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION
:
49 case base::TERMINATION_STATUS_STILL_RUNNING
:
51 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED
:
53 case base::TERMINATION_STATUS_PROCESS_CRASHED
:
54 #if defined(OS_ANDROID)
55 case base::TERMINATION_STATUS_OOM_PROTECTED
:
58 case base::TERMINATION_STATUS_MAX_ENUM
:
61 NOTREACHED() << "Unknown Termination Status.";
65 static std::string
PermissionTypeToString(BrowserPluginPermissionType type
) {
67 case BROWSER_PLUGIN_PERMISSION_TYPE_DOWNLOAD
:
68 return webview::kPermissionTypeDownload
;
69 case BROWSER_PLUGIN_PERMISSION_TYPE_GEOLOCATION
:
70 return webview::kPermissionTypeGeolocation
;
71 case BROWSER_PLUGIN_PERMISSION_TYPE_MEDIA
:
72 return webview::kPermissionTypeMedia
;
73 case BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW
:
74 return webview::kPermissionTypeNewWindow
;
75 case BROWSER_PLUGIN_PERMISSION_TYPE_POINTER_LOCK
:
76 return webview::kPermissionTypePointerLock
;
77 case BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG
:
78 return webview::kPermissionTypeDialog
;
79 case BROWSER_PLUGIN_PERMISSION_TYPE_UNKNOWN
:
83 WebViewPermissionType webview
= static_cast<WebViewPermissionType
>(type
);
85 case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN
:
86 return webview::kPermissionTypeLoadPlugin
;
94 void RemoveWebViewEventListenersOnIOThread(
96 const std::string
& extension_id
,
97 int embedder_process_id
,
98 int view_instance_id
) {
99 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO
));
100 ExtensionWebRequestEventRouter::GetInstance()->RemoveWebViewEventListeners(
107 void AttachWebViewHelpers(WebContents
* contents
) {
108 FaviconTabHelper::CreateForWebContents(contents
);
109 extensions::ExtensionWebContentsObserver::CreateForWebContents(contents
);
110 #if defined(ENABLE_PLUGINS)
111 PluginPermissionHelper::CreateForWebContents(contents
);
117 WebViewGuest::WebViewGuest(WebContents
* guest_web_contents
,
118 const std::string
& extension_id
)
119 : GuestView(guest_web_contents
, extension_id
),
120 WebContentsObserver(guest_web_contents
),
121 script_executor_(new extensions::ScriptExecutor(guest_web_contents
,
122 &script_observers_
)),
123 next_permission_request_id_(0),
124 is_overriding_user_agent_(false),
125 pending_reload_on_attachment_(false) {
126 notification_registrar_
.Add(
127 this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME
,
128 content::Source
<WebContents
>(guest_web_contents
));
130 notification_registrar_
.Add(
131 this, content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT
,
132 content::Source
<WebContents
>(guest_web_contents
));
134 AttachWebViewHelpers(guest_web_contents
);
138 WebViewGuest
* WebViewGuest::From(int embedder_process_id
,
139 int guest_instance_id
) {
140 GuestView
* guest
= GuestView::From(embedder_process_id
, guest_instance_id
);
143 return guest
->AsWebView();
147 WebViewGuest
* WebViewGuest::FromWebContents(WebContents
* contents
) {
148 GuestView
* guest
= GuestView::FromWebContents(contents
);
149 return guest
? guest
->AsWebView() : NULL
;
153 void WebViewGuest::RecordUserInitiatedUMA(const PermissionResponseInfo
& info
,
156 // Note that |allow| == true means the embedder explicitly allowed the
157 // request. For some requests they might still fail. An example of such
158 // scenario would be: an embedder allows geolocation request but doesn't
159 // have geolocation access on its own.
160 switch (info
.permission_type
) {
161 case BROWSER_PLUGIN_PERMISSION_TYPE_DOWNLOAD
:
162 content::RecordAction(
163 UserMetricsAction("BrowserPlugin.PermissionAllow.Download"));
165 case BROWSER_PLUGIN_PERMISSION_TYPE_GEOLOCATION
:
166 content::RecordAction(
167 UserMetricsAction("BrowserPlugin.PermissionAllow.Geolocation"));
169 case BROWSER_PLUGIN_PERMISSION_TYPE_MEDIA
:
170 content::RecordAction(
171 UserMetricsAction("BrowserPlugin.PermissionAllow.Media"));
173 case BROWSER_PLUGIN_PERMISSION_TYPE_POINTER_LOCK
:
174 content::RecordAction(
175 UserMetricsAction("BrowserPlugin.PermissionAllow.PointerLock"));
177 case BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW
:
178 content::RecordAction(
179 UserMetricsAction("BrowserPlugin.PermissionAllow.NewWindow"));
181 case BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG
:
182 content::RecordAction(
183 UserMetricsAction("BrowserPlugin.PermissionAllow.JSDialog"));
185 case BROWSER_PLUGIN_PERMISSION_TYPE_UNKNOWN
:
188 WebViewPermissionType webview_permission_type
=
189 static_cast<WebViewPermissionType
>(info
.permission_type
);
190 switch (webview_permission_type
) {
191 case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN
:
192 content::RecordAction(
193 UserMetricsAction("WebView.Guest.PermissionAllow.PluginLoad"));
201 switch (info
.permission_type
) {
202 case BROWSER_PLUGIN_PERMISSION_TYPE_DOWNLOAD
:
203 content::RecordAction(
204 UserMetricsAction("BrowserPlugin.PermissionDeny.Download"));
206 case BROWSER_PLUGIN_PERMISSION_TYPE_GEOLOCATION
:
207 content::RecordAction(
208 UserMetricsAction("BrowserPlugin.PermissionDeny.Geolocation"));
210 case BROWSER_PLUGIN_PERMISSION_TYPE_MEDIA
:
211 content::RecordAction(
212 UserMetricsAction("BrowserPlugin.PermissionDeny.Media"));
214 case BROWSER_PLUGIN_PERMISSION_TYPE_POINTER_LOCK
:
215 content::RecordAction(
216 UserMetricsAction("BrowserPlugin.PermissionDeny.PointerLock"));
218 case BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW
:
219 content::RecordAction(
220 UserMetricsAction("BrowserPlugin.PermissionDeny.NewWindow"));
222 case BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG
:
223 content::RecordAction(
224 UserMetricsAction("BrowserPlugin.PermissionDeny.JSDialog"));
226 case BROWSER_PLUGIN_PERMISSION_TYPE_UNKNOWN
:
229 WebViewPermissionType webview_permission_type
=
230 static_cast<WebViewPermissionType
>(info
.permission_type
);
231 switch (webview_permission_type
) {
232 case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN
:
233 content::RecordAction(
234 UserMetricsAction("WebView.Guest.PermissionDeny.PluginLoad"));
244 void WebViewGuest::Attach(WebContents
* embedder_web_contents
,
245 const base::DictionaryValue
& args
) {
246 std::string user_agent_override
;
247 if (args
.GetString(webview::kParameterUserAgentOverride
,
248 &user_agent_override
)) {
249 SetUserAgentOverride(user_agent_override
);
251 SetUserAgentOverride("");
254 GuestView::Attach(embedder_web_contents
, args
);
256 AddWebViewToExtensionRendererState();
259 GuestView::Type
WebViewGuest::GetViewType() const {
260 return GuestView::WEBVIEW
;
263 WebViewGuest
* WebViewGuest::AsWebView() {
267 AdViewGuest
* WebViewGuest::AsAdView() {
271 void WebViewGuest::AddMessageToConsole(int32 level
,
272 const base::string16
& message
,
274 const base::string16
& source_id
) {
275 scoped_ptr
<base::DictionaryValue
> args(new base::DictionaryValue());
276 // Log levels are from base/logging.h: LogSeverity.
277 args
->SetInteger(webview::kLevel
, level
);
278 args
->SetString(webview::kMessage
, message
);
279 args
->SetInteger(webview::kLine
, line_no
);
280 args
->SetString(webview::kSourceId
, source_id
);
282 new GuestView::Event(webview::kEventConsoleMessage
, args
.Pass()));
285 void WebViewGuest::Close() {
286 scoped_ptr
<base::DictionaryValue
> args(new base::DictionaryValue());
287 DispatchEvent(new GuestView::Event(webview::kEventClose
, args
.Pass()));
290 void WebViewGuest::DidAttach() {
291 if (pending_reload_on_attachment_
) {
292 pending_reload_on_attachment_
= false;
293 guest_web_contents()->GetController().Reload(false);
297 void WebViewGuest::EmbedderDestroyed() {
298 // TODO(fsamuel): WebRequest event listeners for <webview> should survive
299 // reparenting of a <webview> within a single embedder. Right now, we keep
300 // around the browser state for the listener for the lifetime of the embedder.
301 // Ideally, the lifetime of the listeners should match the lifetime of the
302 // <webview> DOM node. Once http://crbug.com/156219 is resolved we can move
303 // the call to RemoveWebViewEventListenersOnIOThread back to
304 // WebViewGuest::WebContentsDestroyed.
305 content::BrowserThread::PostTask(
306 content::BrowserThread::IO
,
309 &RemoveWebViewEventListenersOnIOThread
,
310 browser_context(), extension_id(),
311 embedder_render_process_id(),
312 view_instance_id()));
315 void WebViewGuest::GuestProcessGone(base::TerminationStatus status
) {
316 scoped_ptr
<base::DictionaryValue
> args(new base::DictionaryValue());
317 args
->SetInteger(webview::kProcessId
,
318 web_contents()->GetRenderProcessHost()->GetID());
319 args
->SetString(webview::kReason
, TerminationStatusToString(status
));
321 new GuestView::Event(webview::kEventExit
, args
.Pass()));
324 bool WebViewGuest::HandleKeyboardEvent(
325 const content::NativeWebKeyboardEvent
& event
) {
326 if (event
.type
!= blink::WebInputEvent::RawKeyDown
)
329 #if defined(OS_MACOSX)
330 if (event
.modifiers
!= blink::WebInputEvent::MetaKey
)
333 if (event
.windowsKeyCode
== ui::VKEY_OEM_4
) {
338 if (event
.windowsKeyCode
== ui::VKEY_OEM_6
) {
343 if (event
.windowsKeyCode
== ui::VKEY_BROWSER_BACK
) {
348 if (event
.windowsKeyCode
== ui::VKEY_BROWSER_FORWARD
) {
356 bool WebViewGuest::IsDragAndDropEnabled() {
357 #if defined(OS_CHROMEOS)
360 chrome::VersionInfo::Channel channel
= chrome::VersionInfo::GetChannel();
361 if (channel
!= chrome::VersionInfo::CHANNEL_STABLE
&&
362 channel
!= chrome::VersionInfo::CHANNEL_BETA
) {
363 // Drag and drop is enabled in canary and dev channel.
367 return CommandLine::ForCurrentProcess()->HasSwitch(
368 switches::kEnableBrowserPluginDragDrop
);
372 bool WebViewGuest::IsOverridingUserAgent() const {
373 return is_overriding_user_agent_
;
376 void WebViewGuest::LoadProgressed(double progress
) {
377 scoped_ptr
<base::DictionaryValue
> args(new base::DictionaryValue());
378 args
->SetString(guestview::kUrl
, web_contents()->GetURL().spec());
379 args
->SetDouble(webview::kProgress
, progress
);
380 DispatchEvent(new GuestView::Event(webview::kEventLoadProgress
, args
.Pass()));
383 void WebViewGuest::LoadAbort(bool is_top_level
,
385 const std::string
& error_type
) {
386 scoped_ptr
<base::DictionaryValue
> args(new base::DictionaryValue());
387 args
->SetBoolean(guestview::kIsTopLevel
, is_top_level
);
388 args
->SetString(guestview::kUrl
, url
.possibly_invalid_spec());
389 args
->SetString(guestview::kReason
, error_type
);
390 DispatchEvent(new GuestView::Event(webview::kEventLoadAbort
, args
.Pass()));
393 // TODO(fsamuel): Find a reliable way to test the 'responsive' and
394 // 'unresponsive' events.
395 void WebViewGuest::RendererResponsive() {
396 scoped_ptr
<base::DictionaryValue
> args(new base::DictionaryValue());
397 args
->SetInteger(webview::kProcessId
,
398 guest_web_contents()->GetRenderProcessHost()->GetID());
399 DispatchEvent(new GuestView::Event(webview::kEventResponsive
, args
.Pass()));
402 void WebViewGuest::RendererUnresponsive() {
403 scoped_ptr
<base::DictionaryValue
> args(new base::DictionaryValue());
404 args
->SetInteger(webview::kProcessId
,
405 guest_web_contents()->GetRenderProcessHost()->GetID());
406 DispatchEvent(new GuestView::Event(webview::kEventUnresponsive
, args
.Pass()));
409 bool WebViewGuest::RequestPermission(
410 BrowserPluginPermissionType permission_type
,
411 const base::DictionaryValue
& request_info
,
412 const PermissionResponseCallback
& callback
,
413 bool allowed_by_default
) {
414 // If there are too many pending permission requests then reject this request.
415 if (pending_permission_requests_
.size() >=
416 webview::kMaxOutstandingPermissionRequests
) {
417 callback
.Run(false, std::string());
421 int request_id
= next_permission_request_id_
++;
422 pending_permission_requests_
[request_id
] =
423 PermissionResponseInfo(callback
, permission_type
, allowed_by_default
);
424 scoped_ptr
<base::DictionaryValue
> args(request_info
.DeepCopy());
425 args
->SetInteger(webview::kRequestId
, request_id
);
426 switch (permission_type
) {
427 case BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW
: {
428 DispatchEvent(new GuestView::Event(webview::kEventNewWindow
,
432 case BROWSER_PLUGIN_PERMISSION_TYPE_JAVASCRIPT_DIALOG
: {
433 chrome::VersionInfo::Channel channel
= chrome::VersionInfo::GetChannel();
434 if (channel
> chrome::VersionInfo::CHANNEL_DEV
) {
435 // 'dialog' API is not available in stable/beta.
436 callback
.Run(false, std::string());
439 DispatchEvent(new GuestView::Event(webview::kEventDialog
,
444 args
->SetString(webview::kPermission
,
445 PermissionTypeToString(permission_type
));
446 DispatchEvent(new GuestView::Event(webview::kEventPermissionRequest
,
454 void WebViewGuest::Observe(int type
,
455 const content::NotificationSource
& source
,
456 const content::NotificationDetails
& details
) {
458 case content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME
: {
459 DCHECK_EQ(content::Source
<WebContents
>(source
).ptr(),
460 guest_web_contents());
461 if (content::Source
<WebContents
>(source
).ptr() == guest_web_contents())
465 case content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT
: {
466 DCHECK_EQ(content::Source
<WebContents
>(source
).ptr(),
467 guest_web_contents());
468 content::ResourceRedirectDetails
* resource_redirect_details
=
469 content::Details
<content::ResourceRedirectDetails
>(details
).ptr();
471 resource_redirect_details
->resource_type
== ResourceType::MAIN_FRAME
;
472 LoadRedirect(resource_redirect_details
->url
,
473 resource_redirect_details
->new_url
,
478 NOTREACHED() << "Unexpected notification sent.";
483 void WebViewGuest::Go(int relative_index
) {
484 guest_web_contents()->GetController().GoToOffset(relative_index
);
487 void WebViewGuest::Reload() {
488 // TODO(fsamuel): Don't check for repost because we don't want to show
489 // Chromium's repost warning. We might want to implement a separate API
490 // for registering a callback if a repost is about to happen.
491 guest_web_contents()->GetController().Reload(false);
494 WebViewGuest::SetPermissionResult
WebViewGuest::SetPermission(
496 PermissionResponseAction action
,
497 const std::string
& user_input
) {
498 RequestMap::iterator request_itr
=
499 pending_permission_requests_
.find(request_id
);
501 if (request_itr
== pending_permission_requests_
.end())
502 return SET_PERMISSION_INVALID
;
504 const PermissionResponseInfo
& info
= request_itr
->second
;
505 bool allow
= (action
== ALLOW
) ||
506 ((action
== DEFAULT
) && info
.allowed_by_default
);
508 info
.callback
.Run(allow
, user_input
);
510 // Only record user initiated (i.e. non-default) actions.
511 if (action
!= DEFAULT
)
512 RecordUserInitiatedUMA(info
, allow
);
514 pending_permission_requests_
.erase(request_itr
);
516 return allow
? SET_PERMISSION_ALLOWED
: SET_PERMISSION_DENIED
;
519 void WebViewGuest::SetUserAgentOverride(
520 const std::string
& user_agent_override
) {
521 is_overriding_user_agent_
= !user_agent_override
.empty();
522 if (is_overriding_user_agent_
) {
523 content::RecordAction(UserMetricsAction("WebView.Guest.OverrideUA"));
525 guest_web_contents()->SetUserAgentOverride(user_agent_override
);
528 void WebViewGuest::Stop() {
529 guest_web_contents()->Stop();
532 void WebViewGuest::Terminate() {
533 content::RecordAction(UserMetricsAction("WebView.Guest.Terminate"));
534 base::ProcessHandle process_handle
=
535 guest_web_contents()->GetRenderProcessHost()->GetHandle();
537 base::KillProcess(process_handle
, content::RESULT_CODE_KILLED
, false);
540 bool WebViewGuest::ClearData(const base::Time remove_since
,
542 const base::Closure
& callback
) {
543 content::RecordAction(UserMetricsAction("WebView.Guest.ClearData"));
544 content::StoragePartition
* partition
=
545 content::BrowserContext::GetStoragePartition(
546 web_contents()->GetBrowserContext(),
547 web_contents()->GetSiteInstance());
552 partition
->ClearData(
554 content::StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL
,
556 content::StoragePartition::OriginMatcherFunction(),
563 WebViewGuest::~WebViewGuest() {
566 void WebViewGuest::DidCommitProvisionalLoadForFrame(
568 const base::string16
& frame_unique_name
,
571 content::PageTransition transition_type
,
572 content::RenderViewHost
* render_view_host
) {
573 scoped_ptr
<base::DictionaryValue
> args(new base::DictionaryValue());
574 args
->SetString(guestview::kUrl
, url
.spec());
575 args
->SetBoolean(guestview::kIsTopLevel
, is_main_frame
);
576 args
->SetInteger(webview::kInternalCurrentEntryIndex
,
577 web_contents()->GetController().GetCurrentEntryIndex());
578 args
->SetInteger(webview::kInternalEntryCount
,
579 web_contents()->GetController().GetEntryCount());
580 args
->SetInteger(webview::kInternalProcessId
,
581 web_contents()->GetRenderProcessHost()->GetID());
582 DispatchEvent(new GuestView::Event(webview::kEventLoadCommit
, args
.Pass()));
585 void WebViewGuest::DidFailProvisionalLoad(
587 const base::string16
& frame_unique_name
,
589 const GURL
& validated_url
,
591 const base::string16
& error_description
,
592 content::RenderViewHost
* render_view_host
) {
593 // Translate the |error_code| into an error string.
594 std::string error_type
;
595 base::RemoveChars(net::ErrorToString(error_code
), "net::", &error_type
);
596 LoadAbort(is_main_frame
, validated_url
, error_type
);
599 void WebViewGuest::DidStartProvisionalLoadForFrame(
601 int64 parent_frame_id
,
603 const GURL
& validated_url
,
605 bool is_iframe_srcdoc
,
606 content::RenderViewHost
* render_view_host
) {
607 scoped_ptr
<base::DictionaryValue
> args(new base::DictionaryValue());
608 args
->SetString(guestview::kUrl
, validated_url
.spec());
609 args
->SetBoolean(guestview::kIsTopLevel
, is_main_frame
);
610 DispatchEvent(new GuestView::Event(webview::kEventLoadStart
, args
.Pass()));
613 void WebViewGuest::DidStopLoading(content::RenderViewHost
* render_view_host
) {
614 scoped_ptr
<base::DictionaryValue
> args(new base::DictionaryValue());
615 DispatchEvent(new GuestView::Event(webview::kEventLoadStop
, args
.Pass()));
618 void WebViewGuest::WebContentsDestroyed(WebContents
* web_contents
) {
619 RemoveWebViewFromExtensionRendererState(web_contents
);
622 void WebViewGuest::UserAgentOverrideSet(const std::string
& user_agent
) {
623 content::NavigationController
& controller
=
624 guest_web_contents()->GetController();
625 content::NavigationEntry
* entry
= controller
.GetVisibleEntry();
628 entry
->SetIsOverridingUserAgent(!user_agent
.empty());
630 // We cannot reload now because all resource loads are suspended until
632 pending_reload_on_attachment_
= true;
635 guest_web_contents()->GetController().Reload(false);
638 void WebViewGuest::LoadHandlerCalled() {
639 scoped_ptr
<base::DictionaryValue
> args(new base::DictionaryValue());
640 DispatchEvent(new GuestView::Event(webview::kEventContentLoad
, args
.Pass()));
643 void WebViewGuest::LoadRedirect(const GURL
& old_url
,
646 scoped_ptr
<base::DictionaryValue
> args(new base::DictionaryValue());
647 args
->SetBoolean(guestview::kIsTopLevel
, is_top_level
);
648 args
->SetString(webview::kNewURL
, new_url
.spec());
649 args
->SetString(webview::kOldURL
, old_url
.spec());
650 DispatchEvent(new GuestView::Event(webview::kEventLoadRedirect
, args
.Pass()));
654 bool WebViewGuest::AllowChromeExtensionURLs() {
655 chrome::VersionInfo::Channel channel
= chrome::VersionInfo::GetChannel();
656 return channel
<= chrome::VersionInfo::CHANNEL_DEV
;
659 void WebViewGuest::AddWebViewToExtensionRendererState() {
660 const GURL
& site_url
= web_contents()->GetSiteInstance()->GetSiteURL();
661 std::string partition_domain
;
662 std::string partition_id
;
664 if (!GetGuestPartitionConfigForSite(
665 site_url
, &partition_domain
, &partition_id
, &in_memory
)) {
669 DCHECK(extension_id() == partition_domain
);
671 ExtensionRendererState::WebViewInfo webview_info
;
672 webview_info
.embedder_process_id
= embedder_render_process_id();
673 webview_info
.instance_id
= view_instance_id();
674 webview_info
.partition_id
= partition_id
;
675 webview_info
.extension_id
= extension_id();
676 webview_info
.allow_chrome_extension_urls
= AllowChromeExtensionURLs();
678 content::BrowserThread::PostTask(
679 content::BrowserThread::IO
, FROM_HERE
,
681 &ExtensionRendererState::AddWebView
,
682 base::Unretained(ExtensionRendererState::GetInstance()),
683 guest_web_contents()->GetRenderProcessHost()->GetID(),
684 guest_web_contents()->GetRoutingID(),
689 void WebViewGuest::RemoveWebViewFromExtensionRendererState(
690 WebContents
* web_contents
) {
691 content::BrowserThread::PostTask(
692 content::BrowserThread::IO
, FROM_HERE
,
694 &ExtensionRendererState::RemoveWebView
,
695 base::Unretained(ExtensionRendererState::GetInstance()),
696 web_contents
->GetRenderProcessHost()->GetID(),
697 web_contents
->GetRoutingID()));
700 GURL
WebViewGuest::ResolveURL(const std::string
& src
) {
701 if (extension_id().empty()) {
706 // Only resolve URL to chrome-extension:// if we support such URLs.
707 if (!AllowChromeExtensionURLs())
710 GURL
default_url(base::StringPrintf("%s://%s/",
711 extensions::kExtensionScheme
,
712 extension_id().c_str()));
713 return default_url
.Resolve(src
);
716 void WebViewGuest::SizeChanged(const gfx::Size
& old_size
,
717 const gfx::Size
& new_size
) {
718 scoped_ptr
<base::DictionaryValue
> args(new base::DictionaryValue());
719 args
->SetInteger(webview::kOldHeight
, old_size
.height());
720 args
->SetInteger(webview::kOldWidth
, old_size
.width());
721 args
->SetInteger(webview::kNewHeight
, new_size
.height());
722 args
->SetInteger(webview::kNewWidth
, new_size
.width());
723 DispatchEvent(new GuestView::Event(webview::kEventSizeChanged
, args
.Pass()));
726 WebViewGuest::PermissionResponseInfo::PermissionResponseInfo()
727 : permission_type(BROWSER_PLUGIN_PERMISSION_TYPE_UNKNOWN
),
728 allowed_by_default(false) {
731 WebViewGuest::PermissionResponseInfo::PermissionResponseInfo(
732 const PermissionResponseCallback
& callback
,
733 BrowserPluginPermissionType permission_type
,
734 bool allowed_by_default
)
735 : callback(callback
),
736 permission_type(permission_type
),
737 allowed_by_default(allowed_by_default
) {
740 WebViewGuest::PermissionResponseInfo::~PermissionResponseInfo() {