summaryrefslogtreecommitdiffstats
path: root/android_webview
diff options
context:
space:
mode:
authormmenke <mmenke@chromium.org>2016-02-25 09:14:46 -0800
committerCommit bot <commit-bot@chromium.org>2016-02-25 17:16:31 +0000
commita7b331e94c7b658c55cb3ce93b712b9d671d2e07 (patch)
tree4663f805ac4dc6a4e3e3a002bbc547f1f1618f98 /android_webview
parent74ab35b50436685c3bc241f22e9d62af23bc7320 (diff)
downloadchromium_src-a7b331e94c7b658c55cb3ce93b712b9d671d2e07.zip
chromium_src-a7b331e94c7b658c55cb3ce93b712b9d671d2e07.tar.gz
chromium_src-a7b331e94c7b658c55cb3ce93b712b9d671d2e07.tar.bz2
Add a cross-thread wrapper around Android Webview's CookieStore.
Android Webview needs to be able to call into its CookieStore on a thread other than the IOThread. Since we're trying to make the CookieStore non-threadsafe, that means we need a CookieStore wrapper to be used by the network stack to access the real CookieStore on another thread. This CL also modifies CookieManager to lazily create the CookieStore on the correct thread. This both allows us to get rid of the last GetCookieMonster call, and will make making the CookieStore non-thread-safe easier. BUG=579653, 579260 Review URL: https://codereview.chromium.org/1693903002 Cr-Commit-Position: refs/heads/master@{#377596}
Diffstat (limited to 'android_webview')
-rw-r--r--android_webview/BUILD.gn2
-rw-r--r--android_webview/android_webview.gyp2
-rw-r--r--android_webview/android_webview_tests.gypi1
-rw-r--r--android_webview/browser/aw_browser_context.cc6
-rw-r--r--android_webview/browser/aw_browser_context.h5
-rw-r--r--android_webview/browser/net/aw_cookie_store_wrapper.cc357
-rw-r--r--android_webview/browser/net/aw_cookie_store_wrapper.h132
-rw-r--r--android_webview/browser/net/aw_cookie_store_wrapper_unittest.cc49
-rw-r--r--android_webview/browser/net/aw_url_request_context_getter.cc5
-rw-r--r--android_webview/browser/net/aw_url_request_context_getter.h1
-rw-r--r--android_webview/browser/net/init_native_callback.h14
-rw-r--r--android_webview/native/cookie_manager.cc257
-rw-r--r--android_webview/test/BUILD.gn1
13 files changed, 681 insertions, 151 deletions
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn
index c9505c3..d3efe00 100644
--- a/android_webview/BUILD.gn
+++ b/android_webview/BUILD.gn
@@ -446,6 +446,8 @@ source_set("common") {
"browser/jni_dependency_factory.h",
"browser/net/android_stream_reader_url_request_job.cc",
"browser/net/android_stream_reader_url_request_job.h",
+ "browser/net/aw_cookie_store_wrapper.cc",
+ "browser/net/aw_cookie_store_wrapper.h",
"browser/net/aw_http_user_agent_settings.cc",
"browser/net/aw_http_user_agent_settings.h",
"browser/net/aw_network_change_notifier.cc",
diff --git a/android_webview/android_webview.gyp b/android_webview/android_webview.gyp
index f9cd183..8378d0e 100644
--- a/android_webview/android_webview.gyp
+++ b/android_webview/android_webview.gyp
@@ -350,6 +350,8 @@
'browser/gl_view_renderer_manager.h',
'browser/net/android_stream_reader_url_request_job.cc',
'browser/net/android_stream_reader_url_request_job.h',
+ 'browser/net/aw_cookie_store_wrapper.cc',
+ 'browser/net/aw_cookie_store_wrapper.h',
'browser/net/aw_http_user_agent_settings.h',
'browser/net/aw_http_user_agent_settings.cc',
'browser/net/aw_network_change_notifier.cc',
diff --git a/android_webview/android_webview_tests.gypi b/android_webview/android_webview_tests.gypi
index 6a2cf65..ab92ffc 100644
--- a/android_webview/android_webview_tests.gypi
+++ b/android_webview/android_webview_tests.gypi
@@ -146,6 +146,7 @@
'browser/aw_form_database_service_unittest.cc',
'browser/browser_view_renderer_unittest.cc',
'browser/net/android_stream_reader_url_request_job_unittest.cc',
+ 'browser/net/aw_cookie_store_wrapper_unittest.cc',
'browser/net/input_stream_reader_unittest.cc',
'browser/test/fake_window.cc',
'browser/test/fake_window.h',
diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc
index a5e985f..02aa751 100644
--- a/android_webview/browser/aw_browser_context.cc
+++ b/android_webview/browser/aw_browser_context.cc
@@ -15,7 +15,6 @@
#include "android_webview/browser/aw_resource_context.h"
#include "android_webview/browser/jni_dependency_factory.h"
#include "android_webview/browser/net/aw_url_request_context_getter.h"
-#include "android_webview/browser/net/init_native_callback.h"
#include "android_webview/common/aw_content_client.h"
#include "base/base_paths_android.h"
#include "base/bind.h"
@@ -42,7 +41,6 @@
#include "content/public/browser/ssl_host_state_delegate.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
-#include "net/cookies/cookie_store.h"
#include "net/proxy/proxy_config_service_android.h"
#include "net/proxy/proxy_service.h"
@@ -182,7 +180,6 @@ void AwBrowserContext::SetLegacyCacheRemovalDelayForTest(int delay_ms) {
}
void AwBrowserContext::PreMainMessageLoopRun() {
- cookie_store_ = CreateCookieStore(this);
FilePath cache_path;
const FilePath fallback_cache_dir =
GetPath().Append(FILE_PATH_LITERAL("Cache"));
@@ -205,8 +202,7 @@ void AwBrowserContext::PreMainMessageLoopRun() {
InitUserPrefService();
url_request_context_getter_ = new AwURLRequestContextGetter(
- cache_path, cookie_store_.get(), CreateProxyConfigService(),
- user_pref_service_.get());
+ cache_path, CreateProxyConfigService(), user_pref_service_.get());
data_reduction_proxy_io_data_.reset(
new data_reduction_proxy::DataReductionProxyIOData(
diff --git a/android_webview/browser/aw_browser_context.h b/android_webview/browser/aw_browser_context.h
index 94f9f57..84f477d 100644
--- a/android_webview/browser/aw_browser_context.h
+++ b/android_webview/browser/aw_browser_context.h
@@ -37,10 +37,6 @@ class DataReductionProxyService;
class DataReductionProxySettings;
}
-namespace net {
-class CookieStore;
-}
-
namespace policy {
class URLBlacklistManager;
class BrowserPolicyConnectorBase;
@@ -149,7 +145,6 @@ class AwBrowserContext : public content::BrowserContext,
base::FilePath context_storage_path_;
JniDependencyFactory* native_factory_;
- scoped_refptr<net::CookieStore> cookie_store_;
scoped_refptr<AwURLRequestContextGetter> url_request_context_getter_;
scoped_refptr<AwQuotaManagerBridge> quota_manager_bridge_;
scoped_ptr<AwFormDatabaseService> form_database_service_;
diff --git a/android_webview/browser/net/aw_cookie_store_wrapper.cc b/android_webview/browser/net/aw_cookie_store_wrapper.cc
new file mode 100644
index 0000000..6b9b063
--- /dev/null
+++ b/android_webview/browser/net/aw_cookie_store_wrapper.cc
@@ -0,0 +1,357 @@
+// Copyright 2016 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 "android_webview/browser/net/aw_cookie_store_wrapper.h"
+
+#include <string>
+
+#include "android_webview/browser/net/init_native_callback.h"
+#include "base/memory/ref_counted_delete_on_message_loop.h"
+#include "base/thread_task_runner_handle.h"
+#include "url/gurl.h"
+
+namespace android_webview {
+
+namespace {
+
+// Posts |task| to the thread that the global CookieStore lives on.
+void PostTaskToCookieStoreTaskRunner(const base::Closure& task) {
+ GetCookieStoreTaskRunner()->PostTask(FROM_HERE, task);
+}
+
+// Wraps a subscription to cookie change notifications for the global
+// CookieStore for a consumer that lives on another thread. Handles passing
+// messages between thread, and destroys itself when the consumer unsubscribes.
+// Must be created on the consumer's thread. Each instance only supports a
+// single subscription.
+class SubscriptionWrapper {
+ public:
+ SubscriptionWrapper() : weak_factory_(this) {}
+
+ scoped_ptr<net::CookieStore::CookieChangedSubscription> Subscribe(
+ const GURL& url,
+ const std::string& name,
+ const net::CookieStore::CookieChangedCallback& callback) {
+ // This class is only intended to be used for a single subscription.
+ DCHECK(callback_list_.empty());
+
+ nested_subscription_ =
+ new NestedSubscription(url, name, weak_factory_.GetWeakPtr());
+ return callback_list_.Add(callback);
+ }
+
+ private:
+ // The NestedSubscription is responsible for creating and managing the
+ // underlying subscription to the real CookieStore, and posting notifications
+ // back to |callback_list_|.
+ class NestedSubscription
+ : public base::RefCountedDeleteOnMessageLoop<NestedSubscription> {
+ public:
+ NestedSubscription(const GURL& url,
+ const std::string& name,
+ base::WeakPtr<SubscriptionWrapper> subscription_wrapper)
+ : base::RefCountedDeleteOnMessageLoop<NestedSubscription>(
+ GetCookieStoreTaskRunner()),
+ subscription_wrapper_(subscription_wrapper),
+ client_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
+ PostTaskToCookieStoreTaskRunner(
+ base::Bind(&NestedSubscription::Subscribe, this, url, name));
+ }
+
+ private:
+ friend class base::RefCountedDeleteOnMessageLoop<NestedSubscription>;
+ friend class base::DeleteHelper<NestedSubscription>;
+
+ ~NestedSubscription() {}
+
+ void Subscribe(const GURL& url, const std::string& name) {
+ GetCookieStore()->AddCallbackForCookie(
+ url, name, base::Bind(&NestedSubscription::OnChanged, this));
+ }
+
+ void OnChanged(const net::CanonicalCookie& cookie, bool removed) {
+ client_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&SubscriptionWrapper::OnChanged,
+ subscription_wrapper_, cookie, removed));
+ }
+
+ base::WeakPtr<SubscriptionWrapper> subscription_wrapper_;
+ scoped_refptr<base::TaskRunner> client_task_runner_;
+
+ scoped_ptr<net::CookieStore::CookieChangedSubscription> subscription_;
+
+ DISALLOW_COPY_AND_ASSIGN(NestedSubscription);
+ };
+
+ void OnChanged(const net::CanonicalCookie& cookie, bool removed) {
+ callback_list_.Notify(cookie, removed);
+ }
+
+ // The "list" only had one entry, so can just clean up now.
+ void OnUnsubscribe() { delete this; }
+
+ scoped_refptr<NestedSubscription> nested_subscription_;
+ net::CookieStore::CookieChangedCallbackList callback_list_;
+ base::WeakPtrFactory<SubscriptionWrapper> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(SubscriptionWrapper);
+};
+
+void SetCookieWithOptionsAsyncOnCookieThread(
+ const GURL& url,
+ const std::string& cookie_line,
+ const net::CookieOptions& options,
+ const net::CookieStore::SetCookiesCallback& callback) {
+ GetCookieStore()->SetCookieWithOptionsAsync(url, cookie_line, options,
+ callback);
+}
+
+void SetCookieWithDetailsAsyncOnCookieThread(
+ const GURL& url,
+ const std::string& name,
+ const std::string& value,
+ const std::string& domain,
+ const std::string& path,
+ base::Time creation_time,
+ base::Time expiration_time,
+ base::Time last_access_time,
+ bool secure,
+ bool http_only,
+ bool same_site,
+ bool enforce_strict_secure,
+ net::CookiePriority priority,
+ const net::CookieStore::SetCookiesCallback& callback) {
+ GetCookieStore()->SetCookieWithDetailsAsync(
+ url, name, value, domain, path, creation_time, expiration_time,
+ last_access_time, secure, http_only, same_site, enforce_strict_secure,
+ priority, callback);
+}
+
+void GetCookiesWithOptionsAsyncOnCookieThread(
+ const GURL& url,
+ const net::CookieOptions& options,
+ const net::CookieStore::GetCookiesCallback& callback) {
+ GetCookieStore()->GetCookiesWithOptionsAsync(url, options, callback);
+}
+
+void GetCookieListWithOptionsAsyncOnCookieThread(
+ const GURL& url,
+ const net::CookieOptions& options,
+ const net::CookieStore::GetCookieListCallback& callback) {
+ GetCookieStore()->GetCookieListWithOptionsAsync(url, options, callback);
+}
+
+void GetAllCookiesAsyncOnCookieThread(
+ const net::CookieStore::GetCookieListCallback& callback) {
+ GetCookieStore()->GetAllCookiesAsync(callback);
+}
+
+void DeleteCookieAsyncOnCookieThread(const GURL& url,
+ const std::string& cookie_name,
+ const base::Closure& callback) {
+ GetCookieStore()->DeleteCookieAsync(url, cookie_name, callback);
+}
+
+void DeleteCanonicalCookieAsyncOnCookieThread(
+ const net::CanonicalCookie& cookie,
+ const net::CookieStore::DeleteCallback& callback) {
+ GetCookieStore()->DeleteCanonicalCookieAsync(cookie, callback);
+}
+
+void DeleteAllCreatedBetweenAsyncOnCookieThread(
+ const base::Time& delete_begin,
+ const base::Time& delete_end,
+ const net::CookieStore::DeleteCallback& callback) {
+ GetCookieStore()->DeleteAllCreatedBetweenAsync(delete_begin, delete_end,
+ callback);
+}
+
+void DeleteAllCreatedBetweenForHostAsyncOnCookieThread(
+ const base::Time delete_begin,
+ const base::Time delete_end,
+ const GURL& url,
+ const net::CookieStore::DeleteCallback& callback) {
+ GetCookieStore()->DeleteAllCreatedBetweenForHostAsync(
+ delete_begin, delete_end, url, callback);
+}
+
+void DeleteSessionCookiesAsyncOnCookieThread(
+ const net::CookieStore::DeleteCallback& callback) {
+ GetCookieStore()->DeleteSessionCookiesAsync(callback);
+}
+
+void FlushStoreOnCookieThread(const base::Closure& callback) {
+ GetCookieStore()->FlushStore(callback);
+}
+
+void SetForceKeepSessionStateOnCookieThread() {
+ GetCookieStore()->SetForceKeepSessionState();
+}
+
+} // namespace
+
+AwCookieStoreWrapper::AwCookieStoreWrapper()
+ : client_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+ weak_factory_(this) {}
+
+void AwCookieStoreWrapper::SetCookieWithOptionsAsync(
+ const GURL& url,
+ const std::string& cookie_line,
+ const net::CookieOptions& options,
+ const net::CookieStore::SetCookiesCallback& callback) {
+ DCHECK(client_task_runner_->RunsTasksOnCurrentThread());
+ PostTaskToCookieStoreTaskRunner(
+ base::Bind(&SetCookieWithOptionsAsyncOnCookieThread, url, cookie_line,
+ options, CreateWrappedCallback<bool>(callback)));
+}
+
+void AwCookieStoreWrapper::SetCookieWithDetailsAsync(
+ const GURL& url,
+ const std::string& name,
+ const std::string& value,
+ const std::string& domain,
+ const std::string& path,
+ base::Time creation_time,
+ base::Time expiration_time,
+ base::Time last_access_time,
+ bool secure,
+ bool http_only,
+ bool same_site,
+ bool enforce_strict_secure,
+ net::CookiePriority priority,
+ const SetCookiesCallback& callback) {
+ DCHECK(client_task_runner_->RunsTasksOnCurrentThread());
+ PostTaskToCookieStoreTaskRunner(
+ base::Bind(&SetCookieWithDetailsAsyncOnCookieThread, url, name, value,
+ domain, path, creation_time, expiration_time, last_access_time,
+ secure, http_only, same_site, enforce_strict_secure, priority,
+ CreateWrappedCallback<bool>(callback)));
+}
+
+void AwCookieStoreWrapper::GetCookiesWithOptionsAsync(
+ const GURL& url,
+ const net::CookieOptions& options,
+ const GetCookiesCallback& callback) {
+ DCHECK(client_task_runner_->RunsTasksOnCurrentThread());
+ PostTaskToCookieStoreTaskRunner(
+ base::Bind(&GetCookiesWithOptionsAsyncOnCookieThread, url, options,
+ CreateWrappedCallback<const std::string&>(callback)));
+}
+
+void AwCookieStoreWrapper::GetCookieListWithOptionsAsync(
+ const GURL& url,
+ const net::CookieOptions& options,
+ const GetCookieListCallback& callback) {
+ DCHECK(client_task_runner_->RunsTasksOnCurrentThread());
+ PostTaskToCookieStoreTaskRunner(
+ base::Bind(&GetCookieListWithOptionsAsyncOnCookieThread, url, options,
+ CreateWrappedCallback<const net::CookieList&>(callback)));
+}
+
+void AwCookieStoreWrapper::GetAllCookiesAsync(
+ const GetCookieListCallback& callback) {
+ DCHECK(client_task_runner_->RunsTasksOnCurrentThread());
+ PostTaskToCookieStoreTaskRunner(
+ base::Bind(&GetAllCookiesAsyncOnCookieThread,
+ CreateWrappedCallback<const net::CookieList&>(callback)));
+}
+
+void AwCookieStoreWrapper::DeleteCookieAsync(const GURL& url,
+ const std::string& cookie_name,
+ const base::Closure& callback) {
+ DCHECK(client_task_runner_->RunsTasksOnCurrentThread());
+ PostTaskToCookieStoreTaskRunner(
+ base::Bind(&DeleteCookieAsyncOnCookieThread, url, cookie_name,
+ CreateWrappedClosureCallback(callback)));
+}
+
+void AwCookieStoreWrapper::DeleteCanonicalCookieAsync(
+ const net::CanonicalCookie& cookie,
+ const DeleteCallback& callback) {
+ DCHECK(client_task_runner_->RunsTasksOnCurrentThread());
+ PostTaskToCookieStoreTaskRunner(
+ base::Bind(&DeleteCanonicalCookieAsyncOnCookieThread, cookie,
+ CreateWrappedCallback<int>(callback)));
+}
+
+void AwCookieStoreWrapper::DeleteAllCreatedBetweenAsync(
+ const base::Time& delete_begin,
+ const base::Time& delete_end,
+ const DeleteCallback& callback) {
+ DCHECK(client_task_runner_->RunsTasksOnCurrentThread());
+ PostTaskToCookieStoreTaskRunner(
+ base::Bind(&DeleteAllCreatedBetweenAsyncOnCookieThread, delete_begin,
+ delete_end, CreateWrappedCallback<int>(callback)));
+}
+
+void AwCookieStoreWrapper::DeleteAllCreatedBetweenForHostAsync(
+ const base::Time delete_begin,
+ const base::Time delete_end,
+ const GURL& url,
+ const DeleteCallback& callback) {
+ DCHECK(client_task_runner_->RunsTasksOnCurrentThread());
+ PostTaskToCookieStoreTaskRunner(base::Bind(
+ &DeleteAllCreatedBetweenForHostAsyncOnCookieThread, delete_begin,
+ delete_end, url, CreateWrappedCallback<int>(callback)));
+}
+
+void AwCookieStoreWrapper::DeleteSessionCookiesAsync(
+ const DeleteCallback& callback) {
+ DCHECK(client_task_runner_->RunsTasksOnCurrentThread());
+ PostTaskToCookieStoreTaskRunner(
+ base::Bind(&DeleteSessionCookiesAsyncOnCookieThread,
+ CreateWrappedCallback<int>(callback)));
+}
+
+void AwCookieStoreWrapper::FlushStore(const base::Closure& callback) {
+ DCHECK(client_task_runner_->RunsTasksOnCurrentThread());
+ PostTaskToCookieStoreTaskRunner(base::Bind(
+ &FlushStoreOnCookieThread, CreateWrappedClosureCallback(callback)));
+}
+
+void AwCookieStoreWrapper::SetForceKeepSessionState() {
+ DCHECK(client_task_runner_->RunsTasksOnCurrentThread());
+ PostTaskToCookieStoreTaskRunner(
+ base::Bind(&SetForceKeepSessionStateOnCookieThread));
+}
+
+net::CookieMonster* AwCookieStoreWrapper::GetCookieMonster() {
+ return nullptr;
+}
+
+scoped_ptr<net::CookieStore::CookieChangedSubscription>
+AwCookieStoreWrapper::AddCallbackForCookie(
+ const GURL& url,
+ const std::string& name,
+ const CookieChangedCallback& callback) {
+ DCHECK(client_task_runner_->RunsTasksOnCurrentThread());
+
+ // The SubscriptionWrapper is owned by the subscription itself, and has no
+ // connection to the AwCookieStoreWrapper after creation. Other CookieStore
+ // implementations DCHECK if a subscription outlasts the cookie store,
+ // unfortunately, this design makes DCHECKing if there's an outstanding
+ // subscription when the AwCookieStoreWrapper is destroyed a bit ugly.
+ // TODO(mmenke): Still worth adding a DCHECK?
+ SubscriptionWrapper* subscription = new SubscriptionWrapper();
+ return subscription->Subscribe(url, name, callback);
+}
+
+AwCookieStoreWrapper::~AwCookieStoreWrapper() {}
+
+base::Closure AwCookieStoreWrapper::CreateWrappedClosureCallback(
+ const base::Closure& callback) {
+ if (callback.is_null())
+ return callback;
+ return base::Bind(base::IgnoreResult(&base::TaskRunner::PostTask),
+ client_task_runner_, FROM_HERE,
+ base::Bind(&AwCookieStoreWrapper::RunClosureCallback,
+ weak_factory_.GetWeakPtr(), callback));
+}
+
+void AwCookieStoreWrapper::RunClosureCallback(const base::Closure& callback) {
+ DCHECK(client_task_runner_->RunsTasksOnCurrentThread());
+ callback.Run();
+}
+
+} // namespace android_webview
diff --git a/android_webview/browser/net/aw_cookie_store_wrapper.h b/android_webview/browser/net/aw_cookie_store_wrapper.h
new file mode 100644
index 0000000..e308fb1
--- /dev/null
+++ b/android_webview/browser/net/aw_cookie_store_wrapper.h
@@ -0,0 +1,132 @@
+// Copyright 2016 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 <string>
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
+#include "base/task_runner.h"
+#include "base/time/time.h"
+#include "net/cookies/canonical_cookie.h"
+#include "net/cookies/cookie_constants.h"
+#include "net/cookies/cookie_store.h"
+
+namespace android_webview {
+
+// A cross-threaded cookie store implementation that wraps the CookieManager's
+// CookieStore. It posts tasks to the CookieStore's thread, and invokes
+// callbacks on the originating thread. Deleting it cancels pending callbacks.
+// This is needed to allow Webview to run the CookieStore on its own thread, to
+// enable synchronous calls into the store on the IO Thread from Java.
+//
+// AwCookieStoreWrapper will only grab the CookieStore pointer from the
+// CookieManager when it's needed, allowing for lazy creation of the
+// CookieStore.
+//
+// AwCookieStoreWrapper may only be called from the thread on which it's
+// created.
+//
+// The CookieManager must outlive the AwCookieStoreWrapper.
+class AwCookieStoreWrapper : public net::CookieStore {
+ public:
+ AwCookieStoreWrapper();
+
+ // CookieStore implementation:
+ void SetCookieWithOptionsAsync(const GURL& url,
+ const std::string& cookie_line,
+ const net::CookieOptions& options,
+ const SetCookiesCallback& callback) override;
+ void SetCookieWithDetailsAsync(const GURL& url,
+ const std::string& name,
+ const std::string& value,
+ const std::string& domain,
+ const std::string& path,
+ base::Time creation_time,
+ base::Time expiration_time,
+ base::Time last_access_time,
+ bool secure,
+ bool http_only,
+ bool same_site,
+ bool enforce_strict_secure,
+ net::CookiePriority priority,
+ const SetCookiesCallback& callback) override;
+ void GetCookiesWithOptionsAsync(const GURL& url,
+ const net::CookieOptions& options,
+ const GetCookiesCallback& callback) override;
+ void GetCookieListWithOptionsAsync(
+ const GURL& url,
+ const net::CookieOptions& options,
+ const GetCookieListCallback& callback) override;
+ void GetAllCookiesAsync(const GetCookieListCallback& callback) override;
+ void DeleteCookieAsync(const GURL& url,
+ const std::string& cookie_name,
+ const base::Closure& callback) override;
+ void DeleteCanonicalCookieAsync(const net::CanonicalCookie& cookie,
+ const DeleteCallback& callback) override;
+ void DeleteAllCreatedBetweenAsync(const base::Time& delete_begin,
+ const base::Time& delete_end,
+ const DeleteCallback& callback) override;
+ void DeleteAllCreatedBetweenForHostAsync(
+ const base::Time delete_begin,
+ const base::Time delete_end,
+ const GURL& url,
+ const DeleteCallback& callback) override;
+ void DeleteSessionCookiesAsync(const DeleteCallback& callback) override;
+ void FlushStore(const base::Closure& callback) override;
+ void SetForceKeepSessionState() override;
+ net::CookieMonster* GetCookieMonster() override;
+ scoped_ptr<CookieChangedSubscription> AddCallbackForCookie(
+ const GURL& url,
+ const std::string& name,
+ const CookieChangedCallback& callback) override;
+
+ private:
+ ~AwCookieStoreWrapper() override;
+
+ // Used by CreateWrappedCallback below. Takes an arugment of Type and posts
+ // a task to |task_runner| to invoke |callback| with that argument. If
+ // |weak_cookie_store| is deleted before the task is run, the task will not
+ // be run.
+ template <class Type>
+ static void RunCallbackOnClientThread(
+ base::TaskRunner* task_runner,
+ base::WeakPtr<AwCookieStoreWrapper> weak_cookie_store,
+ base::Callback<void(Type)> callback,
+ Type argument) {
+ task_runner->PostTask(
+ FROM_HERE,
+ base::Bind(&AwCookieStoreWrapper::RunClosureCallback, weak_cookie_store,
+ base::Bind(callback, argument)));
+ }
+
+ // Returns a base::Callback that takes an argument of Type and posts a task to
+ // the |client_task_runner_| to invoke |callback| with that argument.
+ template <class Type>
+ base::Callback<void(Type)> CreateWrappedCallback(
+ base::Callback<void(Type)> callback) {
+ if (callback.is_null())
+ return callback;
+ return base::Bind(&AwCookieStoreWrapper::RunCallbackOnClientThread<Type>,
+ client_task_runner_, weak_factory_.GetWeakPtr(),
+ callback);
+ }
+
+ // Returns a base::Closure that posts a task to the |client_task_runner_| to
+ // invoke |callback|.
+ base::Closure CreateWrappedClosureCallback(const base::Closure& callback);
+
+ // Runs |callback|. Used to prevent callbacks from being invoked after the
+ // AwCookieStoreWrapper has been destroyed.
+ void RunClosureCallback(const base::Closure& callback);
+
+ scoped_refptr<base::SingleThreadTaskRunner> client_task_runner_;
+
+ base::WeakPtrFactory<AwCookieStoreWrapper> weak_factory_;
+};
+
+} // namesspace android_webview
diff --git a/android_webview/browser/net/aw_cookie_store_wrapper_unittest.cc b/android_webview/browser/net/aw_cookie_store_wrapper_unittest.cc
new file mode 100644
index 0000000..3567afc
--- /dev/null
+++ b/android_webview/browser/net/aw_cookie_store_wrapper_unittest.cc
@@ -0,0 +1,49 @@
+// Copyright 2016 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 "android_webview/browser/net/aw_cookie_store_wrapper.h"
+
+#include "base/memory/ref_counted.h"
+#include "net/cookies/cookie_store.h"
+#include "net/cookies/cookie_store_test_callbacks.h"
+#include "net/cookies/cookie_store_unittest.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace android_webview {
+
+struct AwCookieStoreWrapperTestTraits {
+ static scoped_refptr<net::CookieStore> Create() {
+ scoped_refptr<net::CookieStore> cookie_store(new AwCookieStoreWrapper());
+
+ // Android Webview can run multiple tests without restarting the binary,
+ // so have to delete any cookies the global store may have from an earlier
+ // test.
+ net::ResultSavingCookieCallback<int> callback;
+ cookie_store->DeleteAllAsync(
+ base::Bind(&net::ResultSavingCookieCallback<int>::Run,
+ base::Unretained(&callback)));
+ callback.WaitUntilDone();
+
+ return cookie_store;
+ }
+
+ static const bool is_cookie_monster = false;
+ static const bool supports_http_only = true;
+ static const bool supports_non_dotted_domains = true;
+ static const bool preserves_trailing_dots = true;
+ static const bool filters_schemes = true;
+ static const bool has_path_prefix_bug = false;
+ static const int creation_time_granularity_in_ms = 0;
+ static const bool enforce_strict_secure = false;
+};
+
+} // namespace android_webview
+
+// Run the standard cookie tests with AwCookieStoreWrapper. Macro must be in
+// net namespace.
+namespace net {
+INSTANTIATE_TYPED_TEST_CASE_P(AwCookieStoreWrapper,
+ CookieStoreTest,
+ android_webview::AwCookieStoreWrapperTestTraits);
+} // namespace net
diff --git a/android_webview/browser/net/aw_url_request_context_getter.cc b/android_webview/browser/net/aw_url_request_context_getter.cc
index 7b54fa9..600ea17 100644
--- a/android_webview/browser/net/aw_url_request_context_getter.cc
+++ b/android_webview/browser/net/aw_url_request_context_getter.cc
@@ -9,6 +9,7 @@
#include "android_webview/browser/aw_browser_context.h"
#include "android_webview/browser/aw_content_browser_client.h"
+#include "android_webview/browser/net/aw_cookie_store_wrapper.h"
#include "android_webview/browser/net/aw_http_user_agent_settings.h"
#include "android_webview/browser/net/aw_network_delegate.h"
#include "android_webview/browser/net/aw_request_interceptor.h"
@@ -166,13 +167,11 @@ scoped_ptr<net::URLRequestJobFactory> CreateJobFactory(
AwURLRequestContextGetter::AwURLRequestContextGetter(
const base::FilePath& cache_path,
- net::CookieStore* cookie_store,
scoped_ptr<net::ProxyConfigService> config_service,
PrefService* user_pref_service)
: cache_path_(cache_path),
net_log_(new net::NetLog()),
proxy_config_service_(std::move(config_service)),
- cookie_store_(cookie_store),
http_user_agent_settings_(new AwHttpUserAgentSettings()) {
// CreateSystemProxyConfigService for Android must be called on main thread.
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -201,6 +200,8 @@ void AwURLRequestContextGetter::InitializeURLRequestContext() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!url_request_context_);
+ cookie_store_ = new AwCookieStoreWrapper();
+
net::URLRequestContextBuilder builder;
scoped_ptr<AwNetworkDelegate> aw_network_delegate(new AwNetworkDelegate());
diff --git a/android_webview/browser/net/aw_url_request_context_getter.h b/android_webview/browser/net/aw_url_request_context_getter.h
index 46c2146..763a45c 100644
--- a/android_webview/browser/net/aw_url_request_context_getter.h
+++ b/android_webview/browser/net/aw_url_request_context_getter.h
@@ -36,7 +36,6 @@ class AwURLRequestContextGetter : public net::URLRequestContextGetter {
public:
AwURLRequestContextGetter(
const base::FilePath& cache_path,
- net::CookieStore* cookie_store,
scoped_ptr<net::ProxyConfigService> config_service,
PrefService* pref_service);
diff --git a/android_webview/browser/net/init_native_callback.h b/android_webview/browser/net/init_native_callback.h
index d98867c..34a65c6 100644
--- a/android_webview/browser/net/init_native_callback.h
+++ b/android_webview/browser/net/init_native_callback.h
@@ -8,6 +8,10 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+namespace base {
+class SingleThreadTaskRunner;
+}
+
namespace net {
class CookieStore;
class URLRequestInterceptor;
@@ -16,9 +20,13 @@ class URLRequestInterceptor;
namespace android_webview {
class AwBrowserContext;
-// Called when the CookieMonster needs to be created.
-scoped_refptr<net::CookieStore> CreateCookieStore(
- AwBrowserContext* browser_context);
+// Gets the TaskRunner that the CookieStore must be called on.
+scoped_refptr<base::SingleThreadTaskRunner> GetCookieStoreTaskRunner();
+
+// Gets a pointer to the CookieStore managed by the CookieManager.
+// The CookieStore is never deleted. May only be called on the
+// CookieStore's TaskRunner.
+net::CookieStore* GetCookieStore();
// Called lazily when the job factory is being constructed.
scoped_ptr<net::URLRequestInterceptor>
diff --git a/android_webview/native/cookie_manager.cc b/android_webview/native/cookie_manager.cc
index 08f8246..ebbc67f 100644
--- a/android_webview/native/cookie_manager.cc
+++ b/android_webview/native/cookie_manager.cc
@@ -20,6 +20,7 @@
#include "base/files/file_util.h"
#include "base/lazy_instance.h"
#include "base/location.h"
+#include "base/logging.h"
#include "base/path_service.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
@@ -33,6 +34,7 @@
#include "jni/AwCookieManager_jni.h"
#include "net/cookies/cookie_monster.h"
#include "net/cookies/cookie_options.h"
+#include "net/cookies/cookie_store.h"
#include "net/extras/sqlite/cookie_crypto_delegate.h"
#include "net/url_request/url_request_context.h"
#include "url/url_constants.h"
@@ -44,7 +46,6 @@ using base::android::ConvertJavaStringToUTF16;
using base::android::ScopedJavaGlobalRef;
using content::BrowserThread;
using net::CookieList;
-using net::CookieMonster;
// In the future, we may instead want to inject an explicit CookieStore
// dependency into this object during process initialization to avoid
@@ -74,8 +75,8 @@ class BoolCookieCallbackHolder {
void Invoke(bool result) {
if (!callback_.is_null()) {
JNIEnv* env = base::android::AttachCurrentThread();
- Java_AwCookieManager_invokeBooleanCookieCallback(
- env, callback_.obj(), result);
+ Java_AwCookieManager_invokeBooleanCookieCallback(env, callback_.obj(),
+ result);
}
}
@@ -144,19 +145,28 @@ void GetUserDataDir(FilePath* user_data_dir) {
}
}
+// CookieManager creates and owns Webview's CookieStore, in addition to handling
+// calls into the CookieStore from Java.
+//
+// Since Java calls can be made on the IO Thread, and must synchronously return
+// a result, and the CookieStore API allows it to asynchronously return results,
+// the CookieStore must be run on its own thread, to prevent deadlock.
class CookieManager {
public:
static CookieManager* GetInstance();
- scoped_refptr<net::CookieStore> GetCookieStore();
+ // Returns the TaskRunner on which the CookieStore lives.
+ base::SingleThreadTaskRunner* GetCookieStoreTaskRunner();
+ // Returns the CookieStore, creating it if necessary. This must only be called
+ // on the CookieStore TaskRunner.
+ net::CookieStore* GetCookieStore();
void SetShouldAcceptCookies(bool accept);
bool GetShouldAcceptCookies();
void SetCookie(const GURL& host,
const std::string& cookie_value,
scoped_ptr<BoolCookieCallbackHolder> callback);
- void SetCookieSync(const GURL& host,
- const std::string& cookie_value);
+ void SetCookieSync(const GURL& host, const std::string& cookie_value);
std::string GetCookie(const GURL& host);
void RemoveSessionCookies(scoped_ptr<BoolCookieCallbackHolder> callback);
void RemoveAllCookies(scoped_ptr<BoolCookieCallbackHolder> callback);
@@ -179,10 +189,9 @@ class CookieManager {
void ExecCookieTaskSync(const base::Callback<void(base::Closure)>& task);
void ExecCookieTask(const base::Closure& task);
- void SetCookieHelper(
- const GURL& host,
- const std::string& value,
- BoolCallback callback);
+ void SetCookieHelper(const GURL& host,
+ const std::string& value,
+ BoolCallback callback);
void GetCookieValueAsyncHelper(const GURL& host,
std::string* result,
@@ -200,93 +209,58 @@ class CookieManager {
void HasCookiesAsyncHelper(bool* result, base::Closure complete);
void HasCookiesCompleted(base::Closure complete,
bool* result,
- const CookieList& cookies);
+ const net::CookieList& cookies);
- void CreateCookieMonster(
- const FilePath& user_data_dir,
- const scoped_refptr<base::SequencedTaskRunner>& client_task_runner,
- const scoped_refptr<base::SequencedTaskRunner>& background_task_runner);
- void EnsureCookieMonsterExistsLocked();
- bool AllowFileSchemeCookiesLocked();
- void SetAcceptFileSchemeCookiesLocked(bool accept);
+ // This protects the following two bools, as they're used on multiple threads.
+ base::Lock accept_file_scheme_cookies_lock_;
+ // True if cookies should be allowed for file URLs. Can only be changed prior
+ // to creating the CookieStore.
+ bool accept_file_scheme_cookies_;
+ // True once the cookie store has been created. Just used to track when
+ // |accept_file_scheme_cookies_| can no longer be modified.
+ bool cookie_store_created_;
- scoped_refptr<net::CookieMonster> cookie_monster_;
- scoped_refptr<base::SingleThreadTaskRunner> cookie_monster_task_runner_;
- base::Lock cookie_monster_lock_;
+ base::Thread cookie_store_client_thread_;
+ base::Thread cookie_store_backend_thread_;
- scoped_ptr<base::Thread> cookie_monster_client_thread_;
- scoped_ptr<base::Thread> cookie_monster_backend_thread_;
+ scoped_refptr<base::SingleThreadTaskRunner> cookie_store_task_runner_;
+ scoped_refptr<net::CookieStore> cookie_store_;
DISALLOW_COPY_AND_ASSIGN(CookieManager);
};
base::LazyInstance<CookieManager>::Leaky g_lazy_instance;
+} // namespace
+
// static
CookieManager* CookieManager::GetInstance() {
return g_lazy_instance.Pointer();
}
-CookieManager::CookieManager() {
+CookieManager::CookieManager()
+ : accept_file_scheme_cookies_(kDefaultFileSchemeAllowed),
+ cookie_store_created_(false),
+ cookie_store_client_thread_("CookieMonsterClient"),
+ cookie_store_backend_thread_("CookieMonsterBackend") {
+ cookie_store_client_thread_.Start();
+ cookie_store_backend_thread_.Start();
+ cookie_store_task_runner_ = cookie_store_client_thread_.task_runner();
}
CookieManager::~CookieManager() {
}
-void CookieManager::CreateCookieMonster(
- const FilePath& user_data_dir,
- const scoped_refptr<base::SequencedTaskRunner>& client_task_runner,
- const scoped_refptr<base::SequencedTaskRunner>& background_task_runner) {
- FilePath cookie_store_path =
- user_data_dir.Append(FILE_PATH_LITERAL("Cookies"));
-
- background_task_runner->PostTask(
- FROM_HERE,
- base::Bind(ImportLegacyCookieStore, cookie_store_path));
-
- content::CookieStoreConfig cookie_config(
- cookie_store_path,
- content::CookieStoreConfig::RESTORED_SESSION_COOKIES,
- NULL, NULL);
- cookie_config.client_task_runner = client_task_runner;
- cookie_config.background_task_runner = background_task_runner;
- net::CookieStore* cookie_store = content::CreateCookieStore(cookie_config);
- cookie_monster_ = cookie_store->GetCookieMonster();
- SetAcceptFileSchemeCookiesLocked(kDefaultFileSchemeAllowed);
-}
-
-void CookieManager::EnsureCookieMonsterExistsLocked() {
- cookie_monster_lock_.AssertAcquired();
- if (cookie_monster_.get()) {
- return;
- }
-
- // Create cookie monster using WebView-specific threads, as the rest of the
- // browser has not been started yet.
- FilePath user_data_dir;
- GetUserDataDir(&user_data_dir);
- cookie_monster_client_thread_.reset(
- new base::Thread("CookieMonsterClient"));
- cookie_monster_client_thread_->Start();
- cookie_monster_task_runner_ = cookie_monster_client_thread_->task_runner();
- cookie_monster_backend_thread_.reset(
- new base::Thread("CookieMonsterBackend"));
- cookie_monster_backend_thread_->Start();
-
- CreateCookieMonster(user_data_dir, cookie_monster_task_runner_,
- cookie_monster_backend_thread_->task_runner());
-}
-
-// Executes the |task| on the |cookie_monster_proxy_| message loop and
-// waits for it to complete before returning.
-
+// Executes the |task| on |cookie_store_task_runner_| and waits for it to
+// complete before returning.
+//
// To execute a CookieTask synchronously you must arrange for Signal to be
// called on the waitable event at some point. You can call the bool or int
// versions of ExecCookieTaskSync, these will supply the caller with a dummy
// callback which takes an int/bool, throws it away and calls Signal.
// Alternatively you can call the version which supplies a Closure in which
// case you must call Run on it when you want the unblock the calling code.
-
+//
// Ignore a bool callback.
void CookieManager::ExecCookieTaskSync(
const base::Callback<void(BoolCallback)>& task) {
@@ -317,17 +291,57 @@ void CookieManager::ExecCookieTaskSync(
completion.Wait();
}
-// Executes the |task| on the |cookie_monster_proxy_| message loop.
+// Executes the |task| using |cookie_store_task_runner_|.
void CookieManager::ExecCookieTask(const base::Closure& task) {
- base::AutoLock lock(cookie_monster_lock_);
- EnsureCookieMonsterExistsLocked();
- cookie_monster_task_runner_->PostTask(FROM_HERE, task);
-}
+ cookie_store_task_runner_->PostTask(FROM_HERE, task);
+}
+
+base::SingleThreadTaskRunner* CookieManager::GetCookieStoreTaskRunner() {
+ return cookie_store_task_runner_.get();
+}
+
+net::CookieStore* CookieManager::GetCookieStore() {
+ DCHECK(cookie_store_task_runner_->RunsTasksOnCurrentThread());
+
+ if (!cookie_store_) {
+ FilePath user_data_dir;
+ GetUserDataDir(&user_data_dir);
+ FilePath cookie_store_path =
+ user_data_dir.Append(FILE_PATH_LITERAL("Cookies"));
+
+ cookie_store_backend_thread_.task_runner()->PostTask(
+ FROM_HERE, base::Bind(ImportLegacyCookieStore, cookie_store_path));
+
+ content::CookieStoreConfig cookie_config(
+ cookie_store_path, content::CookieStoreConfig::RESTORED_SESSION_COOKIES,
+ nullptr, nullptr);
+ cookie_config.client_task_runner = cookie_store_task_runner_;
+ cookie_config.background_task_runner =
+ cookie_store_backend_thread_.task_runner();
+
+ {
+ base::AutoLock lock(accept_file_scheme_cookies_lock_);
+
+ // There are some unknowns about how to correctly handle file:// cookies,
+ // and our implementation for this is not robust. http://crbug.com/582985
+ //
+ // TODO(mmenke): This call should be removed once we can deprecate and
+ // remove the Android WebView 'CookieManager::setAcceptFileSchemeCookies'
+ // method. Until then, note that this is just not a great idea.
+ cookie_config.cookieable_schemes.insert(
+ cookie_config.cookieable_schemes.begin(),
+ net::CookieMonster::kDefaultCookieableSchemes,
+ net::CookieMonster::kDefaultCookieableSchemes +
+ net::CookieMonster::kDefaultCookieableSchemesCount);
+ if (accept_file_scheme_cookies_)
+ cookie_config.cookieable_schemes.push_back(url::kFileScheme);
+ cookie_store_created_ = true;
+ }
+
+ cookie_store_ = content::CreateCookieStore(cookie_config);
+ }
-scoped_refptr<net::CookieStore> CookieManager::GetCookieStore() {
- base::AutoLock lock(cookie_monster_lock_);
- EnsureCookieMonsterExistsLocked();
- return cookie_monster_;
+ return cookie_store_.get();
}
void CookieManager::SetShouldAcceptCookies(bool accept) {
@@ -366,8 +380,7 @@ void CookieManager::SetCookieHelper(
net::CookieOptions options;
options.set_include_httponly();
- cookie_monster_->SetCookieWithOptionsAsync(
- host, value, options, callback);
+ GetCookieStore()->SetCookieWithOptionsAsync(host, value, options, callback);
}
std::string CookieManager::GetCookie(const GURL& host) {
@@ -386,13 +399,9 @@ void CookieManager::GetCookieValueAsyncHelper(
net::CookieOptions options;
options.set_include_httponly();
- cookie_monster_->GetCookiesWithOptionsAsync(
- host,
- options,
- base::Bind(&CookieManager::GetCookieValueCompleted,
- base::Unretained(this),
- complete,
- result));
+ GetCookieStore()->GetCookiesWithOptionsAsync(
+ host, options, base::Bind(&CookieManager::GetCookieValueCompleted,
+ base::Unretained(this), complete, result));
}
void CookieManager::GetCookieValueCompleted(base::Closure complete,
@@ -418,9 +427,8 @@ void CookieManager::RemoveSessionCookiesSync() {
void CookieManager::RemoveSessionCookiesHelper(
BoolCallback callback) {
- cookie_monster_->DeleteSessionCookiesAsync(
- base::Bind(&CookieManager::RemoveCookiesCompleted,
- base::Unretained(this),
+ GetCookieStore()->DeleteSessionCookiesAsync(
+ base::Bind(&CookieManager::RemoveCookiesCompleted, base::Unretained(this),
callback));
}
@@ -446,9 +454,8 @@ void CookieManager::RemoveAllCookiesSync() {
void CookieManager::RemoveAllCookiesHelper(
const BoolCallback callback) {
- cookie_monster_->DeleteAllAsync(
- base::Bind(&CookieManager::RemoveCookiesCompleted,
- base::Unretained(this),
+ GetCookieStore()->DeleteAllAsync(
+ base::Bind(&CookieManager::RemoveCookiesCompleted, base::Unretained(this),
callback));
}
@@ -464,7 +471,7 @@ void CookieManager::FlushCookieStore() {
void CookieManager::FlushCookieStoreAsyncHelper(
base::Closure complete) {
- cookie_monster_->FlushStore(complete);
+ GetCookieStore()->FlushStore(complete);
}
bool CookieManager::HasCookies() {
@@ -479,11 +486,9 @@ bool CookieManager::HasCookies() {
// should not be needed.
void CookieManager::HasCookiesAsyncHelper(bool* result,
base::Closure complete) {
- cookie_monster_->GetAllCookiesAsync(
- base::Bind(&CookieManager::HasCookiesCompleted,
- base::Unretained(this),
- complete,
- result));
+ GetCookieStore()->GetAllCookiesAsync(
+ base::Bind(&CookieManager::HasCookiesCompleted, base::Unretained(this),
+ complete, result));
}
void CookieManager::HasCookiesCompleted(base::Closure complete,
@@ -494,42 +499,17 @@ void CookieManager::HasCookiesCompleted(base::Closure complete,
}
bool CookieManager::AllowFileSchemeCookies() {
- base::AutoLock lock(cookie_monster_lock_);
- EnsureCookieMonsterExistsLocked();
- return AllowFileSchemeCookiesLocked();
-}
-
-bool CookieManager::AllowFileSchemeCookiesLocked() {
- return cookie_monster_->IsCookieableScheme(url::kFileScheme);
+ base::AutoLock lock(accept_file_scheme_cookies_lock_);
+ return accept_file_scheme_cookies_;
}
void CookieManager::SetAcceptFileSchemeCookies(bool accept) {
- base::AutoLock lock(cookie_monster_lock_);
- EnsureCookieMonsterExistsLocked();
- SetAcceptFileSchemeCookiesLocked(accept);
-}
-
-void CookieManager::SetAcceptFileSchemeCookiesLocked(bool accept) {
- // There are some unknowns about how to correctly handle file:// cookies,
- // and our implementation for this is not robust. http://crbug.com/582985
- //
- // TODO(mmenke): This call should be removed once we can deprecate and remove
- // the Android WebView 'CookieManager::setAcceptFileSchemeCookies' method.
- // Until then, note that this is just not a great idea.
- std::vector<std::string> schemes;
- schemes.insert(schemes.begin(),
- net::CookieMonster::kDefaultCookieableSchemes,
- net::CookieMonster::kDefaultCookieableSchemes +
- net::CookieMonster::kDefaultCookieableSchemesCount);
-
- if (accept)
- schemes.push_back(url::kFileScheme);
-
- cookie_monster_->SetCookieableSchemes(schemes);
+ base::AutoLock lock(accept_file_scheme_cookies_lock_);
+ // Can only modify this before the cookie store is created.
+ if (!cookie_store_created_)
+ accept_file_scheme_cookies_ = accept;
}
-} // namespace
-
static void SetShouldAcceptCookies(JNIEnv* env,
const JavaParamRef<jobject>& obj,
jboolean accept) {
@@ -623,8 +603,15 @@ static void SetAcceptFileSchemeCookies(JNIEnv* env,
return CookieManager::GetInstance()->SetAcceptFileSchemeCookies(accept);
}
-scoped_refptr<net::CookieStore> CreateCookieStore(
- AwBrowserContext* browser_context) {
+// The following two methods are used to avoid a circular project dependency.
+// TODO(mmenke): This is weird. Maybe there should be a leaky Singleton in
+// browser/net that creates and owns there?
+
+scoped_refptr<base::SingleThreadTaskRunner> GetCookieStoreTaskRunner() {
+ return CookieManager::GetInstance()->GetCookieStoreTaskRunner();
+}
+
+net::CookieStore* GetCookieStore() {
return CookieManager::GetInstance()->GetCookieStore();
}
diff --git a/android_webview/test/BUILD.gn b/android_webview/test/BUILD.gn
index 72f4dd6..92b46fa 100644
--- a/android_webview/test/BUILD.gn
+++ b/android_webview/test/BUILD.gn
@@ -129,6 +129,7 @@ test("android_webview_unittests") {
"../browser/aw_static_cookie_policy_unittest.cc",
"../browser/browser_view_renderer_unittest.cc",
"../browser/net/android_stream_reader_url_request_job_unittest.cc",
+ "../browser/net/aw_cookie_store_wrapper_unittest.cc",
"../browser/net/input_stream_reader_unittest.cc",
"../browser/test/fake_window.cc",
"../browser/test/fake_window.h",