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/public/browser/browser_context.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/content_browser_client.h"
17 #include "content/public/common/content_client.h"
18 #include "jni/MediaResourceGetter_jni.h"
19 #include "net/cookies/cookie_monster.h"
20 #include "net/cookies/cookie_store.h"
21 #include "net/url_request/url_request_context.h"
22 #include "net/url_request/url_request_context_getter.h"
25 using base::android::ConvertUTF8ToJavaString
;
26 using base::android::ScopedJavaLocalRef
;
30 static void ReturnResultOnUIThread(
31 const base::Callback
<void(const std::string
&)>& callback
,
32 const std::string
& result
) {
33 BrowserThread::PostTask(
34 BrowserThread::UI
, FROM_HERE
, base::Bind(callback
, result
));
37 // Get the metadata from a media URL. When finished, a task is posted to the UI
38 // thread to run the callback function.
39 static void GetMediaMetadata(
40 const std::string
& url
, const std::string
& cookies
,
41 const std::string
& user_agent
,
42 const media::MediaResourceGetter::ExtractMediaMetadataCB
& callback
) {
43 JNIEnv
* env
= base::android::AttachCurrentThread();
45 ScopedJavaLocalRef
<jstring
> j_url_string
= ConvertUTF8ToJavaString(env
, url
);
46 ScopedJavaLocalRef
<jstring
> j_cookies
= ConvertUTF8ToJavaString(env
, cookies
);
47 jobject j_context
= base::android::GetApplicationContext();
48 ScopedJavaLocalRef
<jstring
> j_user_agent
= ConvertUTF8ToJavaString(
50 ScopedJavaLocalRef
<jobject
> j_metadata
=
51 Java_MediaResourceGetter_extractMediaMetadata(env
,
56 BrowserThread::PostTask(
57 BrowserThread::UI
, FROM_HERE
,
58 base::Bind(callback
, base::TimeDelta::FromMilliseconds(
59 Java_MediaMetadata_getDurationInMilliseconds(
60 env
, j_metadata
.obj())),
61 Java_MediaMetadata_getWidth(env
, j_metadata
.obj()),
62 Java_MediaMetadata_getHeight(env
, j_metadata
.obj()),
63 Java_MediaMetadata_isSuccess(env
, j_metadata
.obj())));
66 // The task object that retrieves cookie on the IO thread.
67 // TODO(qinmin): refactor this class to make the code reusable by others as
68 // there are lots of duplicated functionalities elsewhere.
69 class CookieGetterTask
70 : public base::RefCountedThreadSafe
<CookieGetterTask
> {
72 CookieGetterTask(BrowserContext
* browser_context
,
73 int renderer_id
, int routing_id
);
75 // Called by CookieGetterImpl to start getting cookies for a URL.
77 const GURL
& url
, const GURL
& first_party_for_cookies
,
78 const media::MediaResourceGetter::GetCookieCB
& callback
);
81 friend class base::RefCountedThreadSafe
<CookieGetterTask
>;
82 virtual ~CookieGetterTask();
84 void CheckPolicyForCookies(
85 const GURL
& url
, const GURL
& first_party_for_cookies
,
86 const media::MediaResourceGetter::GetCookieCB
& callback
,
87 const net::CookieList
& cookie_list
);
89 // Context getter used to get the CookieStore.
90 net::URLRequestContextGetter
* context_getter_
;
92 // Resource context for checking cookie policies.
93 ResourceContext
* resource_context_
;
95 // Render process id, used to check whether the process can access cookies.
98 // Routing id for the render view, used to check tab specific cookie policy.
101 DISALLOW_COPY_AND_ASSIGN(CookieGetterTask
);
104 CookieGetterTask::CookieGetterTask(
105 BrowserContext
* browser_context
, int renderer_id
, int routing_id
)
106 : context_getter_(browser_context
->GetRequestContext()),
107 resource_context_(browser_context
->GetResourceContext()),
108 renderer_id_(renderer_id
),
109 routing_id_(routing_id
) {
112 CookieGetterTask::~CookieGetterTask() {}
114 void CookieGetterTask::RequestCookies(
115 const GURL
& url
, const GURL
& first_party_for_cookies
,
116 const media::MediaResourceGetter::GetCookieCB
& callback
) {
117 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
118 ChildProcessSecurityPolicyImpl
* policy
=
119 ChildProcessSecurityPolicyImpl::GetInstance();
120 if (!policy
->CanAccessCookiesForOrigin(renderer_id_
, url
)) {
121 callback
.Run(std::string());
125 net::CookieStore
* cookie_store
=
126 context_getter_
->GetURLRequestContext()->cookie_store();
128 callback
.Run(std::string());
132 net::CookieMonster
* cookie_monster
= cookie_store
->GetCookieMonster();
133 if (cookie_monster
) {
134 cookie_monster
->GetAllCookiesForURLAsync(url
, base::Bind(
135 &CookieGetterTask::CheckPolicyForCookies
, this,
136 url
, first_party_for_cookies
, callback
));
138 callback
.Run(std::string());
142 void CookieGetterTask::CheckPolicyForCookies(
143 const GURL
& url
, const GURL
& first_party_for_cookies
,
144 const media::MediaResourceGetter::GetCookieCB
& callback
,
145 const net::CookieList
& cookie_list
) {
146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
147 if (GetContentClient()->browser()->AllowGetCookie(
148 url
, first_party_for_cookies
, cookie_list
,
149 resource_context_
, renderer_id_
, routing_id_
)) {
150 net::CookieStore
* cookie_store
=
151 context_getter_
->GetURLRequestContext()->cookie_store();
152 cookie_store
->GetCookiesWithOptionsAsync(
153 url
, net::CookieOptions(), callback
);
155 callback
.Run(std::string());
159 // The task object that retrieves platform path on the FILE thread.
160 class PlatformPathGetterTask
161 : public base::RefCountedThreadSafe
<PlatformPathGetterTask
> {
163 PlatformPathGetterTask(fileapi::FileSystemContext
* file_system_context
,
166 // Called by MediaResourceGetterImpl to get the platform path from a file
168 void RequestPlaformPath(
170 const media::MediaResourceGetter::GetPlatformPathCB
& callback
);
173 friend class base::RefCountedThreadSafe
<PlatformPathGetterTask
>;
174 virtual ~PlatformPathGetterTask();
176 // File system context for getting the platform path.
177 fileapi::FileSystemContext
* file_system_context_
;
179 // Render process id, used to check whether the process can access the URL.
182 DISALLOW_COPY_AND_ASSIGN(PlatformPathGetterTask
);
185 PlatformPathGetterTask::PlatformPathGetterTask(
186 fileapi::FileSystemContext
* file_system_context
, int renderer_id
)
187 : file_system_context_(file_system_context
),
188 renderer_id_(renderer_id
) {
191 PlatformPathGetterTask::~PlatformPathGetterTask() {}
193 void PlatformPathGetterTask::RequestPlaformPath(
195 const media::MediaResourceGetter::GetPlatformPathCB
& callback
) {
196 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
197 base::FilePath platform_path
;
198 SyncGetPlatformPath(file_system_context_
,
202 base::FilePath data_storage_path
;
203 PathService::Get(base::DIR_ANDROID_APP_DATA
, &data_storage_path
);
204 if (data_storage_path
.IsParent(platform_path
))
205 callback
.Run(platform_path
.value());
207 callback
.Run(std::string());
210 MediaResourceGetterImpl::MediaResourceGetterImpl(
211 BrowserContext
* browser_context
,
212 fileapi::FileSystemContext
* file_system_context
,
213 int renderer_id
, int routing_id
)
214 : browser_context_(browser_context
),
215 file_system_context_(file_system_context
),
217 renderer_id_(renderer_id
),
218 routing_id_(routing_id
) {
221 MediaResourceGetterImpl::~MediaResourceGetterImpl() {}
223 void MediaResourceGetterImpl::GetCookies(
224 const GURL
& url
, const GURL
& first_party_for_cookies
,
225 const GetCookieCB
& callback
) {
226 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
227 scoped_refptr
<CookieGetterTask
> task
= new CookieGetterTask(
228 browser_context_
, renderer_id_
, routing_id_
);
230 GetCookieCB cb
= base::Bind(&MediaResourceGetterImpl::GetCookiesCallback
,
231 weak_this_
.GetWeakPtr(), callback
);
232 BrowserThread::PostTask(
235 base::Bind(&CookieGetterTask::RequestCookies
,
236 task
, url
, first_party_for_cookies
,
237 base::Bind(&ReturnResultOnUIThread
, cb
)));
240 void MediaResourceGetterImpl::GetCookiesCallback(
241 const GetCookieCB
& callback
, const std::string
& cookies
) {
242 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
243 callback
.Run(cookies
);
246 void MediaResourceGetterImpl::GetPlatformPathFromFileSystemURL(
247 const GURL
& url
, const GetPlatformPathCB
& callback
) {
248 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
249 scoped_refptr
<PlatformPathGetterTask
> task
= new PlatformPathGetterTask(
250 file_system_context_
, renderer_id_
);
252 GetPlatformPathCB cb
= base::Bind(
253 &MediaResourceGetterImpl::GetPlatformPathCallback
,
254 weak_this_
.GetWeakPtr(), callback
);
255 BrowserThread::PostTask(
258 base::Bind(&PlatformPathGetterTask::RequestPlaformPath
,
260 base::Bind(&ReturnResultOnUIThread
, cb
)));
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