| Index: chrome/browser/guest_view/web_view/web_view_guest.cc
|
| diff --git a/chrome/browser/guest_view/web_view/web_view_guest.cc b/chrome/browser/guest_view/web_view/web_view_guest.cc
|
| index 02279b2e0bc0b0b2479e46eac2a63c8e623bca27..465495e7a3c9cfd107f733072dbdaa9218b49dcd 100644
|
| --- a/chrome/browser/guest_view/web_view/web_view_guest.cc
|
| +++ b/chrome/browser/guest_view/web_view/web_view_guest.cc
|
| @@ -4,8 +4,10 @@
|
|
|
| #include "chrome/browser/guest_view/web_view/web_view_guest.h"
|
|
|
| +#include "base/debug/stack_trace.h"
|
| #include "base/message_loop/message_loop.h"
|
| #include "base/strings/stringprintf.h"
|
| +#include "base/strings/utf_string_conversions.h"
|
| #include "chrome/browser/chrome_notification_types.h"
|
| #include "chrome/browser/extensions/api/web_request/web_request_api.h"
|
| #include "chrome/browser/extensions/api/webview/webview_api.h"
|
| @@ -15,12 +17,14 @@
|
| #include "chrome/browser/extensions/script_executor.h"
|
| #include "chrome/browser/favicon/favicon_tab_helper.h"
|
| #include "chrome/browser/guest_view/guest_view_constants.h"
|
| +#include "chrome/browser/guest_view/guest_view_manager.h"
|
| #include "chrome/browser/guest_view/web_view/web_view_constants.h"
|
| #include "chrome/browser/guest_view/web_view/web_view_permission_types.h"
|
| #include "chrome/browser/renderer_context_menu/context_menu_delegate.h"
|
| #include "chrome/browser/renderer_context_menu/render_view_context_menu.h"
|
| #include "chrome/common/chrome_version_info.h"
|
| #include "content/public/browser/browser_thread.h"
|
| +#include "content/public/browser/child_process_security_policy.h"
|
| #include "content/public/browser/geolocation_permission_context.h"
|
| #include "content/public/browser/native_web_keyboard_event.h"
|
| #include "content/public/browser/navigation_entry.h"
|
| @@ -39,6 +43,7 @@
|
| #include "content/public/common/page_zoom.h"
|
| #include "content/public/common/result_codes.h"
|
| #include "content/public/common/stop_find_action.h"
|
| +#include "content/public/common/url_constants.h"
|
| #include "extensions/common/constants.h"
|
| #include "net/base/net_errors.h"
|
| #include "third_party/WebKit/public/web/WebFindOptions.h"
|
| @@ -66,6 +71,29 @@ using content::WebContents;
|
|
|
| namespace {
|
|
|
| +std::string WindowOpenDispositionToString(
|
| + WindowOpenDisposition window_open_disposition) {
|
| + switch (window_open_disposition) {
|
| + case IGNORE_ACTION:
|
| + return "ignore";
|
| + case SAVE_TO_DISK:
|
| + return "save_to_disk";
|
| + case CURRENT_TAB:
|
| + return "current_tab";
|
| + case NEW_BACKGROUND_TAB:
|
| + return "new_background_tab";
|
| + case NEW_FOREGROUND_TAB:
|
| + return "new_foreground_tab";
|
| + case NEW_WINDOW:
|
| + return "new_window";
|
| + case NEW_POPUP:
|
| + return "new_popup";
|
| + default:
|
| + NOTREACHED() << "Unknown Window Open Disposition";
|
| + return "ignore";
|
| + }
|
| +}
|
| +
|
| static std::string TerminationStatusToString(base::TerminationStatus status) {
|
| switch (status) {
|
| case base::TERMINATION_STATUS_NORMAL_TERMINATION:
|
| @@ -87,33 +115,26 @@ static std::string TerminationStatusToString(base::TerminationStatus status) {
|
| return "unknown";
|
| }
|
|
|
| -static std::string PermissionTypeToString(BrowserPluginPermissionType type) {
|
| +static std::string PermissionTypeToString(WebViewPermissionType type) {
|
| switch (type) {
|
| - case BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW:
|
| + case WEB_VIEW_PERMISSION_TYPE_DOWNLOAD:
|
| + return webview::kPermissionTypeDownload;
|
| + case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION:
|
| + return webview::kPermissionTypeGeolocation;
|
| + case WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG:
|
| + return webview::kPermissionTypeDialog;
|
| + case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
|
| + return webview::kPermissionTypeLoadPlugin;
|
| + case WEB_VIEW_PERMISSION_TYPE_MEDIA:
|
| + return webview::kPermissionTypeMedia;
|
| + case WEB_VIEW_PERMISSION_TYPE_NEW_WINDOW:
|
| return webview::kPermissionTypeNewWindow;
|
| - case BROWSER_PLUGIN_PERMISSION_TYPE_UNKNOWN:
|
| - NOTREACHED();
|
| - break;
|
| - default: {
|
| - WebViewPermissionType webview = static_cast<WebViewPermissionType>(type);
|
| - switch (webview) {
|
| - case WEB_VIEW_PERMISSION_TYPE_DOWNLOAD:
|
| - return webview::kPermissionTypeDownload;
|
| - case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION:
|
| - return webview::kPermissionTypeGeolocation;
|
| - case WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG:
|
| - return webview::kPermissionTypeDialog;
|
| - case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
|
| - return webview::kPermissionTypeLoadPlugin;
|
| - case WEB_VIEW_PERMISSION_TYPE_MEDIA:
|
| - return webview::kPermissionTypeMedia;
|
| - case WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK:
|
| - return webview::kPermissionTypePointerLock;
|
| - }
|
| + case WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK:
|
| + return webview::kPermissionTypePointerLock;
|
| + default:
|
| NOTREACHED();
|
| - }
|
| + return std::string();
|
| }
|
| - return std::string();
|
| }
|
|
|
| void RemoveWebViewEventListenersOnIOThread(
|
| @@ -148,12 +169,12 @@ void AttachWebViewHelpers(WebContents* contents) {
|
|
|
| } // namespace
|
|
|
| -WebViewGuest::WebViewGuest(WebContents* guest_web_contents,
|
| - const std::string& embedder_extension_id,
|
| - const base::WeakPtr<GuestViewBase>& opener)
|
| - : GuestView<WebViewGuest>(guest_web_contents,
|
| - embedder_extension_id,
|
| - opener),
|
| +WebViewGuest::WebViewGuest(int guest_instance_id,
|
| + WebContents* guest_web_contents,
|
| + const std::string& embedder_extension_id)
|
| + : GuestView<WebViewGuest>(guest_instance_id,
|
| + guest_web_contents,
|
| + embedder_extension_id),
|
| WebContentsObserver(guest_web_contents),
|
| script_executor_(new extensions::ScriptExecutor(guest_web_contents,
|
| &script_observers_)),
|
| @@ -206,83 +227,67 @@ void WebViewGuest::RecordUserInitiatedUMA(const PermissionResponseInfo& info,
|
| // scenario would be: an embedder allows geolocation request but doesn't
|
| // have geolocation access on its own.
|
| switch (info.permission_type) {
|
| - case BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW:
|
| + case WEB_VIEW_PERMISSION_TYPE_DOWNLOAD:
|
| + content::RecordAction(
|
| + UserMetricsAction("WebView.PermissionAllow.Download"));
|
| + break;
|
| + case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION:
|
| + content::RecordAction(
|
| + UserMetricsAction("WebView.PermissionAllow.Geolocation"));
|
| + break;
|
| + case WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG:
|
| + content::RecordAction(
|
| + UserMetricsAction("WebView.PermissionAllow.JSDialog"));
|
| + break;
|
| + case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
|
| + content::RecordAction(
|
| + UserMetricsAction("WebView.Guest.PermissionAllow.PluginLoad"));
|
| + case WEB_VIEW_PERMISSION_TYPE_MEDIA:
|
| + content::RecordAction(
|
| + UserMetricsAction("WebView.PermissionAllow.Media"));
|
| + break;
|
| + case WEB_VIEW_PERMISSION_TYPE_NEW_WINDOW:
|
| content::RecordAction(
|
| UserMetricsAction("BrowserPlugin.PermissionAllow.NewWindow"));
|
| break;
|
| - case BROWSER_PLUGIN_PERMISSION_TYPE_UNKNOWN:
|
| + case WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK:
|
| + content::RecordAction(
|
| + UserMetricsAction("WebView.PermissionAllow.PointerLock"));
|
| + break;
|
| + default:
|
| break;
|
| - default: {
|
| - WebViewPermissionType webview_permission_type =
|
| - static_cast<WebViewPermissionType>(info.permission_type);
|
| - switch (webview_permission_type) {
|
| - case WEB_VIEW_PERMISSION_TYPE_DOWNLOAD:
|
| - content::RecordAction(
|
| - UserMetricsAction("WebView.PermissionAllow.Download"));
|
| - break;
|
| - case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION:
|
| - content::RecordAction(
|
| - UserMetricsAction("WebView.PermissionAllow.Geolocation"));
|
| - break;
|
| - case WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG:
|
| - content::RecordAction(
|
| - UserMetricsAction("WebView.PermissionAllow.JSDialog"));
|
| - break;
|
| - case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
|
| - content::RecordAction(
|
| - UserMetricsAction("WebView.Guest.PermissionAllow.PluginLoad"));
|
| - case WEB_VIEW_PERMISSION_TYPE_MEDIA:
|
| - content::RecordAction(
|
| - UserMetricsAction("WebView.PermissionAllow.Media"));
|
| - break;
|
| - case WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK:
|
| - content::RecordAction(
|
| - UserMetricsAction("WebView.PermissionAllow.PointerLock"));
|
| - break;
|
| - default:
|
| - break;
|
| - }
|
| - }
|
| }
|
| } else {
|
| switch (info.permission_type) {
|
| - case BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW:
|
| + case WEB_VIEW_PERMISSION_TYPE_DOWNLOAD:
|
| + content::RecordAction(
|
| + UserMetricsAction("WebView.PermissionDeny.Download"));
|
| + break;
|
| + case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION:
|
| + content::RecordAction(
|
| + UserMetricsAction("WebView.PermissionDeny.Geolocation"));
|
| + break;
|
| + case WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG:
|
| + content::RecordAction(
|
| + UserMetricsAction("WebView.PermissionDeny.JSDialog"));
|
| + break;
|
| + case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
|
| + content::RecordAction(
|
| + UserMetricsAction("WebView.Guest.PermissionDeny.PluginLoad"));
|
| + case WEB_VIEW_PERMISSION_TYPE_MEDIA:
|
| + content::RecordAction(
|
| + UserMetricsAction("WebView.PermissionDeny.Media"));
|
| + break;
|
| + case WEB_VIEW_PERMISSION_TYPE_NEW_WINDOW:
|
| content::RecordAction(
|
| UserMetricsAction("BrowserPlugin.PermissionDeny.NewWindow"));
|
| break;
|
| - case BROWSER_PLUGIN_PERMISSION_TYPE_UNKNOWN:
|
| + case WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK:
|
| + content::RecordAction(
|
| + UserMetricsAction("WebView.PermissionDeny.PointerLock"));
|
| + break;
|
| + default:
|
| break;
|
| - default: {
|
| - WebViewPermissionType webview_permission_type =
|
| - static_cast<WebViewPermissionType>(info.permission_type);
|
| - switch (webview_permission_type) {
|
| - case WEB_VIEW_PERMISSION_TYPE_DOWNLOAD:
|
| - content::RecordAction(
|
| - UserMetricsAction("WebView.PermissionDeny.Download"));
|
| - break;
|
| - case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION:
|
| - content::RecordAction(
|
| - UserMetricsAction("WebView.PermissionDeny.Geolocation"));
|
| - break;
|
| - case WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG:
|
| - content::RecordAction(
|
| - UserMetricsAction("WebView.PermissionDeny.JSDialog"));
|
| - break;
|
| - case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
|
| - content::RecordAction(
|
| - UserMetricsAction("WebView.Guest.PermissionDeny.PluginLoad"));
|
| - case WEB_VIEW_PERMISSION_TYPE_MEDIA:
|
| - content::RecordAction(
|
| - UserMetricsAction("WebView.PermissionDeny.Media"));
|
| - break;
|
| - case WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK:
|
| - content::RecordAction(
|
| - UserMetricsAction("WebView.PermissionDeny.PointerLock"));
|
| - break;
|
| - default:
|
| - break;
|
| - }
|
| - }
|
| }
|
| }
|
| }
|
| @@ -358,6 +363,25 @@ void WebViewGuest::Close() {
|
| }
|
|
|
| void WebViewGuest::DidAttach() {
|
| + if (GetOpener()) {
|
| + // We need to do a navigation here if the target URL has changed between
|
| + // the time the WebContents was created and the time it was attached.
|
| + // We also need to do an initial navigation if a RenderView was never
|
| + // created for the new window in cases where there is no referrer.
|
| + PendingWindowMap::iterator it =
|
| + GetOpener()->pending_new_windows_.find(this);
|
| + if (it != GetOpener()->pending_new_windows_.end()) {
|
| + const NewWindowInfo& new_window_info = it->second;
|
| + NavigateGuest(new_window_info.url.spec());
|
| + } else {
|
| + NOTREACHED();
|
| + }
|
| +
|
| + // Once a new guest is attached to the DOM of the embedder page, then the
|
| + // lifetime of the new guest is no longer managed by the opener guest.
|
| + GetOpener()->pending_new_windows_.erase(this);
|
| + }
|
| +
|
| if (pending_reload_on_attachment_) {
|
| pending_reload_on_attachment_ = false;
|
| guest_web_contents()->GetController().Reload(false);
|
| @@ -424,10 +448,6 @@ bool WebViewGuest::IsDragAndDropEnabled() {
|
| return true;
|
| }
|
|
|
| -bool WebViewGuest::IsOverridingUserAgent() const {
|
| - return is_overriding_user_agent_;
|
| -}
|
| -
|
| void WebViewGuest::LoadProgressed(double progress) {
|
| scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
|
| args->SetString(guestview::kUrl, guest_web_contents()->GetURL().spec());
|
| @@ -447,6 +467,45 @@ void WebViewGuest::LoadAbort(bool is_top_level,
|
| new GuestViewBase::Event(webview::kEventLoadAbort, args.Pass()));
|
| }
|
|
|
| +WebViewGuest* WebViewGuest::CreateNewGuestWindow(
|
| + const content::OpenURLParams& params) {
|
| +
|
| + GuestViewManager* guest_manager =
|
| + GuestViewManager::FromBrowserContext(browser_context());
|
| + // Allocate a new instance ID for the new guest.
|
| + int instance_id = guest_manager->GetNextInstanceID();
|
| +
|
| + // Set the attach params to use the same partition as the opener.
|
| + // We pull the partition information from the site's URL, which is of the
|
| + // form guest://site/{persist}?{partition_name}.
|
| + const GURL& site_url = guest_web_contents()->GetSiteInstance()->GetSiteURL();
|
| +
|
| + scoped_ptr<base::DictionaryValue> create_params(extra_params()->DeepCopy());
|
| + const std::string& storage_partition_id = site_url.query();
|
| + bool persist_storage =
|
| + site_url.path().find("persist") != std::string::npos;
|
| + WebContents* new_guest_web_contents =
|
| + guest_manager->CreateGuest(guest_web_contents()->GetSiteInstance(),
|
| + instance_id,
|
| + storage_partition_id,
|
| + persist_storage,
|
| + create_params.Pass());
|
| + WebViewGuest* new_guest =
|
| + WebViewGuest::FromWebContents(new_guest_web_contents);
|
| + new_guest->SetOpener(this);
|
| +
|
| + // Take ownership of |new_guest|.
|
| + pending_new_windows_.insert(
|
| + std::make_pair(new_guest, NewWindowInfo(params.url, std::string())));
|
| +
|
| + // Request permission to show the new window.
|
| + RequestNewWindowPermission(params.disposition, gfx::Rect(),
|
| + params.user_gesture,
|
| + new_guest->guest_web_contents());
|
| +
|
| + return new_guest;
|
| +}
|
| +
|
| // TODO(fsamuel): Find a reliable way to test the 'responsive' and
|
| // 'unresponsive' events.
|
| void WebViewGuest::RendererResponsive() {
|
| @@ -465,17 +524,6 @@ void WebViewGuest::RendererUnresponsive() {
|
| new GuestViewBase::Event(webview::kEventUnresponsive, args.Pass()));
|
| }
|
|
|
| -void WebViewGuest::RequestPermission(
|
| - BrowserPluginPermissionType permission_type,
|
| - const base::DictionaryValue& request_info,
|
| - const PermissionResponseCallback& callback,
|
| - bool allowed_by_default) {
|
| - RequestPermissionInternal(permission_type,
|
| - request_info,
|
| - callback,
|
| - allowed_by_default);
|
| -}
|
| -
|
| void WebViewGuest::Observe(int type,
|
| const content::NotificationSource& source,
|
| const content::NotificationDetails& details) {
|
| @@ -545,7 +593,6 @@ void WebViewGuest::Reload() {
|
| guest_web_contents()->GetController().Reload(false);
|
| }
|
|
|
| -
|
| void WebViewGuest::RequestGeolocationPermission(
|
| int bridge_id,
|
| const GURL& requesting_frame,
|
| @@ -565,9 +612,8 @@ void WebViewGuest::RequestGeolocationPermission(
|
| bridge_id,
|
| user_gesture,
|
| callback);
|
| - int request_id = RequestPermissionInternal(
|
| - static_cast<BrowserPluginPermissionType>(
|
| - WEB_VIEW_PERMISSION_TYPE_GEOLOCATION),
|
| + int request_id = RequestPermission(
|
| + WEB_VIEW_PERMISSION_TYPE_GEOLOCATION,
|
| request_info,
|
| permission_callback,
|
| false /* allowed_by_default */);
|
| @@ -876,18 +922,6 @@ void WebViewGuest::RemoveWebViewFromExtensionRendererState(
|
| web_contents->GetRoutingID()));
|
| }
|
|
|
| -GURL WebViewGuest::ResolveURL(const std::string& src) {
|
| - if (!in_extension()) {
|
| - NOTREACHED();
|
| - return GURL(src);
|
| - }
|
| -
|
| - GURL default_url(base::StringPrintf("%s://%s/",
|
| - extensions::kExtensionScheme,
|
| - embedder_extension_id().c_str()));
|
| - return default_url.Resolve(src);
|
| -}
|
| -
|
| void WebViewGuest::SizeChanged(const gfx::Size& old_size,
|
| const gfx::Size& new_size) {
|
| scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
|
| @@ -906,8 +940,7 @@ void WebViewGuest::RequestMediaAccessPermission(
|
| request_info.Set(
|
| guestview::kUrl,
|
| base::Value::CreateStringValue(request.security_origin.spec()));
|
| - RequestPermission(static_cast<BrowserPluginPermissionType>(
|
| - WEB_VIEW_PERMISSION_TYPE_MEDIA),
|
| + RequestPermission(WEB_VIEW_PERMISSION_TYPE_MEDIA,
|
| request_info,
|
| base::Bind(&WebViewGuest::OnWebViewMediaPermissionResponse,
|
| base::Unretained(this),
|
| @@ -925,8 +958,7 @@ void WebViewGuest::CanDownload(
|
| guestview::kUrl,
|
| base::Value::CreateStringValue(url.spec()));
|
| RequestPermission(
|
| - static_cast<BrowserPluginPermissionType>(
|
| - WEB_VIEW_PERMISSION_TYPE_DOWNLOAD),
|
| + WEB_VIEW_PERMISSION_TYPE_DOWNLOAD,
|
| request_info,
|
| base::Bind(&WebViewGuest::OnWebViewDownloadPermissionResponse,
|
| base::Unretained(this),
|
| @@ -948,8 +980,7 @@ void WebViewGuest::RequestPointerLockPermission(
|
| guest_web_contents()->GetLastCommittedURL().spec()));
|
|
|
| RequestPermission(
|
| - static_cast<BrowserPluginPermissionType>(
|
| - WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK),
|
| + WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK,
|
| request_info,
|
| base::Bind(&WebViewGuest::OnWebViewPointerLockPermissionResponse,
|
| base::Unretained(this),
|
| @@ -980,6 +1011,38 @@ void WebViewGuest::RunFileChooser(WebContents* web_contents,
|
| embedder_web_contents()->GetDelegate()->RunFileChooser(web_contents, params);
|
| }
|
|
|
| +void WebViewGuest::NavigateGuest(const std::string& src) {
|
| + GURL url = ResolveURL(src);
|
| +
|
| + // Do not allow navigating a guest to schemes other than known safe schemes.
|
| + // This will block the embedder trying to load unwanted schemes, e.g.
|
| + // chrome://settings.
|
| + bool scheme_is_blocked =
|
| + (!content::ChildProcessSecurityPolicy::GetInstance()->IsWebSafeScheme(
|
| + url.scheme()) &&
|
| + !url.SchemeIs(content::kAboutScheme)) ||
|
| + url.SchemeIs(content::kJavaScriptScheme);
|
| + if (scheme_is_blocked || !url.is_valid()) {
|
| + std::string error_type;
|
| + base::RemoveChars(net::ErrorToString(net::ERR_ABORTED), "net::",
|
| + &error_type);
|
| + LoadAbort(true /* is_top_level */, url, error_type);
|
| + return;
|
| + }
|
| +
|
| + GURL validated_url(url);
|
| + guest_web_contents()->GetRenderProcessHost()->
|
| + FilterURL(false, &validated_url);
|
| + // As guests do not swap processes on navigation, only navigations to
|
| + // normal web URLs are supported. No protocol handlers are installed for
|
| + // other schemes (e.g., WebUI or extensions), and no permissions or bindings
|
| + // can be granted to the guest process.
|
| + LoadURLWithParams(validated_url,
|
| + content::Referrer(),
|
| + content::PAGE_TRANSITION_AUTO_TOPLEVEL,
|
| + guest_web_contents());
|
| +}
|
| +
|
| #if defined(OS_CHROMEOS)
|
| void WebViewGuest::OnAccessibilityStatusChanged(
|
| const chromeos::AccessibilityStatusEventDetails& details) {
|
| @@ -1020,8 +1083,8 @@ int WebViewGuest::RemoveBridgeID(int bridge_id) {
|
| return request_id;
|
| }
|
|
|
| -int WebViewGuest::RequestPermissionInternal(
|
| - BrowserPluginPermissionType permission_type,
|
| +int WebViewGuest::RequestPermission(
|
| + WebViewPermissionType permission_type,
|
| const base::DictionaryValue& request_info,
|
| const PermissionResponseCallback& callback,
|
| bool allowed_by_default) {
|
| @@ -1046,8 +1109,8 @@ int WebViewGuest::RequestPermissionInternal(
|
| PermissionResponseInfo(callback, permission_type, allowed_by_default);
|
| scoped_ptr<base::DictionaryValue> args(request_info.DeepCopy());
|
| args->SetInteger(webview::kRequestId, request_id);
|
| - switch (static_cast<int>(permission_type)) {
|
| - case BROWSER_PLUGIN_PERMISSION_TYPE_NEW_WINDOW: {
|
| + switch (permission_type) {
|
| + case WEB_VIEW_PERMISSION_TYPE_NEW_WINDOW: {
|
| DispatchEvent(
|
| new GuestViewBase::Event(webview::kEventNewWindow, args.Pass()));
|
| break;
|
| @@ -1109,13 +1172,13 @@ bool WebViewGuest::HandleKeyboardShortcuts(
|
| }
|
|
|
| WebViewGuest::PermissionResponseInfo::PermissionResponseInfo()
|
| - : permission_type(BROWSER_PLUGIN_PERMISSION_TYPE_UNKNOWN),
|
| + : permission_type(WEB_VIEW_PERMISSION_TYPE_UNKNOWN),
|
| allowed_by_default(false) {
|
| }
|
|
|
| WebViewGuest::PermissionResponseInfo::PermissionResponseInfo(
|
| const PermissionResponseCallback& callback,
|
| - BrowserPluginPermissionType permission_type,
|
| + WebViewPermissionType permission_type,
|
| bool allowed_by_default)
|
| : callback(callback),
|
| permission_type(permission_type),
|
| @@ -1141,3 +1204,156 @@ void WebViewGuest::ShowContextMenu(int request_id,
|
| ContextMenuDelegate::FromWebContents(guest_web_contents());
|
| menu_delegate->ShowMenu(pending_menu_.Pass());
|
| }
|
| +
|
| +void WebViewGuest::Destroy() {
|
| + if (!attached() && GetOpener())
|
| + GetOpener()->pending_new_windows_.erase(this);
|
| + DestroyUnattachedWindows();
|
| + GuestViewBase::Destroy();
|
| +}
|
| +
|
| +void WebViewGuest::AddNewContents(content::WebContents* source,
|
| + content::WebContents* new_contents,
|
| + WindowOpenDisposition disposition,
|
| + const gfx::Rect& initial_pos,
|
| + bool user_gesture,
|
| + bool* was_blocked) {
|
| + if (was_blocked)
|
| + *was_blocked = false;
|
| + RequestNewWindowPermission(disposition,
|
| + initial_pos,
|
| + user_gesture,
|
| + new_contents);
|
| +}
|
| +
|
| +content::WebContents* WebViewGuest::OpenURLFromTab(
|
| + content::WebContents* source,
|
| + const content::OpenURLParams& params) {
|
| + // If the guest wishes to navigate away prior to attachment then we save the
|
| + // navigation to perform upon attachment. Navigation initializes a lot of
|
| + // state that assumes an embedder exists, such as RenderWidgetHostViewGuest.
|
| + // Navigation also resumes resource loading which we don't want to allow
|
| + // until attachment.
|
| + if (!attached()) {
|
| + WebViewGuest* opener = GetOpener();
|
| + PendingWindowMap::iterator it =
|
| + opener->pending_new_windows_.find(this);
|
| + if (it == opener->pending_new_windows_.end())
|
| + return NULL;
|
| + const NewWindowInfo& old_target_url = it->second;
|
| + NewWindowInfo new_window_info(params.url, old_target_url.name);
|
| + it->second = new_window_info;
|
| + return NULL;
|
| + }
|
| + if (params.disposition == CURRENT_TAB) {
|
| + // This can happen for cross-site redirects.
|
| + LoadURLWithParams(params.url, params.referrer, params.transition, source);
|
| + return source;
|
| + }
|
| +
|
| + return CreateNewGuestWindow(params)->guest_web_contents();
|
| +}
|
| +
|
| +void WebViewGuest::WebContentsCreated(WebContents* source_contents,
|
| + int opener_render_frame_id,
|
| + const base::string16& frame_name,
|
| + const GURL& target_url,
|
| + content::WebContents* new_contents) {
|
| + WebViewGuest* guest = WebViewGuest::FromWebContents(new_contents);
|
| + CHECK(guest);
|
| + guest->SetOpener(this);
|
| + std::string guest_name = base::UTF16ToUTF8(frame_name);
|
| + pending_new_windows_.insert(
|
| + std::make_pair(guest, NewWindowInfo(target_url, guest_name)));
|
| +}
|
| +
|
| +void WebViewGuest::LoadURLWithParams(const GURL& url,
|
| + const content::Referrer& referrer,
|
| + content::PageTransition transition_type,
|
| + content::WebContents* web_contents) {
|
| + content::NavigationController::LoadURLParams load_url_params(url);
|
| + load_url_params.referrer = referrer;
|
| + load_url_params.transition_type = transition_type;
|
| + load_url_params.extra_headers = std::string();
|
| + if (is_overriding_user_agent_) {
|
| + load_url_params.override_user_agent =
|
| + content::NavigationController::UA_OVERRIDE_TRUE;
|
| + }
|
| + web_contents->GetController().LoadURLWithParams(load_url_params);
|
| +}
|
| +
|
| +void WebViewGuest::RequestNewWindowPermission(
|
| + WindowOpenDisposition disposition,
|
| + const gfx::Rect& initial_bounds,
|
| + bool user_gesture,
|
| + content::WebContents* new_contents) {
|
| + WebViewGuest* guest = WebViewGuest::FromWebContents(new_contents);
|
| + if (!guest)
|
| + return;
|
| + PendingWindowMap::iterator it = pending_new_windows_.find(guest);
|
| + if (it == pending_new_windows_.end())
|
| + return;
|
| + const NewWindowInfo& new_window_info = it->second;
|
| +
|
| + base::DictionaryValue request_info;
|
| + request_info.Set(webview::kInitialHeight,
|
| + base::Value::CreateIntegerValue(initial_bounds.height()));
|
| + request_info.Set(webview::kInitialWidth,
|
| + base::Value::CreateIntegerValue(initial_bounds.width()));
|
| + request_info.Set(webview::kTargetURL,
|
| + base::Value::CreateStringValue(new_window_info.url.spec()));
|
| + request_info.Set(webview::kName,
|
| + base::Value::CreateStringValue(new_window_info.name));
|
| + request_info.Set(webview::kWindowID,
|
| + base::Value::CreateIntegerValue(guest->guest_instance_id()));
|
| + request_info.Set(webview::kWindowOpenDisposition,
|
| + base::Value::CreateStringValue(
|
| + WindowOpenDispositionToString(disposition)));
|
| +
|
| + RequestPermission(WEB_VIEW_PERMISSION_TYPE_NEW_WINDOW,
|
| + request_info,
|
| + base::Bind(&WebViewGuest::OnWebViewNewWindowResponse,
|
| + base::Unretained(this),
|
| + guest->guest_instance_id()),
|
| + false /* allowed_by_default */);
|
| +}
|
| +
|
| +void WebViewGuest::DestroyUnattachedWindows() {
|
| + // Destroy() reaches in and removes the WebViewGuest from its opener's
|
| + // pending_new_windows_ set. To avoid mutating the set while iterating, we
|
| + // create a copy of the pending new windows set and iterate over the copy.
|
| + PendingWindowMap pending_new_windows(pending_new_windows_);
|
| + // Clean up unattached new windows opened by this guest.
|
| + for (PendingWindowMap::const_iterator it = pending_new_windows.begin();
|
| + it != pending_new_windows.end(); ++it) {
|
| + it->first->Destroy();
|
| + }
|
| + // All pending windows should be removed from the set after Destroy() is
|
| + // called on all of them.
|
| + DCHECK(pending_new_windows_.empty());
|
| +}
|
| +
|
| +GURL WebViewGuest::ResolveURL(const std::string& src) {
|
| + if (!in_extension()) {
|
| + NOTREACHED();
|
| + return GURL(src);
|
| + }
|
| +
|
| + GURL default_url(base::StringPrintf("%s://%s/",
|
| + extensions::kExtensionScheme,
|
| + embedder_extension_id().c_str()));
|
| + return default_url.Resolve(src);
|
| +}
|
| +
|
| +void WebViewGuest::OnWebViewNewWindowResponse(
|
| + int new_window_instance_id,
|
| + bool allow,
|
| + const std::string& user_input) {
|
| + WebViewGuest* guest =
|
| + WebViewGuest::From(embedder_render_process_id(), new_window_instance_id);
|
| + if (!guest)
|
| + return;
|
| +
|
| + if (!allow)
|
| + guest->Destroy();
|
| +}
|
|
|