Index: extensions/browser/guest_view/web_view/web_view_guest.cc |
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc |
index fce1b6d0dd7301210ed877a2f3b7f2794649e4fe..eacef42e6fe5200bde185713101f503d660a4bc4 100644 |
--- a/extensions/browser/guest_view/web_view/web_view_guest.cc |
+++ b/extensions/browser/guest_view/web_view/web_view_guest.cc |
@@ -875,35 +875,9 @@ 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(url::kAboutScheme)) || |
- url.SchemeIs(url::kJavaScriptScheme); |
- if (scheme_is_blocked || !url.is_valid()) { |
- LoadAbort(true /* is_top_level */, url, |
- net::ErrorToShortString(net::ERR_ABORTED)); |
- NavigateGuest(url::kAboutBlankURL, true /* force_navigation */); |
- return; |
- } |
- if (!force_navigation && (src_ == url)) |
- return; |
- |
- GURL validated_url(url); |
- 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(), |
+ LoadURLWithParams(url, content::Referrer(), |
ui::PAGE_TRANSITION_AUTO_TOPLEVEL, |
- web_contents()); |
- |
- src_ = validated_url; |
+ force_navigation); |
} |
bool WebViewGuest::HandleKeyboardShortcuts( |
@@ -1118,6 +1092,23 @@ void WebViewGuest::AddNewContents(content::WebContents* source, |
content::WebContents* WebViewGuest::OpenURLFromTab( |
content::WebContents* source, |
const content::OpenURLParams& params) { |
+ // There are two use cases to consider from a security perspective: |
+ // 1.) Renderer-initiated navigation to chrome:// must always be blocked even |
+ // if the <webview> is in WebUI. This is handled by |
+ // WebViewGuest::LoadURLWithParams. WebViewGuest::NavigateGuest will also |
+ // call LoadURLWithParams. CreateNewGuestWebViewWindow creates a new |
+ // WebViewGuest which will call NavigateGuest in DidInitialize. |
+ // 2.) The Language Settings context menu item should always work, both in |
+ // Chrome Apps and WebUI. This is a browser initiated request and so |
+ // we pass it along to the embedder's WebContentsDelegate to get the |
+ // browser to perform the action for the <webview>. |
+ if (!params.is_renderer_initiated) { |
+ if (!owner_web_contents()->GetDelegate()) |
+ return nullptr; |
+ return owner_web_contents()->GetDelegate()->OpenURLFromTab( |
+ owner_web_contents(), 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. |
@@ -1134,12 +1125,25 @@ content::WebContents* WebViewGuest::OpenURLFromTab( |
it->second = new_window_info; |
return nullptr; |
} |
+ |
+ // This code path is taken if RenderFrameImpl::DecidePolicyForNavigation |
+ // decides that a fork should happen. At the time of writing this comment, |
+ // the only way a well behaving guest could hit this code path is if it |
+ // navigates to a URL that's associated with the default search engine. |
+ // This list of URLs is generated by chrome::GetSearchURLs. Validity checks |
+ // are performed inside LoadURLWithParams such that if the guest attempts |
+ // to navigate to a URL that it is not allowed to navigate to, a 'loadabort' |
+ // event will fire in the embedder, and the guest will be navigated to |
+ // about:blank. |
if (params.disposition == CURRENT_TAB) { |
- // This can happen for cross-site redirects. |
- LoadURLWithParams(params.url, params.referrer, params.transition, source); |
- return source; |
+ LoadURLWithParams(params.url, params.referrer, params.transition, |
+ true /* force_navigation */); |
+ return web_contents(); |
} |
+ // This code path is taken if Ctrl+Click, middle click or any of the |
+ // keyboard/mouse combinations are used to open a link in a new tab/window. |
+ // This code path is also taken on client-side redirects from about:blank. |
CreateNewGuestWebViewWindow(params); |
return nullptr; |
} |
@@ -1161,8 +1165,32 @@ void WebViewGuest::WebContentsCreated(WebContents* source_contents, |
void WebViewGuest::LoadURLWithParams(const GURL& url, |
const content::Referrer& referrer, |
ui::PageTransition transition_type, |
- content::WebContents* web_contents) { |
- content::NavigationController::LoadURLParams load_url_params(url); |
+ bool force_navigation) { |
+ // 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://. |
+ bool scheme_is_blocked = |
+ (!content::ChildProcessSecurityPolicy::GetInstance()->IsWebSafeScheme( |
+ url.scheme()) && |
+ !url.SchemeIs(url::kAboutScheme)) || |
+ url.SchemeIs(url::kJavaScriptScheme); |
+ if (scheme_is_blocked || !url.is_valid()) { |
+ LoadAbort(true /* is_top_level */, url, |
+ net::ErrorToShortString(net::ERR_ABORTED)); |
+ NavigateGuest(url::kAboutBlankURL, true /* force_navigation */); |
+ return; |
+ } |
+ |
+ if (!force_navigation && (src_ == url)) |
+ return; |
+ |
+ GURL validated_url(url); |
+ 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. |
+ content::NavigationController::LoadURLParams load_url_params(validated_url); |
load_url_params.referrer = referrer; |
load_url_params.transition_type = transition_type; |
load_url_params.extra_headers = std::string(); |
@@ -1170,7 +1198,9 @@ void WebViewGuest::LoadURLWithParams(const GURL& url, |
load_url_params.override_user_agent = |
content::NavigationController::UA_OVERRIDE_TRUE; |
} |
- web_contents->GetController().LoadURLWithParams(load_url_params); |
+ web_contents()->GetController().LoadURLWithParams(load_url_params); |
+ |
+ src_ = validated_url; |
} |
void WebViewGuest::RequestNewWindowPermission( |