Commit 99cba223 authored by Wez's avatar Wez Committed by Commit Bot

[Fuchsia] Implement the fuchsia.web.Frame.GetCookieManager() API.

The CookieManager API can be used to query and observe changes to the
cookies in a fuchsia.web.Context. Queries and observations can be
global, restricted by URL, or to a particular URL and cookie name.

Bug: 858853
Change-Id: Ibe9c9ac6fc6a0fea37c6170731e5345fdbdd0a18
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1673602
Commit-Queue: Wez <wez@chromium.org>
Reviewed-by: default avatarKen Rockot <rockot@google.com>
Reviewed-by: default avatarTom Sepez <tsepez@chromium.org>
Reviewed-by: default avatarKevin Marshall <kmarshall@chromium.org>
Reviewed-by: default avatarMaks Orlovich <morlovich@chromium.org>
Auto-Submit: Wez <wez@chromium.org>
Cr-Commit-Position: refs/heads/master@{#687394}
parent 8578f770
...@@ -84,6 +84,7 @@ component("web_engine_core") { ...@@ -84,6 +84,7 @@ component("web_engine_core") {
"//media/fuchsia/mojom", "//media/fuchsia/mojom",
"//mojo/public/cpp/bindings", "//mojo/public/cpp/bindings",
"//services/network/public/cpp", "//services/network/public/cpp",
"//services/network/public/mojom",
"//services/service_manager/sandbox", "//services/service_manager/sandbox",
"//skia/public/mojom", "//skia/public/mojom",
"//third_party/blink/public/common", "//third_party/blink/public/common",
...@@ -110,6 +111,8 @@ component("web_engine_core") { ...@@ -110,6 +111,8 @@ component("web_engine_core") {
sources = [ sources = [
"browser/context_impl.cc", "browser/context_impl.cc",
"browser/context_impl.h", "browser/context_impl.h",
"browser/cookie_manager_impl.cc",
"browser/cookie_manager_impl.h",
"browser/discarding_event_filter.cc", "browser/discarding_event_filter.cc",
"browser/discarding_event_filter.h", "browser/discarding_event_filter.h",
"browser/frame_impl.cc", "browser/frame_impl.cc",
...@@ -237,15 +240,20 @@ test("web_engine_browsertests") { ...@@ -237,15 +240,20 @@ test("web_engine_browsertests") {
test("web_engine_unittests") { test("web_engine_unittests") {
sources = [ sources = [
"browser/cookie_manager_impl_unittest.cc",
"browser/frame_impl_unittest.cc", "browser/frame_impl_unittest.cc",
"context_provider_impl_unittest.cc", "context_provider_impl_unittest.cc",
"fake_context.cc", "fake_context.cc",
"fake_context.h", "fake_context.h",
"test/run_all_unittests.cc",
] ]
deps = [ deps = [
":web_engine_core", ":web_engine_core",
"//base/test:run_all_unittests",
"//base/test:test_support", "//base/test:test_support",
"//fuchsia/base:test_support",
"//mojo/core/embedder",
"//services/network:network_service",
"//services/network/public/mojom",
"//testing/gmock", "//testing/gmock",
"//testing/gtest", "//testing/gtest",
"//third_party/fuchsia-sdk/sdk:web", "//third_party/fuchsia-sdk/sdk:web",
......
...@@ -3,12 +3,12 @@ include_rules = [ ...@@ -3,12 +3,12 @@ include_rules = [
"+components/version_info", "+components/version_info",
"+content/public/common", "+content/public/common",
"+content/public/browser", "+content/public/browser",
"+content/public/test",
"+media/base", "+media/base",
"+media/fuchsia/cdm/service", "+media/fuchsia/cdm/service",
"+media/fuchsia/mojom", "+media/fuchsia/mojom",
"+mojo/public/cpp/bindings", "+mojo/public/cpp/bindings",
"+mojo/public/cpp/system", "+mojo/public/cpp/system",
"+services/network/public/mojom",
"+third_party/blink/public/common/associated_interfaces", "+third_party/blink/public/common/associated_interfaces",
"+third_party/blink/public/common/logging", "+third_party/blink/public/common/logging",
"+third_party/blink/public/common/messaging", "+third_party/blink/public/common/messaging",
...@@ -22,3 +22,10 @@ include_rules = [ ...@@ -22,3 +22,10 @@ include_rules = [
"+ui/platform_window", "+ui/platform_window",
"+ui/wm/core", "+ui/wm/core",
] ]
specific_include_rules = {
".*_(unit|browser|api)test\.cc": [
"+content/public/test",
"+services/network",
],
}
...@@ -4,18 +4,24 @@ ...@@ -4,18 +4,24 @@
#include "fuchsia/engine/browser/context_impl.h" #include "fuchsia/engine/browser/context_impl.h"
#include <lib/zx/object.h> #include <lib/zx/channel.h>
#include <memory> #include <memory>
#include <utility> #include <utility>
#include "base/bind.h"
#include "base/fuchsia/fuchsia_logging.h" #include "base/fuchsia/fuchsia_logging.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "fuchsia/engine/browser/frame_impl.h" #include "fuchsia/engine/browser/frame_impl.h"
#include "fuchsia/engine/browser/web_engine_browser_context.h"
#include "fuchsia/engine/common.h" #include "fuchsia/engine/common.h"
ContextImpl::ContextImpl(content::BrowserContext* browser_context) ContextImpl::ContextImpl(content::BrowserContext* browser_context)
: browser_context_(browser_context) {} : browser_context_(browser_context),
cookie_manager_(base::BindRepeating(
&content::StoragePartition::GetNetworkContext,
base::Unretained(content::BrowserContext::GetDefaultStoragePartition(
browser_context_)))) {}
ContextImpl::~ContextImpl() = default; ContextImpl::~ContextImpl() = default;
...@@ -42,6 +48,11 @@ void ContextImpl::CreateFrame( ...@@ -42,6 +48,11 @@ void ContextImpl::CreateFrame(
std::move(frame))); std::move(frame)));
} }
void ContextImpl::GetCookieManager(
fidl::InterfaceRequest<fuchsia::web::CookieManager> request) {
cookie_manager_bindings_.AddBinding(&cookie_manager_, std::move(request));
}
void ContextImpl::GetRemoteDebuggingPort( void ContextImpl::GetRemoteDebuggingPort(
GetRemoteDebuggingPortCallback callback) { GetRemoteDebuggingPortCallback callback) {
web_engine_remote_debugging_.GetRemoteDebuggingPort(std::move(callback)); web_engine_remote_debugging_.GetRemoteDebuggingPort(std::move(callback));
......
...@@ -6,11 +6,13 @@ ...@@ -6,11 +6,13 @@
#define FUCHSIA_ENGINE_BROWSER_CONTEXT_IMPL_H_ #define FUCHSIA_ENGINE_BROWSER_CONTEXT_IMPL_H_
#include <fuchsia/web/cpp/fidl.h> #include <fuchsia/web/cpp/fidl.h>
#include <lib/fidl/cpp/binding_set.h>
#include <memory> #include <memory>
#include <set> #include <set>
#include "base/containers/unique_ptr_adapters.h" #include "base/containers/unique_ptr_adapters.h"
#include "base/macros.h" #include "base/macros.h"
#include "fuchsia/engine/browser/cookie_manager_impl.h"
#include "fuchsia/engine/browser/web_engine_remote_debugging.h" #include "fuchsia/engine/browser/web_engine_remote_debugging.h"
#include "fuchsia/engine/web_engine_export.h" #include "fuchsia/engine/web_engine_export.h"
...@@ -29,7 +31,7 @@ class WEB_ENGINE_EXPORT ContextImpl : public fuchsia::web::Context { ...@@ -29,7 +31,7 @@ class WEB_ENGINE_EXPORT ContextImpl : public fuchsia::web::Context {
explicit ContextImpl(content::BrowserContext* browser_context); explicit ContextImpl(content::BrowserContext* browser_context);
// Tears down the Context, destroying any active Frames in the process. // Tears down the Context, destroying any active Frames in the process.
~ContextImpl() override; ~ContextImpl() final;
content::BrowserContext* browser_context_for_test() { content::BrowserContext* browser_context_for_test() {
return browser_context_; return browser_context_;
...@@ -47,7 +49,9 @@ class WEB_ENGINE_EXPORT ContextImpl : public fuchsia::web::Context { ...@@ -47,7 +49,9 @@ class WEB_ENGINE_EXPORT ContextImpl : public fuchsia::web::Context {
void OnDebugDevToolsPortReady(); void OnDebugDevToolsPortReady();
// fuchsia::web::Context implementation. // fuchsia::web::Context implementation.
void CreateFrame(fidl::InterfaceRequest<fuchsia::web::Frame> frame) override; void CreateFrame(fidl::InterfaceRequest<fuchsia::web::Frame> frame) final;
void GetCookieManager(
fidl::InterfaceRequest<fuchsia::web::CookieManager> manager) final;
void GetRemoteDebuggingPort(GetRemoteDebuggingPortCallback callback) override; void GetRemoteDebuggingPort(GetRemoteDebuggingPortCallback callback) override;
// Gets the underlying FrameImpl service object associated with a connected // Gets the underlying FrameImpl service object associated with a connected
...@@ -57,6 +61,9 @@ class WEB_ENGINE_EXPORT ContextImpl : public fuchsia::web::Context { ...@@ -57,6 +61,9 @@ class WEB_ENGINE_EXPORT ContextImpl : public fuchsia::web::Context {
private: private:
content::BrowserContext* const browser_context_; content::BrowserContext* const browser_context_;
CookieManagerImpl cookie_manager_;
fidl::BindingSet<fuchsia::web::CookieManager> cookie_manager_bindings_;
// TODO(crbug.com/893236): Make this false by default, and allow it to be // TODO(crbug.com/893236): Make this false by default, and allow it to be
// initialized at Context creation time. // initialized at Context creation time.
bool allow_javascript_injection_ = true; bool allow_javascript_injection_ = true;
......
...@@ -20,23 +20,11 @@ ...@@ -20,23 +20,11 @@
#include "fuchsia/engine/test/web_engine_browser_test.h" #include "fuchsia/engine/test/web_engine_browser_test.h"
#include "services/network/public/mojom/cookie_manager.mojom.h" #include "services/network/public/mojom/cookie_manager.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h" #include "services/network/public/mojom/network_context.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "url/url_constants.h" #include "url/url_constants.h"
using testing::_;
using testing::Field;
using testing::InvokeWithoutArgs;
namespace { namespace {
void OnCookiesReceived(net::CookieList* output,
base::OnceClosure on_received_cb,
const net::CookieList& cookies) {
*output = cookies;
std::move(on_received_cb).Run();
}
// Defines a suite of tests that exercise browser-level configuration and // Defines a suite of tests that exercise browser-level configuration and
// functionality. // functionality.
class ContextImplTest : public cr_fuchsia::WebEngineBrowserTest { class ContextImplTest : public cr_fuchsia::WebEngineBrowserTest {
...@@ -50,19 +38,39 @@ class ContextImplTest : public cr_fuchsia::WebEngineBrowserTest { ...@@ -50,19 +38,39 @@ class ContextImplTest : public cr_fuchsia::WebEngineBrowserTest {
return WebEngineBrowserTest::CreateFrame(&navigation_listener_); return WebEngineBrowserTest::CreateFrame(&navigation_listener_);
} }
// Synchronously gets a list of cookies for this BrowserContext. // Synchronously gets the list of all cookies from the fuchsia.web.Context.
net::CookieList GetCookies() { std::vector<fuchsia::web::Cookie> GetCookies() {
base::RunLoop run_loop; base::RunLoop get_cookies_loop;
net::CookieList cookies;
network::mojom::CookieManagerPtr cookie_manager; // Connect to the Context's CookieManager and request all the cookies.
content::BrowserContext::GetDefaultStoragePartition( fuchsia::web::CookieManagerPtr cookie_manager;
context_impl()->browser_context_for_test()) context()->GetCookieManager(cookie_manager.NewRequest());
->GetNetworkContext() fuchsia::web::CookiesIteratorPtr cookies_iterator;
->GetCookieManager(mojo::MakeRequest(&cookie_manager)); cookie_manager->GetCookieList(nullptr, nullptr,
cookie_manager->GetAllCookies(base::BindOnce(&OnCookiesReceived, cookies_iterator.NewRequest());
base::Unretained(&cookies),
run_loop.QuitClosure())); // |cookies_iterator| will disconnect once after the last cookies have been
run_loop.Run(); // returned by GetNext().
cookies_iterator.set_error_handler([&](zx_status_t status) {
EXPECT_EQ(ZX_ERR_PEER_CLOSED, status);
get_cookies_loop.Quit();
});
std::vector<fuchsia::web::Cookie> cookies;
// std::function<> must be used here because fit::function<> is move-only
// and this callback will be used both for the initial GetNext() call, and
// for the follow-up calls made each time GetNext() results are received.
std::function<void(std::vector<fuchsia::web::Cookie>)> get_next_callback =
[&](std::vector<fuchsia::web::Cookie> new_cookies) {
cookies.insert(cookies.end(),
std::make_move_iterator(new_cookies.begin()),
std::make_move_iterator(new_cookies.end()));
cookies_iterator->GetNext(get_next_callback);
};
cookies_iterator->GetNext(get_next_callback);
get_cookies_loop.Run();
return cookies; return cookies;
} }
...@@ -74,44 +82,41 @@ class ContextImplTest : public cr_fuchsia::WebEngineBrowserTest { ...@@ -74,44 +82,41 @@ class ContextImplTest : public cr_fuchsia::WebEngineBrowserTest {
} // namespace } // namespace
// Verifies that the BrowserContext has a working cookie store by setting // BrowserContext with persistent storage stores cookies such that they can
// cookies in the content layer and then querying the CookieStore afterward. // be retrieved via the CookieManager API.
IN_PROC_BROWSER_TEST_F(ContextImplTest, VerifyPersistentCookieStore) { IN_PROC_BROWSER_TEST_F(ContextImplTest, PersistentCookieStore) {
ASSERT_TRUE(embedded_test_server()->Start()); ASSERT_TRUE(embedded_test_server()->Start());
GURL cookie_url(embedded_test_server()->GetURL("/set-cookie?foo=bar"));
fuchsia::web::FramePtr frame = CreateFrame(); fuchsia::web::FramePtr frame = CreateFrame();
fuchsia::web::NavigationControllerPtr navigation_controller; fuchsia::web::NavigationControllerPtr controller;
frame->GetNavigationController(navigation_controller.NewRequest()); frame->GetNavigationController(controller.NewRequest());
cr_fuchsia::LoadUrlAndExpectResponse(navigation_controller.get(), const GURL kSetCookieUrl(
fuchsia::web::LoadUrlParams(), embedded_test_server()->GetURL("/set-cookie?foo=bar"));
cookie_url.spec()); cr_fuchsia::LoadUrlAndExpectResponse(
navigation_listener_.RunUntilUrlEquals(cookie_url); controller.get(), fuchsia::web::LoadUrlParams(), kSetCookieUrl.spec());
navigation_listener_.RunUntilUrlEquals(kSetCookieUrl);
auto cookies = GetCookies();
bool found = false; std::vector<fuchsia::web::Cookie> cookies = GetCookies();
for (auto c : cookies) { ASSERT_EQ(cookies.size(), 1u);
if (c.Name() == "foo" && c.Value() == "bar") { ASSERT_TRUE(cookies[0].has_id());
found = true; ASSERT_TRUE(cookies[0].id().has_name());
break; ASSERT_TRUE(cookies[0].has_value());
} EXPECT_EQ(cookies[0].id().name(), "foo");
} EXPECT_EQ(cookies[0].value(), "bar");
EXPECT_TRUE(found);
// Check that the cookie persists beyond the lifetime of the Frame by // Check that the cookie persists beyond the lifetime of the Frame by
// releasing the Frame and re-querying the CookieStore. // releasing the Frame and re-querying the CookieStore.
frame.Unbind(); frame.Unbind();
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
found = false; cookies = GetCookies();
for (auto c : cookies) { ASSERT_EQ(cookies.size(), 1u);
if (c.Name() == "foo" && c.Value() == "bar") { ASSERT_TRUE(cookies[0].has_id());
found = true; ASSERT_TRUE(cookies[0].id().has_name());
break; ASSERT_TRUE(cookies[0].has_value());
} EXPECT_EQ(cookies[0].id().name(), "foo");
} EXPECT_EQ(cookies[0].value(), "bar");
EXPECT_TRUE(found);
} }
// Suite for tests which run the BrowserContext in incognito mode (no data // Suite for tests which run the BrowserContext in incognito mode (no data
...@@ -145,25 +150,25 @@ IN_PROC_BROWSER_TEST_F(IncognitoContextImplTest, NavigateFrame) { ...@@ -145,25 +150,25 @@ IN_PROC_BROWSER_TEST_F(IncognitoContextImplTest, NavigateFrame) {
frame.Unbind(); frame.Unbind();
} }
IN_PROC_BROWSER_TEST_F(IncognitoContextImplTest, VerifyInMemoryCookieStore) { // In-memory cookie store stores cookies, and is accessible via CookieManager.
IN_PROC_BROWSER_TEST_F(IncognitoContextImplTest, InMemoryCookieStore) {
ASSERT_TRUE(embedded_test_server()->Start()); ASSERT_TRUE(embedded_test_server()->Start());
GURL cookie_url(embedded_test_server()->GetURL("/set-cookie?foo=bar"));
fuchsia::web::FramePtr frame = CreateFrame(); fuchsia::web::FramePtr frame = CreateFrame();
fuchsia::web::NavigationControllerPtr controller; fuchsia::web::NavigationControllerPtr controller;
frame->GetNavigationController(controller.NewRequest()); frame->GetNavigationController(controller.NewRequest());
EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse( const GURL kSetCookieUrl(
controller.get(), fuchsia::web::LoadUrlParams(), cookie_url.spec())); embedded_test_server()->GetURL("/set-cookie?foo=bar"));
navigation_listener_.RunUntilUrlEquals(cookie_url); cr_fuchsia::LoadUrlAndExpectResponse(
controller.get(), fuchsia::web::LoadUrlParams(), kSetCookieUrl.spec());
auto cookies = GetCookies(); navigation_listener_.RunUntilUrlEquals(kSetCookieUrl);
bool found = false;
for (auto c : cookies) { std::vector<fuchsia::web::Cookie> cookies = GetCookies();
if (c.Name() == "foo" && c.Value() == "bar") { ASSERT_EQ(cookies.size(), 1u);
found = true; ASSERT_TRUE(cookies[0].has_id());
break; ASSERT_TRUE(cookies[0].id().has_name());
} ASSERT_TRUE(cookies[0].has_value());
} EXPECT_EQ(cookies[0].id().name(), "foo");
EXPECT_TRUE(found); EXPECT_EQ(cookies[0].value(), "bar");
} }
// Copyright 2019 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 "fuchsia/engine/browser/cookie_manager_impl.h"
#include <lib/fidl/cpp/binding.h>
#include "base/fuchsia/fuchsia_logging.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "net/cookies/canonical_cookie.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "url/gurl.h"
namespace {
fuchsia::web::Cookie ConvertCanonicalCookie(
const net::CanonicalCookie& canonical_cookie,
network::mojom::CookieChangeCause cause) {
fuchsia::web::CookieId id;
id.set_name(canonical_cookie.Name());
id.set_domain(canonical_cookie.Domain());
id.set_path(canonical_cookie.Path());
fuchsia::web::Cookie cookie;
cookie.set_id(std::move(id));
switch (cause) {
case network::mojom::CookieChangeCause::INSERTED:
cookie.set_value(canonical_cookie.Value());
break;
case network::mojom::CookieChangeCause::EXPLICIT:
case network::mojom::CookieChangeCause::UNKNOWN_DELETION:
case network::mojom::CookieChangeCause::OVERWRITE:
case network::mojom::CookieChangeCause::EXPIRED:
case network::mojom::CookieChangeCause::EVICTED:
case network::mojom::CookieChangeCause::EXPIRED_OVERWRITE:
break;
};
return cookie;
}
class CookiesIteratorImpl : public fuchsia::web::CookiesIterator,
public network::mojom::CookieChangeListener {
public:
// |this| will delete itself when |mojo_request| or |changes| disconnect.
CookiesIteratorImpl(
mojo::InterfaceRequest<network::mojom::CookieChangeListener> mojo_request,
fidl::InterfaceRequest<fuchsia::web::CookiesIterator> changes)
: CookiesIteratorImpl(std::move(changes)) {
mojo_binding_.Bind(std::move(mojo_request));
mojo_binding_.set_connection_error_handler(base::BindOnce(
&CookiesIteratorImpl::OnMojoError, base::Unretained(this)));
}
// |this| will delete itself when |iterator| disconnects, or if a GetNext()
// leaves |queued_cookies_| empty.
CookiesIteratorImpl(
const std::vector<net::CanonicalCookie>& cookies,
fidl::InterfaceRequest<fuchsia::web::CookiesIterator> iterator)
: CookiesIteratorImpl(std::move(iterator)) {
for (const auto& cookie : cookies) {
queued_cookies_[cookie.UniqueKey()] = ConvertCanonicalCookie(
cookie, network::mojom::CookieChangeCause::INSERTED);
}
}
~CookiesIteratorImpl() final = default;
// fuchsia::web::CookiesIterator implementation:
void GetNext(GetNextCallback callback) final {
DCHECK(!get_next_callback_);
get_next_callback_ = std::move(callback);
MaybeSendQueuedCookies();
}
private:
explicit CookiesIteratorImpl(
fidl::InterfaceRequest<fuchsia::web::CookiesIterator> iterator)
: mojo_binding_(this), fidl_binding_(this) {
fidl_binding_.Bind(std::move(iterator));
fidl_binding_.set_error_handler([this](zx_status_t status) {
ZX_LOG_IF(ERROR, status != ZX_ERR_PEER_CLOSED, status)
<< "CookieChangeListener disconnected.";
delete this;
});
}
void OnMojoError() {
LOG(ERROR) << "NetworkService disconnected CookiesIterator.";
fidl_binding_.Close(ZX_ERR_UNAVAILABLE);
delete this;
}
void MaybeSendQueuedCookies() {
// Assuming cookies values never exceed 4KB in size, plus some overhead for
// the name, domain and path, and that Zircon messages can be up to 64KB.
constexpr int kMaxCookiesPerMessage = 8;
if (!get_next_callback_)
return;
if (mojo_binding_.is_bound() && queued_cookies_.empty())
return;
// Build a vector of Cookies to return to the caller.
fuchsia::web::CookiesIterator::GetNextCallback callback(
std::move(get_next_callback_));
std::vector<fuchsia::web::Cookie> cookies;
while (!queued_cookies_.empty() && cookies.size() < kMaxCookiesPerMessage) {
auto cookie = queued_cookies_.begin();
cookies.emplace_back(std::move(cookie->second));
queued_cookies_.erase(cookie);
}
callback(std::move(cookies));
// If this is a one-off CookieIterator then tear down once |queued_cookies_|
// is empty.
if (queued_cookies_.empty() && !mojo_binding_.is_bound())
delete this;
}
// network::mojom::CookieChangeListener implementation:
void OnCookieChange(const net::CanonicalCookie& cookie,
network::mojom::CookieChangeCause cause) final {
queued_cookies_[cookie.UniqueKey()] = ConvertCanonicalCookie(cookie, cause);
MaybeSendQueuedCookies();
}
mojo::Binding<network::mojom::CookieChangeListener> mojo_binding_;
fidl::Binding<fuchsia::web::CookiesIterator> fidl_binding_;
GetNextCallback get_next_callback_;
// Map from "unique key"s (see net::CanonicalCookie::UniqueKey()) to the
// corresponding fuchsia::web::Cookie.
std::map<std::tuple<std::string, std::string, std::string>,
fuchsia::web::Cookie>
queued_cookies_;
DISALLOW_COPY_AND_ASSIGN(CookiesIteratorImpl);
};
void OnCookiesReceived(
fidl::InterfaceRequest<fuchsia::web::CookiesIterator> iterator,
const std::vector<net::CanonicalCookie>& cookies) {
new CookiesIteratorImpl(cookies, std::move(iterator));
}
void OnCookiesAndExcludedReceived(
fidl::InterfaceRequest<fuchsia::web::CookiesIterator> iterator,
const std::vector<net::CanonicalCookie>& cookies,
const std::vector<net::CookieWithStatus>& excluded_cookies) {
// Since CookieOptions::set_return_excluded_cookies() is not used when calling
// the Mojo GetCookieList() API, |excluded_cookies| should be empty.
DCHECK(excluded_cookies.empty());
OnCookiesReceived(std::move(iterator), cookies);
}
} // namespace
CookieManagerImpl::CookieManagerImpl(
GetNetworkContextCallback get_network_context)
: get_network_context_(std::move(get_network_context)) {}
CookieManagerImpl::~CookieManagerImpl() = default;
void CookieManagerImpl::ObserveCookieChanges(
fidl::StringPtr url,
fidl::StringPtr name,
fidl::InterfaceRequest<fuchsia::web::CookiesIterator> changes) {
EnsureCookieManager();
network::mojom::CookieChangeListenerPtr mojo_listener;
new CookiesIteratorImpl(mojo::MakeRequest(&mojo_listener),
std::move(changes));
if (url) {
base::Optional<std::string> maybe_name;
if (name)
maybe_name = *name;
cookie_manager_->AddCookieChangeListener(GURL(*url), maybe_name,
std::move(mojo_listener));
} else {
cookie_manager_->AddGlobalChangeListener(std::move(mojo_listener));
}
}
void CookieManagerImpl::GetCookieList(
fidl::StringPtr url,
fidl::StringPtr name,
fidl::InterfaceRequest<fuchsia::web::CookiesIterator> iterator) {
EnsureCookieManager();
if (!url && !name) {
cookie_manager_->GetAllCookies(
base::BindOnce(&OnCookiesReceived, std::move(iterator)));
} else {
if (!name) {
// Include HTTP and 1st-party-only cookies in those returned.
net::CookieOptions options;
options.set_include_httponly();
options.set_same_site_cookie_context(
net::CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT);
cookie_manager_->GetCookieList(
GURL(*url), options,
base::BindOnce(&OnCookiesAndExcludedReceived, std::move(iterator)));
} else {
// TODO(858853): Support filtering by name.
iterator.Close(ZX_ERR_NOT_SUPPORTED);
}
}
}
void CookieManagerImpl::EnsureCookieManager() {
if (cookie_manager_.is_bound())
return;
get_network_context_.Run()->GetCookieManager(
mojo::MakeRequest(&cookie_manager_));
cookie_manager_.set_connection_error_handler(
base::BindOnce(&CookieManagerImpl::OnMojoError, base::Unretained(this)));
}
void CookieManagerImpl::OnMojoError() {
LOG(ERROR) << "NetworkService disconnected CookieManager.";
cookie_manager_.reset();
}
// Copyright 2019 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.
#ifndef FUCHSIA_ENGINE_BROWSER_COOKIE_MANAGER_IMPL_H_
#define FUCHSIA_ENGINE_BROWSER_COOKIE_MANAGER_IMPL_H_
#include <fuchsia/web/cpp/fidl.h>
#include "base/callback.h"
#include "base/macros.h"
#include "fuchsia/engine/web_engine_export.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
namespace network {
namespace mojom {
class NetworkContext;
} // namespace mojom
} // namespace network
class WEB_ENGINE_EXPORT CookieManagerImpl : public fuchsia::web::CookieManager {
public:
// Used to request the BrowserContext's CookieManager. Since the
// NetworkContext may change, e.g. if the NetworkService crashes, the returned
// pointer will be used immediately, and not cached by the CookieManagerImpl.
using GetNetworkContextCallback =
base::RepeatingCallback<network::mojom::NetworkContext*()>;
// |get_network_context| will be called to (re)connect to CookieManager,
// on-demand, in response to query/observation requests.
explicit CookieManagerImpl(GetNetworkContextCallback get_network_context);
~CookieManagerImpl() final;
// fuchsia::web::CookieManager implementation:
void ObserveCookieChanges(
fidl::StringPtr url,
fidl::StringPtr name,
fidl::InterfaceRequest<fuchsia::web::CookiesIterator> changes) final;
void GetCookieList(
fidl::StringPtr url,
fidl::StringPtr name,
fidl::InterfaceRequest<fuchsia::web::CookiesIterator> cookies) final;
private:
// (Re)connects |cookie_manager_| if not currently connected.
void EnsureCookieManager();
// Handles errors on the |cookie_manager_| Mojo channel.
void OnMojoError();
const GetNetworkContextCallback get_network_context_;
network::mojom::CookieManagerPtr cookie_manager_;
DISALLOW_COPY_AND_ASSIGN(CookieManagerImpl);
};
#endif // FUCHSIA_ENGINE_BROWSER_COOKIE_MANAGER_IMPL_H_
This diff is collapsed.
...@@ -2,5 +2,6 @@ include_rules = [ ...@@ -2,5 +2,6 @@ include_rules = [
"+content/public/browser", "+content/public/browser",
"+content/public/common", "+content/public/common",
"+content/public/test", "+content/public/test",
"+mojo/core/embedder",
"+ui/ozone/public", "+ui/ozone/public",
] ]
// Copyright 2019 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 "base/bind.h"
#include "base/test/launcher/unit_test_launcher.h"
#include "base/test/test_suite.h"
#include "mojo/core/embedder/embedder.h"
int main(int argc, char** argv) {
base::TestSuite test_suite(argc, argv);
mojo::core::Init();
return base::LaunchUnitTests(
argc, argv,
base::BindOnce(&base::TestSuite::Run, base::Unretained(&test_suite)));
}
...@@ -119,20 +119,27 @@ void CookieManager::DeleteCookies(mojom::CookieDeletionFilterPtr filter, ...@@ -119,20 +119,27 @@ void CookieManager::DeleteCookies(mojom::CookieDeletionFilterPtr filter,
void CookieManager::AddCookieChangeListener( void CookieManager::AddCookieChangeListener(
const GURL& url, const GURL& url,
const std::string& name, const base::Optional<std::string>& name,
mojom::CookieChangeListenerPtr listener) { mojom::CookieChangeListenerPtr listener) {
auto listener_registration = std::make_unique<ListenerRegistration>(); auto listener_registration = std::make_unique<ListenerRegistration>();
listener_registration->listener = std::move(listener); listener_registration->listener = std::move(listener);
listener_registration->subscription = auto cookie_change_callback = base::BindRepeating(
cookie_store_->GetChangeDispatcher().AddCallbackForCookie( &CookieManager::ListenerRegistration::DispatchCookieStoreChange,
url, name, // base::Unretained is safe as destruction of the
base::BindRepeating( // ListenerRegistration will also destroy the
&CookieManager::ListenerRegistration::DispatchCookieStoreChange, // CookieChangedSubscription, unregistering the callback.
// base::Unretained is safe as destruction of the base::Unretained(listener_registration.get()));
// ListenerRegistration will also destroy the
// CookieChangedSubscription, unregistering the callback. if (name) {
base::Unretained(listener_registration.get()))); listener_registration->subscription =
cookie_store_->GetChangeDispatcher().AddCallbackForCookie(
url, *name, std::move(cookie_change_callback));
} else {
listener_registration->subscription =
cookie_store_->GetChangeDispatcher().AddCallbackForUrl(
url, std::move(cookie_change_callback));
}
listener_registration->listener.set_connection_error_handler( listener_registration->listener.set_connection_error_handler(
base::BindOnce(&CookieManager::RemoveChangeListener, base::BindOnce(&CookieManager::RemoveChangeListener,
......
...@@ -69,7 +69,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CookieManager ...@@ -69,7 +69,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CookieManager
DeleteCookiesCallback callback) override; DeleteCookiesCallback callback) override;
void AddCookieChangeListener( void AddCookieChangeListener(
const GURL& url, const GURL& url,
const std::string& name, const base::Optional<std::string>& name,
mojom::CookieChangeListenerPtr listener) override; mojom::CookieChangeListenerPtr listener) override;
void AddGlobalChangeListener( void AddGlobalChangeListener(
mojom::CookieChangeListenerPtr listener) override; mojom::CookieChangeListenerPtr listener) override;
......
...@@ -257,13 +257,15 @@ interface CookieManager { ...@@ -257,13 +257,15 @@ interface CookieManager {
// information about the tracked cookie, to make sure that a change to the // information about the tracked cookie, to make sure that a change to the
// cookie did not happen right before the listener was registered. // cookie did not happen right before the listener was registered.
// //
// If |name| is omitted then changes are returned for all cookies for |url|.
//
// TODO(rdsmith): Should this have a filter to register for a lot of // TODO(rdsmith): Should this have a filter to register for a lot of
// notifications at once? Maybe combine with the deletion filter? // notifications at once? Maybe combine with the deletion filter?
// TODO(rdsmith): Describe the performance implications of using this meethod. // TODO(rdsmith): Describe the performance implications of using this method.
// The comments in CookieMonster::AddCallbackForCookie look pretty scary. // The comments in CookieMonster::AddCallbackForCookie look pretty scary.
AddCookieChangeListener( AddCookieChangeListener(
url.mojom.Url url, url.mojom.Url url,
string name, string? name,
CookieChangeListener listener); CookieChangeListener listener);
// Subscribes the given listener to changes to this CookieManager's cookies. // Subscribes the given listener to changes to this CookieManager's cookies.
......
...@@ -28,7 +28,7 @@ void TestCookieManager::SetCanonicalCookie( ...@@ -28,7 +28,7 @@ void TestCookieManager::SetCanonicalCookie(
void TestCookieManager::AddCookieChangeListener( void TestCookieManager::AddCookieChangeListener(
const GURL& url, const GURL& url,
const std::string& name, const base::Optional<std::string>& name,
network::mojom::CookieChangeListenerPtr listener) { network::mojom::CookieChangeListenerPtr listener) {
cookie_change_listeners_.push_back(std::move(listener)); cookie_change_listeners_.push_back(std::move(listener));
} }
......
...@@ -35,7 +35,7 @@ class TestCookieManager : public network::mojom::CookieManager { ...@@ -35,7 +35,7 @@ class TestCookieManager : public network::mojom::CookieManager {
DeleteCookiesCallback callback) override {} DeleteCookiesCallback callback) override {}
void AddCookieChangeListener( void AddCookieChangeListener(
const GURL& url, const GURL& url,
const std::string& name, const base::Optional<std::string>& name,
network::mojom::CookieChangeListenerPtr listener) override; network::mojom::CookieChangeListenerPtr listener) override;
void AddGlobalChangeListener( void AddGlobalChangeListener(
network::mojom::CookieChangeListenerPtr notification_pointer) override {} network::mojom::CookieChangeListenerPtr notification_pointer) override {}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment