Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "android_webview/native/aw_contents_io_thread_delegate.h" | |
| 6 | |
| 7 #include "android_webview/native/intercepted_request_data.h" | |
| 8 #include "base/android/jni_helper.h" | |
| 9 #include "base/android/jni_string.h" | |
| 10 #include "base/hash_tables.h" | |
| 11 #include "base/memory/linked_ptr.h" | |
| 12 #include "base/memory/scoped_ptr.h" | |
| 13 #include "base/synchronization/lock.h" | |
| 14 #include "content/public/browser/browser_thread.h" | |
| 15 #include "content/public/browser/render_view_host.h" | |
| 16 #include "content/public/browser/web_contents.h" | |
| 17 #include "content/public/browser/web_contents_observer.h" | |
| 18 #include "net/url_request/url_request.h" | |
| 19 | |
| 20 #include "jni/AwWebContentsIoThreadDelegate_jni.h" | |
| 21 | |
| 22 using namespace base::android; | |
| 23 using content::BrowserThread; | |
| 24 using content::RenderViewHost; | |
| 25 using content::WebContents; | |
| 26 | |
| 27 #if defined(COMPILER_GCC) | |
| 28 namespace BASE_HASH_NAMESPACE { | |
| 29 | |
| 30 template<> | |
| 31 struct hash<content::WebContents*> { | |
| 32 size_t operator()(content::WebContents* value) const { | |
| 33 return hash<void*>()(static_cast<void*>(value)); | |
| 34 } | |
| 35 }; | |
| 36 | |
| 37 template<> | |
| 38 struct hash<content::RenderViewHost*> { | |
| 39 size_t operator()(content::RenderViewHost* value) const { | |
| 40 return hash<void*>()(static_cast<void*>(value)); | |
| 41 } | |
| 42 }; | |
| 43 | |
| 44 } // 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
| |
| 45 #endif | |
| 46 | |
| 47 namespace { | |
| 48 | |
| 49 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.
| |
| 50 typedef base::hash_map<RenderViewHost*, WebContents*> | |
| 51 RenderViewHostToWebContentsMapType; | |
| 52 typedef std::map<WebContents*, LinkedJavaWeakRef> | |
| 53 WebContentsToWeakClientMapType; | |
| 54 | |
| 55 base::Lock g_map_lock; | |
| 56 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
| |
| 57 WebContentsToWeakClientMapType g_web_contents_to_weak_delegate_map; | |
|
joth
2012/09/01 01:24:14
LazyInstance...
and will need comments about why
| |
| 58 | |
| 59 } // namespace | |
| 60 | |
| 61 // WebContentsObserver -------------------------------------------------------- | |
| 62 | |
| 63 class AwWebContentsIoThreadDelegate::WebContentsObserver | |
| 64 : public content::WebContentsObserver { | |
| 65 public: | |
| 66 WebContentsObserver(JNIEnv* env, jobject jdelegate, | |
| 67 WebContents* web_contents); | |
| 68 | |
| 69 virtual void RenderViewCreated(RenderViewHost* render_view_host) OVERRIDE; | |
| 70 virtual void RenderViewForInterstitialPageCreated( | |
| 71 RenderViewHost* render_view_host) OVERRIDE; | |
| 72 virtual void RenderViewDeleted(RenderViewHost* render_view_host) OVERRIDE; | |
| 73 virtual void WebContentsDestroyed(WebContents* web_contents); | |
| 74 }; | |
| 75 | |
| 76 AwWebContentsIoThreadDelegate::WebContentsObserver::WebContentsObserver( | |
| 77 JNIEnv* env, jobject jdelegate, | |
| 78 WebContents* web_contents) | |
| 79 : content::WebContentsObserver(web_contents) { | |
| 80 DCHECK(web_contents); | |
| 81 DCHECK(jdelegate); | |
| 82 LinkedJavaWeakRef linked_weak_delegate_ref = LinkedJavaWeakRef( | |
| 83 new JavaObjectWeakGlobalRef(env, jdelegate)); | |
| 84 base::AutoLock lock(g_map_lock); | |
| 85 g_web_contents_to_weak_delegate_map[web_contents] = linked_weak_delegate_ref; | |
| 86 } | |
| 87 | |
| 88 void AwWebContentsIoThreadDelegate::WebContentsObserver::RenderViewCreated( | |
| 89 RenderViewHost* rvh) { | |
| 90 DCHECK(rvh); | |
| 91 DCHECK(web_contents()); | |
| 92 base::AutoLock lock(g_map_lock); | |
| 93 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
| |
| 94 } | |
| 95 | |
| 96 void AwWebContentsIoThreadDelegate::WebContentsObserver:: | |
| 97 RenderViewForInterstitialPageCreated(RenderViewHost* rvh) { | |
| 98 RenderViewCreated(rvh); | |
| 99 } | |
| 100 | |
| 101 void AwWebContentsIoThreadDelegate::WebContentsObserver::RenderViewDeleted( | |
| 102 RenderViewHost* rvh) { | |
| 103 DCHECK(rvh); | |
| 104 base::AutoLock lock(g_map_lock); | |
| 105 g_rvh_to_web_contents_map.erase(rvh); | |
| 106 } | |
| 107 | |
| 108 void AwWebContentsIoThreadDelegate::WebContentsObserver::WebContentsDestroyed( | |
| 109 WebContents* web_contents) { | |
| 110 scoped_ptr<AwWebContentsIoThreadDelegate> io_thread_delegate = | |
| 111 AwWebContentsIoThreadDelegate::ForWebContents(web_contents); | |
| 112 if (io_thread_delegate.get()) | |
| 113 io_thread_delegate->OnWebContentsDestroyed(); | |
| 114 { | |
| 115 base::AutoLock lock(g_map_lock); | |
| 116 g_web_contents_to_weak_delegate_map.erase(web_contents); | |
| 117 } | |
| 118 delete this; | |
| 119 } | |
| 120 | |
| 121 // AwWebContentsIoThreadDelegate ---------------------------------------------- | |
| 122 | |
| 123 // JNI Methods ---------------------------------------------------------------- | |
| 124 | |
| 125 void Init(JNIEnv* env, jobject jdelegate, | |
| 126 jint native_web_contents) { | |
| 127 WebContents* web_contents = | |
| 128 reinterpret_cast<WebContents*>(native_web_contents); | |
| 129 // The observer's lifespan is tied to that of the WebContents. | |
| 130 new AwWebContentsIoThreadDelegate::WebContentsObserver( | |
| 131 env, jdelegate, web_contents); | |
| 132 } | |
| 133 | |
| 134 bool AwWebContentsIoThreadDelegate::RegisterAwWebContentsIoThreadDelegate( | |
| 135 JNIEnv* env) { | |
| 136 return RegisterNativesImpl(env); | |
| 137 } | |
| 138 | |
| 139 // Static methods ------------------------------------------------------------- | |
| 140 | |
| 141 scoped_ptr<AwWebContentsIoThreadDelegate> | |
| 142 AwWebContentsIoThreadDelegate::ForRenderViewHost(RenderViewHost* rvh) { | |
| 143 DCHECK(rvh); | |
| 144 WebContents* web_contents = NULL; | |
| 145 { | |
| 146 base::AutoLock lock(g_map_lock); | |
| 147 RenderViewHostToWebContentsMapType::iterator web_contents_iterator = | |
| 148 g_rvh_to_web_contents_map.find(rvh); | |
| 149 if (web_contents_iterator != g_rvh_to_web_contents_map.end()) | |
| 150 web_contents = web_contents_iterator->second; | |
| 151 } | |
| 152 if (web_contents == NULL) | |
| 153 return scoped_ptr<AwWebContentsIoThreadDelegate>(); | |
| 154 return ForWebContents(web_contents).Pass(); | |
| 155 } | |
| 156 | |
| 157 scoped_ptr<AwWebContentsIoThreadDelegate> | |
| 158 AwWebContentsIoThreadDelegate::ForWebContents(WebContents* web_contents) { | |
| 159 DCHECK(web_contents); | |
| 160 base::AutoLock lock(g_map_lock); | |
| 161 WebContentsToWeakClientMapType::iterator weak_delegate_iterator = | |
| 162 g_web_contents_to_weak_delegate_map.find(web_contents); | |
| 163 if (weak_delegate_iterator == g_web_contents_to_weak_delegate_map.end()) | |
| 164 return scoped_ptr<AwWebContentsIoThreadDelegate>(); | |
| 165 | |
| 166 JNIEnv* env = AttachCurrentThread(); | |
| 167 ScopedJavaLocalRef<jobject> java_delegate = | |
| 168 weak_delegate_iterator->second->get(env); | |
| 169 if (!java_delegate.obj()) | |
| 170 return scoped_ptr<AwWebContentsIoThreadDelegate>(); | |
| 171 | |
| 172 return scoped_ptr<AwWebContentsIoThreadDelegate>( | |
| 173 new AwWebContentsIoThreadDelegate(java_delegate)); | |
| 174 } | |
| 175 | |
| 176 // regular methods ------------------------------------------------------------ | |
| 177 | |
| 178 AwWebContentsIoThreadDelegate::AwWebContentsIoThreadDelegate( | |
| 179 const JavaRef<jobject>& obj) | |
| 180 : java_object_(obj) { | |
| 181 } | |
| 182 | |
| 183 AwWebContentsIoThreadDelegate::~AwWebContentsIoThreadDelegate() { | |
| 184 } | |
| 185 | |
| 186 void AwWebContentsIoThreadDelegate::OnWebContentsDestroyed() { | |
| 187 JNIEnv* env = AttachCurrentThread(); | |
| 188 Java_AwWebContentsIoThreadDelegate_onWebContentsDestroyed( | |
| 189 env, java_object_.obj()); | |
| 190 } | |
| 191 | |
| 192 scoped_ptr<InterceptedRequestData> | |
| 193 AwWebContentsIoThreadDelegate::ShouldInterceptRequest( | |
| 194 const net::URLRequest* request) { | |
| 195 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 196 JNIEnv* env = AttachCurrentThread(); | |
| 197 ScopedJavaLocalRef<jstring> jstring_url = | |
| 198 ConvertUTF8ToJavaString(env, request->url().spec()); | |
| 199 ScopedJavaLocalRef<jobject> ret = | |
| 200 Java_AwWebContentsIoThreadDelegate_shouldInterceptRequest( | |
| 201 env, java_object_.obj(), jstring_url.obj()); | |
| 202 if (ret.is_null()) | |
| 203 return scoped_ptr<InterceptedRequestData>(); | |
| 204 return scoped_ptr<InterceptedRequestData>( | |
| 205 new InterceptedRequestData(ret)); | |
| 206 } | |
| OLD | NEW |