Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / content / browser / media / android / media_resource_getter_impl.cc
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.
4
5 #include "content/browser/media/android/media_resource_getter_impl.h"
6
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h"
9 #include "base/bind.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 "media/base/android/media_url_interceptor.h"
22 #include "net/base/auth.h"
23 #include "net/cookies/cookie_monster.h"
24 #include "net/cookies/cookie_store.h"
25 #include "net/url_request/url_request_context.h"
26 #include "net/url_request/url_request_context_getter.h"
27 #include "url/gurl.h"
28 #include "webkit/browser/blob/blob_data_handle.h"
29 #include "webkit/browser/blob/blob_storage_context.h"
30
31 using base::android::ConvertUTF8ToJavaString;
32 using base::android::ScopedJavaLocalRef;
33
34 namespace content {
35
36 static void ReturnResultOnUIThread(
37     const base::Callback<void(const std::string&)>& callback,
38     const std::string& result) {
39   BrowserThread::PostTask(
40       BrowserThread::UI, FROM_HERE, base::Bind(callback, result));
41 }
42
43 static void RequestPlatformPathFromBlobURL(
44     const GURL& url,
45     BrowserContext* browser_context,
46     const base::Callback<void(const std::string&)>& callback) {
47   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
48   ChromeBlobStorageContext* context =
49       ChromeBlobStorageContext::GetFor(browser_context);
50   scoped_ptr<webkit_blob::BlobDataHandle> handle =
51       context->context()->GetBlobDataFromPublicURL(url);
52   const std::vector<webkit_blob::BlobData::Item> items =
53       handle->data()->items();
54
55   // TODO(qinmin): handle the case when the blob data is not a single file.
56   DLOG_IF(WARNING, items.size() != 1u)
57       << "More than one blob data are present: " << items.size();
58   ReturnResultOnUIThread(callback, items[0].path().value());
59 }
60
61 static void RequestPlaformPathFromFileSystemURL(
62     const GURL& url,
63     int render_process_id,
64     scoped_refptr<fileapi::FileSystemContext> file_system_context,
65     const base::Callback<void(const std::string&)>& callback) {
66   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
67   base::FilePath platform_path;
68   SyncGetPlatformPath(file_system_context.get(),
69                       render_process_id,
70                       url,
71                       &platform_path);
72   base::FilePath data_storage_path;
73   PathService::Get(base::DIR_ANDROID_APP_DATA, &data_storage_path);
74   if (data_storage_path.IsParent(platform_path))
75     ReturnResultOnUIThread(callback, platform_path.value());
76   else
77     ReturnResultOnUIThread(callback, std::string());
78 }
79
80 // Posts a task to the UI thread to run the callback function.
81 static void PostMediaMetadataCallbackTask(
82     const media::MediaResourceGetter::ExtractMediaMetadataCB& callback,
83     JNIEnv* env, ScopedJavaLocalRef<jobject>& j_metadata) {
84   BrowserThread::PostTask(
85         BrowserThread::UI, FROM_HERE,
86         base::Bind(callback, base::TimeDelta::FromMilliseconds(
87                        Java_MediaMetadata_getDurationInMilliseconds(
88                            env, j_metadata.obj())),
89                    Java_MediaMetadata_getWidth(env, j_metadata.obj()),
90                    Java_MediaMetadata_getHeight(env, j_metadata.obj()),
91                    Java_MediaMetadata_isSuccess(env, j_metadata.obj())));
92 }
93
94 // Gets the metadata from a media URL. When finished, a task is posted to the UI
95 // thread to run the callback function.
96 static void GetMediaMetadata(
97     const std::string& url, const std::string& cookies,
98     const std::string& user_agent,
99     const media::MediaResourceGetter::ExtractMediaMetadataCB& callback) {
100   JNIEnv* env = base::android::AttachCurrentThread();
101
102   ScopedJavaLocalRef<jstring> j_url_string = ConvertUTF8ToJavaString(env, url);
103   ScopedJavaLocalRef<jstring> j_cookies = ConvertUTF8ToJavaString(env, cookies);
104   jobject j_context = base::android::GetApplicationContext();
105   ScopedJavaLocalRef<jstring> j_user_agent = ConvertUTF8ToJavaString(
106       env, user_agent);
107   ScopedJavaLocalRef<jobject> j_metadata =
108       Java_MediaResourceGetter_extractMediaMetadata(env,
109                                                     j_context,
110                                                     j_url_string.obj(),
111                                                     j_cookies.obj(),
112                                                     j_user_agent.obj());
113
114   PostMediaMetadataCallbackTask(callback, env, j_metadata);
115 }
116
117 // Gets the metadata from a file descriptor. When finished, a task is posted to
118 // the UI thread to run the callback function.
119 static void GetMediaMetadataFromFd(
120     const int fd, const int64 offset, const int64 size,
121     const media::MediaResourceGetter::ExtractMediaMetadataCB& callback) {
122   JNIEnv* env = base::android::AttachCurrentThread();
123
124   ScopedJavaLocalRef<jobject> j_metadata =
125       Java_MediaResourceGetter_extractMediaMetadataFromFd(
126           env, fd, offset, size);
127
128   PostMediaMetadataCallbackTask(callback, env, j_metadata);
129 }
130
131 // The task object that retrieves cookie on the IO thread.
132 // TODO(qinmin): refactor this class to make the code reusable by others as
133 // there are lots of duplicated functionalities elsewhere.
134 class CookieGetterTask
135      : public base::RefCountedThreadSafe<CookieGetterTask> {
136  public:
137   CookieGetterTask(BrowserContext* browser_context,
138                    int render_process_id, int render_frame_id);
139
140   // Called by CookieGetterImpl to start getting cookies for a URL.
141   void RequestCookies(
142       const GURL& url, const GURL& first_party_for_cookies,
143       const media::MediaResourceGetter::GetCookieCB& callback);
144
145  private:
146   friend class base::RefCountedThreadSafe<CookieGetterTask>;
147   virtual ~CookieGetterTask();
148
149   void CheckPolicyForCookies(
150       const GURL& url, const GURL& first_party_for_cookies,
151       const media::MediaResourceGetter::GetCookieCB& callback,
152       const net::CookieList& cookie_list);
153
154   // Context getter used to get the CookieStore.
155   net::URLRequestContextGetter* context_getter_;
156
157   // Resource context for checking cookie policies.
158   ResourceContext* resource_context_;
159
160   // Render process id, used to check whether the process can access cookies.
161   int render_process_id_;
162
163   // Render frame id, used to check tab specific cookie policy.
164   int render_frame_id_;
165
166   DISALLOW_COPY_AND_ASSIGN(CookieGetterTask);
167 };
168
169 CookieGetterTask::CookieGetterTask(
170     BrowserContext* browser_context, int render_process_id, int render_frame_id)
171     : context_getter_(browser_context->GetRequestContext()),
172       resource_context_(browser_context->GetResourceContext()),
173       render_process_id_(render_process_id),
174       render_frame_id_(render_frame_id) {
175 }
176
177 CookieGetterTask::~CookieGetterTask() {}
178
179 void CookieGetterTask::RequestCookies(
180     const GURL& url, const GURL& first_party_for_cookies,
181     const media::MediaResourceGetter::GetCookieCB& callback) {
182   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
183   ChildProcessSecurityPolicyImpl* policy =
184       ChildProcessSecurityPolicyImpl::GetInstance();
185   if (!policy->CanAccessCookiesForOrigin(render_process_id_, url)) {
186     callback.Run(std::string());
187     return;
188   }
189
190   net::CookieStore* cookie_store =
191       context_getter_->GetURLRequestContext()->cookie_store();
192   if (!cookie_store) {
193     callback.Run(std::string());
194     return;
195   }
196
197   net::CookieMonster* cookie_monster = cookie_store->GetCookieMonster();
198   if (cookie_monster) {
199     cookie_monster->GetAllCookiesForURLAsync(url, base::Bind(
200         &CookieGetterTask::CheckPolicyForCookies, this,
201         url, first_party_for_cookies, callback));
202   } else {
203     callback.Run(std::string());
204   }
205 }
206
207 void CookieGetterTask::CheckPolicyForCookies(
208     const GURL& url, const GURL& first_party_for_cookies,
209     const media::MediaResourceGetter::GetCookieCB& callback,
210     const net::CookieList& cookie_list) {
211   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
212   if (GetContentClient()->browser()->AllowGetCookie(
213       url, first_party_for_cookies, cookie_list,
214       resource_context_, render_process_id_, render_frame_id_)) {
215     net::CookieStore* cookie_store =
216         context_getter_->GetURLRequestContext()->cookie_store();
217     cookie_store->GetCookiesWithOptionsAsync(
218         url, net::CookieOptions(), callback);
219   } else {
220     callback.Run(std::string());
221   }
222 }
223
224 MediaResourceGetterImpl::MediaResourceGetterImpl(
225     BrowserContext* browser_context,
226     fileapi::FileSystemContext* file_system_context,
227     int render_process_id,
228     int render_frame_id)
229     : browser_context_(browser_context),
230       file_system_context_(file_system_context),
231       render_process_id_(render_process_id),
232       render_frame_id_(render_frame_id),
233       weak_factory_(this) {}
234
235 MediaResourceGetterImpl::~MediaResourceGetterImpl() {}
236
237 void MediaResourceGetterImpl::GetCookies(
238     const GURL& url, const GURL& first_party_for_cookies,
239     const GetCookieCB& callback) {
240   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
241   scoped_refptr<CookieGetterTask> task = new CookieGetterTask(
242       browser_context_, render_process_id_, render_frame_id_);
243
244   GetCookieCB cb = base::Bind(&MediaResourceGetterImpl::GetCookiesCallback,
245                               weak_factory_.GetWeakPtr(),
246                               callback);
247   BrowserThread::PostTask(
248       BrowserThread::IO,
249       FROM_HERE,
250       base::Bind(&CookieGetterTask::RequestCookies,
251                  task, url, first_party_for_cookies,
252                  base::Bind(&ReturnResultOnUIThread, cb)));
253 }
254
255 void MediaResourceGetterImpl::GetCookiesCallback(
256     const GetCookieCB& callback, const std::string& cookies) {
257   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
258   callback.Run(cookies);
259 }
260
261 void MediaResourceGetterImpl::GetPlatformPathFromURL(
262     const GURL& url, const GetPlatformPathCB& callback) {
263   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
264   DCHECK(url.SchemeIsFileSystem() || url.SchemeIs(url::kBlobScheme));
265
266   GetPlatformPathCB cb =
267       base::Bind(&MediaResourceGetterImpl::GetPlatformPathCallback,
268                  weak_factory_.GetWeakPtr(),
269                  callback);
270
271   if (url.SchemeIs(url::kBlobScheme)) {
272     BrowserThread::PostTask(
273         BrowserThread::IO,
274         FROM_HERE,
275         base::Bind(&RequestPlatformPathFromBlobURL, url, browser_context_, cb));
276     return;
277   }
278
279   scoped_refptr<fileapi::FileSystemContext> context(file_system_context_);
280   BrowserThread::PostTask(
281       BrowserThread::FILE,
282       FROM_HERE,
283       base::Bind(&RequestPlaformPathFromFileSystemURL, url, render_process_id_,
284                  context, cb));
285 }
286
287 void MediaResourceGetterImpl::GetPlatformPathCallback(
288     const GetPlatformPathCB& callback, const std::string& platform_path) {
289   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
290   callback.Run(platform_path);
291 }
292
293 void MediaResourceGetterImpl::ExtractMediaMetadata(
294     const std::string& url, const std::string& cookies,
295     const std::string& user_agent, const ExtractMediaMetadataCB& callback) {
296   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
297   base::SequencedWorkerPool* pool = content::BrowserThread::GetBlockingPool();
298   pool->PostWorkerTask(
299       FROM_HERE,
300       base::Bind(&GetMediaMetadata, url, cookies, user_agent, callback));
301 }
302
303 void MediaResourceGetterImpl::ExtractMediaMetadata(
304     const int fd, const int64 offset, const int64 size,
305     const ExtractMediaMetadataCB& callback) {
306   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
307   base::SequencedWorkerPool* pool = content::BrowserThread::GetBlockingPool();
308   pool->PostWorkerTask(
309       FROM_HERE,
310       base::Bind(&GetMediaMetadataFromFd, fd, offset, size, callback));
311 }
312
313 // static
314 bool MediaResourceGetterImpl::RegisterMediaResourceGetter(JNIEnv* env) {
315   return RegisterNativesImpl(env);
316 }
317
318 }  // namespace content