Chromium Code Reviews| Index: android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc |
| 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 b24eb2b56eac50e61bccdadb308a07a74515d6c0..198b7920420a0a3fa640bc8c97278b0ae0453d51 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 |
| @@ -10,6 +10,7 @@ |
| #include "base/memory/scoped_ptr.h" |
| #include "base/memory/scoped_vector.h" |
| #include "content/components/navigation_interception/intercept_navigation_delegate.h" |
| +#include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/resource_controller.h" |
| #include "content/public/browser/resource_dispatcher_host.h" |
| #include "content/public/browser/resource_dispatcher_host_login_delegate.h" |
| @@ -23,6 +24,7 @@ using content::InterceptNavigationDelegate; |
| namespace { |
| using android_webview::AwContentsIoThreadClient; |
| +using content::BrowserThread; |
| base::LazyInstance<android_webview::AwResourceDispatcherHostDelegate> |
| g_webview_resource_dispatcher_host_delegate = LAZY_INSTANCE_INITIALIZER; |
| @@ -37,68 +39,114 @@ void SetOnlyAllowLoadFromCache( |
| request->set_load_flags(load_flags); |
| } |
| -// May cancel this resource request based on result of Java callbacks. |
| -class MaybeCancelResourceThrottle : public content::ResourceThrottle { |
| +// Calls through the IoThreadClient to check the embedders settings to determine |
| +// if the request should be cancelled. There may not always be an IoThreadClient |
| +// available for the |child_id|, |route_id| pair (in the case of newly created |
| +// pop up windows, for example) and in that case the request and the client |
| +// callbacks will be deferred the request until a client is ready. |
| +class IoThreadClientThrottle |
| + : public content::ResourceThrottle, |
| + public AwContentsIoThreadClient::ReadyObserver { |
| public: |
| - MaybeCancelResourceThrottle(int child_id, |
| - int route_id, |
| - net::URLRequest* request) |
| - : child_id_(child_id), |
| - route_id_(route_id), |
| - request_(request) { } |
| - virtual void WillStartRequest(bool* defer) OVERRIDE; |
| - |
| - scoped_ptr<AwContentsIoThreadClient> GetIoThreadClient() { |
| - return AwContentsIoThreadClient::FromID(child_id_, route_id_); |
| + IoThreadClientThrottle(int child_id, int route_id, net::URLRequest* request) |
| + : child_id_(child_id), |
| + route_id_(route_id), |
| + request_(request), |
| + handled_(false), |
| + added_observer_(false) { |
| } |
| - private: |
| - int child_id_; |
| - int route_id_; |
| - net::URLRequest* request_; |
| -}; |
| + virtual ~IoThreadClientThrottle() { |
| + if (added_observer_) { |
| + AwContentsIoThreadClient::RemoveReadyObserver(this); |
| + } |
| + } |
| -void MaybeCancelResourceThrottle::WillStartRequest(bool* defer) { |
| - // If there is no IO thread client set at this point, use a |
| - // restrictive policy. This can happen for blocked popup |
| - // windows for example. |
| - // TODO(benm): Revert this to a DCHECK when the we support |
| - // pop up windows being created in the WebView, as at that |
| - // time we should always have an IoThreadClient at this |
| - // point (i.e., the one associated with the new popup). |
| - if (!GetIoThreadClient()) { |
| - controller()->CancelWithError(net::ERR_ACCESS_DENIED); |
| - return; |
| + virtual void WillStartRequest(bool* defer) OVERRIDE { |
| + if (!MaybeDeferRequest(defer)) { |
| + MaybeBlockRequest(); |
| + } |
| } |
| - // Part of implementation of WebSettings.allowContentAccess. |
| - if (request_->url().SchemeIs(android_webview::kContentScheme) && |
| - GetIoThreadClient()->ShouldBlockContentUrls()) { |
| - controller()->CancelWithError(net::ERR_ACCESS_DENIED); |
| - return; |
| + virtual void WillRedirectRequest(const GURL& new_url, bool* defer) OVERRIDE { |
| + WillStartRequest(defer); |
| } |
| - // Part of implementation of WebSettings.allowFileAccess. |
| - if (request_->url().SchemeIsFile() && |
| - GetIoThreadClient()->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)) { |
| - controller()->CancelWithError(net::ERR_ACCESS_DENIED); |
| - return; |
| + bool MaybeDeferRequest(bool* defer) { |
| + scoped_ptr<AwContentsIoThreadClient> io_client = |
| + AwContentsIoThreadClient::FromID(child_id_, route_id_); |
| + if (!io_client.get()) { |
| + *defer = true; |
| + AwContentsIoThreadClient::AddReadyObserver(this); |
| + added_observer_ = true; |
| + return true; |
| + } else { |
| + *defer = false; |
| + } |
| + return false; |
| + } |
| + |
| + void OnIoThreadClientReady(int new_child_id, int new_route_id) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + // If we've now got the IoThreadClient that we were waiting on, |
| + // resume the request. |
| + if (!handled_ && new_child_id == child_id_ && new_route_id == route_id_) { |
| + if (!MaybeBlockRequest()) { |
| + controller()->Resume(); |
| + handled_ = true; |
| + } |
| } |
|
joth
2012/11/16 21:52:57
add:
AwContentsIoThreadClient::RemoveReadyObserve
benm (inactive)
2012/11/28 20:00:05
This should all go away and become simpler in next
|
| } |
| - if (GetIoThreadClient()->ShouldBlockNetworkLoads()) { |
| - if (request_->url().SchemeIs(chrome::kFtpScheme)) { |
| + bool MaybeBlockRequest() { |
| + if (ShouldBlockRequest()) { |
| controller()->CancelWithError(net::ERR_ACCESS_DENIED); |
| - return; |
| + handled_ = true; |
| + return true; |
| } |
| - SetOnlyAllowLoadFromCache(request_); |
| + return false; |
| } |
| -} |
| + |
| + bool ShouldBlockRequest() { |
| + scoped_ptr<AwContentsIoThreadClient> io_client = |
| + AwContentsIoThreadClient::FromID(child_id_, route_id_); |
| + DCHECK(io_client.get()); |
| + |
| + // Part of implementation of WebSettings.allowContentAccess. |
| + if (request_->url().SchemeIs(android_webview::kContentScheme) && |
| + io_client->ShouldBlockContentUrls()) { |
| + return true; |
| + } |
| + |
| + // 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; |
| + } |
| + } |
| + |
| + if (io_client->ShouldBlockNetworkLoads()) { |
| + if (request_->url().SchemeIs(chrome::kFtpScheme)) { |
| + return true; |
| + } |
| + SetOnlyAllowLoadFromCache(request_); |
| + } |
| + |
| + return false; |
| + } |
| + |
| +private: |
| + int child_id_; |
| + int route_id_; |
| + net::URLRequest* request_; |
| + bool handled_; |
| + bool added_observer_; |
| +}; |
| } // namespace |
| @@ -127,8 +175,7 @@ void AwResourceDispatcherHostDelegate::RequestBeginning( |
| bool is_continuation_of_transferred_request, |
| ScopedVector<content::ResourceThrottle>* throttles) { |
| - throttles->push_back(new MaybeCancelResourceThrottle( |
| - child_id, route_id, request)); |
| + throttles->push_back(new IoThreadClientThrottle(child_id, route_id, request)); |
| if (resource_type == ResourceType::MAIN_FRAME) { |
| throttles->push_back(InterceptNavigationDelegate::CreateThrottleFor( |