Chromium Code Reviews| Index: android_webview/native/aw_contents_io_thread_delegate.cc |
| diff --git a/android_webview/native/aw_contents_io_thread_delegate.cc b/android_webview/native/aw_contents_io_thread_delegate.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..0988d2fabd65c93c4dac2e215838e32df2433d9f |
| --- /dev/null |
| +++ b/android_webview/native/aw_contents_io_thread_delegate.cc |
| @@ -0,0 +1,206 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "android_webview/native/aw_contents_io_thread_delegate.h" |
| + |
| +#include "android_webview/native/intercepted_request_data.h" |
| +#include "base/android/jni_helper.h" |
| +#include "base/android/jni_string.h" |
| +#include "base/hash_tables.h" |
| +#include "base/memory/linked_ptr.h" |
| +#include "base/memory/scoped_ptr.h" |
| +#include "base/synchronization/lock.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "content/public/browser/render_view_host.h" |
| +#include "content/public/browser/web_contents.h" |
| +#include "content/public/browser/web_contents_observer.h" |
| +#include "net/url_request/url_request.h" |
| + |
| +#include "jni/AwWebContentsIoThreadDelegate_jni.h" |
| + |
| +using namespace base::android; |
| +using content::BrowserThread; |
| +using content::RenderViewHost; |
| +using content::WebContents; |
| + |
| +#if defined(COMPILER_GCC) |
| +namespace BASE_HASH_NAMESPACE { |
| + |
| +template<> |
| +struct hash<content::WebContents*> { |
| + size_t operator()(content::WebContents* value) const { |
| + return hash<void*>()(static_cast<void*>(value)); |
| + } |
| +}; |
| + |
| +template<> |
| +struct hash<content::RenderViewHost*> { |
| + size_t operator()(content::RenderViewHost* value) const { |
| + return hash<void*>()(static_cast<void*>(value)); |
| + } |
| +}; |
| + |
| +} // namespace BASE_HASH_NAMESPACE |
|
joth
2012/09/01 01:24:14
IIRC we specifically don't use hash_tables on andr
mkosiba (inactive)
2012/09/11 01:22:25
that's sad.. a map<> is usually some form of a bal
|
| +#endif |
| + |
| +namespace { |
| + |
| +typedef linked_ptr<JavaObjectWeakGlobalRef> LinkedJavaWeakRef; |
|
joth
2012/09/01 01:24:14
we could give JavaObjectWeakGlobalRef a copy c'tor
joth
2012/09/01 01:24:14
we could give JavaObjectWeakGlobalRef a copy c'tor
mkosiba (inactive)
2012/09/11 01:22:25
Done.
|
| +typedef base::hash_map<RenderViewHost*, WebContents*> |
| + RenderViewHostToWebContentsMapType; |
| +typedef std::map<WebContents*, LinkedJavaWeakRef> |
| + WebContentsToWeakClientMapType; |
| + |
| +base::Lock g_map_lock; |
| +RenderViewHostToWebContentsMapType g_rvh_to_web_contents_map; |
|
boliu
2012/09/06 00:46:23
WebContents::FromRenderViewHost can't be used here
mkosiba (inactive)
2012/09/11 01:22:25
yes, the problem is that while you can get a WebCo
|
| +WebContentsToWeakClientMapType g_web_contents_to_weak_delegate_map; |
|
joth
2012/09/01 01:24:14
LazyInstance...
and will need comments about why
|
| + |
| +} // namespace |
| + |
| +// WebContentsObserver -------------------------------------------------------- |
| + |
| +class AwWebContentsIoThreadDelegate::WebContentsObserver |
| + : public content::WebContentsObserver { |
| + public: |
| + WebContentsObserver(JNIEnv* env, jobject jdelegate, |
| + WebContents* web_contents); |
| + |
| + virtual void RenderViewCreated(RenderViewHost* render_view_host) OVERRIDE; |
| + virtual void RenderViewForInterstitialPageCreated( |
| + RenderViewHost* render_view_host) OVERRIDE; |
| + virtual void RenderViewDeleted(RenderViewHost* render_view_host) OVERRIDE; |
| + virtual void WebContentsDestroyed(WebContents* web_contents); |
| +}; |
| + |
| +AwWebContentsIoThreadDelegate::WebContentsObserver::WebContentsObserver( |
| + JNIEnv* env, jobject jdelegate, |
| + WebContents* web_contents) |
| + : content::WebContentsObserver(web_contents) { |
| + DCHECK(web_contents); |
| + DCHECK(jdelegate); |
| + LinkedJavaWeakRef linked_weak_delegate_ref = LinkedJavaWeakRef( |
| + new JavaObjectWeakGlobalRef(env, jdelegate)); |
| + base::AutoLock lock(g_map_lock); |
| + g_web_contents_to_weak_delegate_map[web_contents] = linked_weak_delegate_ref; |
| +} |
| + |
| +void AwWebContentsIoThreadDelegate::WebContentsObserver::RenderViewCreated( |
| + RenderViewHost* rvh) { |
| + DCHECK(rvh); |
| + DCHECK(web_contents()); |
| + base::AutoLock lock(g_map_lock); |
| + g_rvh_to_web_contents_map[rvh] = web_contents(); |
|
joth
2012/09/01 01:24:14
if you hold the weak ref as a member of this WebCo
mkosiba (inactive)
2012/09/11 01:22:25
I had it work like that in one of the initial iter
|
| +} |
| + |
| +void AwWebContentsIoThreadDelegate::WebContentsObserver:: |
| +RenderViewForInterstitialPageCreated(RenderViewHost* rvh) { |
| + RenderViewCreated(rvh); |
| +} |
| + |
| +void AwWebContentsIoThreadDelegate::WebContentsObserver::RenderViewDeleted( |
| + RenderViewHost* rvh) { |
| + DCHECK(rvh); |
| + base::AutoLock lock(g_map_lock); |
| + g_rvh_to_web_contents_map.erase(rvh); |
| +} |
| + |
| +void AwWebContentsIoThreadDelegate::WebContentsObserver::WebContentsDestroyed( |
| + WebContents* web_contents) { |
| + scoped_ptr<AwWebContentsIoThreadDelegate> io_thread_delegate = |
| + AwWebContentsIoThreadDelegate::ForWebContents(web_contents); |
| + if (io_thread_delegate.get()) |
| + io_thread_delegate->OnWebContentsDestroyed(); |
| + { |
| + base::AutoLock lock(g_map_lock); |
| + g_web_contents_to_weak_delegate_map.erase(web_contents); |
| + } |
| + delete this; |
| +} |
| + |
| +// AwWebContentsIoThreadDelegate ---------------------------------------------- |
| + |
| +// JNI Methods ---------------------------------------------------------------- |
| + |
| +void Init(JNIEnv* env, jobject jdelegate, |
| + jint native_web_contents) { |
| + WebContents* web_contents = |
| + reinterpret_cast<WebContents*>(native_web_contents); |
| + // The observer's lifespan is tied to that of the WebContents. |
| + new AwWebContentsIoThreadDelegate::WebContentsObserver( |
| + env, jdelegate, web_contents); |
| +} |
| + |
| +bool AwWebContentsIoThreadDelegate::RegisterAwWebContentsIoThreadDelegate( |
| + JNIEnv* env) { |
| + return RegisterNativesImpl(env); |
| +} |
| + |
| +// Static methods ------------------------------------------------------------- |
| + |
| +scoped_ptr<AwWebContentsIoThreadDelegate> |
| +AwWebContentsIoThreadDelegate::ForRenderViewHost(RenderViewHost* rvh) { |
| + DCHECK(rvh); |
| + WebContents* web_contents = NULL; |
| + { |
| + base::AutoLock lock(g_map_lock); |
| + RenderViewHostToWebContentsMapType::iterator web_contents_iterator = |
| + g_rvh_to_web_contents_map.find(rvh); |
| + if (web_contents_iterator != g_rvh_to_web_contents_map.end()) |
| + web_contents = web_contents_iterator->second; |
| + } |
| + if (web_contents == NULL) |
| + return scoped_ptr<AwWebContentsIoThreadDelegate>(); |
| + return ForWebContents(web_contents).Pass(); |
| +} |
| + |
| +scoped_ptr<AwWebContentsIoThreadDelegate> |
| +AwWebContentsIoThreadDelegate::ForWebContents(WebContents* web_contents) { |
| + DCHECK(web_contents); |
| + base::AutoLock lock(g_map_lock); |
| + WebContentsToWeakClientMapType::iterator weak_delegate_iterator = |
| + g_web_contents_to_weak_delegate_map.find(web_contents); |
| + if (weak_delegate_iterator == g_web_contents_to_weak_delegate_map.end()) |
| + return scoped_ptr<AwWebContentsIoThreadDelegate>(); |
| + |
| + JNIEnv* env = AttachCurrentThread(); |
| + ScopedJavaLocalRef<jobject> java_delegate = |
| + weak_delegate_iterator->second->get(env); |
| + if (!java_delegate.obj()) |
| + return scoped_ptr<AwWebContentsIoThreadDelegate>(); |
| + |
| + return scoped_ptr<AwWebContentsIoThreadDelegate>( |
| + new AwWebContentsIoThreadDelegate(java_delegate)); |
| +} |
| + |
| +// regular methods ------------------------------------------------------------ |
| + |
| +AwWebContentsIoThreadDelegate::AwWebContentsIoThreadDelegate( |
| + const JavaRef<jobject>& obj) |
| + : java_object_(obj) { |
| +} |
| + |
| +AwWebContentsIoThreadDelegate::~AwWebContentsIoThreadDelegate() { |
| +} |
| + |
| +void AwWebContentsIoThreadDelegate::OnWebContentsDestroyed() { |
| + JNIEnv* env = AttachCurrentThread(); |
| + Java_AwWebContentsIoThreadDelegate_onWebContentsDestroyed( |
| + env, java_object_.obj()); |
| +} |
| + |
| +scoped_ptr<InterceptedRequestData> |
| +AwWebContentsIoThreadDelegate::ShouldInterceptRequest( |
| + const net::URLRequest* request) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + JNIEnv* env = AttachCurrentThread(); |
| + ScopedJavaLocalRef<jstring> jstring_url = |
| + ConvertUTF8ToJavaString(env, request->url().spec()); |
| + ScopedJavaLocalRef<jobject> ret = |
| + Java_AwWebContentsIoThreadDelegate_shouldInterceptRequest( |
| + env, java_object_.obj(), jstring_url.obj()); |
| + if (ret.is_null()) |
| + return scoped_ptr<InterceptedRequestData>(); |
| + return scoped_ptr<InterceptedRequestData>( |
| + new InterceptedRequestData(ret)); |
| +} |