blob: 0a2f221cb540569506bdc97f652b57b0258c23de [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/media/android/media_resource_getter_impl.h"
#include "base/bind.h"
#include "base/macros.h"
#include "base/path_service.h"
#include "base/single_thread_task_runner.h"
#include "base/task/post_task.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/fileapi/browser_file_system_helper.h"
#include "content/browser/resource_context_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_client.h"
#include "content/public/common/url_constants.h"
#include "media/base/android/media_url_interceptor.h"
#include "net/base/auth.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_store.h"
#include "net/http/http_auth.h"
#include "net/http/http_transaction_factory.h"
#include "url/gurl.h"
namespace content {
namespace {
// Returns the cookie service for the |browser_context| at the client end of the
// mojo pipe.
network::mojom::CookieManager* GetCookieServiceForContext(
BrowserContext* browser_context) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return BrowserContext::GetDefaultStoragePartition(browser_context)
->GetCookieManagerForBrowserProcess();
}
void ReturnResultOnUIThread(
base::OnceCallback<void(const std::string&)> callback,
const std::string& result) {
base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback), result));
}
// Checks the policy for get cookies and returns the cookie line if allowed.
std::string GetCookiesOnIO(const GURL& url,
const GURL& site_for_cookies,
content::ResourceContext* resource_context,
int render_process_id,
int render_frame_id,
const net::CookieList& cookie_list) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!GetContentClient()->browser()->AllowGetCookie(
url, site_for_cookies, cookie_list, resource_context,
render_process_id, render_frame_id)) {
return std::string();
}
return net::CanonicalCookie::BuildCookieLine(cookie_list);
}
void CheckPolicyForCookies(const GURL& url,
const GURL& site_for_cookies,
content::ResourceContext* resource_context,
int render_process_id,
int render_frame_id,
MediaResourceGetterImpl::GetCookieCB callback,
const net::CookieList& cookie_list) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// AllowGetCookie has to be called on IO thread.
base::PostTaskWithTraitsAndReplyWithResult(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(&GetCookiesOnIO, url, site_for_cookies, resource_context,
render_process_id, render_frame_id, cookie_list),
std::move(callback));
}
void OnSyncGetPlatformPathDone(
scoped_refptr<storage::FileSystemContext> file_system_context,
media::MediaResourceGetter::GetPlatformPathCB callback,
const base::FilePath& platform_path) {
DCHECK(file_system_context->default_file_task_runner()
->RunsTasksInCurrentSequence());
base::FilePath data_storage_path;
base::PathService::Get(base::DIR_ANDROID_APP_DATA, &data_storage_path);
if (data_storage_path.IsParent(platform_path))
ReturnResultOnUIThread(std::move(callback), platform_path.value());
else
ReturnResultOnUIThread(std::move(callback), std::string());
}
void RequestPlatformPathFromFileSystemURL(
const GURL& url,
int render_process_id,
scoped_refptr<storage::FileSystemContext> file_system_context,
media::MediaResourceGetter::GetPlatformPathCB callback) {
DCHECK(file_system_context->default_file_task_runner()
->RunsTasksInCurrentSequence());
SyncGetPlatformPath(file_system_context.get(), render_process_id, url,
base::BindOnce(&OnSyncGetPlatformPathDone,
file_system_context, std::move(callback)));
}
} // namespace
MediaResourceGetterImpl::MediaResourceGetterImpl(
BrowserContext* browser_context,
storage::FileSystemContext* file_system_context,
int render_process_id,
int render_frame_id)
: browser_context_(browser_context),
file_system_context_(file_system_context),
render_process_id_(render_process_id),
render_frame_id_(render_frame_id),
weak_factory_(this) {
}
MediaResourceGetterImpl::~MediaResourceGetterImpl() {}
void MediaResourceGetterImpl::GetAuthCredentials(
const GURL& url,
GetAuthCredentialsCB callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Non-standard URLs, such as data, will not be found in HTTP auth cache
// anyway, because they have no valid origin, so don't waste the time.
if (!url.IsStandard()) {
GetAuthCredentialsCallback(std::move(callback), base::nullopt);
return;
}
BrowserContext::GetDefaultStoragePartition(browser_context_)
->GetNetworkContext()
->LookupBasicAuthCredentials(
url,
base::BindOnce(&MediaResourceGetterImpl::GetAuthCredentialsCallback,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
void MediaResourceGetterImpl::GetCookies(const GURL& url,
const GURL& site_for_cookies,
GetCookieCB callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
if (!policy->CanAccessDataForOrigin(render_process_id_, url)) {
// Running the callback asynchronously on the caller thread to avoid
// reentrancy issues.
ReturnResultOnUIThread(std::move(callback), std::string());
return;
}
net::CookieOptions options;
options.set_include_httponly();
options.set_same_site_cookie_mode(
net::CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
options.set_do_not_update_access_time();
GetCookieServiceForContext(browser_context_)
->GetCookieList(
url, options,
base::BindOnce(&CheckPolicyForCookies, url, site_for_cookies,
browser_context_->GetResourceContext(),
render_process_id_, render_frame_id_,
std::move(callback)));
}
void MediaResourceGetterImpl::GetAuthCredentialsCallback(
GetAuthCredentialsCB callback,
const base::Optional<net::AuthCredentials>& credentials) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (credentials)
std::move(callback).Run(credentials->username(), credentials->password());
else
std::move(callback).Run(base::string16(), base::string16());
}
void MediaResourceGetterImpl::GetPlatformPathFromURL(
const GURL& url,
GetPlatformPathCB callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(url.SchemeIsFileSystem());
GetPlatformPathCB cb =
base::BindOnce(&MediaResourceGetterImpl::GetPlatformPathCallback,
weak_factory_.GetWeakPtr(), std::move(callback));
scoped_refptr<storage::FileSystemContext> context(file_system_context_);
context->default_file_task_runner()->PostTask(
FROM_HERE, base::BindOnce(&RequestPlatformPathFromFileSystemURL, url,
render_process_id_, context, std::move(cb)));
}
void MediaResourceGetterImpl::GetPlatformPathCallback(
GetPlatformPathCB callback,
const std::string& platform_path) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
std::move(callback).Run(platform_path);
}
} // namespace content