forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor Blink's ServiceConnector and add ability to mock in layout t…
…ests This CL refactors the implementation of Blink's ServiceConnector so that layout tests can mock remote interfaces of arbitrary services in JS. Specifically, it changes the organization to be roughly parallel to Platform::interfaceProvider(). - Blink has a Connector interface. - Platform has a connector() method. - //content/renderer has a BlinkConnectorImpl backed directly by //content/renderer's Connector. - BlinkConnectorImpl also has the ability to override interfaces with local implementations, similar to service_manager::InterfaceProvider. - We add a JS wrapper of BlinkConnectorImpl to expose that ability to JS. Review-Url: https://codereview.chromium.org/2643063002 Cr-Commit-Position: refs/heads/master@{#459064}
- Loading branch information
1 parent
70fc37e
commit 43dd7b3
Showing
22 changed files
with
620 additions
and
123 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// Copyright 2017 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/renderer/mojo/blink_connector_impl.h" | ||
|
||
#include <utility> | ||
|
||
#include "base/bind.h" | ||
#include "base/single_thread_task_runner.h" | ||
#include "base/threading/thread_task_runner_handle.h" | ||
#include "services/service_manager/public/cpp/identity.h" | ||
#include "services/service_manager/public/cpp/interface_provider.h" | ||
|
||
namespace content { | ||
|
||
BlinkConnectorImpl::BlinkConnectorImpl( | ||
std::unique_ptr<service_manager::Connector> connector) | ||
: connector_(std::move(connector)), | ||
main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()), | ||
weak_ptr_factory_(this) {} | ||
|
||
BlinkConnectorImpl::~BlinkConnectorImpl() = default; | ||
|
||
void BlinkConnectorImpl::bindInterface(const char* service_name, | ||
const char* interface_name, | ||
mojo::ScopedMessagePipeHandle handle) { | ||
// |connector_| is null in some testing contexts. | ||
if (!connector_) | ||
return; | ||
|
||
if (!main_thread_task_runner_->BelongsToCurrentThread()) { | ||
main_thread_task_runner_->PostTask( | ||
FROM_HERE, | ||
base::Bind(&BlinkConnectorImpl::bindInterface, GetWeakPtr(), | ||
service_name, interface_name, base::Passed(&handle))); | ||
return; | ||
} | ||
|
||
// Tests might have overridden this interface with a local implementation. | ||
InterfaceBinderMap* overrides_for_service = | ||
GetOverridesForService(service_name); | ||
if (overrides_for_service) { | ||
auto it = overrides_for_service->find(std::string(interface_name)); | ||
if (it != overrides_for_service->end()) { | ||
it->second.Run(std::move(handle)); | ||
return; | ||
} | ||
} | ||
|
||
service_manager::Identity service_identity( | ||
service_name, service_manager::mojom::kInheritUserID); | ||
connector_->BindInterface(service_identity, interface_name, | ||
std::move(handle)); | ||
} | ||
|
||
void BlinkConnectorImpl::AddOverrideForTesting( | ||
const std::string& service_name, | ||
const std::string& interface_name, | ||
const base::Callback<void(mojo::ScopedMessagePipeHandle)>& binder) { | ||
if (service_binders_.find(service_name) == service_binders_.end()) | ||
service_binders_[service_name] = base::MakeUnique<InterfaceBinderMap>(); | ||
|
||
(*(service_binders_[service_name]))[interface_name] = binder; | ||
} | ||
|
||
void BlinkConnectorImpl::ClearOverridesForTesting() { | ||
service_binders_.clear(); | ||
} | ||
|
||
base::WeakPtr<BlinkConnectorImpl> BlinkConnectorImpl::GetWeakPtr() { | ||
return weak_ptr_factory_.GetWeakPtr(); | ||
} | ||
|
||
BlinkConnectorImpl::InterfaceBinderMap* | ||
BlinkConnectorImpl::GetOverridesForService(const char* service_name) { | ||
// Short-circuit out in the case where there are no overrides (always true in | ||
// production). | ||
if (service_binders_.empty()) | ||
return nullptr; | ||
|
||
auto it = service_binders_.find(std::string(service_name)); | ||
|
||
if (it != service_binders_.end()) | ||
return it->second.get(); | ||
|
||
return nullptr; | ||
} | ||
|
||
} // namespace content |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// Copyright 2017 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 CONTENT_RENDERER_MOJO_BLINK_CONNECTOR_IMPL_H_ | ||
#define CONTENT_RENDERER_MOJO_BLINK_CONNECTOR_IMPL_H_ | ||
|
||
#include "base/macros.h" | ||
#include "base/memory/ref_counted.h" | ||
#include "base/memory/weak_ptr.h" | ||
#include "content/common/content_export.h" | ||
#include "mojo/public/cpp/system/message_pipe.h" | ||
#include "services/service_manager/public/cpp/connector.h" | ||
#include "third_party/WebKit/public/platform/Connector.h" | ||
|
||
namespace base { | ||
class SingleThreadTaskRunner; | ||
} | ||
|
||
namespace content { | ||
|
||
// An implementation of blink::Connector that forwards to a | ||
// service_manager::Connector. | ||
class CONTENT_EXPORT BlinkConnectorImpl : public blink::Connector { | ||
public: | ||
explicit BlinkConnectorImpl( | ||
std::unique_ptr<service_manager::Connector> connector); | ||
~BlinkConnectorImpl(); | ||
|
||
// blink::Connector override. | ||
void bindInterface(const char* service_name, | ||
const char* interface_name, | ||
mojo::ScopedMessagePipeHandle handle) override; | ||
|
||
void AddOverrideForTesting( | ||
const std::string& service_name, | ||
const std::string& interface_name, | ||
const base::Callback<void(mojo::ScopedMessagePipeHandle)>& binder); | ||
|
||
void ClearOverridesForTesting(); | ||
|
||
void SetConnector(std::unique_ptr<service_manager::Connector> connector) { | ||
connector_ = std::move(connector); | ||
} | ||
|
||
base::WeakPtr<BlinkConnectorImpl> GetWeakPtr(); | ||
|
||
private: | ||
using Binder = base::Callback<void(mojo::ScopedMessagePipeHandle)>; | ||
using InterfaceBinderMap = std::map<std::string, Binder>; | ||
using ServiceBinderMap = | ||
std::map<std::string, std::unique_ptr<InterfaceBinderMap>>; | ||
|
||
// Returns a pointer to the InterfaceBinderMap in action for |service_name|, | ||
// or nullptr if |service_name| has no overrides in action. | ||
InterfaceBinderMap* GetOverridesForService(const char* service_name); | ||
|
||
// Maps service names to the per-interface overrides that have been set for | ||
// that service. | ||
ServiceBinderMap service_binders_; | ||
|
||
std::unique_ptr<service_manager::Connector> connector_; | ||
|
||
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; | ||
|
||
base::WeakPtrFactory<BlinkConnectorImpl> weak_ptr_factory_; | ||
|
||
DISALLOW_COPY_AND_ASSIGN(BlinkConnectorImpl); | ||
}; | ||
|
||
} // namespace content | ||
|
||
#endif // CONTENT_RENDERER_MOJO_BLINK_CONNECTOR_IMPL_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
// Copyright 2017 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/renderer/mojo/blink_connector_impl.h" | ||
|
||
#include "base/macros.h" | ||
#include "base/memory/weak_ptr.h" | ||
#include "base/message_loop/message_loop.h" | ||
#include "services/service_manager/public/cpp/connector.h" | ||
#include "testing/gtest/include/gtest/gtest.h" | ||
|
||
namespace content { | ||
|
||
namespace { | ||
class MockConnector : public service_manager::Connector { | ||
public: | ||
MockConnector(int* foo_baz_impl_requests, int* bar_baz_impl_requests) | ||
: foo_baz_impl_requests_(foo_baz_impl_requests), | ||
bar_baz_impl_requests_(bar_baz_impl_requests), | ||
weak_factory_(this) {} | ||
|
||
// Connector: | ||
void StartService(const service_manager::Identity& identity, | ||
service_manager::mojom::ServicePtr service, | ||
service_manager::mojom::PIDReceiverRequest | ||
pid_receiver_request) override {} | ||
std::unique_ptr<service_manager::Connection> Connect( | ||
const std::string& name) override { | ||
return nullptr; | ||
} | ||
std::unique_ptr<service_manager::Connection> Connect( | ||
const service_manager::Identity& target) override { | ||
return nullptr; | ||
} | ||
void BindInterface(const service_manager::Identity& target, | ||
const std::string& interface_name, | ||
mojo::ScopedMessagePipeHandle interface_pipe) override; | ||
std::unique_ptr<Connector> Clone() override { return nullptr; } | ||
void BindConnectorRequest( | ||
service_manager::mojom::ConnectorRequest request) override {} | ||
base::WeakPtr<Connector> GetWeakPtr() override { | ||
return weak_factory_.GetWeakPtr(); | ||
} | ||
|
||
protected: | ||
void OverrideBinderForTesting(const std::string& interface_name, | ||
const TestApi::Binder& binder) override {} | ||
void ClearBinderOverrides() override {} | ||
|
||
private: | ||
int* foo_baz_impl_requests_; | ||
int* bar_baz_impl_requests_; | ||
base::WeakPtrFactory<MockConnector> weak_factory_; | ||
}; | ||
|
||
void MockConnector::BindInterface( | ||
const service_manager::Identity& target, | ||
const std::string& interface_name, | ||
mojo::ScopedMessagePipeHandle interface_pipe) { | ||
if (target.name() == "foo" && interface_name == "baz") { | ||
(*foo_baz_impl_requests_)++; | ||
return; | ||
} | ||
|
||
if (target.name() == "bar" && interface_name == "baz") { | ||
(*bar_baz_impl_requests_)++; | ||
return; | ||
} | ||
|
||
NOTREACHED(); | ||
} | ||
|
||
} // namespace | ||
|
||
class BlinkConnectorImplTest : public testing::Test { | ||
public: | ||
BlinkConnectorImplTest() | ||
: foo_baz_impl_requests_(0), | ||
bar_baz_impl_requests_(0), | ||
foo_baz_override_requests_(0), | ||
bar_baz_override_requests_(0), | ||
connector_(base::MakeUnique<MockConnector>(&foo_baz_impl_requests_, | ||
&bar_baz_impl_requests_)) {} | ||
|
||
void OverrideFooBaz(mojo::ScopedMessagePipeHandle interface_pipe) { | ||
foo_baz_override_requests_++; | ||
} | ||
|
||
void OverrideBarBaz(mojo::ScopedMessagePipeHandle interface_pipe) { | ||
bar_baz_override_requests_++; | ||
} | ||
|
||
protected: | ||
BlinkConnectorImpl* connector() { return &connector_; } | ||
int foo_baz_impl_requests() { return foo_baz_impl_requests_; } | ||
int bar_baz_impl_requests() { return bar_baz_impl_requests_; } | ||
int foo_baz_override_requests() { return foo_baz_override_requests_; } | ||
int bar_baz_override_requests() { return bar_baz_override_requests_; } | ||
|
||
private: | ||
base::MessageLoop loop_; | ||
int foo_baz_impl_requests_; | ||
int bar_baz_impl_requests_; | ||
int foo_baz_override_requests_; | ||
int bar_baz_override_requests_; | ||
BlinkConnectorImpl connector_; | ||
|
||
DISALLOW_COPY_AND_ASSIGN(BlinkConnectorImplTest); | ||
}; | ||
|
||
TEST_F(BlinkConnectorImplTest, Basic) { | ||
EXPECT_EQ(0, foo_baz_impl_requests()); | ||
EXPECT_EQ(0, bar_baz_impl_requests()); | ||
|
||
mojo::MessagePipe pipe1; | ||
connector()->bindInterface("foo", "baz", std::move(pipe1.handle0)); | ||
EXPECT_EQ(1, foo_baz_impl_requests()); | ||
EXPECT_EQ(0, bar_baz_impl_requests()); | ||
|
||
mojo::MessagePipe pipe2; | ||
connector()->bindInterface("bar", "baz", std::move(pipe2.handle0)); | ||
EXPECT_EQ(1, foo_baz_impl_requests()); | ||
EXPECT_EQ(1, bar_baz_impl_requests()); | ||
} | ||
|
||
TEST_F(BlinkConnectorImplTest, Override) { | ||
EXPECT_EQ(0, foo_baz_impl_requests()); | ||
EXPECT_EQ(0, foo_baz_override_requests()); | ||
EXPECT_EQ(0, bar_baz_impl_requests()); | ||
|
||
connector()->AddOverrideForTesting( | ||
"foo", "baz", | ||
base::Bind(&BlinkConnectorImplTest::OverrideFooBaz, | ||
base::Unretained(this))); | ||
|
||
mojo::MessagePipe pipe1; | ||
connector()->bindInterface("foo", "baz", std::move(pipe1.handle0)); | ||
EXPECT_EQ(0, foo_baz_impl_requests()); | ||
EXPECT_EQ(1, foo_baz_override_requests()); | ||
EXPECT_EQ(0, bar_baz_impl_requests()); | ||
|
||
mojo::MessagePipe pipe2; | ||
connector()->bindInterface("bar", "baz", std::move(pipe2.handle0)); | ||
EXPECT_EQ(0, foo_baz_impl_requests()); | ||
EXPECT_EQ(1, foo_baz_override_requests()); | ||
EXPECT_EQ(1, bar_baz_impl_requests()); | ||
|
||
connector()->ClearOverridesForTesting(); | ||
|
||
mojo::MessagePipe pipe3; | ||
connector()->bindInterface("foo", "baz", std::move(pipe3.handle0)); | ||
EXPECT_EQ(1, foo_baz_impl_requests()); | ||
EXPECT_EQ(1, foo_baz_override_requests()); | ||
EXPECT_EQ(1, bar_baz_impl_requests()); | ||
} | ||
|
||
} // namespace content |
Oops, something went wrong.