Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(240)

Side by Side Diff: content/browser/android/download_controller.cc

Issue 10449017: Add android download controller. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: John's comments Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/browser/android/download_controller.h ('k') | content/content_browser.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 "content/browser/android/download_controller.h"
6
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h"
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "content/browser/download/download_item_impl.h"
13 #include "content/browser/renderer_host/render_process_host_impl.h"
14 #include "content/browser/renderer_host/render_view_host_delegate.h"
15 #include "content/browser/renderer_host/render_view_host_impl.h"
16 #include "content/browser/renderer_host/resource_dispatcher_host_impl.h"
17 #include "content/browser/web_contents/web_contents_impl.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/global_request_id.h"
20 #include "jni/download_controller_jni.h"
21 #include "net/cookies/cookie_options.h"
22 #include "net/cookies/cookie_store.h"
23 #include "net/http/http_request_headers.h"
24 #include "net/url_request/url_request.h"
25 #include "net/url_request/url_request_context.h"
26
27 using base::android::AttachCurrentThread;
28 using base::android::CheckException;
29 using base::android::ConvertUTF8ToJavaString;
30 using base::android::GetClass;
31 using base::android::ScopedJavaLocalRef;
32
33 // JNI methods
34 static void Init(JNIEnv* env, jobject obj) {
35 content::DownloadController::GetInstance()->Init(env, obj);
36 }
37
38 namespace {
39 const char* kDownloadControllerClassPathName =
40 "org/chromium/content/browser/DownloadController";
41 } // namespace
42
43 namespace content {
44
45 struct DownloadController::JavaObject {
46 ScopedJavaLocalRef<jobject> Controller(JNIEnv* env) {
47 return GetRealObject(env, obj);
48 }
49 jweak obj;
50 };
51
52 // static
53 bool DownloadController::RegisterDownloadController(JNIEnv* env) {
54 return RegisterNativesImpl(env);
55 }
56
57 DownloadController* DownloadController::GetInstance() {
58 return Singleton<DownloadController>::get();
59 }
60
61 DownloadController::DownloadController()
62 : java_object_(NULL) {
63 }
64
65 DownloadController::~DownloadController() {
66 if (java_object_) {
67 JNIEnv* env = AttachCurrentThread();
68 env->DeleteWeakGlobalRef(java_object_->obj);
69 delete java_object_;
70 CheckException(env);
71 }
72 }
73
74 // Initialize references to Java object.
75 void DownloadController::Init(JNIEnv* env, jobject obj) {
76 java_object_ = new JavaObject;
77 java_object_->obj = env->NewWeakGlobalRef(obj);
78 }
79
80 void DownloadController::CreateGETDownload(
81 RenderViewHost* render_view_host,
82 int request_id) {
83 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
84 int render_process_id = render_view_host->GetProcess()->GetID();
85 GlobalRequestID global_id(render_process_id, request_id);
86
87 // We are yielding the UI thread and render_view_host may go away by
88 // the time we come back. Pass along render_process_id and render_view_id
89 // to retrieve it later (if it still exists).
90 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
91 base::Bind(&DownloadController::PrepareDownloadInfo,
92 base::Unretained(this), global_id,
93 render_process_id,
94 render_view_host->GetRoutingID()));
95 }
96
97 void DownloadController::PrepareDownloadInfo(
98 const GlobalRequestID& global_id,
99 int render_process_id, int render_view_id) {
100 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
101
102 net::URLRequest* request =
103 ResourceDispatcherHostImpl::Get()->GetURLRequest(global_id);
104 DCHECK(request) << "Request to download not found.";
105
106 DownloadInfoAndroid info_android(request);
107
108 net::CookieStore* cookie_store = request->context()->cookie_store();
109 if (cookie_store) {
110 net::CookieMonster* cookie_monster = cookie_store->GetCookieMonster();
111 if (cookie_monster) {
112 cookie_monster->GetAllCookiesForURLAsync(
113 request->url(),
114 base::Bind(&DownloadController::CheckPolicyAndLoadCookies,
115 base::Unretained(this), info_android, render_process_id,
116 render_view_id, global_id));
117 } else {
118 DoLoadCookies(
119 info_android, render_process_id, render_view_id, global_id);
120 }
121 } else {
122 // Can't get any cookies, start android download.
123 StartAndroidDownload(info_android, render_process_id, render_view_id);
124 }
125 }
126
127 void DownloadController::CheckPolicyAndLoadCookies(
128 const DownloadInfoAndroid& info, int render_process_id,
129 int render_view_id, const GlobalRequestID& global_id,
130 const net::CookieList& cookie_list) {
131 net::URLRequest* request =
132 ResourceDispatcherHostImpl::Get()->GetURLRequest(global_id);
133 DCHECK(request) << "Request to download not found.";
134
135 if (request->context()->network_delegate()->CanGetCookies(
136 *request, cookie_list)) {
137 DoLoadCookies(info, render_process_id, render_view_id, global_id);
138 } else {
139 StartAndroidDownload(info, render_process_id, render_view_id);
140 }
141 }
142
143 void DownloadController::DoLoadCookies(
144 const DownloadInfoAndroid& info, int render_process_id,
145 int render_view_id, const GlobalRequestID& global_id) {
146 net::CookieOptions options;
147 options.set_include_httponly();
148
149 net::URLRequest* request =
150 ResourceDispatcherHostImpl::Get()->GetURLRequest(global_id);
151 DCHECK(request) << "Request to download not found.";
152
153 request->context()->cookie_store()->GetCookiesWithOptionsAsync(
154 info.url, options,
155 base::Bind(&DownloadController::OnCookieResponse,
156 base::Unretained(this), info, render_process_id,
157 render_view_id));
158 }
159
160 void DownloadController::OnCookieResponse(DownloadInfoAndroid download_info,
161 int render_process_id,
162 int render_view_id,
163 const std::string& cookie) {
164 download_info.cookie = cookie;
165
166 // We have everything we need, start Android download.
167 StartAndroidDownload(download_info, render_process_id, render_view_id);
168 }
169
170 void DownloadController::StartAndroidDownload(
171 const DownloadInfoAndroid& info,
172 int render_process_id,
173 int render_view_id) {
174 // Call ourself on the UI thread if not already on it.
175 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
176 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
jam 2012/05/30 14:59:49 nit: to follow the style guide, for each line with
nilesh 2012/05/30 17:04:09 Done.
177 base::Bind(&DownloadController::StartAndroidDownload,
178 base::Unretained(this), info, render_process_id,
179 render_view_id));
180 return;
181 }
182
183 JNIEnv* env = AttachCurrentThread();
184
185 // Call newHttpGetDownload
186 jobject view = GetContentView(render_process_id, render_view_id);
187 if (!view) {
188 // The view went away. Can't proceed.
189 LOG(ERROR) << "Download failed on URL:" << info.url.spec();
190 return;
191 }
192
193 ScopedJavaLocalRef<jstring> jurl =
194 ConvertUTF8ToJavaString(env, info.url.spec());
195 ScopedJavaLocalRef<jstring> juser_agent =
196 ConvertUTF8ToJavaString(env, info.user_agent);
197 ScopedJavaLocalRef<jstring> jcontent_disposition =
198 ConvertUTF8ToJavaString(env, info.content_disposition);
199 ScopedJavaLocalRef<jstring> jmime_type =
200 ConvertUTF8ToJavaString(env, info.original_mime_type);
201 ScopedJavaLocalRef<jstring> jcookie =
202 ConvertUTF8ToJavaString(env, info.cookie);
203
204 Java_DownloadController_newHttpGetDownload(
205 env, GetJavaObject()->Controller(env).obj(), view, jurl.obj(),
206 juser_agent.obj(), jcontent_disposition.obj(), jmime_type.obj(),
207 jcookie.obj(), info.total_bytes);
208 }
209
210 void DownloadController::OnPostDownloadStarted(
211 WebContents* web_contents,
212 DownloadItem* download_item) {
213 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
214 JNIEnv* env = AttachCurrentThread();
215
216 // Register for updates to the DownloadItem.
217 download_item->AddObserver(this);
218
219 jobject view = GetContentViewFromWebContents(web_contents);
220 if(!view) {
221 // The view went away. Can't proceed.
222 return;
223 }
224
225 Java_DownloadController_onHttpPostDownloadStarted(
226 env, GetJavaObject()->Controller(env).obj(), view);
227 }
228
229 void DownloadController::OnDownloadUpdated(DownloadItem* item) {
230 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
231
232 if (item->GetState() != DownloadItem::COMPLETE)
233 return;
234
235 // Call onHttpPostDownloadCompleted
236 JNIEnv* env = AttachCurrentThread();
237 ScopedJavaLocalRef<jstring> jurl =
238 ConvertUTF8ToJavaString(env, item->GetURL().spec());
239 ScopedJavaLocalRef<jstring> jcontent_disposition =
240 ConvertUTF8ToJavaString(env, item->GetContentDisposition());
241 ScopedJavaLocalRef<jstring> jmime_type =
242 ConvertUTF8ToJavaString(env, item->GetMimeType());
243 ScopedJavaLocalRef<jstring> jpath =
244 ConvertUTF8ToJavaString(env, item->GetFullPath().value());
245
246 jobject view = GetContentViewFromWebContents(item->GetWebContents());
247 if(!view) {
248 // We can get NULL WebContents from the DownloadItem.
249 return;
250 }
251
252 Java_DownloadController_onHttpPostDownloadCompleted(env,
253 GetJavaObject()->Controller(env).obj(), view, jurl.obj(),
254 jcontent_disposition.obj(), jmime_type.obj(), jpath.obj(),
255 item->GetReceivedBytes(), true);
256 }
257
258 void DownloadController::OnDownloadOpened(DownloadItem* item) {
259 }
260
261 jobject DownloadController::GetContentView(int render_process_id,
262 int render_view_id) {
263 RenderViewHost* render_view_host =
264 RenderViewHost::FromID(render_process_id, render_view_id);
265
266 if (!render_view_host)
267 return NULL;
268
269 WebContents* web_contents =
270 render_view_host->GetDelegate()->GetAsWebContents();
271
272 if (!web_contents)
273 return NULL;
274
275 return GetContentViewFromWebContents(web_contents);
276 }
277
278 jobject DownloadController::GetContentViewFromWebContents(
279 WebContents* web_contents) {
280 NOTIMPLEMENTED();
281 return NULL;
282 }
283
284 DownloadController::JavaObject* DownloadController::GetJavaObject() {
285 if (!java_object_) {
286 // Initialize Java DownloadController by calling
287 // DownloadController.getInstance(), which will call Init()
288 // if Java DownloadController is not instantiated already.
289 JNIEnv* env = AttachCurrentThread();
290 ScopedJavaLocalRef<jclass> clazz =
291 GetClass(env, kDownloadControllerClassPathName);
292 jmethodID get_instance = GetStaticMethodID(env, clazz, "getInstance",
293 "()Lorg/chromium/content/browser/DownloadController;");
294 ScopedJavaLocalRef<jobject> jobj(env,
295 env->CallStaticObjectMethod(clazz.obj(), get_instance));
296 CheckException(env);
297 }
298
299 DCHECK(java_object_);
300 return java_object_;
301 }
302
303 DownloadController::DownloadInfoAndroid::DownloadInfoAndroid(
304 net::URLRequest* request) {
305 request->GetResponseHeaderByName("content-disposition", &content_disposition);
306 request->GetResponseHeaderByName("mime-type", &original_mime_type);
307 request->extra_request_headers().GetHeader(
308 net::HttpRequestHeaders::kUserAgent,
309 &user_agent);
310 if (!request->url_chain().empty()) {
311 original_url = request->url_chain().front();
312 url = request->url_chain().back();
313 }
314 }
315
316 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/android/download_controller.h ('k') | content/content_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698