1 // Copyright 2013 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 "content/browser/media/android/media_resource_getter_impl.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h"
10 #include "base/path_service.h"
11 #include "base/threading/sequenced_worker_pool.h"
12 #include "content/browser/child_process_security_policy_impl.h"
13 #include "content/browser/fileapi/browser_file_system_helper.h"
14 #include "content/browser/fileapi/chrome_blob_storage_context.h"
15 #include "content/public/browser/browser_context.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/content_browser_client.h"
18 #include "content/public/common/content_client.h"
19 #include "content/public/common/url_constants.h"
20 #include "jni/MediaResourceGetter_jni.h"
21 #include "net/cookies/cookie_monster.h"
22 #include "net/cookies/cookie_store.h"
23 #include "net/url_request/url_request_context.h"
24 #include "net/url_request/url_request_context_getter.h"
26 #include "webkit/browser/blob/blob_data_handle.h"
27 #include "webkit/browser/blob/blob_storage_context.h"
29 using base::android::ConvertUTF8ToJavaString
;
30 using base::android::ScopedJavaLocalRef
;
34 static void ReturnResultOnUIThread(
35 const base::Callback
<void(const std::string
&)>& callback
,
36 const std::string
& result
) {
37 BrowserThread::PostTask(
38 BrowserThread::UI
, FROM_HERE
, base::Bind(callback
, result
));
41 static void RequestPlatformPathFromBlobURL(
43 BrowserContext
* browser_context
,
44 const base::Callback
<void(const std::string
&)>& callback
) {
45 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
46 ChromeBlobStorageContext
* context
=
47 ChromeBlobStorageContext::GetFor(browser_context
);
48 scoped_ptr
<webkit_blob::BlobDataHandle
> handle
=
49 context
->context()->GetBlobDataFromPublicURL(url
);
50 const std::vector
<webkit_blob::BlobData::Item
> items
=
51 handle
->data()->items();
53 // TODO(qinmin): handle the case when the blob data is not a single file.
54 DLOG_IF(WARNING
, items
.size() != 1u)
55 << "More than one blob data are present: " << items
.size();
56 ReturnResultOnUIThread(callback
, items
[0].path().value());
59 static void RequestPlaformPathFromFileSystemURL(
62 scoped_refptr
<fileapi::FileSystemContext
> file_system_context
,
63 const base::Callback
<void(const std::string
&)>& callback
) {
64 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
65 base::FilePath platform_path
;
66 SyncGetPlatformPath(file_system_context
.get(),
70 base::FilePath data_storage_path
;
71 PathService::Get(base::DIR_ANDROID_APP_DATA
, &data_storage_path
);
72 if (data_storage_path
.IsParent(platform_path
))
73 ReturnResultOnUIThread(callback
, platform_path
.value());
75 ReturnResultOnUIThread(callback
, std::string());
78 // Get the metadata from a media URL. When finished, a task is posted to the UI
79 // thread to run the callback function.
80 static void GetMediaMetadata(
81 const std::string
& url
, const std::string
& cookies
,
82 const std::string
& user_agent
,
83 const media::MediaResourceGetter::ExtractMediaMetadataCB
& callback
) {
84 JNIEnv
* env
= base::android::AttachCurrentThread();
86 ScopedJavaLocalRef
<jstring
> j_url_string
= ConvertUTF8ToJavaString(env
, url
);
87 ScopedJavaLocalRef
<jstring
> j_cookies
= ConvertUTF8ToJavaString(env
, cookies
);
88 jobject j_context
= base::android::GetApplicationContext();
89 ScopedJavaLocalRef
<jstring
> j_user_agent
= ConvertUTF8ToJavaString(
91 ScopedJavaLocalRef
<jobject
> j_metadata
=
92 Java_MediaResourceGetter_extractMediaMetadata(env
,
97 BrowserThread::PostTask(
98 BrowserThread::UI
, FROM_HERE
,
99 base::Bind(callback
, base::TimeDelta::FromMilliseconds(
100 Java_MediaMetadata_getDurationInMilliseconds(
101 env
, j_metadata
.obj())),
102 Java_MediaMetadata_getWidth(env
, j_metadata
.obj()),
103 Java_MediaMetadata_getHeight(env
, j_metadata
.obj()),
104 Java_MediaMetadata_isSuccess(env
, j_metadata
.obj())));
107 // The task object that retrieves cookie on the IO thread.
108 // TODO(qinmin): refactor this class to make the code reusable by others as
109 // there are lots of duplicated functionalities elsewhere.
110 class CookieGetterTask
111 : public base::RefCountedThreadSafe
<CookieGetterTask
> {
113 CookieGetterTask(BrowserContext
* browser_context
,
114 int renderer_id
, int routing_id
);
116 // Called by CookieGetterImpl to start getting cookies for a URL.
118 const GURL
& url
, const GURL
& first_party_for_cookies
,
119 const media::MediaResourceGetter::GetCookieCB
& callback
);
122 friend class base::RefCountedThreadSafe
<CookieGetterTask
>;
123 virtual ~CookieGetterTask();
125 void CheckPolicyForCookies(
126 const GURL
& url
, const GURL
& first_party_for_cookies
,
127 const media::MediaResourceGetter::GetCookieCB
& callback
,
128 const net::CookieList
& cookie_list
);
130 // Context getter used to get the CookieStore.
131 net::URLRequestContextGetter
* context_getter_
;
133 // Resource context for checking cookie policies.
134 ResourceContext
* resource_context_
;
136 // Render process id, used to check whether the process can access cookies.
139 // Routing id for the render view, used to check tab specific cookie policy.
142 DISALLOW_COPY_AND_ASSIGN(CookieGetterTask
);
145 CookieGetterTask::CookieGetterTask(
146 BrowserContext
* browser_context
, int renderer_id
, int routing_id
)
147 : context_getter_(browser_context
->GetRequestContext()),
148 resource_context_(browser_context
->GetResourceContext()),
149 renderer_id_(renderer_id
),
150 routing_id_(routing_id
) {
153 CookieGetterTask::~CookieGetterTask() {}
155 void CookieGetterTask::RequestCookies(
156 const GURL
& url
, const GURL
& first_party_for_cookies
,
157 const media::MediaResourceGetter::GetCookieCB
& callback
) {
158 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
159 ChildProcessSecurityPolicyImpl
* policy
=
160 ChildProcessSecurityPolicyImpl::GetInstance();
161 if (!policy
->CanAccessCookiesForOrigin(renderer_id_
, url
)) {
162 callback
.Run(std::string());
166 net::CookieStore
* cookie_store
=
167 context_getter_
->GetURLRequestContext()->cookie_store();
169 callback
.Run(std::string());
173 net::CookieMonster
* cookie_monster
= cookie_store
->GetCookieMonster();
174 if (cookie_monster
) {
175 cookie_monster
->GetAllCookiesForURLAsync(url
, base::Bind(
176 &CookieGetterTask::CheckPolicyForCookies
, this,
177 url
, first_party_for_cookies
, callback
));
179 callback
.Run(std::string());
183 void CookieGetterTask::CheckPolicyForCookies(
184 const GURL
& url
, const GURL
& first_party_for_cookies
,
185 const media::MediaResourceGetter::GetCookieCB
& callback
,
186 const net::CookieList
& cookie_list
) {
187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
188 if (GetContentClient()->browser()->AllowGetCookie(
189 url
, first_party_for_cookies
, cookie_list
,
190 resource_context_
, renderer_id_
, routing_id_
)) {
191 net::CookieStore
* cookie_store
=
192 context_getter_
->GetURLRequestContext()->cookie_store();
193 cookie_store
->GetCookiesWithOptionsAsync(
194 url
, net::CookieOptions(), callback
);
196 callback
.Run(std::string());
200 MediaResourceGetterImpl::MediaResourceGetterImpl(
201 BrowserContext
* browser_context
,
202 fileapi::FileSystemContext
* file_system_context
,
205 : browser_context_(browser_context
),
206 file_system_context_(file_system_context
),
207 renderer_id_(renderer_id
),
208 routing_id_(routing_id
),
209 weak_factory_(this) {}
211 MediaResourceGetterImpl::~MediaResourceGetterImpl() {}
213 void MediaResourceGetterImpl::GetCookies(
214 const GURL
& url
, const GURL
& first_party_for_cookies
,
215 const GetCookieCB
& callback
) {
216 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
217 scoped_refptr
<CookieGetterTask
> task
= new CookieGetterTask(
218 browser_context_
, renderer_id_
, routing_id_
);
220 GetCookieCB cb
= base::Bind(&MediaResourceGetterImpl::GetCookiesCallback
,
221 weak_factory_
.GetWeakPtr(),
223 BrowserThread::PostTask(
226 base::Bind(&CookieGetterTask::RequestCookies
,
227 task
, url
, first_party_for_cookies
,
228 base::Bind(&ReturnResultOnUIThread
, cb
)));
231 void MediaResourceGetterImpl::GetCookiesCallback(
232 const GetCookieCB
& callback
, const std::string
& cookies
) {
233 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
234 callback
.Run(cookies
);
237 void MediaResourceGetterImpl::GetPlatformPathFromURL(
238 const GURL
& url
, const GetPlatformPathCB
& callback
) {
239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
240 DCHECK(url
.SchemeIsFileSystem() || url
.SchemeIs(kBlobScheme
));
242 GetPlatformPathCB cb
=
243 base::Bind(&MediaResourceGetterImpl::GetPlatformPathCallback
,
244 weak_factory_
.GetWeakPtr(),
247 if (url
.SchemeIs(kBlobScheme
)) {
248 BrowserThread::PostTask(
251 base::Bind(&RequestPlatformPathFromBlobURL
, url
, browser_context_
, cb
));
255 scoped_refptr
<fileapi::FileSystemContext
> context(file_system_context_
);
256 BrowserThread::PostTask(
259 base::Bind(&RequestPlaformPathFromFileSystemURL
, url
, renderer_id_
,
263 void MediaResourceGetterImpl::GetPlatformPathCallback(
264 const GetPlatformPathCB
& callback
, const std::string
& platform_path
) {
265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
266 callback
.Run(platform_path
);
269 void MediaResourceGetterImpl::ExtractMediaMetadata(
270 const std::string
& url
, const std::string
& cookies
,
271 const std::string
& user_agent
, const ExtractMediaMetadataCB
& callback
) {
272 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
273 base::SequencedWorkerPool
* pool
= content::BrowserThread::GetBlockingPool();
274 pool
->PostWorkerTask(
276 base::Bind(&GetMediaMetadata
, url
, cookies
, user_agent
, callback
));
280 bool MediaResourceGetterImpl::RegisterMediaResourceGetter(JNIEnv
* env
) {
281 return RegisterNativesImpl(env
);
284 } // namespace content