diff options
author | boliu@chromium.org <boliu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-14 05:35:34 +0000 |
---|---|---|
committer | boliu@chromium.org <boliu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-14 05:35:34 +0000 |
commit | 2adc0c65a3e3a932cce1cf8d926a65a14605d1f5 (patch) | |
tree | 0989c3d44efe981a9f78ae897d988b30c0f4ede2 /android_webview | |
parent | ed66d1c729afdad61eb7a37e6b635a38ca5c0d94 (diff) | |
download | chromium_src-2adc0c65a3e3a932cce1cf8d926a65a14605d1f5.zip chromium_src-2adc0c65a3e3a932cce1cf8d926a65a14605d1f5.tar.gz chromium_src-2adc0c65a3e3a932cce1cf8d926a65a14605d1f5.tar.bz2 |
[Android WebView] Do not interfere with requests after destroy
Currently, android webview defers network requests made after
destroy indefinitely since we do not distinguish this case
from the new pop up AwContents case. In both cases, io_client
is null.
This CL changes the pop up case to return to io_client that
is not associated with a Java counter part so these two cases
can be distinguished and handled appropriately.
In after destroy case, do not add any throttles or interfere
with the request in any way.
BUG=290563, 290564
Review URL: https://chromiumcodereview.appspot.com/23890017
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@223229 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'android_webview')
5 files changed, 83 insertions, 36 deletions
diff --git a/android_webview/browser/aw_contents_io_thread_client.h b/android_webview/browser/aw_contents_io_thread_client.h index fd1de8b..aedfba2 100644 --- a/android_webview/browser/aw_contents_io_thread_client.h +++ b/android_webview/browser/aw_contents_io_thread_client.h @@ -47,6 +47,10 @@ class AwContentsIoThreadClient { virtual ~AwContentsIoThreadClient() {} + // Returns whether this is a new pop up that is still waiting for association + // with the java counter part. + virtual bool PendingAssociation() const = 0; + // Retrieve CacheMode setting value of this AwContents. // This method is called on the IO thread only. virtual CacheMode GetCacheMode() const = 0; 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 1bab66b..df68b7a 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 @@ -70,7 +70,6 @@ class IoThreadClientThrottle : public content::ResourceThrottle { void OnIoThreadClientReady(int new_child_id, int new_route_id); bool MaybeBlockRequest(); bool ShouldBlockRequest(); - scoped_ptr<AwContentsIoThreadClient> GetIoThreadClient(); int get_child_id() const { return child_id_; } int get_route_id() const { return route_id_; } @@ -112,10 +111,13 @@ void IoThreadClientThrottle::WillRedirectRequest(const GURL& new_url, } bool IoThreadClientThrottle::MaybeDeferRequest(bool* defer) { + *defer = false; + + // Defer all requests of a pop up that is still not associated with Java + // client so that the client will get a chance to override requests. scoped_ptr<AwContentsIoThreadClient> io_client = AwContentsIoThreadClient::FromID(child_id_, route_id_); - *defer = false; - if (!io_client.get()) { + if (io_client && io_client->PendingAssociation()) { *defer = true; AwResourceDispatcherHostDelegate::AddPendingThrottle( child_id_, route_id_, this); @@ -169,8 +171,7 @@ bool IoThreadClientThrottle::ShouldBlockRequest() { } SetCacheControlFlag(request_, net::LOAD_ONLY_FROM_CACHE); } else { - AwContentsIoThreadClient::CacheMode cache_mode = - GetIoThreadClient()->GetCacheMode(); + AwContentsIoThreadClient::CacheMode cache_mode = io_client->GetCacheMode(); switch(cache_mode) { case AwContentsIoThreadClient::LOAD_CACHE_ELSE_NETWORK: SetCacheControlFlag(request_, net::LOAD_PREFERRING_CACHE); @@ -188,11 +189,6 @@ bool IoThreadClientThrottle::ShouldBlockRequest() { return false; } -scoped_ptr<AwContentsIoThreadClient> - IoThreadClientThrottle::GetIoThreadClient() { - return AwContentsIoThreadClient::FromID(child_id_, route_id_); -} - // static void AwResourceDispatcherHostDelegate::ResourceDispatcherHostCreated() { content::ResourceDispatcherHost::Get()->SetDelegate( @@ -215,6 +211,14 @@ void AwResourceDispatcherHostDelegate::RequestBeginning( int route_id, bool is_continuation_of_transferred_request, ScopedVector<content::ResourceThrottle>* throttles) { + // If io_client is NULL, then the browser side objects have already been + // destroyed, so do not do anything to the request. Conversely if the + // request relates to a not-yet-created popup window, then the client will + // be non-NULL but PopupPendingAssociation() will be set. + scoped_ptr<AwContentsIoThreadClient> io_client = + AwContentsIoThreadClient::FromID(child_id, route_id); + if (!io_client) + return; throttles->push_back(new IoThreadClientThrottle( child_id, route_id, request)); diff --git a/android_webview/native/aw_contents.cc b/android_webview/native/aw_contents.cc index e920cf8..91753e7 100644 --- a/android_webview/native/aw_contents.cc +++ b/android_webview/native/aw_contents.cc @@ -142,6 +142,7 @@ AwContents::AwContents(scoped_ptr<WebContents> web_contents) new AwContentsUserData(this)); render_view_host_ext_.reset( new AwRenderViewHostExt(this, web_contents_.get())); + AwContentsIoThreadClientImpl::RegisterPendingContents(web_contents_.get()); AwAutofillManagerDelegate* autofill_manager_delegate = AwAutofillManagerDelegate::FromWebContents(web_contents_.get()); diff --git a/android_webview/native/aw_contents_io_thread_client_impl.cc b/android_webview/native/aw_contents_io_thread_client_impl.cc index 8002851..4c64db2 100644 --- a/android_webview/native/aw_contents_io_thread_client_impl.cc +++ b/android_webview/native/aw_contents_io_thread_client_impl.cc @@ -39,8 +39,17 @@ namespace android_webview { namespace { -typedef map<pair<int, int>, JavaObjectWeakGlobalRef> - RenderViewHostToWeakDelegateMapType; +struct IoThreadClientData { + bool pending_association; + JavaObjectWeakGlobalRef io_thread_client; + + IoThreadClientData(); +}; + +IoThreadClientData::IoThreadClientData() : pending_association(false) {} + +typedef map<pair<int, int>, IoThreadClientData> + RenderViewHostToIoThreadClientType; static pair<int, int> GetRenderViewHostIdPair(RenderViewHost* rvh) { return pair<int, int>(rvh->GetProcess()->GetID(), rvh->GetRoutingID()); @@ -50,14 +59,14 @@ static pair<int, int> GetRenderViewHostIdPair(RenderViewHost* rvh) { class RvhToIoThreadClientMap { public: static RvhToIoThreadClientMap* GetInstance(); - void Insert(pair<int, int> rvh_id, JavaObjectWeakGlobalRef jdelegate); - ScopedJavaLocalRef<jobject> Get(pair<int, int> rvh_id); + void Set(pair<int, int> rvh_id, const IoThreadClientData& client); + bool Get(pair<int, int> rvh_id, IoThreadClientData* client); void Erase(pair<int, int> rvh_id); private: static LazyInstance<RvhToIoThreadClientMap> g_instance_; base::Lock map_lock_; - RenderViewHostToWeakDelegateMapType rvh_to_weak_delegate_map_; + RenderViewHostToIoThreadClientType rvh_to_io_thread_client_; }; // static @@ -69,27 +78,27 @@ RvhToIoThreadClientMap* RvhToIoThreadClientMap::GetInstance() { return g_instance_.Pointer(); } -void RvhToIoThreadClientMap::Insert(pair<int, int> rvh_id, - JavaObjectWeakGlobalRef jdelegate) { +void RvhToIoThreadClientMap::Set(pair<int, int> rvh_id, + const IoThreadClientData& client) { base::AutoLock lock(map_lock_); - rvh_to_weak_delegate_map_[rvh_id] = jdelegate; + rvh_to_io_thread_client_[rvh_id] = client; } -ScopedJavaLocalRef<jobject> RvhToIoThreadClientMap::Get( - pair<int, int> rvh_id) { +bool RvhToIoThreadClientMap::Get( + pair<int, int> rvh_id, IoThreadClientData* client) { base::AutoLock lock(map_lock_); - RenderViewHostToWeakDelegateMapType::iterator weak_delegate_iterator = - rvh_to_weak_delegate_map_.find(rvh_id); - if (weak_delegate_iterator == rvh_to_weak_delegate_map_.end()) - return ScopedJavaLocalRef<jobject>(); + RenderViewHostToIoThreadClientType::iterator iterator = + rvh_to_io_thread_client_.find(rvh_id); + if (iterator == rvh_to_io_thread_client_.end()) + return false; - JNIEnv* env = AttachCurrentThread(); - return weak_delegate_iterator->second.get(env); + *client = iterator->second; + return true; } void RvhToIoThreadClientMap::Erase(pair<int, int> rvh_id) { base::AutoLock lock(map_lock_); - rvh_to_weak_delegate_map_.erase(rvh_id); + rvh_to_io_thread_client_.erase(rvh_id); } // ClientMapEntryUpdater ------------------------------------------------------ @@ -122,8 +131,11 @@ ClientMapEntryUpdater::ClientMapEntryUpdater(JNIEnv* env, } void ClientMapEntryUpdater::RenderViewCreated(RenderViewHost* rvh) { - RvhToIoThreadClientMap::GetInstance()->Insert( - GetRenderViewHostIdPair(rvh), jdelegate_); + IoThreadClientData client_data; + client_data.io_thread_client = jdelegate_; + client_data.pending_association = false; + RvhToIoThreadClientMap::GetInstance()->Set( + GetRenderViewHostIdPair(rvh), client_data); } void ClientMapEntryUpdater::RenderViewForInterstitialPageCreated( @@ -149,13 +161,25 @@ void ClientMapEntryUpdater::WebContentsDestroyed(WebContents* web_contents) { scoped_ptr<AwContentsIoThreadClient> AwContentsIoThreadClient::FromID(int render_process_id, int render_view_id) { pair<int, int> rvh_id(render_process_id, render_view_id); - ScopedJavaLocalRef<jobject> java_delegate = - RvhToIoThreadClientMap::GetInstance()->Get(rvh_id); - if (java_delegate.is_null()) + IoThreadClientData client_data; + if (!RvhToIoThreadClientMap::GetInstance()->Get(rvh_id, &client_data)) return scoped_ptr<AwContentsIoThreadClient>(); - return scoped_ptr<AwContentsIoThreadClient>( - new AwContentsIoThreadClientImpl(java_delegate)); + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobject> java_delegate = + client_data.io_thread_client.get(env); + DCHECK(!client_data.pending_association || java_delegate.is_null()); + return scoped_ptr<AwContentsIoThreadClient>(new AwContentsIoThreadClientImpl( + client_data.pending_association, java_delegate)); +} + +// static +void AwContentsIoThreadClientImpl::RegisterPendingContents( + WebContents* web_contents) { + IoThreadClientData client_data; + client_data.pending_association = true; + RvhToIoThreadClientMap::GetInstance()->Set( + GetRenderViewHostIdPair(web_contents->GetRenderViewHost()), client_data); } // static @@ -168,14 +192,20 @@ void AwContentsIoThreadClientImpl::Associate( } AwContentsIoThreadClientImpl::AwContentsIoThreadClientImpl( + bool pending_association, const JavaRef<jobject>& obj) - : java_object_(obj) { + : pending_association_(pending_association), + java_object_(obj) { } AwContentsIoThreadClientImpl::~AwContentsIoThreadClientImpl() { // explict, out-of-line destructor. } +bool AwContentsIoThreadClientImpl::PendingAssociation() const { + return pending_association_; +} + AwContentsIoThreadClient::CacheMode AwContentsIoThreadClientImpl::GetCacheMode() const { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); diff --git a/android_webview/native/aw_contents_io_thread_client_impl.h b/android_webview/native/aw_contents_io_thread_client_impl.h index bb34950..e2561af 100644 --- a/android_webview/native/aw_contents_io_thread_client_impl.h +++ b/android_webview/native/aw_contents_io_thread_client_impl.h @@ -28,16 +28,23 @@ class InterceptedRequestData; class AwContentsIoThreadClientImpl : public AwContentsIoThreadClient { public: + // Called when AwContents is created before there is a Java client. + static void RegisterPendingContents(content::WebContents* web_contents); + // Associates the |jclient| instance (which must implement the // AwContentsIoThreadClient Java interface) with the |web_contents|. // This should be called at most once per |web_contents|. static void Associate(content::WebContents* web_contents, const base::android::JavaRef<jobject>& jclient); - AwContentsIoThreadClientImpl(const base::android::JavaRef<jobject>& jclient); + // Either |pending_associate| is true or |jclient| holds a non-null + // Java object. + AwContentsIoThreadClientImpl(bool pending_associate, + const base::android::JavaRef<jobject>& jclient); virtual ~AwContentsIoThreadClientImpl() OVERRIDE; // Implementation of AwContentsIoThreadClient. + virtual bool PendingAssociation() const OVERRIDE; virtual CacheMode GetCacheMode() const OVERRIDE; virtual scoped_ptr<InterceptedRequestData> ShouldInterceptRequest( const GURL& location, @@ -55,6 +62,7 @@ class AwContentsIoThreadClientImpl : public AwContentsIoThreadClient { const std::string& args) OVERRIDE; private: + bool pending_association_; base::android::ScopedJavaGlobalRef<jobject> java_object_; DISALLOW_COPY_AND_ASSIGN(AwContentsIoThreadClientImpl); |