diff options
author | mnaganov <mnaganov@chromium.org> | 2015-08-13 09:33:32 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-08-13 16:34:34 +0000 |
commit | b58eaaad66463aba894d5c92589e260245e63de2 (patch) | |
tree | 464bffabbae9666e4d17894ab557b637f1ae3844 /android_webview | |
parent | 32eb5395a9ce0ac6115d66d6c0482c5009ee5e37 (diff) | |
download | chromium_src-b58eaaad66463aba894d5c92589e260245e63de2.zip chromium_src-b58eaaad66463aba894d5c92589e260245e63de2.tar.gz chromium_src-b58eaaad66463aba894d5c92589e260245e63de2.tar.bz2 |
Implement AwContentBrowserClient::IsHandledURL
Implemented similarly to ChromeContentBrowserClient. The only trick is that 'false' is still returned for "special" Android file URLs (file:///android_asset/* and file:///android_res/) that should work even if file access is disabled. By returning 'false' from IsHandledURL we bypass the scheme check in ChildProcessSecurityPolicy.
Access to 'file:' scheme is granted to child processes after the first call to WebView.loadDataWithBaseUrl with non-data: base URL.
Access to 'content:' scheme is always granted, as access to it is enabled by default in WebSettings.
BUG=516546
Review URL: https://codereview.chromium.org/1275163004
Cr-Commit-Position: refs/heads/master@{#343214}
Diffstat (limited to 'android_webview')
11 files changed, 74 insertions, 38 deletions
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc index 1f59823..fb16ceb 100644 --- a/android_webview/browser/aw_content_browser_client.cc +++ b/android_webview/browser/aw_content_browser_client.cc @@ -168,6 +168,12 @@ AwContentBrowserClient::GetWebContentsViewDelegate( void AwContentBrowserClient::RenderProcessWillLaunch( content::RenderProcessHost* host) { + // Grant content: scheme access to the whole renderer process, since we impose + // per-view access checks, and access is granted by default (see + // AwSettings.mAllowContentUrlAccess). + content::ChildProcessSecurityPolicy::GetInstance()->GrantScheme( + host->GetID(), url::kContentScheme); + host->AddFilter(new AwContentsMessageFilter(host->GetID())); host->AddFilter(new cdm::CdmMessageFilterAndroid()); host->AddFilter(new AwPrintingMessageFilter(host->GetID())); @@ -197,6 +203,37 @@ AwContentBrowserClient::CreateRequestContextForStoragePartition( request_interceptors.Pass()); } +bool AwContentBrowserClient::IsHandledURL(const GURL& url) { + if (!url.is_valid()) { + // We handle error cases. + return true; + } + + const std::string scheme = url.scheme(); + DCHECK_EQ(scheme, base::ToLowerASCII(scheme)); + // See CreateJobFactory in aw_url_request_context_getter.cc for the + // list of protocols that are handled. + // TODO(mnaganov): Make this automatic. + static const char* const kProtocolList[] = { + url::kDataScheme, + url::kBlobScheme, + url::kFileSystemScheme, + content::kChromeUIScheme, + content::kChromeDevToolsScheme, + url::kContentScheme, + }; + if (scheme == url::kFileScheme) { + // Return false for the "special" file URLs, so they can be loaded + // even if access to file: scheme is not granted to the child process. + return !IsAndroidSpecialFileUrl(url); + } + for (size_t i = 0; i < arraysize(kProtocolList); ++i) { + if (scheme == kProtocolList[i]) + return true; + } + return net::URLRequest::IsHandledProtocol(scheme); +} + std::string AwContentBrowserClient::GetCanonicalEncodingNameByAliasName( const std::string& alias_name) { return alias_name; diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h index 2f0e472..45e9f86 100644 --- a/android_webview/browser/aw_content_browser_client.h +++ b/android_webview/browser/aw_content_browser_client.h @@ -48,6 +48,7 @@ class AwContentBrowserClient : public content::ContentBrowserClient { bool in_memory, content::ProtocolHandlerMap* protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptors) override; + bool IsHandledURL(const GURL& url) override; std::string GetCanonicalEncodingNameByAliasName( const std::string& alias_name) override; void AppendExtraCommandLineSwitches(base::CommandLine* command_line, diff --git a/android_webview/browser/net/aw_url_request_context_getter.cc b/android_webview/browser/net/aw_url_request_context_getter.cc index b2058c4..68ba631 100644 --- a/android_webview/browser/net/aw_url_request_context_getter.cc +++ b/android_webview/browser/net/aw_url_request_context_getter.cc @@ -112,6 +112,8 @@ scoped_ptr<net::URLRequestJobFactory> CreateJobFactory( content::ProtocolHandlerMap* protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptors) { scoped_ptr<AwURLRequestJobFactory> aw_job_factory(new AwURLRequestJobFactory); + // Note that the registered schemes must also be specified in + // AwContentBrowserClient::IsHandledURL. bool set_protocol = aw_job_factory->SetProtocolHandler( url::kFileScheme, new net::FileProtocolHandler( diff --git a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc index 577c355..1d9e585 100644 --- a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc +++ b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc @@ -160,13 +160,8 @@ bool IoThreadClientThrottle::ShouldBlockRequest() { // Part of implementation of WebSettings.allowFileAccess. if (request_->url().SchemeIsFile() && io_client->ShouldBlockFileUrls()) { - const GURL& url = request_->url(); - if (!url.has_path() || - // Application's assets and resources are always available. - (url.path().find(android_webview::kAndroidResourcePath) != 0 && - url.path().find(android_webview::kAndroidAssetPath) != 0)) { - return true; - } + // Application's assets and resources are always available. + return !IsAndroidSpecialFileUrl(request_->url()); } if (io_client->ShouldBlockNetworkLoads()) { diff --git a/android_webview/common/url_constants.cc b/android_webview/common/url_constants.cc index 89a32bb..ff870ac 100644 --- a/android_webview/common/url_constants.cc +++ b/android_webview/common/url_constants.cc @@ -4,6 +4,8 @@ #include "android_webview/common/url_constants.h" +#include "base/strings/string_util.h" + namespace android_webview { // These are special paths used with the file: scheme to access application @@ -15,4 +17,13 @@ const char kAndroidResourcePath[] = "/android_res/"; // This scheme is used to display a default HTML5 video poster. const char kAndroidWebViewVideoPosterScheme[] = "android-webview-video-poster"; +bool IsAndroidSpecialFileUrl(const GURL& url) { + if (!url.is_valid() || !url.SchemeIsFile() || !url.has_path()) + return false; + return base::StartsWith(url.path(), kAndroidAssetPath, + base::CompareCase::SENSITIVE) || + base::StartsWith(url.path(), kAndroidResourcePath, + base::CompareCase::SENSITIVE); +} + } // namespace android_webview diff --git a/android_webview/common/url_constants.h b/android_webview/common/url_constants.h index 80c3571..2d0e316 100644 --- a/android_webview/common/url_constants.h +++ b/android_webview/common/url_constants.h @@ -7,11 +7,15 @@ #ifndef ANDROID_WEBVIEW_COMMON_URL_CONSTANTS_H_ #define ANDROID_WEBVIEW_COMMON_URL_CONSTANTS_H_ +#include "url/gurl.h" + namespace android_webview { // Special Android file paths. extern const char kAndroidAssetPath[]; extern const char kAndroidResourcePath[]; +// Returns whether the given URL is for loading a file from a special path. +bool IsAndroidSpecialFileUrl(const GURL& url); extern const char kAndroidWebViewVideoPosterScheme[]; diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java index bdcbd37..a486243 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java @@ -1414,6 +1414,9 @@ public class AwContents implements SmartClipProvider, Log.wtf(TAG, "Unable to load data string " + data, e); return; } + // When loading data with a non-data: base URL, WebView must allow renderers + // to access file: URLs. + nativeGrantFileSchemeAccesstoChildProcess(mNativeAwContents); } loadUrl(loadUrlParams); } @@ -3149,4 +3152,6 @@ public class AwContents implements SmartClipProvider, String message, String targetOrigin, int[] msgPorts); private native void nativeCreateMessageChannel(long nativeAwContents, AwMessagePort[] ports); + + private native void nativeGrantFileSchemeAccesstoChildProcess(long nativeAwContents); } diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java index 25cfa8d..994f002 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java @@ -251,8 +251,8 @@ public class AwTestBase runTestOnUiThread(new Runnable() { @Override public void run() { - awContents.loadUrl(LoadUrlParams.createLoadDataParamsWithBaseUrl( - data, mimeType, isBase64Encoded, baseUrl, historyUrl)); + awContents.loadDataWithBaseURL( + baseUrl, data, mimeType, isBase64Encoded ? "base64" : null, historyUrl); } }); } diff --git a/android_webview/native/android_protocol_handler.cc b/android_webview/native/android_protocol_handler.cc index dd4db90..be3376c 100644 --- a/android_webview/native/android_protocol_handler.cc +++ b/android_webview/native/android_protocol_handler.cc @@ -11,7 +11,6 @@ #include "base/android/jni_android.h" #include "base/android/jni_string.h" #include "base/android/jni_weak_ref.h" -#include "base/strings/string_util.h" #include "content/public/common/url_constants.h" #include "jni/AndroidProtocolHandler_jni.h" #include "net/base/io_buffer.h" @@ -95,15 +94,7 @@ class AndroidRequestInterceptorBase : public net::URLRequestInterceptor { class AssetFileRequestInterceptor : public AndroidRequestInterceptorBase { public: AssetFileRequestInterceptor(); - - ~AssetFileRequestInterceptor() override; bool ShouldHandleRequest(const net::URLRequest* request) const override; - - private: - // file:///android_asset/ - const std::string asset_prefix_; - // file:///android_res/ - const std::string resource_prefix_; }; // Protocol handler for content:// scheme requests. @@ -235,30 +226,12 @@ net::URLRequestJob* AndroidRequestInterceptorBase::MaybeInterceptRequest( // AssetFileRequestInterceptor ------------------------------------------------ -AssetFileRequestInterceptor::AssetFileRequestInterceptor() - : asset_prefix_(std::string(url::kFileScheme) + - std::string(url::kStandardSchemeSeparator) + - android_webview::kAndroidAssetPath), - resource_prefix_(std::string(url::kFileScheme) + - std::string(url::kStandardSchemeSeparator) + - android_webview::kAndroidResourcePath) { -} - -AssetFileRequestInterceptor::~AssetFileRequestInterceptor() { +AssetFileRequestInterceptor::AssetFileRequestInterceptor() { } bool AssetFileRequestInterceptor::ShouldHandleRequest( const net::URLRequest* request) const { - if (!request->url().SchemeIsFile()) - return false; - - const std::string& url = request->url().spec(); - if (!base::StartsWith(url, asset_prefix_, base::CompareCase::SENSITIVE) && - !base::StartsWith(url, resource_prefix_, base::CompareCase::SENSITIVE)) { - return false; - } - - return true; + return android_webview::IsAndroidSpecialFileUrl(request->url()); } // ContentSchemeRequestInterceptor -------------------------------------------- diff --git a/android_webview/native/aw_contents.cc b/android_webview/native/aw_contents.cc index 7d34034..84c2457 100644 --- a/android_webview/native/aw_contents.cc +++ b/android_webview/native/aw_contents.cc @@ -53,6 +53,7 @@ #include "content/public/browser/android/synchronous_compositor.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/cert_store.h" +#include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/favicon_status.h" #include "content/public/browser/message_port_provider.h" #include "content/public/browser/navigation_entry.h" @@ -1205,6 +1206,11 @@ void AwContents::CreateMessageChannel(JNIEnv* env, jobject obj, GetMessagePortMessageFilter()); } +void AwContents::GrantFileSchemeAccesstoChildProcess(JNIEnv* env, jobject obj) { + content::ChildProcessSecurityPolicy::GetInstance()->GrantScheme( + web_contents_->GetRenderProcessHost()->GetID(), url::kFileScheme); +} + void SetShouldDownloadFavicons(JNIEnv* env, jclass jclazz) { g_should_download_favicons = true; } diff --git a/android_webview/native/aw_contents.h b/android_webview/native/aw_contents.h index 7600051..cbdb8b2 100644 --- a/android_webview/native/aw_contents.h +++ b/android_webview/native/aw_contents.h @@ -237,6 +237,8 @@ class AwContents : public FindHelper::Listener, jstring message, jstring target_origin, jintArray sent_ports); void CreateMessageChannel(JNIEnv* env, jobject obj, jobjectArray ports); + void GrantFileSchemeAccesstoChildProcess(JNIEnv* env, jobject obj); + private: void InitDataReductionProxyIfNecessary(); void InitAutofillIfNecessary(bool enabled); |