Load the default favicon as a native image, rather than as a Skia image.
[chromium-blink-merge.git] / android_webview / native / aw_contents_io_thread_client_impl.cc
blobfd47138691a3efcdcfd2923706d07aa8ef0f0955
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"
7 #include <map>
8 #include <utility>
10 #include "android_webview/common/devtools_instrumentation.h"
11 #include "android_webview/native/intercepted_request_data_impl.h"
12 #include "base/android/jni_string.h"
13 #include "base/android/jni_weak_ref.h"
14 #include "base/lazy_instance.h"
15 #include "base/memory/linked_ptr.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/synchronization/lock.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/render_frame_host.h"
20 #include "content/public/browser/render_process_host.h"
21 #include "content/public/browser/render_view_host.h"
22 #include "content/public/browser/resource_request_info.h"
23 #include "content/public/browser/web_contents.h"
24 #include "content/public/browser/web_contents_observer.h"
25 #include "jni/AwContentsIoThreadClient_jni.h"
26 #include "net/url_request/url_request.h"
27 #include "url/gurl.h"
29 using base::android::AttachCurrentThread;
30 using base::android::ConvertUTF8ToJavaString;
31 using base::android::JavaRef;
32 using base::android::ScopedJavaLocalRef;
33 using base::LazyInstance;
34 using content::BrowserThread;
35 using content::RenderFrameHost;
36 using content::WebContents;
37 using std::map;
38 using std::pair;
40 namespace android_webview {
42 namespace {
44 struct IoThreadClientData {
45 bool pending_association;
46 JavaObjectWeakGlobalRef io_thread_client;
48 IoThreadClientData();
51 IoThreadClientData::IoThreadClientData() : pending_association(false) {}
53 typedef map<pair<int, int>, IoThreadClientData>
54 RenderFrameHostToIoThreadClientType;
56 static pair<int, int> GetRenderFrameHostIdPair(RenderFrameHost* rfh) {
57 return pair<int, int>(rfh->GetProcess()->GetID(), rfh->GetRoutingID());
60 // RfhToIoThreadClientMap -----------------------------------------------------
61 class RfhToIoThreadClientMap {
62 public:
63 static RfhToIoThreadClientMap* GetInstance();
64 void Set(pair<int, int> rfh_id, const IoThreadClientData& client);
65 bool Get(pair<int, int> rfh_id, IoThreadClientData* client);
66 void Erase(pair<int, int> rfh_id);
68 private:
69 static LazyInstance<RfhToIoThreadClientMap> g_instance_;
70 base::Lock map_lock_;
71 RenderFrameHostToIoThreadClientType rfh_to_io_thread_client_;
74 // static
75 LazyInstance<RfhToIoThreadClientMap> RfhToIoThreadClientMap::g_instance_ =
76 LAZY_INSTANCE_INITIALIZER;
78 // static
79 RfhToIoThreadClientMap* RfhToIoThreadClientMap::GetInstance() {
80 return g_instance_.Pointer();
83 void RfhToIoThreadClientMap::Set(pair<int, int> rfh_id,
84 const IoThreadClientData& client) {
85 base::AutoLock lock(map_lock_);
86 rfh_to_io_thread_client_[rfh_id] = client;
89 bool RfhToIoThreadClientMap::Get(
90 pair<int, int> rfh_id, IoThreadClientData* client) {
91 base::AutoLock lock(map_lock_);
92 RenderFrameHostToIoThreadClientType::iterator iterator =
93 rfh_to_io_thread_client_.find(rfh_id);
94 if (iterator == rfh_to_io_thread_client_.end())
95 return false;
97 *client = iterator->second;
98 return true;
101 void RfhToIoThreadClientMap::Erase(pair<int, int> rfh_id) {
102 base::AutoLock lock(map_lock_);
103 rfh_to_io_thread_client_.erase(rfh_id);
106 // ClientMapEntryUpdater ------------------------------------------------------
108 class ClientMapEntryUpdater : public content::WebContentsObserver {
109 public:
110 ClientMapEntryUpdater(JNIEnv* env, WebContents* web_contents,
111 jobject jdelegate);
113 virtual void RenderFrameCreated(RenderFrameHost* render_frame_host) OVERRIDE;
114 virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) OVERRIDE;
115 virtual void WebContentsDestroyed() OVERRIDE;
117 private:
118 JavaObjectWeakGlobalRef jdelegate_;
121 ClientMapEntryUpdater::ClientMapEntryUpdater(JNIEnv* env,
122 WebContents* web_contents,
123 jobject jdelegate)
124 : content::WebContentsObserver(web_contents),
125 jdelegate_(env, jdelegate) {
126 DCHECK(web_contents);
127 DCHECK(jdelegate);
129 if (web_contents->GetMainFrame())
130 RenderFrameCreated(web_contents->GetMainFrame());
133 void ClientMapEntryUpdater::RenderFrameCreated(RenderFrameHost* rfh) {
134 IoThreadClientData client_data;
135 client_data.io_thread_client = jdelegate_;
136 client_data.pending_association = false;
137 RfhToIoThreadClientMap::GetInstance()->Set(
138 GetRenderFrameHostIdPair(rfh), client_data);
141 void ClientMapEntryUpdater::RenderFrameDeleted(RenderFrameHost* rfh) {
142 RfhToIoThreadClientMap::GetInstance()->Erase(GetRenderFrameHostIdPair(rfh));
145 void ClientMapEntryUpdater::WebContentsDestroyed() {
146 delete this;
149 } // namespace
151 // AwContentsIoThreadClientImpl -----------------------------------------------
153 // static
154 scoped_ptr<AwContentsIoThreadClient>
155 AwContentsIoThreadClient::FromID(int render_process_id, int render_frame_id) {
156 pair<int, int> rfh_id(render_process_id, render_frame_id);
157 IoThreadClientData client_data;
158 if (!RfhToIoThreadClientMap::GetInstance()->Get(rfh_id, &client_data))
159 return scoped_ptr<AwContentsIoThreadClient>();
161 JNIEnv* env = AttachCurrentThread();
162 ScopedJavaLocalRef<jobject> java_delegate =
163 client_data.io_thread_client.get(env);
164 DCHECK(!client_data.pending_association || java_delegate.is_null());
165 return scoped_ptr<AwContentsIoThreadClient>(new AwContentsIoThreadClientImpl(
166 client_data.pending_association, java_delegate));
169 // static
170 void AwContentsIoThreadClient::SubFrameCreated(int render_process_id,
171 int parent_render_frame_id,
172 int child_render_frame_id) {
173 pair<int, int> parent_rfh_id(render_process_id, parent_render_frame_id);
174 pair<int, int> child_rfh_id(render_process_id, child_render_frame_id);
175 IoThreadClientData client_data;
176 if (!RfhToIoThreadClientMap::GetInstance()->Get(parent_rfh_id,
177 &client_data)) {
178 NOTREACHED();
179 return;
182 RfhToIoThreadClientMap::GetInstance()->Set(child_rfh_id, client_data);
185 // static
186 void AwContentsIoThreadClientImpl::RegisterPendingContents(
187 WebContents* web_contents) {
188 IoThreadClientData client_data;
189 client_data.pending_association = true;
190 RfhToIoThreadClientMap::GetInstance()->Set(
191 GetRenderFrameHostIdPair(web_contents->GetMainFrame()), client_data);
194 // static
195 void AwContentsIoThreadClientImpl::Associate(
196 WebContents* web_contents,
197 const JavaRef<jobject>& jclient) {
198 JNIEnv* env = AttachCurrentThread();
199 // The ClientMapEntryUpdater lifespan is tied to the WebContents.
200 new ClientMapEntryUpdater(env, web_contents, jclient.obj());
203 AwContentsIoThreadClientImpl::AwContentsIoThreadClientImpl(
204 bool pending_association,
205 const JavaRef<jobject>& obj)
206 : pending_association_(pending_association),
207 java_object_(obj) {
210 AwContentsIoThreadClientImpl::~AwContentsIoThreadClientImpl() {
211 // explict, out-of-line destructor.
214 bool AwContentsIoThreadClientImpl::PendingAssociation() const {
215 return pending_association_;
218 AwContentsIoThreadClient::CacheMode
219 AwContentsIoThreadClientImpl::GetCacheMode() const {
220 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
221 if (java_object_.is_null())
222 return AwContentsIoThreadClient::LOAD_DEFAULT;
224 JNIEnv* env = AttachCurrentThread();
225 return static_cast<AwContentsIoThreadClient::CacheMode>(
226 Java_AwContentsIoThreadClient_getCacheMode(
227 env, java_object_.obj()));
230 scoped_ptr<InterceptedRequestData>
231 AwContentsIoThreadClientImpl::ShouldInterceptRequest(
232 const GURL& location,
233 const net::URLRequest* request) {
234 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
235 if (java_object_.is_null())
236 return scoped_ptr<InterceptedRequestData>();
237 const content::ResourceRequestInfo* info =
238 content::ResourceRequestInfo::ForRequest(request);
239 bool is_main_frame = info &&
240 info->GetResourceType() == ResourceType::MAIN_FRAME;
242 JNIEnv* env = AttachCurrentThread();
243 ScopedJavaLocalRef<jstring> jstring_url =
244 ConvertUTF8ToJavaString(env, location.spec());
245 devtools_instrumentation::ScopedEmbedderCallbackTask embedder_callback(
246 "shouldInterceptRequest");
247 ScopedJavaLocalRef<jobject> ret =
248 Java_AwContentsIoThreadClient_shouldInterceptRequest(
249 env, java_object_.obj(), jstring_url.obj(), is_main_frame);
250 if (ret.is_null())
251 return scoped_ptr<InterceptedRequestData>();
252 return scoped_ptr<InterceptedRequestData>(
253 new InterceptedRequestDataImpl(ret));
256 bool AwContentsIoThreadClientImpl::ShouldBlockContentUrls() const {
257 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
258 if (java_object_.is_null())
259 return false;
261 JNIEnv* env = AttachCurrentThread();
262 return Java_AwContentsIoThreadClient_shouldBlockContentUrls(
263 env, java_object_.obj());
266 bool AwContentsIoThreadClientImpl::ShouldBlockFileUrls() const {
267 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
268 if (java_object_.is_null())
269 return false;
271 JNIEnv* env = AttachCurrentThread();
272 return Java_AwContentsIoThreadClient_shouldBlockFileUrls(
273 env, java_object_.obj());
276 bool AwContentsIoThreadClientImpl::ShouldAcceptThirdPartyCookies() const {
277 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
278 if (java_object_.is_null())
279 return false;
281 JNIEnv* env = AttachCurrentThread();
282 return Java_AwContentsIoThreadClient_shouldAcceptThirdPartyCookies(
283 env, java_object_.obj());
286 bool AwContentsIoThreadClientImpl::ShouldBlockNetworkLoads() const {
287 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
288 if (java_object_.is_null())
289 return false;
291 JNIEnv* env = AttachCurrentThread();
292 return Java_AwContentsIoThreadClient_shouldBlockNetworkLoads(
293 env, java_object_.obj());
296 void AwContentsIoThreadClientImpl::NewDownload(
297 const GURL& url,
298 const std::string& user_agent,
299 const std::string& content_disposition,
300 const std::string& mime_type,
301 int64 content_length) {
302 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
303 if (java_object_.is_null())
304 return;
306 JNIEnv* env = AttachCurrentThread();
307 ScopedJavaLocalRef<jstring> jstring_url =
308 ConvertUTF8ToJavaString(env, url.spec());
309 ScopedJavaLocalRef<jstring> jstring_user_agent =
310 ConvertUTF8ToJavaString(env, user_agent);
311 ScopedJavaLocalRef<jstring> jstring_content_disposition =
312 ConvertUTF8ToJavaString(env, content_disposition);
313 ScopedJavaLocalRef<jstring> jstring_mime_type =
314 ConvertUTF8ToJavaString(env, mime_type);
316 Java_AwContentsIoThreadClient_onDownloadStart(
317 env,
318 java_object_.obj(),
319 jstring_url.obj(),
320 jstring_user_agent.obj(),
321 jstring_content_disposition.obj(),
322 jstring_mime_type.obj(),
323 content_length);
326 void AwContentsIoThreadClientImpl::NewLoginRequest(const std::string& realm,
327 const std::string& account,
328 const std::string& args) {
329 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
330 if (java_object_.is_null())
331 return;
333 JNIEnv* env = AttachCurrentThread();
334 ScopedJavaLocalRef<jstring> jrealm = ConvertUTF8ToJavaString(env, realm);
335 ScopedJavaLocalRef<jstring> jargs = ConvertUTF8ToJavaString(env, args);
337 ScopedJavaLocalRef<jstring> jaccount;
338 if (!account.empty())
339 jaccount = ConvertUTF8ToJavaString(env, account);
341 Java_AwContentsIoThreadClient_newLoginRequest(
342 env, java_object_.obj(), jrealm.obj(), jaccount.obj(), jargs.obj());
345 bool RegisterAwContentsIoThreadClientImpl(JNIEnv* env) {
346 return RegisterNativesImpl(env);
349 } // namespace android_webview