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.
5 #include "android_webview/native/aw_contents_io_thread_client_impl.h"
10 #include "android_webview/native/intercepted_request_data_impl.h"
11 #include "base/android/jni_helper.h"
12 #include "base/android/jni_string.h"
13 #include "base/lazy_instance.h"
14 #include "base/memory/linked_ptr.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/synchronization/lock.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/browser/render_process_host.h"
19 #include "content/public/browser/render_view_host.h"
20 #include "content/public/browser/resource_request_info.h"
21 #include "content/public/browser/web_contents.h"
22 #include "content/public/browser/web_contents_observer.h"
23 #include "googleurl/src/gurl.h"
24 #include "net/url_request/url_request.h"
26 #include "jni/AwContentsIoThreadClient_jni.h"
28 using base::android::AttachCurrentThread
;
29 using base::android::ConvertUTF8ToJavaString
;
30 using base::android::JavaRef
;
31 using base::android::ScopedJavaLocalRef
;
32 using base::LazyInstance
;
33 using content::BrowserThread
;
34 using content::RenderViewHost
;
35 using content::WebContents
;
39 namespace android_webview
{
43 typedef map
<pair
<int, int>, JavaObjectWeakGlobalRef
>
44 RenderViewHostToWeakDelegateMapType
;
46 static pair
<int, int> GetRenderViewHostIdPair(RenderViewHost
* rvh
) {
47 return pair
<int, int>(rvh
->GetProcess()->GetID(), rvh
->GetRoutingID());
50 // RvhToIoThreadClientMap -----------------------------------------------------
51 class RvhToIoThreadClientMap
{
53 static RvhToIoThreadClientMap
* GetInstance();
54 void Insert(pair
<int, int> rvh_id
, JavaObjectWeakGlobalRef jdelegate
);
55 ScopedJavaLocalRef
<jobject
> Get(pair
<int, int> rvh_id
);
56 void Erase(pair
<int, int> rvh_id
);
59 static LazyInstance
<RvhToIoThreadClientMap
> g_instance_
;
61 RenderViewHostToWeakDelegateMapType rvh_to_weak_delegate_map_
;
65 LazyInstance
<RvhToIoThreadClientMap
> RvhToIoThreadClientMap::g_instance_
=
66 LAZY_INSTANCE_INITIALIZER
;
69 RvhToIoThreadClientMap
* RvhToIoThreadClientMap::GetInstance() {
70 return g_instance_
.Pointer();
73 void RvhToIoThreadClientMap::Insert(pair
<int, int> rvh_id
,
74 JavaObjectWeakGlobalRef jdelegate
) {
75 base::AutoLock
lock(map_lock_
);
76 rvh_to_weak_delegate_map_
[rvh_id
] = jdelegate
;
79 ScopedJavaLocalRef
<jobject
> RvhToIoThreadClientMap::Get(
80 pair
<int, int> rvh_id
) {
81 base::AutoLock
lock(map_lock_
);
82 RenderViewHostToWeakDelegateMapType::iterator weak_delegate_iterator
=
83 rvh_to_weak_delegate_map_
.find(rvh_id
);
84 if (weak_delegate_iterator
== rvh_to_weak_delegate_map_
.end())
85 return ScopedJavaLocalRef
<jobject
>();
87 JNIEnv
* env
= AttachCurrentThread();
88 return weak_delegate_iterator
->second
.get(env
);
91 void RvhToIoThreadClientMap::Erase(pair
<int, int> rvh_id
) {
92 base::AutoLock
lock(map_lock_
);
93 rvh_to_weak_delegate_map_
.erase(rvh_id
);
96 // ClientMapEntryUpdater ------------------------------------------------------
98 class ClientMapEntryUpdater
: public content::WebContentsObserver
{
100 ClientMapEntryUpdater(JNIEnv
* env
, WebContents
* web_contents
,
103 virtual void RenderViewCreated(RenderViewHost
* render_view_host
) OVERRIDE
;
104 virtual void RenderViewForInterstitialPageCreated(
105 RenderViewHost
* render_view_host
) OVERRIDE
;
106 virtual void RenderViewDeleted(RenderViewHost
* render_view_host
) OVERRIDE
;
107 virtual void WebContentsDestroyed(WebContents
* web_contents
);
110 JavaObjectWeakGlobalRef jdelegate_
;
113 ClientMapEntryUpdater::ClientMapEntryUpdater(JNIEnv
* env
,
114 WebContents
* web_contents
,
116 : content::WebContentsObserver(web_contents
),
117 jdelegate_(env
, jdelegate
) {
118 DCHECK(web_contents
);
121 if (web_contents
->GetRenderViewHost())
122 RenderViewCreated(web_contents
->GetRenderViewHost());
125 void ClientMapEntryUpdater::RenderViewCreated(RenderViewHost
* rvh
) {
126 RvhToIoThreadClientMap::GetInstance()->Insert(
127 GetRenderViewHostIdPair(rvh
), jdelegate_
);
130 void ClientMapEntryUpdater::RenderViewForInterstitialPageCreated(
131 RenderViewHost
* rvh
) {
132 RenderViewCreated(rvh
);
135 void ClientMapEntryUpdater::RenderViewDeleted(RenderViewHost
* rvh
) {
136 RvhToIoThreadClientMap::GetInstance()->Erase(GetRenderViewHostIdPair(rvh
));
139 void ClientMapEntryUpdater::WebContentsDestroyed(WebContents
* web_contents
) {
140 if (web_contents
->GetRenderViewHost())
141 RenderViewDeleted(web_contents
->GetRenderViewHost());
147 // AwContentsIoThreadClientImpl -----------------------------------------------
150 scoped_ptr
<AwContentsIoThreadClient
>
151 AwContentsIoThreadClient::FromID(int render_process_id
, int render_view_id
) {
152 pair
<int, int> rvh_id(render_process_id
, render_view_id
);
153 ScopedJavaLocalRef
<jobject
> java_delegate
=
154 RvhToIoThreadClientMap::GetInstance()->Get(rvh_id
);
155 if (java_delegate
.is_null())
156 return scoped_ptr
<AwContentsIoThreadClient
>();
158 return scoped_ptr
<AwContentsIoThreadClient
>(
159 new AwContentsIoThreadClientImpl(java_delegate
));
163 void AwContentsIoThreadClientImpl::Associate(
164 WebContents
* web_contents
,
165 const JavaRef
<jobject
>& jclient
) {
166 JNIEnv
* env
= AttachCurrentThread();
167 // The ClientMapEntryUpdater lifespan is tied to the WebContents.
168 new ClientMapEntryUpdater(env
, web_contents
, jclient
.obj());
171 AwContentsIoThreadClientImpl::AwContentsIoThreadClientImpl(
172 const JavaRef
<jobject
>& obj
)
173 : java_object_(obj
) {
176 AwContentsIoThreadClientImpl::~AwContentsIoThreadClientImpl() {
177 // explict, out-of-line destructor.
180 AwContentsIoThreadClient::CacheMode
181 AwContentsIoThreadClientImpl::GetCacheMode() const {
182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
183 if (java_object_
.is_null())
184 return AwContentsIoThreadClient::LOAD_DEFAULT
;
186 JNIEnv
* env
= AttachCurrentThread();
187 return static_cast<AwContentsIoThreadClient::CacheMode
>(
188 Java_AwContentsIoThreadClient_getCacheMode(
189 env
, java_object_
.obj()));
192 scoped_ptr
<InterceptedRequestData
>
193 AwContentsIoThreadClientImpl::ShouldInterceptRequest(
194 const GURL
& location
,
195 const net::URLRequest
* request
) {
196 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
197 if (java_object_
.is_null())
198 return scoped_ptr
<InterceptedRequestData
>();
199 const content::ResourceRequestInfo
* info
=
200 content::ResourceRequestInfo::ForRequest(request
);
201 bool is_main_frame
= info
&& info
->IsMainFrame();
203 JNIEnv
* env
= AttachCurrentThread();
204 ScopedJavaLocalRef
<jstring
> jstring_url
=
205 ConvertUTF8ToJavaString(env
, location
.spec());
206 ScopedJavaLocalRef
<jobject
> ret
=
207 Java_AwContentsIoThreadClient_shouldInterceptRequest(
208 env
, java_object_
.obj(), jstring_url
.obj(), is_main_frame
);
210 return scoped_ptr
<InterceptedRequestData
>();
211 return scoped_ptr
<InterceptedRequestData
>(
212 new InterceptedRequestDataImpl(ret
));
215 bool AwContentsIoThreadClientImpl::ShouldBlockContentUrls() const {
216 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
217 if (java_object_
.is_null())
220 JNIEnv
* env
= AttachCurrentThread();
221 return Java_AwContentsIoThreadClient_shouldBlockContentUrls(
222 env
, java_object_
.obj());
225 bool AwContentsIoThreadClientImpl::ShouldBlockFileUrls() const {
226 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
227 if (java_object_
.is_null())
230 JNIEnv
* env
= AttachCurrentThread();
231 return Java_AwContentsIoThreadClient_shouldBlockFileUrls(
232 env
, java_object_
.obj());
235 bool AwContentsIoThreadClientImpl::ShouldBlockNetworkLoads() const {
236 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
237 if (java_object_
.is_null())
240 JNIEnv
* env
= AttachCurrentThread();
241 return Java_AwContentsIoThreadClient_shouldBlockNetworkLoads(
242 env
, java_object_
.obj());
245 void AwContentsIoThreadClientImpl::NewDownload(
247 const std::string
& user_agent
,
248 const std::string
& content_disposition
,
249 const std::string
& mime_type
,
250 int64 content_length
) {
251 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
252 if (java_object_
.is_null())
255 JNIEnv
* env
= AttachCurrentThread();
256 ScopedJavaLocalRef
<jstring
> jstring_url
=
257 ConvertUTF8ToJavaString(env
, url
.spec());
258 ScopedJavaLocalRef
<jstring
> jstring_user_agent
=
259 ConvertUTF8ToJavaString(env
, user_agent
);
260 ScopedJavaLocalRef
<jstring
> jstring_content_disposition
=
261 ConvertUTF8ToJavaString(env
, content_disposition
);
262 ScopedJavaLocalRef
<jstring
> jstring_mime_type
=
263 ConvertUTF8ToJavaString(env
, mime_type
);
265 Java_AwContentsIoThreadClient_onDownloadStart(
269 jstring_user_agent
.obj(),
270 jstring_content_disposition
.obj(),
271 jstring_mime_type
.obj(),
275 void AwContentsIoThreadClientImpl::NewLoginRequest(const std::string
& realm
,
276 const std::string
& account
,
277 const std::string
& args
) {
278 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
279 if (java_object_
.is_null())
282 JNIEnv
* env
= AttachCurrentThread();
283 ScopedJavaLocalRef
<jstring
> jrealm
= ConvertUTF8ToJavaString(env
, realm
);
284 ScopedJavaLocalRef
<jstring
> jargs
= ConvertUTF8ToJavaString(env
, args
);
286 ScopedJavaLocalRef
<jstring
> jaccount
;
287 if (!account
.empty())
288 jaccount
= ConvertUTF8ToJavaString(env
, account
);
290 Java_AwContentsIoThreadClient_newLoginRequest(
291 env
, java_object_
.obj(), jrealm
.obj(), jaccount
.obj(), jargs
.obj());
294 bool RegisterAwContentsIoThreadClientImpl(JNIEnv
* env
) {
295 return RegisterNativesImpl(env
);
298 } // namespace android_webview