| Index: android_webview/native/android_protocol_handler.cc
|
| diff --git a/android_webview/native/android_protocol_handler.cc b/android_webview/native/android_protocol_handler.cc
|
| index 907881bae85822301eb9d1d435e0c8d1e23f7443..7705e8461f30074767a8cbf0356fcf817173af1d 100644
|
| --- a/android_webview/native/android_protocol_handler.cc
|
| +++ b/android_webview/native/android_protocol_handler.cc
|
| @@ -44,6 +44,17 @@ void ResetResourceContext(JavaObjectWeakGlobalRef* ref) {
|
| g_resource_context = ref;
|
| }
|
|
|
| +void* kPreviouslyFailedKey = &kPreviouslyFailedKey;
|
| +
|
| +void MarkRequestAsFailed(net::URLRequest* request) {
|
| + request->SetUserData(kPreviouslyFailedKey,
|
| + new base::SupportsUserData::Data());
|
| +}
|
| +
|
| +bool HasRequestPreviouslyFailed(net::URLRequest* request) {
|
| + return request->GetUserData(kPreviouslyFailedKey) != NULL;
|
| +}
|
| +
|
| class AndroidStreamReaderURLRequestJobDelegateImpl
|
| : public AndroidStreamReaderURLRequestJob::Delegate {
|
| public:
|
| @@ -51,7 +62,10 @@ class AndroidStreamReaderURLRequestJobDelegateImpl
|
|
|
| virtual scoped_ptr<InputStream> OpenInputStream(
|
| JNIEnv* env,
|
| - net::URLRequest* request) OVERRIDE;
|
| + const GURL& url) OVERRIDE;
|
| +
|
| + virtual void OnInputStreamOpenFailed(net::URLRequest* request,
|
| + bool* restart) OVERRIDE;
|
|
|
| virtual bool GetMimeType(JNIEnv* env,
|
| net::URLRequest* request,
|
| @@ -66,19 +80,24 @@ class AndroidStreamReaderURLRequestJobDelegateImpl
|
| virtual ~AndroidStreamReaderURLRequestJobDelegateImpl();
|
| };
|
|
|
| -class AssetFileProtocolInterceptor :
|
| - public net::URLRequestJobFactory::ProtocolHandler {
|
| +class AndroidProtocolHandlerBase :
|
| + public net::URLRequestJobFactory::ProtocolHandler {
|
| public:
|
| - virtual ~AssetFileProtocolInterceptor() OVERRIDE;
|
| - static scoped_ptr<net::URLRequestJobFactory> CreateURLRequestJobFactory(
|
| - scoped_ptr<net::URLRequestJobFactory> base_job_factory);
|
| virtual net::URLRequestJob* MaybeCreateJob(
|
| net::URLRequest* request,
|
| net::NetworkDelegate* network_delegate) const OVERRIDE;
|
|
|
| - private:
|
| - AssetFileProtocolInterceptor();
|
| + virtual bool CanHandleRequest(const net::URLRequest* request) const = 0;
|
| +};
|
| +
|
| +class AssetFileProtocolHandler : public AndroidProtocolHandlerBase {
|
| + public:
|
| + AssetFileProtocolHandler();
|
|
|
| + virtual ~AssetFileProtocolHandler() OVERRIDE;
|
| + virtual bool CanHandleRequest(const net::URLRequest* request) const OVERRIDE;
|
| +
|
| + private:
|
| // file:///android_asset/
|
| const std::string asset_prefix_;
|
| // file:///android_res/
|
| @@ -86,21 +105,10 @@ class AssetFileProtocolInterceptor :
|
| };
|
|
|
| // Protocol handler for content:// scheme requests.
|
| -class ContentSchemeProtocolHandler :
|
| - public net::URLRequestJobFactory::ProtocolHandler {
|
| +class ContentSchemeProtocolHandler : public AndroidProtocolHandlerBase {
|
| public:
|
| - ContentSchemeProtocolHandler() {}
|
| -
|
| - virtual net::URLRequestJob* MaybeCreateJob(
|
| - net::URLRequest* request,
|
| - net::NetworkDelegate* network_delegate) const OVERRIDE {
|
| - DCHECK(request->url().SchemeIs(android_webview::kContentScheme));
|
| - return new AndroidStreamReaderURLRequestJob(
|
| - request,
|
| - network_delegate,
|
| - scoped_ptr<AndroidStreamReaderURLRequestJob::Delegate>(
|
| - new AndroidStreamReaderURLRequestJobDelegateImpl()));
|
| - }
|
| + ContentSchemeProtocolHandler();
|
| + virtual bool CanHandleRequest(const net::URLRequest* request) const OVERRIDE;
|
| };
|
|
|
| static ScopedJavaLocalRef<jobject> GetResourceContext(JNIEnv* env) {
|
| @@ -114,9 +122,10 @@ static ScopedJavaLocalRef<jobject> GetResourceContext(JNIEnv* env) {
|
| return context;
|
| }
|
|
|
| +// AndroidStreamReaderURLRequestJobDelegateImpl -------------------------------
|
| +
|
| AndroidStreamReaderURLRequestJobDelegateImpl::
|
| -AndroidStreamReaderURLRequestJobDelegateImpl() {
|
| -}
|
| + AndroidStreamReaderURLRequestJobDelegateImpl() {}
|
|
|
| AndroidStreamReaderURLRequestJobDelegateImpl::
|
| ~AndroidStreamReaderURLRequestJobDelegateImpl() {
|
| @@ -124,18 +133,18 @@ AndroidStreamReaderURLRequestJobDelegateImpl::
|
|
|
| scoped_ptr<InputStream>
|
| AndroidStreamReaderURLRequestJobDelegateImpl::OpenInputStream(
|
| - JNIEnv* env, net::URLRequest* request) {
|
| - DCHECK(request);
|
| + JNIEnv* env, const GURL& url) {
|
| + DCHECK(url.is_valid());
|
| DCHECK(env);
|
|
|
| // Open the input stream.
|
| - ScopedJavaLocalRef<jstring> url =
|
| - ConvertUTF8ToJavaString(env, request->url().spec());
|
| + ScopedJavaLocalRef<jstring> jurl =
|
| + ConvertUTF8ToJavaString(env, url.spec());
|
| ScopedJavaLocalRef<jobject> stream =
|
| android_webview::Java_AndroidProtocolHandler_open(
|
| env,
|
| GetResourceContext(env).obj(),
|
| - url.obj());
|
| + jurl.obj());
|
|
|
| // Check and clear pending exceptions.
|
| if (ClearException(env) || stream.is_null()) {
|
| @@ -145,6 +154,14 @@ AndroidStreamReaderURLRequestJobDelegateImpl::OpenInputStream(
|
| return make_scoped_ptr<InputStream>(new InputStreamImpl(stream));
|
| }
|
|
|
| +void AndroidStreamReaderURLRequestJobDelegateImpl::OnInputStreamOpenFailed(
|
| + net::URLRequest* request,
|
| + bool* restart) {
|
| + DCHECK(!HasRequestPreviouslyFailed(request));
|
| + MarkRequestAsFailed(request);
|
| + *restart = true;
|
| +}
|
| +
|
| bool AndroidStreamReaderURLRequestJobDelegateImpl::GetMimeType(
|
| JNIEnv* env,
|
| net::URLRequest* request,
|
| @@ -181,7 +198,37 @@ bool AndroidStreamReaderURLRequestJobDelegateImpl::GetCharset(
|
| return false;
|
| }
|
|
|
| -AssetFileProtocolInterceptor::AssetFileProtocolInterceptor()
|
| +// AndroidProtocolHandlerBase -------------------------------------------------
|
| +
|
| +net::URLRequestJob* AndroidProtocolHandlerBase::MaybeCreateJob(
|
| + net::URLRequest* request,
|
| + net::NetworkDelegate* network_delegate) const {
|
| + if (!CanHandleRequest(request)) return NULL;
|
| +
|
| + // For WebViewClassic compatibility this job can only accept URLs that can be
|
| + // opened. URLs that cannot be opened should be resolved by the next handler.
|
| + //
|
| + // If a request is initially handled here but the job fails due to it being
|
| + // unable to open the InputStream for that request the request is marked as
|
| + // previously failed and restarted.
|
| + // Restarting a request involves creating a new job for that request. This
|
| + // handler will ignore requests know to have previously failed to 1) prevent
|
| + // an infinite loop, 2) ensure that the next handler in line gets the
|
| + // opportunity to create a job for the request.
|
| + if (HasRequestPreviouslyFailed(request)) return NULL;
|
| +
|
| + scoped_ptr<AndroidStreamReaderURLRequestJobDelegateImpl> reader_delegate(
|
| + new AndroidStreamReaderURLRequestJobDelegateImpl());
|
| +
|
| + return new AndroidStreamReaderURLRequestJob(
|
| + request,
|
| + network_delegate,
|
| + reader_delegate.PassAs<AndroidStreamReaderURLRequestJob::Delegate>());
|
| +}
|
| +
|
| +// AssetFileProtocolHandler ---------------------------------------------------
|
| +
|
| +AssetFileProtocolHandler::AssetFileProtocolHandler()
|
| : asset_prefix_(std::string(chrome::kFileScheme) +
|
| std::string(content::kStandardSchemeSeparator) +
|
| android_webview::kAndroidAssetPath),
|
| @@ -190,36 +237,31 @@ AssetFileProtocolInterceptor::AssetFileProtocolInterceptor()
|
| android_webview::kAndroidResourcePath) {
|
| }
|
|
|
| -AssetFileProtocolInterceptor::~AssetFileProtocolInterceptor() {
|
| +AssetFileProtocolHandler::~AssetFileProtocolHandler() {
|
| }
|
|
|
| -// static
|
| -scoped_ptr<net::URLRequestJobFactory>
|
| -AssetFileProtocolInterceptor::CreateURLRequestJobFactory(
|
| - scoped_ptr<net::URLRequestJobFactory> base_job_factory) {
|
| - scoped_ptr<net::URLRequestJobFactory> top_job_factory(
|
| - new net::ProtocolInterceptJobFactory(
|
| - base_job_factory.Pass(),
|
| - scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(
|
| - new AssetFileProtocolInterceptor())));
|
| - return top_job_factory.Pass();
|
| -}
|
| -
|
| -net::URLRequestJob* AssetFileProtocolInterceptor::MaybeCreateJob(
|
| - net::URLRequest* request, net::NetworkDelegate* network_delegate) const {
|
| - if (!request->url().SchemeIsFile()) return NULL;
|
| +bool AssetFileProtocolHandler::CanHandleRequest(
|
| + const net::URLRequest* request) const {
|
| + if (!request->url().SchemeIsFile())
|
| + return false;
|
|
|
| const std::string& url = request->url().spec();
|
| if (!StartsWithASCII(url, asset_prefix_, /*case_sensitive=*/ true) &&
|
| - !StartsWithASCII(url, resource_prefix_, /*case_sensitive=*/ true)) {
|
| - return NULL;
|
| + !StartsWithASCII(url, resource_prefix_, /*case_sensitive=*/ true)) {
|
| + return false;
|
| }
|
|
|
| - return new AndroidStreamReaderURLRequestJob(
|
| - request,
|
| - network_delegate,
|
| - scoped_ptr<AndroidStreamReaderURLRequestJob::Delegate>(
|
| - new AndroidStreamReaderURLRequestJobDelegateImpl()));
|
| + return true;
|
| +}
|
| +
|
| +// ContentSchemeProtocolHandler -----------------------------------------------
|
| +
|
| +ContentSchemeProtocolHandler::ContentSchemeProtocolHandler() {
|
| +}
|
| +
|
| +bool ContentSchemeProtocolHandler::CanHandleRequest(
|
| + const net::URLRequest* request) const {
|
| + return request->url().SchemeIs(android_webview::kContentScheme);
|
| }
|
|
|
| } // namespace
|
| @@ -231,18 +273,17 @@ bool RegisterAndroidProtocolHandler(JNIEnv* env) {
|
| }
|
|
|
| // static
|
| -scoped_ptr<net::URLRequestJobFactory> CreateAndroidRequestJobFactory(
|
| - scoped_ptr<AwURLRequestJobFactory> job_factory) {
|
| - // Register content://. Note that even though a scheme is
|
| - // registered here, it cannot be used by child processes until access to it is
|
| - // granted via ChildProcessSecurityPolicy::GrantScheme(). This is done in
|
| - // AwContentBrowserClient.
|
| - // The job factory takes ownership of the handler.
|
| - bool set_protocol = job_factory->SetProtocolHandler(
|
| - android_webview::kContentScheme, new ContentSchemeProtocolHandler());
|
| - DCHECK(set_protocol);
|
| - return AssetFileProtocolInterceptor::CreateURLRequestJobFactory(
|
| - job_factory.PassAs<net::URLRequestJobFactory>());
|
| +scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>
|
| +CreateContentSchemeProtocolHandler() {
|
| + return make_scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(
|
| + new ContentSchemeProtocolHandler());
|
| +}
|
| +
|
| +// static
|
| +scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>
|
| +CreateAssetFileProtocolHandler() {
|
| + return make_scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(
|
| + new AssetFileProtocolHandler());
|
| }
|
|
|
| // Set a context object to be used for resolving resource queries. This can
|
|
|