Commit 940d7dfd authored by Kyle Horimoto's avatar Kyle Horimoto Committed by Commit Bot

[CrOS MultiDevice] Create a skeleton MultiDeviceSetup service.

See go/unified-better-together-cros for an outline of this service.

This CL does the following:
(1) Creates a Mojo interface for the service, adding only a single
    function for now.
(2) Creates the MultiDeviceSetupService and MultiDeviceSetupImpl classes
    which implement this interface, as well as a test for the service.
(3) Registers the service in the browser process via ProfileImpl.
(4) Generates JavaScript files for the interface; because these files
    are the first resources generated in //chromeos, this CL also adds a
    new chromeos_resources.grd.
(5) Adds the new "multidevice_setup" capability to the content_browser
    manifest file so that it can be used by content_renderer.
(6) Adds a new button on the chrome://proximity-auth debug WebUI page
    which makes a Mojo call to the service.

Change-Id: I0b74373b78a1c92fe01d789028342707321c2134
Reviewed-on: https://chromium-review.googlesource.com/954010Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avataragrieve <agrieve@chromium.org>
Reviewed-by: default avataranthonyvd <anthonyvd@chromium.org>
Reviewed-by: default avatarKen Rockot <rockot@chromium.org>
Commit-Queue: Kyle Horimoto <khorimoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#543894}
parent 0c1d42b7
......@@ -458,6 +458,9 @@ service_manifest("chrome_content_browser_manifest_overlay") {
if (enable_cros_assistant) {
packaged_services += [ "//chromeos/services/assistant:manifest" ]
}
if (is_chromeos) {
packaged_services += [ "//chromeos/services/multidevice_setup:manifest" ]
}
}
service_manifest("chrome_test_browser_overlay") {
......
......@@ -2852,6 +2852,8 @@ jumbo_split_static_library("browser") {
"//ash/components/quick_launch/public/mojom:constants",
"//ash/public/cpp",
"//chrome/browser/chromeos",
"//chromeos/services/multidevice_setup",
"//chromeos/services/multidevice_setup/public/mojom",
"//components/services/font:lib",
"//components/services/font/public/interfaces",
"//services/ui/public/cpp/input_devices",
......
......@@ -44,6 +44,7 @@
// Only used in classic ash case.
"local_state": [ "pref_client" ],
"media_gallery_util": [ "parse_media" ],
"multidevice_setup": [ "multidevice_setup" ],
"nacl_broker": [ "browser" ],
"nacl_loader": [ "browser" ],
"patch": [ "patch_file" ],
......@@ -97,7 +98,8 @@
"mojom::PluginsPageHandler",
"mojom::SiteEngagementDetailsProvider",
"mojom::UsbInternalsPageHandler"
]
],
"multidevice_setup" : [ "multidevice_setup::mojom::MultiDeviceSetup" ]
}
},
"navigation:dedicated_worker": {
......
......@@ -27,6 +27,9 @@
"safe_browsing::mojom::PhishingDetector",
"spellcheck::mojom::SpellCheckPanel"
]
},
"requires": {
"content_browser": [ "multidevice_setup" ]
}
}
}
......
......@@ -144,6 +144,9 @@
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h"
#include "chromeos/assistant/buildflags.h"
#include "chromeos/services/multidevice_setup/multidevice_setup_service.h"
#include "chromeos/services/multidevice_setup/public/mojom/constants.mojom.h"
#include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h"
#include "components/session_manager/core/session_manager.h"
#include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h"
......@@ -1120,6 +1123,17 @@ void ProfileImpl::RegisterInProcessServices(StaticServiceMap* services) {
std::make_pair(chromeos::assistant::mojom::kServiceName, info));
}
#endif
if (base::FeatureList::IsEnabled(features::kEnableUnifiedMultiDeviceSetup)) {
service_manager::EmbeddedServiceInfo info;
info.task_runner = base::ThreadTaskRunnerHandle::Get();
info.factory = base::BindRepeating([] {
return std::unique_ptr<service_manager::Service>(
std::make_unique<chromeos::multidevice::MultiDeviceSetupService>());
});
services->insert(
std::make_pair(multidevice_setup::mojom::kServiceName, info));
}
#endif
service_manager::EmbeddedServiceInfo identity_service_info;
......
......@@ -151,10 +151,12 @@ template("chrome_extra_paks") {
}
if (is_chromeos) {
sources += [
"$root_gen_dir/chromeos/chromeos_resources.pak",
"$root_gen_dir/components/chrome_apps/chrome_apps_resources.pak",
"$root_gen_dir/ui/file_manager/file_manager_resources.pak",
]
deps += [
"//chromeos/resources",
"//components/chrome_apps:resources",
"//ui/file_manager:resources",
]
......
......@@ -644,8 +644,8 @@ test("chromeos_unittests") {
":power_manager_proto",
":test_support",
":test_support_without_gmock",
"//base/test:run_all_unittests",
"//base/test:test_support",
"//chromeos/services:unit_tests",
"//components/onc",
"//components/prefs:test_support",
"//components/proxy_config",
......@@ -655,6 +655,7 @@ test("chromeos_unittests") {
"//dbus:test_support",
"//google_apis",
"//media/base:video_facing",
"//mojo/edk",
"//net",
"//net:test_support",
"//testing/gmock",
......@@ -736,6 +737,7 @@ test("chromeos_unittests") {
"printing/printer_translator_unittest.cc",
"process_proxy/process_output_watcher_unittest.cc",
"process_proxy/process_proxy_unittest.cc",
"run_all_unittests.cc",
"settings/timezone_settings_unittest.cc",
"system/cpu_temperature_reader_unittest.cc",
"system/name_value_pairs_parser_unittest.cc",
......
......@@ -10,6 +10,7 @@ include_rules = [
"+components/user_manager/known_user.h",
"+crypto",
"+media/base/video_facing.h",
"+mojo/edk/embedder/embedder.h",
"+net",
"+third_party/cros_system_api",
"+third_party/protobuf",
......
......@@ -16,7 +16,6 @@ test("chromeos_components_unittests") {
deps = [
"//base",
"//base/test:test_support",
"//chromeos/components/multidevice_setup:unit_tests",
"//chromeos/components/tether:unit_tests",
]
}
# Copyright 2018 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.
import("//tools/grit/grit_rule.gni")
assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos")
grit("resources") {
source = "chromeos_resources.grd"
source_is_generated = true
outputs = [
"grit/chromeos_resources.h",
"chromeos_resources.pak",
]
output_dir = "$root_gen_dir/chromeos"
grit_flags = [
"-E",
"mojom_root=" + rebase_path(root_gen_dir, root_build_dir),
]
deps = [
"//chromeos/services/multidevice_setup/public/mojom:mojom_js",
]
}
<?xml version="1.0" encoding="UTF-8"?>
<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
<outputs>
<output filename="grit/chromeos_resources.h" type="rc_header">
<emit emit_type='prepend'></emit>
</output>
<output filename="chromeos_resources.pak" type="data_package" />
</outputs>
<release seq="1">
<includes>
<include name="IDR_MULTIDEVICE_SETUP_MOJOM_JS"
file="${mojom_root}/chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.js"
use_base_dir="false"
type="BINDATA" />
<include name="IDR_MULTIDEVICE_SETUP_CONSTANTS_MOJOM_JS"
file="${mojom_root}/chromeos/services/multidevice_setup/public/mojom/constants.mojom.js"
use_base_dir="false"
type="BINDATA" />
</includes>
</release>
</grit>
// Copyright 2018 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/edk/embedder/embedder.h"
int main(int argc, char** argv) {
// Some unit tests make Mojo calls.
mojo::edk::Init();
base::TestSuite test_suite(argc, argv);
return base::LaunchUnitTests(
argc, argv,
base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite)));
}
......@@ -8,14 +8,29 @@ import("//services/catalog/public/tools/catalog.gni")
import("//services/service_manager/public/tools/test/service_test.gni")
import("//testing/test.gni")
# This is modeled after //services:services_unittests
# One Big Target for services to register their unit test sources. This exists
# to avoid having to maintain a separate test binary for every service.
assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos")
# Use this target for adding new unit tests. To add a unit test to this target,
# create a "unit_tests" source_set in your service and add it as a dependency
# here.
#
# Unit tests are generally preferred over service tests as they are simpler to
# create and maintain. Check out service_manager::TestConnectorFactory for an
# easy way to test your services.
source_set("unit_tests") {
testonly = true
deps = [
"//chromeos/services/multidevice_setup:unit_tests",
]
}
# Use this target for adding new service tests. To add a unit test to this
# target, create a "tests" source_set in your service and add it as a dependency
# here.
#
# To add tests for a new service, please define a "tests" source_set in the
# service subdirectory and add it as a dependency here. If your unit tests
# use the ServiceTest framework, you must also include corresponding catalog
# entries in the "chromeos_services_unittests_catalog" target below.
# If your unit tests use the ServiceTest framework, you must also include
# corresponding catalog entries in the "chromeos_services_unittests_catalog"
# target below.
service_test("chromeos_services_unittests") {
deps = []
......
......@@ -2,27 +2,49 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//services/service_manager/public/cpp/service.gni")
import("//services/service_manager/public/service_manifest.gni")
import("//services/service_manager/public/tools/test/service_test.gni")
assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos")
static_library("multidevice_setup") {
sources = []
sources = [
"multidevice_setup_impl.cc",
"multidevice_setup_impl.h",
"multidevice_setup_service.cc",
"multidevice_setup_service.h",
]
deps = [
"//base",
"//chromeos/services/multidevice_setup/public/mojom",
"//components/proximity_auth/logging",
"//services/service_manager/public/cpp",
]
}
service_manifest("manifest") {
name = "multidevice_setup"
source = "manifest.json"
}
static_library("test_support") {
testonly = true
sources = []
sources = [
"fake_multidevice_setup_observer.cc",
"fake_multidevice_setup_observer.h",
]
public_deps = [
":multidevice_setup",
]
deps = [
":multidevice_setup",
"//base",
"//chromeos/services/multidevice_setup/public/mojom",
"//testing/gmock",
"//testing/gtest",
]
......@@ -31,12 +53,16 @@ static_library("test_support") {
source_set("unit_tests") {
testonly = true
sources = []
sources = [
"multidevice_setup_service_unittest.cc",
]
deps = [
":multidevice_setup",
":test_support",
"//base/test:test_support",
"//chromeos/services/multidevice_setup/public/mojom",
"//services/service_manager/public/cpp/test:test_support",
"//testing/gmock",
"//testing/gtest",
]
......
include_rules = [
"+components/proximity_auth/logging/logging.h",
"+mojo/public/cpp/bindings/binding_set.h",
"+services/service_manager/public",
]
khorimoto@chromium.org
jlklein@chromium.org
per-file manifest.json=set noparent
per-file manifest.json=file://ipc/SECURITY_OWNERS
# COMPONENT: UI>ProximityAuth
// Copyright 2018 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 "chromeos/services/multidevice_setup/fake_multidevice_setup_observer.h"
namespace chromeos {
namespace multidevice {
FakeMultiDeviceSetupObserver::FakeMultiDeviceSetupObserver() = default;
FakeMultiDeviceSetupObserver::~FakeMultiDeviceSetupObserver() = default;
multidevice_setup::mojom::MultiDeviceSetupObserverPtr
FakeMultiDeviceSetupObserver::GenerateInterfacePtr() {
multidevice_setup::mojom::MultiDeviceSetupObserverPtr interface_ptr;
bindings_.AddBinding(this, mojo::MakeRequest(&interface_ptr));
return interface_ptr;
}
void FakeMultiDeviceSetupObserver::OnPotentialHostExistsForNewUser() {
++num_new_user_events_handled_;
}
void FakeMultiDeviceSetupObserver::OnConnectedHostSwitchedForExistingUser() {
++num_existing_user_host_switched_events_handled_;
}
void FakeMultiDeviceSetupObserver::OnNewChromebookAddedForExistingUser() {
++num_existing_user_chromebook_added_events_handled_;
}
} // namespace multidevice
} // namespace chromeos
// Copyright 2018 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 CHROMEOS_SERVICES_MULTIDEVICE_SETUP_FAKE_MULTIDEVICE_SETUP_OBSERVER_H_
#define CHROMEOS_SERVICES_MULTIDEVICE_SETUP_FAKE_MULTIDEVICE_SETUP_OBSERVER_H_
#include "base/macros.h"
#include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h"
#include "mojo/public/cpp/bindings/binding_set.h"
namespace chromeos {
namespace multidevice {
// Fake MultiDeviceSetupObserver implementation for tests.
class FakeMultiDeviceSetupObserver
: public multidevice_setup::mojom::MultiDeviceSetupObserver {
public:
FakeMultiDeviceSetupObserver();
~FakeMultiDeviceSetupObserver() override;
multidevice_setup::mojom::MultiDeviceSetupObserverPtr GenerateInterfacePtr();
size_t num_new_user_events_handled() { return num_new_user_events_handled_; }
size_t num_existing_user_host_switched_events_handled() {
return num_existing_user_host_switched_events_handled_;
}
size_t num_existing_user_chromebook_added_events_handled() {
return num_existing_user_chromebook_added_events_handled_;
}
// multidevice_setup::mojom::MultiDeviceSetupObserver:
void OnPotentialHostExistsForNewUser() override;
void OnConnectedHostSwitchedForExistingUser() override;
void OnNewChromebookAddedForExistingUser() override;
private:
size_t num_new_user_events_handled_ = 0u;
size_t num_existing_user_host_switched_events_handled_ = 0u;
size_t num_existing_user_chromebook_added_events_handled_ = 0u;
mojo::BindingSet<multidevice_setup::mojom::MultiDeviceSetupObserver>
bindings_;
DISALLOW_COPY_AND_ASSIGN(FakeMultiDeviceSetupObserver);
};
} // namespace multidevice
} // namespace chromeos
#endif // CHROMEOS_SERVICES_MULTIDEVICE_SETUP_FAKE_MULTIDEVICE_SETUP_OBSERVER_H_
{
"name": "multidevice_setup",
"display_name": "MultiDevice Setup Service",
"interface_provider_specs": {
"service_manager:connector": {
"provides": {
"multidevice_setup" : [ "multidevice_setup::mojom::MultiDeviceSetup" ]
}
}
}
}
// Copyright 2018 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 "chromeos/services/multidevice_setup/multidevice_setup_impl.h"
#include "components/proximity_auth/logging/logging.h"
namespace chromeos {
namespace multidevice {
namespace {
using EventType = multidevice_setup::mojom::EventTypeForDebugging;
std::string EventTypeEnumToString(EventType type) {
switch (type) {
case EventType::kNewUserPotentialHostExists:
return "kNewUserPotentialHostExists";
case EventType::kExistingUserConnectedHostSwitched:
return "kExistingUserConnectedHostSwitched";
case EventType::kExistingUserNewChromebookAdded:
return "kExistingUserNewChromebookAdded";
default:
NOTREACHED();
return "[invalid input]";
}
}
} // namespace
MultiDeviceSetupImpl::MultiDeviceSetupImpl() = default;
MultiDeviceSetupImpl::~MultiDeviceSetupImpl() = default;
void MultiDeviceSetupImpl::BindRequest(
multidevice_setup::mojom::MultiDeviceSetupRequest request) {
bindings_.AddBinding(this, std::move(request));
}
void MultiDeviceSetupImpl::SetObserver(
multidevice_setup::mojom::MultiDeviceSetupObserverPtr observer,
SetObserverCallback callback) {
if (observer_.is_bound()) {
PA_LOG(ERROR) << "SetObserver() called when a MultiDeviceSetupObserver was "
<< "already set. Replacing the previously-set "
<< "MultiDeviceSetupObserver.";
}
PA_LOG(INFO) << "MultiDeviceSetupImpl::SetObserver()";
observer_ = std::move(observer);
std::move(callback).Run();
}
void MultiDeviceSetupImpl::TriggerEventForDebugging(
EventType type,
TriggerEventForDebuggingCallback callback) {
PA_LOG(INFO) << "TriggerEventForDebugging(" << EventTypeEnumToString(type)
<< ") called.";
if (!observer_.is_bound()) {
PA_LOG(ERROR) << "No MultiDeviceSetupObserver has been set. Cannot "
<< "proceed.";
std::move(callback).Run(false /* success */);
return;
}
switch (type) {
case EventType::kNewUserPotentialHostExists:
observer_->OnPotentialHostExistsForNewUser();
break;
case EventType::kExistingUserConnectedHostSwitched:
observer_->OnConnectedHostSwitchedForExistingUser();
break;
case EventType::kExistingUserNewChromebookAdded:
observer_->OnNewChromebookAddedForExistingUser();
break;
default:
NOTREACHED();
}
std::move(callback).Run(true /* success */);
}
} // namespace multidevice
} // namespace chromeos
// Copyright 2018 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 CHROMEOS_SERVICES_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_IMPL_H_
#define CHROMEOS_SERVICES_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_IMPL_H_
#include <memory>
#include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/cpp/service.h"
namespace chromeos {
namespace multidevice {
// Concrete MultiDeviceSetup implementation.
class MultiDeviceSetupImpl : public multidevice_setup::mojom::MultiDeviceSetup {
public:
MultiDeviceSetupImpl();
~MultiDeviceSetupImpl() override;
// Binds a request to this implementation. Should be called each time that the
// service receives a request.
void BindRequest(multidevice_setup::mojom::MultiDeviceSetupRequest request);
// multidevice_setup::mojom::MultiDeviceSetup:
void SetObserver(
multidevice_setup::mojom::MultiDeviceSetupObserverPtr presenter,
SetObserverCallback callback) override;
void TriggerEventForDebugging(
multidevice_setup::mojom::EventTypeForDebugging type,
TriggerEventForDebuggingCallback callback) override;
private:
multidevice_setup::mojom::MultiDeviceSetupObserverPtr observer_;
mojo::BindingSet<multidevice_setup::mojom::MultiDeviceSetup> bindings_;
DISALLOW_COPY_AND_ASSIGN(MultiDeviceSetupImpl);
};
} // namespace multidevice
} // namespace chromeos
#endif // CHROMEOS_SERVICES_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_IMPL_H_
// Copyright 2018 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 "chromeos/services/multidevice_setup/multidevice_setup_service.h"
#include "chromeos/services/multidevice_setup/multidevice_setup_impl.h"
#include "components/proximity_auth/logging/logging.h"
namespace chromeos {
namespace multidevice {
MultiDeviceSetupService::MultiDeviceSetupService()
: multidevice_setup_impl_(std::make_unique<MultiDeviceSetupImpl>()) {}
MultiDeviceSetupService::~MultiDeviceSetupService() = default;
void MultiDeviceSetupService::OnStart() {
PA_LOG(INFO) << "MultiDeviceSetupService::OnStart()";
registry_.AddInterface(base::Bind(&MultiDeviceSetupService::BindRequest,
base::Unretained(this)));
}
void MultiDeviceSetupService::OnBindInterface(
const service_manager::BindSourceInfo& source_info,
const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) {
PA_LOG(INFO) << "MultiDeviceSetupService::OnBindInterface() from interface "
<< interface_name << ".";
registry_.BindInterface(interface_name, std::move(interface_pipe));
}
void MultiDeviceSetupService::BindRequest(
multidevice_setup::mojom::MultiDeviceSetupRequest request) {
multidevice_setup_impl_->BindRequest(std::move(request));
}
} // namespace multidevice
} // namespace chromeos
// Copyright 2018 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 CHROMEOS_SERVICES_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_SERVICE_H_
#define CHROMEOS_SERVICES_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_SERVICE_H_
#include <memory>
#include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/cpp/service.h"
namespace chromeos {
namespace multidevice {
class MultiDeviceSetupImpl;
// Service which provides an implementation for
// multidevice_setup::mojom::MultiDeviceSetup. This service creates one
// implementation and shares it among all connection requests.
class MultiDeviceSetupService : public service_manager::Service {
public:
MultiDeviceSetupService();
~MultiDeviceSetupService() override;
private:
// service_manager::Service:
void OnStart() override;
void OnBindInterface(const service_manager::BindSourceInfo& source_info,
const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) override;
void BindRequest(multidevice_setup::mojom::MultiDeviceSetupRequest request);
std::unique_ptr<MultiDeviceSetupImpl> multidevice_setup_impl_;
service_manager::BinderRegistry registry_;
DISALLOW_COPY_AND_ASSIGN(MultiDeviceSetupService);
};
} // namespace multidevice
} // namespace chromeos
#endif // CHROMEOS_SERVICES_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_SERVICE_H_
// Copyright 2018 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 <memory>
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
#include "chromeos/services/multidevice_setup/fake_multidevice_setup_observer.h"
#include "chromeos/services/multidevice_setup/multidevice_setup_service.h"
#include "chromeos/services/multidevice_setup/public/mojom/constants.mojom.h"
#include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h"
#include "services/service_manager/public/cpp/test/test_connector_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace multidevice {
using EventType = multidevice_setup::mojom::EventTypeForDebugging;
class MultiDeviceSetupServiceTest : public testing::Test {
protected:
MultiDeviceSetupServiceTest() = default;
~MultiDeviceSetupServiceTest() override = default;
void SetUp() override {
fake_multidevice_setup_observer_ =
std::make_unique<FakeMultiDeviceSetupObserver>();
connector_factory_ =
service_manager::TestConnectorFactory::CreateForUniqueService(
std::make_unique<MultiDeviceSetupService>());
}
multidevice_setup::mojom::MultiDeviceSetup* GetMultiDeviceSetup() {
if (!multidevice_setup_) {
EXPECT_EQ(nullptr, connector_);
// Create the Connector and bind it to |multidevice_setup_|.
connector_ = connector_factory_->CreateConnector();
connector_->BindInterface(multidevice_setup::mojom::kServiceName,
&multidevice_setup_);
// Set |fake_multidevice_setup_observer_|.
CallSetObserver();
}
return multidevice_setup_.get();
}
FakeMultiDeviceSetupObserver* fake_multidevice_setup_observer() {
return fake_multidevice_setup_observer_.get();
}
void CallSetObserver() {
base::RunLoop run_loop;
multidevice_setup_->SetObserver(
fake_multidevice_setup_observer_->GenerateInterfacePtr(),
base::BindRepeating(
&MultiDeviceSetupServiceTest::OnNotificationPresenterRegistered,
base::Unretained(this), run_loop.QuitClosure()));
run_loop.Run();
}
void CallTriggerEventForDebugging(EventType type) {
base::RunLoop run_loop;
GetMultiDeviceSetup()->TriggerEventForDebugging(
type, base::BindRepeating(
&MultiDeviceSetupServiceTest::OnNotificationTriggered,
base::Unretained(this), run_loop.QuitClosure()));
run_loop.Run();
}
private:
void OnNotificationPresenterRegistered(
const base::RepeatingClosure& quit_closure) {
quit_closure.Run();
}
void OnNotificationTriggered(const base::RepeatingClosure& quit_closure,
bool success) {
// NotificationPresenter is set in GetMultiDeviceSetup().
EXPECT_TRUE(success);
quit_closure.Run();
}
const base::test::ScopedTaskEnvironment scoped_task_environment_;
std::unique_ptr<service_manager::TestConnectorFactory> connector_factory_;
std::unique_ptr<service_manager::Connector> connector_;
std::unique_ptr<FakeMultiDeviceSetupObserver>
fake_multidevice_setup_observer_;
multidevice_setup::mojom::MultiDeviceSetupPtr multidevice_setup_;
DISALLOW_COPY_AND_ASSIGN(MultiDeviceSetupServiceTest);
};
TEST_F(MultiDeviceSetupServiceTest,
TriggerEventForDebugging_kNewUserPotentialHostExists) {
CallTriggerEventForDebugging(EventType::kNewUserPotentialHostExists);
EXPECT_EQ(1u,
fake_multidevice_setup_observer()->num_new_user_events_handled());
}
TEST_F(MultiDeviceSetupServiceTest,
TriggerEventForDebugging_kExistingUserConnectedHostSwitched) {
CallTriggerEventForDebugging(EventType::kExistingUserConnectedHostSwitched);
EXPECT_EQ(1u, fake_multidevice_setup_observer()
->num_existing_user_host_switched_events_handled());
}
TEST_F(MultiDeviceSetupServiceTest,
TriggerEventForDebugging_kExistingUserNewChromebookAdded) {
CallTriggerEventForDebugging(EventType::kExistingUserNewChromebookAdded);
EXPECT_EQ(1u, fake_multidevice_setup_observer()
->num_existing_user_chromebook_added_events_handled());
}
} // namespace multidevice
} // namespace chromeos
# Copyright 2018 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.
import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojom") {
sources = [
"constants.mojom",
"multidevice_setup.mojom",
]
}
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
// Copyright 2018 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.
module multidevice_setup.mojom;
const string kServiceName = "multidevice_setup";
// Copyright 2018 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.
module multidevice_setup.mojom;
// Handles events dispatched by MultiDeviceSetup.
interface MultiDeviceSetupObserver {
// Callback which indicates that one or more MultiDevice host phones are
// available for setup with the MultiDevice setup flow. This function is only
// called if the current user has not yet set up MultiDevice features.
OnPotentialHostExistsForNewUser();
// Callback which indicates that the currently-connected MultiDevice host has
// changed. This likely means that the user has changed MultiDevice settings
// on another device. This function is only called if the current user has
// already set up MultiDevice features.
OnConnectedHostSwitchedForExistingUser();
// Callback which indicates that a new Chromebook was added to the account of
// the current user. This function is only called if the current user has
// already set up MultiDevice features.
OnNewChromebookAddedForExistingUser();
};
// Enumeration of event types which can be dispatched. Only used for debugging
// purposes.
enum EventTypeForDebugging {
kNewUserPotentialHostExists,
kExistingUserConnectedHostSwitched,
kExistingUserNewChromebookAdded,
};
// Provides an API to the MultiDevice Setup flow. Designed to be exposed
// primarily to the MultiDevice setup flow at chrome://multidevice-setup (normal
// usage) as well as the ProximityAuth debug WebUI page at
// chrome://proximity-auth (debugging only).
// TODO(khorimoto): Finish fleshing out this interface.
interface MultiDeviceSetup {
// Registers the observer to be used by the service. Once this function has
// been called, the service will begin monitoring changes to synced devices
// and will notify |observer| when appropriate. Only one observer can be
// active at a time; calling this function a second time will remove the
// first observer added.
SetObserver(MultiDeviceSetupObserver observer) => ();
// Triggers an event to be dispatched by the service. This API function is
// intended to be used only for debugging in the chrome://proximity-auth page.
// During normal usage, events are triggered internally within the service.
TriggerEventForDebugging(EventTypeForDebugging type) => (bool success);
};
......@@ -19,6 +19,8 @@ static_library("webui") {
deps = [
"//base",
"//base:i18n",
"//chromeos/resources",
"//chromeos/services/multidevice_setup/public/mojom",
"//components/cryptauth",
"//components/prefs",
"//components/proximity_auth",
......@@ -27,5 +29,6 @@ static_library("webui") {
"//content/public/browser",
"//device/bluetooth",
"//ui/resources",
"//ui/webui",
]
}
include_rules = [
"+chromeos/grit/chromeos_resources.h",
"+chromeos/services/multidevice_setup/public/mojom",
"+content/public/browser",
"+components/grit/components_resources.h",
"+services/service_manager/public/cpp",
"+ui/webui",
]
......@@ -6,6 +6,8 @@
#include <memory>
#include "chromeos/grit/chromeos_resources.h"
#include "chromeos/services/multidevice_setup/public/mojom/constants.mojom.h"
#include "components/grit/components_resources.h"
#include "components/proximity_auth/webui/proximity_auth_webui_handler.h"
#include "components/proximity_auth/webui/url_constants.h"
......@@ -13,12 +15,14 @@
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "services/service_manager/public/cpp/connector.h"
namespace proximity_auth {
ProximityAuthUI::ProximityAuthUI(content::WebUI* web_ui,
ProximityAuthClient* delegate)
: content::WebUIController(web_ui) {
: ui::MojoWebUIController<multidevice_setup::mojom::MultiDeviceSetup>(
web_ui) {
content::WebUIDataSource* source =
content::WebUIDataSource::Create(kChromeUIProximityAuthHost);
source->SetDefaultResource(IDR_PROXIMITY_AUTH_INDEX_HTML);
......@@ -34,6 +38,14 @@ ProximityAuthUI::ProximityAuthUI(content::WebUI* web_ui,
source->AddResourcePath("pollux.html", IDR_PROXIMITY_AUTH_POLLUX_HTML);
source->AddResourcePath("pollux.css", IDR_PROXIMITY_AUTH_POLLUX_CSS);
source->AddResourcePath("pollux.js", IDR_PROXIMITY_AUTH_POLLUX_JS);
source->AddResourcePath(
"chromeos/services/multidevice_setup/public/mojom/"
"multidevice_setup.mojom.js",
IDR_MULTIDEVICE_SETUP_MOJOM_JS);
source->AddResourcePath(
"chromeos/services/multidevice_setup/public/mojom/"
"multidevice_setup_constants.mojom.js",
IDR_MULTIDEVICE_SETUP_CONSTANTS_MOJOM_JS);
content::BrowserContext* browser_context =
web_ui->GetWebContents()->GetBrowserContext();
......@@ -42,7 +54,17 @@ ProximityAuthUI::ProximityAuthUI(content::WebUI* web_ui,
std::make_unique<ProximityAuthWebUIHandler>(delegate));
}
ProximityAuthUI::~ProximityAuthUI() {
ProximityAuthUI::~ProximityAuthUI() = default;
void ProximityAuthUI::BindUIHandler(
multidevice_setup::mojom::MultiDeviceSetupRequest request) {
service_manager::Connector* connector =
content::BrowserContext::GetConnectorFor(
web_ui()->GetWebContents()->GetBrowserContext());
DCHECK(connector);
connector->BindInterface(multidevice_setup::mojom::kServiceName,
std::move(request));
}
} // namespace proximity_auth
......@@ -8,20 +8,28 @@
#include <string>
#include "base/macros.h"
#include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h"
#include "content/public/browser/web_ui_controller.h"
#include "ui/webui/mojo_web_ui_controller.h"
namespace proximity_auth {
class ProximityAuthClient;
// The WebUI controller for chrome://proximity-auth.
class ProximityAuthUI : public content::WebUIController {
class ProximityAuthUI : public ui::MojoWebUIController<
multidevice_setup::mojom::MultiDeviceSetup> {
public:
// Note: |web_ui| and |delegate| are not owned by this instance and must
// outlive this instance.
ProximityAuthUI(content::WebUI* web_ui, ProximityAuthClient* delegate);
~ProximityAuthUI() override;
protected:
// ui::MojoWebUIController overrides:
void BindUIHandler(
multidevice_setup::mojom::MultiDeviceSetupRequest request) override;
private:
DISALLOW_COPY_AND_ASSIGN(ProximityAuthUI);
};
......
......@@ -8,9 +8,14 @@
<link href="common.css" rel="stylesheet">
<link href="proximity_auth.css" rel="stylesheet">
<script src='webui.js' type='text/javascript'></script>
<script src='logs.js' type='text/javascript'></script>
<script src='proximity_auth.js' type='text/javascript'></script>
<script src="webui.js"></script>
<script src="logs.js"></script>
<script src="proximity_auth.js"></script>
<script src="chrome://resources/js/mojo_bindings.js"></script>
<script src="chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.js">
</script>
<script src="chromeos/services/multidevice_setup/public/mojom/multidevice_setup_constants.mojom.js">
</script>
</head>
<body>
......@@ -29,6 +34,7 @@
<td>DEVICE ID (truncated)</td>
<td colspan="2" id='local-device-id'>----</td>
</tr>
<tr><td id='enrollment-title' state='synced'>ENROLLMENT</td></tr>
<tr class='subrow'>
<td>Last Success</td>
......@@ -54,6 +60,27 @@
<tr class='subrow'>
<td><button id='force-device-sync'>Sync</button></td>
</tr>
<tr>
<td>MULTIDEVICE NOTIFICATIONS</td>
</tr>
<tr class='subrow'>
<td><button id='show-new-user-notif'>New User</button></td>
</tr>
<tr class='subrow'>
<td>
<button id='show-existing-user-new-host-notif'>
Existing User (new host)
</button>
</td>
</tr>
<tr class='subrow'>
<td>
<button id='show-existing-user-new-chromebook-notif'>
Existing User (new Chromebook)
</button>
</td>
</tr>
</table>
</div>
......
......@@ -37,10 +37,26 @@ class CryptAuthController {
lastDeviceSync: document.getElementById('last-device-sync'),
nextDeviceSync: document.getElementById('next-device-sync'),
deviceSyncButton: document.getElementById('force-device-sync'),
newUserNotifButton: document.getElementById('show-new-user-notif'),
existingUserNewHostNotifButton:
document.getElementById('show-existing-user-new-host-notif'),
existingUserNewChromebookNotifButton:
document.getElementById('show-existing-user-new-chromebook-notif'),
};
this.elements_.enrollmentButton.onclick = this.forceEnrollment_.bind(this);
this.elements_.deviceSyncButton.onclick = this.forceDeviceSync_.bind(this);
this.elements_.newUserNotifButton.onclick =
this.showNewUserNotification_.bind(this);
this.elements_.existingUserNewHostNotifButton.onclick =
this.showExistingUserNewHostNotification_.bind(this);
this.elements_.existingUserNewChromebookNotifButton.onclick =
this.showExistingUserNewChromebookNotification_.bind(this);
this.multiDeviceSetup = new multideviceSetup.mojom.MultiDeviceSetupPtr();
Mojo.bindInterface(
multideviceSetup.mojom.MultiDeviceSetup.name,
mojo.makeRequest(this.multiDeviceSetup).handle);
}
/**
......@@ -136,6 +152,51 @@ class CryptAuthController {
forceDeviceSync_() {
WebUI.forceDeviceSync();
}
/**
* Shows the "new user, potential host exists" notification.
*/
showNewUserNotification_() {
this.showMultiDeviceSetupPromoNotification_(
multideviceSetup.mojom.EventTypeForDebugging.
kNewUserPotentialHostExists);
}
/**
* Shows the "existing user, new host" notification.
*/
showExistingUserNewHostNotification_() {
this.showMultiDeviceSetupPromoNotification_(
multideviceSetup.mojom.EventTypeForDebugging.
kExistingUserConnectedHostSwitched);
}
/**
* Shows the "existing user, new Chromebook" notification.
*/
showExistingUserNewChromebookNotification_() {
this.showMultiDeviceSetupPromoNotification_(
multideviceSetup.mojom.EventTypeForDebugging.
kExistingUserNewChromebookAdded);
}
/**
* Shows a "MultiDevice Setup" notification of the given type.
*/
showMultiDeviceSetupPromoNotification_(type) {
this.multiDeviceSetup.triggerEventForDebugging(type).then(
function(responseParams) {
if (responseParams.success) {
console.log('Successfully triggered notification for type ' +
type + '.');
} else {
console.error('Failed to trigger notification for type ' + type +
'; no NotificationPresenter has been registered.');
}
}).catch(function(error) {
console.error('Failed to trigger notification type. ' + error);
});
}
};
/**
......
......@@ -141,6 +141,12 @@
},
# END chrome/ miscellaneous section.
# START chromeos/ section.
"chromeos/resources/chromeos_resources.grd": {
"includes": [14000],
},
# END chromeos/ section.
# START components/ section.
"components/autofill/android/autofill_strings.grd": {
"messages": [15000],
......
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