summaryrefslogtreecommitdiff
path: root/chromium/components/arc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-01-29 16:35:13 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-02-01 15:33:35 +0000
commitc8c2d1901aec01e934adf561a9fdf0cc776cdef8 (patch)
tree9157c3d9815e5870799e070b113813bec53e0535 /chromium/components/arc
parentabefd5095b41dac94ca451d784ab6e27372e981a (diff)
downloadqtwebengine-chromium-c8c2d1901aec01e934adf561a9fdf0cc776cdef8.tar.gz
BASELINE: Update Chromium to 64.0.3282.139
Change-Id: I1cae68fe9c94ff7608b26b8382fc19862cdb293a Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/components/arc')
-rw-r--r--chromium/components/arc/BUILD.gn98
-rw-r--r--chromium/components/arc/DEPS3
-rw-r--r--chromium/components/arc/arc_bridge_host_impl.cc40
-rw-r--r--chromium/components/arc/arc_bridge_host_impl.h9
-rw-r--r--chromium/components/arc/arc_bridge_service.cc2
-rw-r--r--chromium/components/arc/arc_bridge_service.h231
-rw-r--r--chromium/components/arc/arc_data_remover_unittest.cc1
-rw-r--r--chromium/components/arc/arc_features.cc4
-rw-r--r--chromium/components/arc/arc_instance_mode.cc21
-rw-r--r--chromium/components/arc/arc_instance_mode.h4
-rw-r--r--chromium/components/arc/arc_prefs.cc8
-rw-r--r--chromium/components/arc/arc_prefs.h1
-rw-r--r--chromium/components/arc/arc_session.cc681
-rw-r--r--chromium/components/arc/arc_session.h31
-rw-r--r--chromium/components/arc/arc_session_impl.cc637
-rw-r--r--chromium/components/arc/arc_session_impl.h242
-rw-r--r--chromium/components/arc/arc_session_impl_unittest.cc648
-rw-r--r--chromium/components/arc/arc_session_runner.cc119
-rw-r--r--chromium/components/arc/arc_session_runner.h23
-rw-r--r--chromium/components/arc/arc_session_runner_unittest.cc164
-rw-r--r--chromium/components/arc/arc_stop_reason.h5
-rw-r--r--chromium/components/arc/arc_util.cc5
-rw-r--r--chromium/components/arc/arc_util_unittest.cc43
-rw-r--r--chromium/components/arc/audio/arc_audio_bridge.cc15
-rw-r--r--chromium/components/arc/audio/arc_audio_bridge.h13
-rw-r--r--chromium/components/arc/bluetooth/bluetooth_type_converters_unittest.cc616
-rw-r--r--chromium/components/arc/clipboard/arc_clipboard_bridge.cc14
-rw-r--r--chromium/components/arc/clipboard/arc_clipboard_bridge.h14
-rw-r--r--chromium/components/arc/common/BUILD.gn76
-rw-r--r--chromium/components/arc/common/DEPS3
-rw-r--r--chromium/components/arc/common/accessibility_helper.mojom50
-rw-r--r--chromium/components/arc/common/app.mojom59
-rw-r--r--chromium/components/arc/common/app.typemap15
-rw-r--r--chromium/components/arc/common/app_struct_traits.cc20
-rw-r--r--chromium/components/arc/common/app_struct_traits.h24
-rw-r--r--chromium/components/arc/common/arc_bridge.mojom8
-rw-r--r--chromium/components/arc/common/arc_gfx_struct_traits.cc28
-rw-r--r--chromium/components/arc/common/arc_gfx_struct_traits.h (renamed from chromium/components/arc/ime/arc_ime_struct_traits.h)17
-rw-r--r--chromium/components/arc/common/audio.mojom9
-rw-r--r--chromium/components/arc/common/auth.mojom9
-rw-r--r--chromium/components/arc/common/backup_settings.mojom16
-rw-r--r--chromium/components/arc/common/bluetooth.mojom10
-rw-r--r--chromium/components/arc/common/bluetooth.typemap3
-rw-r--r--chromium/components/arc/common/boot_phase_monitor.mojom9
-rw-r--r--chromium/components/arc/common/cert_store.mojom9
-rw-r--r--chromium/components/arc/common/clipboard.mojom13
-rw-r--r--chromium/components/arc/common/crash_collector.mojom10
-rw-r--r--chromium/components/arc/common/enterprise_reporting.mojom9
-rw-r--r--chromium/components/arc/common/file_system.mojom9
-rw-r--r--chromium/components/arc/common/file_system.typemap3
-rw-r--r--chromium/components/arc/common/gfx.mojom28
-rw-r--r--chromium/components/arc/common/gfx.typemap (renamed from chromium/components/arc/common/ime.typemap)15
-rw-r--r--chromium/components/arc/common/ime.mojom41
-rw-r--r--chromium/components/arc/common/intent_helper.mojom44
-rw-r--r--chromium/components/arc/common/kiosk.mojom11
-rw-r--r--chromium/components/arc/common/metrics.mojom10
-rw-r--r--chromium/components/arc/common/midis.mojom10
-rw-r--r--chromium/components/arc/common/net.mojom9
-rw-r--r--chromium/components/arc/common/notifications.mojom31
-rw-r--r--chromium/components/arc/common/obb_mounter.mojom10
-rw-r--r--chromium/components/arc/common/oemcrypto.mojom10
-rw-r--r--chromium/components/arc/common/oemcrypto_daemon.mojom2
-rw-r--r--chromium/components/arc/common/policy.mojom9
-rw-r--r--chromium/components/arc/common/power.mojom9
-rw-r--r--chromium/components/arc/common/print.mojom9
-rw-r--r--chromium/components/arc/common/protected_buffer_manager.mojom2
-rw-r--r--chromium/components/arc/common/screen_rect.mojom13
-rw-r--r--chromium/components/arc/common/tts.mojom9
-rw-r--r--chromium/components/arc/common/typemaps.gni4
-rw-r--r--chromium/components/arc/common/video.mojom14
-rw-r--r--chromium/components/arc/common/video_accelerator_struct_traits.cc (renamed from chromium/components/arc/video_accelerator/video_accelerator_struct_traits.cc)2
-rw-r--r--chromium/components/arc/common/video_accelerator_struct_traits.h (renamed from chromium/components/arc/video_accelerator/video_accelerator_struct_traits.h)8
-rw-r--r--chromium/components/arc/common/video_common.typemap10
-rw-r--r--chromium/components/arc/common/video_decode_accelerator.mojom10
-rw-r--r--chromium/components/arc/common/video_encode_accelerator.mojom15
-rw-r--r--chromium/components/arc/common/video_encode_accelerator.typemap7
-rw-r--r--chromium/components/arc/common/video_encode_accelerator_struct_traits.cc (renamed from chromium/components/arc/video_accelerator/video_encode_accelerator_struct_traits.cc)4
-rw-r--r--chromium/components/arc/common/video_encode_accelerator_struct_traits.h (renamed from chromium/components/arc/video_accelerator/video_encode_accelerator_struct_traits.h)6
-rw-r--r--chromium/components/arc/common/voice_interaction_arc_home.mojom23
-rw-r--r--chromium/components/arc/common/voice_interaction_framework.mojom31
-rw-r--r--chromium/components/arc/common/voice_interaction_framework.typemap13
-rw-r--r--chromium/components/arc/common/volume_mounter.typemap10
-rw-r--r--chromium/components/arc/common/wallpaper.mojom13
-rw-r--r--chromium/components/arc/connection_holder.h386
-rw-r--r--chromium/components/arc/connection_notifier.cc39
-rw-r--r--chromium/components/arc/connection_notifier.h43
-rw-r--r--chromium/components/arc/connection_observer.h38
-rw-r--r--chromium/components/arc/crash_collector/arc_crash_collector_bridge.cc15
-rw-r--r--chromium/components/arc/crash_collector/arc_crash_collector_bridge.h8
-rw-r--r--chromium/components/arc/ime/arc_ime_bridge_impl.cc22
-rw-r--r--chromium/components/arc/ime/arc_ime_bridge_impl.h18
-rw-r--r--chromium/components/arc/ime/arc_ime_service.cc8
-rw-r--r--chromium/components/arc/ime/arc_ime_service.h7
-rw-r--r--chromium/components/arc/ime/arc_ime_service_unittest.cc1
-rw-r--r--chromium/components/arc/ime/arc_ime_struct_traits.cc27
-rw-r--r--chromium/components/arc/instance_holder.h133
-rw-r--r--chromium/components/arc/intent_helper/DEPS1
-rw-r--r--chromium/components/arc/intent_helper/activity_icon_loader.cc32
-rw-r--r--chromium/components/arc/intent_helper/activity_icon_loader.h10
-rw-r--r--chromium/components/arc/intent_helper/activity_icon_loader_unittest.cc4
-rw-r--r--chromium/components/arc/intent_helper/arc_intent_helper_bridge.cc148
-rw-r--r--chromium/components/arc/intent_helper/arc_intent_helper_bridge.h26
-rw-r--r--chromium/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc178
-rw-r--r--chromium/components/arc/intent_helper/intent_filter.cc7
-rw-r--r--chromium/components/arc/intent_helper/link_handler_model.cc4
-rw-r--r--chromium/components/arc/lock_screen/arc_lock_screen_bridge.cc2
-rw-r--r--chromium/components/arc/lock_screen/arc_lock_screen_bridge.h8
-rw-r--r--chromium/components/arc/metrics/arc_metrics_service.cc92
-rw-r--r--chromium/components/arc/metrics/arc_metrics_service.h41
-rw-r--r--chromium/components/arc/metrics/arc_metrics_service_unittest.cc228
-rw-r--r--chromium/components/arc/midis/arc_midis_bridge.cc20
-rw-r--r--chromium/components/arc/midis/arc_midis_bridge.h7
-rw-r--r--chromium/components/arc/net/arc_net_host_impl.cc93
-rw-r--r--chromium/components/arc/net/arc_net_host_impl.h15
-rw-r--r--chromium/components/arc/obb_mounter/arc_obb_mounter_bridge.cc15
-rw-r--r--chromium/components/arc/obb_mounter/arc_obb_mounter_bridge.h8
-rw-r--r--chromium/components/arc/power/DEPS3
-rw-r--r--chromium/components/arc/power/arc_power_bridge.cc188
-rw-r--r--chromium/components/arc/power/arc_power_bridge.h52
-rw-r--r--chromium/components/arc/power/arc_power_bridge_unittest.cc235
-rw-r--r--chromium/components/arc/rotation_lock/arc_rotation_lock_bridge.cc16
-rw-r--r--chromium/components/arc/rotation_lock/arc_rotation_lock_bridge.h8
-rw-r--r--chromium/components/arc/storage_manager/arc_storage_manager.cc5
-rw-r--r--chromium/components/arc/storage_manager/arc_storage_manager.h4
-rw-r--r--chromium/components/arc/video_accelerator/BUILD.gn25
-rw-r--r--chromium/components/arc/video_accelerator/DEPS11
-rw-r--r--chromium/components/arc/video_accelerator/OWNERS7
-rw-r--r--chromium/components/arc/video_accelerator/arc_video_decode_accelerator.h182
-rw-r--r--chromium/components/arc/video_accelerator/chrome_arc_video_decode_accelerator.cc633
-rw-r--r--chromium/components/arc/video_accelerator/chrome_arc_video_decode_accelerator.h194
-rw-r--r--chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc269
-rw-r--r--chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h88
-rw-r--r--chromium/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc257
-rw-r--r--chromium/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h88
-rw-r--r--chromium/components/arc/video_accelerator/protected_buffer_manager.cc408
-rw-r--r--chromium/components/arc/video_accelerator/protected_buffer_manager.h143
-rw-r--r--chromium/components/arc/video_accelerator/protected_buffer_manager_proxy.cc51
-rw-r--r--chromium/components/arc/video_accelerator/protected_buffer_manager_proxy.h37
-rw-r--r--chromium/components/arc/video_accelerator/video_frame_plane.h (renamed from chromium/components/arc/video_accelerator/video_accelerator.h)8
-rw-r--r--chromium/components/arc/voice_interaction/OWNERS3
-rw-r--r--chromium/components/arc/voice_interaction/voice_interaction_struct_traits.h53
-rw-r--r--chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.cc2
-rw-r--r--chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.h8
143 files changed, 6962 insertions, 2243 deletions
diff --git a/chromium/components/arc/BUILD.gn b/chromium/components/arc/BUILD.gn
index 3785ffe4dbb..a4550c6f2a9 100644
--- a/chromium/components/arc/BUILD.gn
+++ b/chromium/components/arc/BUILD.gn
@@ -2,23 +2,18 @@
# 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")
import("//testing/test.gni")
static_library("arc") {
sources = [
"audio/arc_audio_bridge.cc",
"audio/arc_audio_bridge.h",
- "bluetooth/bluetooth_struct_traits.cc",
- "bluetooth/bluetooth_struct_traits.h",
"bluetooth/bluetooth_type_converters.cc",
"bluetooth/bluetooth_type_converters.h",
"clipboard/arc_clipboard_bridge.cc",
"clipboard/arc_clipboard_bridge.h",
"crash_collector/arc_crash_collector_bridge.cc",
"crash_collector/arc_crash_collector_bridge.h",
- "file_system/file_system_struct_traits.cc",
- "file_system/file_system_struct_traits.h",
"ime/arc_ime_bridge.h",
"ime/arc_ime_bridge_impl.cc",
"ime/arc_ime_bridge_impl.h",
@@ -55,8 +50,6 @@ static_library("arc") {
"rotation_lock/arc_rotation_lock_bridge.h",
"storage_manager/arc_storage_manager.cc",
"storage_manager/arc_storage_manager.h",
- "video_accelerator/video_accelerator_struct_traits.cc",
- "video_accelerator/video_accelerator_struct_traits.h",
"volume_mounter/arc_volume_mounter_bridge.cc",
"volume_mounter/arc_volume_mounter_bridge.h",
]
@@ -68,7 +61,7 @@ static_library("arc") {
deps = [
"//ash:ash",
- "//ash/public/cpp:ash_public_cpp",
+ "//ash/public/cpp",
"//base",
"//chromeos",
"//chromeos:login_manager_proto",
@@ -79,10 +72,13 @@ static_library("arc") {
"//components/prefs",
"//components/session_manager/core",
"//components/signin/core/account_id",
+ "//components/url_formatter",
"//components/user_manager",
+ "//content/public/common",
"//device/bluetooth",
"//google_apis",
"//mojo/edk/system",
+ "//services/device/public/interfaces",
"//skia",
"//third_party/re2:re2",
"//ui/aura",
@@ -129,16 +125,22 @@ static_library("arc_base") {
"arc_service_manager.h",
"arc_session.cc",
"arc_session.h",
+ "arc_session_impl.cc",
+ "arc_session_impl.h",
"arc_session_runner.cc",
"arc_session_runner.h",
"arc_stop_reason.cc",
"arc_stop_reason.h",
"arc_util.cc",
"arc_util.h",
- "instance_holder.h",
+ "connection_holder.h",
+ "connection_notifier.cc",
+ "connection_notifier.h",
+ "connection_observer.h",
]
deps = [
+ "//ash/public/cpp",
"//base",
"//chromeos",
"//components/keyed_service/content",
@@ -150,62 +152,8 @@ static_library("arc_base") {
]
public_deps = [
- ":arc_bindings",
":prefs",
- ]
-}
-
-mojom("arc_bindings") {
- sources = [
- "common/accessibility_helper.mojom",
- "common/app.mojom",
- "common/arc_bridge.mojom",
- "common/audio.mojom",
- "common/auth.mojom",
- "common/bitmap.mojom",
- "common/bluetooth.mojom",
- "common/boot_phase_monitor.mojom",
- "common/cast_receiver.mojom",
- "common/cert_store.mojom",
- "common/clipboard.mojom",
- "common/crash_collector.mojom",
- "common/enterprise_reporting.mojom",
- "common/file_system.mojom",
- "common/ime.mojom",
- "common/intent_helper.mojom",
- "common/kiosk.mojom",
- "common/lock_screen.mojom",
- "common/metrics.mojom",
- "common/midis.mojom",
- "common/net.mojom",
- "common/notifications.mojom",
- "common/obb_mounter.mojom",
- "common/oemcrypto.mojom",
- "common/oemcrypto_daemon.mojom",
- "common/policy.mojom",
- "common/power.mojom",
- "common/print.mojom",
- "common/process.mojom",
- "common/protected_buffer_manager.mojom",
- "common/rotation_lock.mojom",
- "common/scale_factor.mojom",
- "common/screen_rect.mojom",
- "common/storage_manager.mojom",
- "common/tracing.mojom",
- "common/tts.mojom",
- "common/video.mojom",
- "common/video_common.mojom",
- "common/video_decode_accelerator.mojom",
- "common/video_encode_accelerator.mojom",
- "common/voice_interaction_arc_home.mojom",
- "common/voice_interaction_framework.mojom",
- "common/volume_mounter.mojom",
- "common/wallpaper.mojom",
- ]
-
- public_deps = [
- "//mojo/common:common_custom_types",
- "//ui/gfx/geometry/mojo",
+ "//components/arc/common",
]
}
@@ -214,6 +162,8 @@ static_library("arc_test_support") {
sources = [
"test/fake_app_instance.cc",
"test/fake_app_instance.h",
+ "test/fake_arc_bridge_host.cc",
+ "test/fake_arc_bridge_host.h",
"test/fake_arc_session.cc",
"test/fake_arc_session.h",
"test/fake_bluetooth_instance.cc",
@@ -226,10 +176,14 @@ static_library("arc_test_support") {
"test/fake_notifications_instance.h",
"test/fake_policy_instance.cc",
"test/fake_policy_instance.h",
+ "test/fake_power_instance.cc",
+ "test/fake_power_instance.h",
"test/fake_voice_interaction_framework_instance.cc",
"test/fake_voice_interaction_framework_instance.h",
"test/fake_wallpaper_instance.cc",
"test/fake_wallpaper_instance.h",
+ "test/test_browser_context.cc",
+ "test/test_browser_context.h",
]
public_deps = [
@@ -238,6 +192,10 @@ static_library("arc_test_support") {
deps = [
"//base",
+ "//components/keyed_service/content",
+ "//components/prefs:test_support",
+ "//components/user_prefs",
+ "//content/test:test_support",
"//mojo/common:common_base",
"//mojo/edk/embedder:headers",
]
@@ -247,6 +205,7 @@ source_set("unit_tests") {
testonly = true
sources = [
"arc_data_remover_unittest.cc",
+ "arc_session_impl_unittest.cc",
"arc_session_runner_unittest.cc",
"arc_util_unittest.cc",
"bluetooth/bluetooth_struct_traits_unittest.cc",
@@ -258,21 +217,30 @@ source_set("unit_tests") {
"intent_helper/intent_filter_unittest.cc",
"intent_helper/link_handler_model_unittest.cc",
"intent_helper/page_transition_util_unittest.cc",
+ "metrics/arc_metrics_service_unittest.cc",
+ "power/arc_power_bridge_unittest.cc",
]
deps = [
":arc_test_support",
- "//ash/public/cpp:ash_public_cpp",
+ "//ash/public/cpp",
"//base",
"//base/test:test_support",
"//chromeos",
+ "//chromeos:power_manager_proto",
"//chromeos:test_support_without_gmock",
+ "//components/keyed_service/content",
"//components/prefs:test_support",
"//components/signin/core/account_id",
"//components/user_manager",
"//components/user_manager:test_support",
+ "//content/public/common",
+ "//content/test:test_support",
"//device/bluetooth",
"//mojo/public/cpp/system:system",
+ "//services/device/public/cpp/test:test_support",
+ "//services/device/public/interfaces:interfaces",
+ "//services/service_manager/public/cpp/test:test_support",
"//testing/gmock",
"//testing/gtest",
"//ui/aura",
diff --git a/chromium/components/arc/DEPS b/chromium/components/arc/DEPS
index cbf51bdb619..adc47438ce3 100644
--- a/chromium/components/arc/DEPS
+++ b/chromium/components/arc/DEPS
@@ -25,4 +25,7 @@ specific_include_rules = {
"arc_util_unittest.cc": [
"+ui/aura",
],
+ ".*_unittest.cc": [
+ "+content/public/test/test_browser_thread_bundle.h"
+ ]
}
diff --git a/chromium/components/arc/arc_bridge_host_impl.cc b/chromium/components/arc/arc_bridge_host_impl.cc
index 08101dbd975..a0f3b962b0b 100644
--- a/chromium/components/arc/arc_bridge_host_impl.cc
+++ b/chromium/components/arc/arc_bridge_host_impl.cc
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "components/arc/arc_bridge_service.h"
-#include "components/arc/instance_holder.h"
namespace arc {
@@ -30,24 +29,25 @@ namespace {
// The thin wrapper for InterfacePtr<T>, where T is one of ARC mojo Instance
// class.
-template <typename T>
+template <typename InstanceType, typename HostType>
class MojoChannelImpl : public ArcBridgeHostImpl::MojoChannel {
public:
- MojoChannelImpl(InstanceHolder<T>* holder, mojo::InterfacePtr<T> ptr)
+ MojoChannelImpl(ConnectionHolder<InstanceType, HostType>* holder,
+ mojo::InterfacePtr<InstanceType> ptr)
: holder_(holder), ptr_(std::move(ptr)) {
- // Delay registration to the InstanceHolder until the version is ready.
+ // Delay registration to the ConnectionHolder until the version is ready.
}
~MojoChannelImpl() override { holder_->SetInstance(nullptr, 0); }
- void set_connection_error_handler(const base::Closure& error_handler) {
- ptr_.set_connection_error_handler(error_handler);
+ void set_connection_error_handler(base::OnceClosure error_handler) {
+ ptr_.set_connection_error_handler(std::move(error_handler));
}
void QueryVersion() {
// Note: the callback will not be called if |ptr_| is destroyed.
- ptr_.QueryVersion(base::Bind(&MojoChannelImpl<T>::OnVersionReady,
- base::Unretained(this)));
+ ptr_.QueryVersion(
+ base::Bind(&MojoChannelImpl::OnVersionReady, base::Unretained(this)));
}
private:
@@ -56,11 +56,11 @@ class MojoChannelImpl : public ArcBridgeHostImpl::MojoChannel {
}
// Owned by ArcBridgeService.
- InstanceHolder<T>* const holder_;
+ ConnectionHolder<InstanceType, HostType>* const holder_;
// Put as a last member to ensure that any callback tied to the |ptr_|
// is not invoked.
- mojo::InterfacePtr<T> ptr_;
+ mojo::InterfacePtr<InstanceType> ptr_;
DISALLOW_COPY_AND_ASSIGN(MojoChannelImpl);
};
@@ -75,7 +75,7 @@ ArcBridgeHostImpl::ArcBridgeHostImpl(ArcBridgeService* arc_bridge_service,
DCHECK(arc_bridge_service_);
DCHECK(instance_.is_bound());
instance_.set_connection_error_handler(
- base::Bind(&ArcBridgeHostImpl::OnClosed, base::Unretained(this)));
+ base::BindOnce(&ArcBridgeHostImpl::OnClosed, base::Unretained(this)));
mojom::ArcBridgeHostPtr host_proxy;
binding_.Bind(mojo::MakeRequest(&host_proxy));
instance_->Init(std::move(host_proxy));
@@ -104,6 +104,12 @@ void ArcBridgeHostImpl::OnAuthInstanceReady(mojom::AuthInstancePtr auth_ptr) {
OnInstanceReady(arc_bridge_service_->auth(), std::move(auth_ptr));
}
+void ArcBridgeHostImpl::OnBackupSettingsInstanceReady(
+ mojom::BackupSettingsInstancePtr backup_settings_ptr) {
+ OnInstanceReady(arc_bridge_service_->backup_settings(),
+ std::move(backup_settings_ptr));
+}
+
void ArcBridgeHostImpl::OnBluetoothInstanceReady(
mojom::BluetoothInstancePtr bluetooth_ptr) {
OnInstanceReady(arc_bridge_service_->bluetooth(), std::move(bluetooth_ptr));
@@ -281,9 +287,10 @@ void ArcBridgeHostImpl::OnClosed() {
binding_.Close();
}
-template <typename T>
-void ArcBridgeHostImpl::OnInstanceReady(InstanceHolder<T>* holder,
- mojo::InterfacePtr<T> ptr) {
+template <typename InstanceType, typename HostType>
+void ArcBridgeHostImpl::OnInstanceReady(
+ ConnectionHolder<InstanceType, HostType>* holder,
+ mojo::InterfacePtr<InstanceType> ptr) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(binding_.is_bound());
DCHECK(ptr.is_bound());
@@ -291,13 +298,14 @@ void ArcBridgeHostImpl::OnInstanceReady(InstanceHolder<T>* holder,
// Track |channel|'s lifetime via |mojo_channels_| so that it will be
// closed on ArcBridgeHost/Instance closing or the ArcBridgeHostImpl's
// destruction.
- auto* channel = new MojoChannelImpl<T>(holder, std::move(ptr));
+ auto* channel =
+ new MojoChannelImpl<InstanceType, HostType>(holder, std::move(ptr));
mojo_channels_.emplace_back(channel);
// Since |channel| is managed by |mojo_channels_|, its lifetime is shorter
// than |this|. Thus, the connection error handler will be invoked only
// when |this| is alive and base::Unretained is safe here.
- channel->set_connection_error_handler(base::Bind(
+ channel->set_connection_error_handler(base::BindOnce(
&ArcBridgeHostImpl::OnChannelClosed, base::Unretained(this), channel));
// Call QueryVersion so that the version info is properly stored in the
diff --git a/chromium/components/arc/arc_bridge_host_impl.h b/chromium/components/arc/arc_bridge_host_impl.h
index d5695f7e405..604aedb252e 100644
--- a/chromium/components/arc/arc_bridge_host_impl.h
+++ b/chromium/components/arc/arc_bridge_host_impl.h
@@ -11,7 +11,7 @@
#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "components/arc/common/arc_bridge.mojom.h"
-#include "components/arc/instance_holder.h"
+#include "components/arc/connection_holder.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/interface_ptr.h"
@@ -43,6 +43,8 @@ class ArcBridgeHostImpl : public mojom::ArcBridgeHost {
void OnAppInstanceReady(mojom::AppInstancePtr app_ptr) override;
void OnAudioInstanceReady(mojom::AudioInstancePtr audio_ptr) override;
void OnAuthInstanceReady(mojom::AuthInstancePtr auth_ptr) override;
+ void OnBackupSettingsInstanceReady(
+ mojom::BackupSettingsInstancePtr backup_settings_ptr) override;
void OnBluetoothInstanceReady(
mojom::BluetoothInstancePtr bluetooth_ptr) override;
void OnBootPhaseMonitorInstanceReady(
@@ -101,8 +103,9 @@ class ArcBridgeHostImpl : public mojom::ArcBridgeHost {
// The common implementation to handle ArcBridgeHost overrides.
// |T| is a ARC Mojo Instance type.
- template <typename T>
- void OnInstanceReady(InstanceHolder<T>* holder, mojo::InterfacePtr<T> ptr);
+ template <typename InstanceType, typename HostType>
+ void OnInstanceReady(ConnectionHolder<InstanceType, HostType>* holder,
+ mojo::InterfacePtr<InstanceType> ptr);
// Called if one of the established channels is closed.
void OnChannelClosed(MojoChannel* channel);
diff --git a/chromium/components/arc/arc_bridge_service.cc b/chromium/components/arc/arc_bridge_service.cc
index e1ed78ac8a3..3c1b50402bf 100644
--- a/chromium/components/arc/arc_bridge_service.cc
+++ b/chromium/components/arc/arc_bridge_service.cc
@@ -4,6 +4,8 @@
#include "components/arc/arc_bridge_service.h"
+#include "components/arc/common/arc_bridge.mojom.h"
+
namespace arc {
ArcBridgeService::ArcBridgeService() = default;
diff --git a/chromium/components/arc/arc_bridge_service.h b/chromium/components/arc/arc_bridge_service.h
index f37e4fb5e66..50aef34ec23 100644
--- a/chromium/components/arc/arc_bridge_service.h
+++ b/chromium/components/arc/arc_bridge_service.h
@@ -6,7 +6,7 @@
#define COMPONENTS_ARC_ARC_BRIDGE_SERVICE_H_
#include "base/macros.h"
-#include "components/arc/instance_holder.h"
+#include "components/arc/connection_holder.h"
namespace arc {
@@ -14,40 +14,69 @@ namespace mojom {
// Instead of including components/arc/common/arc_bridge.mojom.h, list all the
// instance classes here for faster build.
+class AccessibilityHelperHost;
class AccessibilityHelperInstance;
+class AppHost;
class AppInstance;
+class AudioHost;
class AudioInstance;
+class AuthHost;
class AuthInstance;
+class BackupSettingsInstance;
+class BluetoothHost;
class BluetoothInstance;
+class BootPhaseMonitorHost;
class BootPhaseMonitorInstance;
class CastReceiverInstance;
+class CertStoreHost;
class CertStoreInstance;
+class ClipboardHost;
class ClipboardInstance;
+class CrashCollectorHost;
class CrashCollectorInstance;
+class EnterpriseReportingHost;
class EnterpriseReportingInstance;
+class FileSystemHost;
class FileSystemInstance;
+class ImeHost;
class ImeInstance;
+class IntentHelperHost;
class IntentHelperInstance;
+class KioskHost;
class KioskInstance;
class LockScreenInstance;
+class MetricsHost;
class MetricsInstance;
+class MidisHost;
class MidisInstance;
+class NetHost;
class NetInstance;
+class NotificationsHost;
class NotificationsInstance;
+class ObbMounterHost;
class ObbMounterInstance;
+class OemCryptoHost;
class OemCryptoInstance;
+class PolicyHost;
class PolicyInstance;
+class PowerHost;
class PowerInstance;
+class PrintHost;
class PrintInstance;
class ProcessInstance;
class RotationLockInstance;
class StorageManagerInstance;
class TracingInstance;
+class TtsHost;
class TtsInstance;
+class VideoHost;
class VideoInstance;
+class VoiceInteractionArcHomeHost;
class VoiceInteractionArcHomeInstance;
+class VoiceInteractionFrameworkHost;
class VoiceInteractionFrameworkInstance;
class VolumeMounterInstance;
+class WallpaperHost;
class WallpaperInstance;
} // namespace mojom
@@ -59,114 +88,174 @@ class ArcBridgeService {
ArcBridgeService();
~ArcBridgeService();
- InstanceHolder<mojom::AccessibilityHelperInstance>* accessibility_helper() {
+ ConnectionHolder<mojom::AccessibilityHelperInstance,
+ mojom::AccessibilityHelperHost>*
+ accessibility_helper() {
return &accessibility_helper_;
}
- InstanceHolder<mojom::AppInstance>* app() { return &app_; }
- InstanceHolder<mojom::AudioInstance>* audio() { return &audio_; }
- InstanceHolder<mojom::AuthInstance>* auth() { return &auth_; }
- InstanceHolder<mojom::BluetoothInstance>* bluetooth() { return &bluetooth_; }
- InstanceHolder<mojom::BootPhaseMonitorInstance>* boot_phase_monitor() {
+ ConnectionHolder<mojom::AppInstance, mojom::AppHost>* app() { return &app_; }
+ ConnectionHolder<mojom::AudioInstance, mojom::AudioHost>* audio() {
+ return &audio_;
+ }
+ ConnectionHolder<mojom::AuthInstance, mojom::AuthHost>* auth() {
+ return &auth_;
+ }
+ ConnectionHolder<mojom::BackupSettingsInstance>* backup_settings() {
+ return &backup_settings_;
+ }
+ ConnectionHolder<mojom::BluetoothInstance, mojom::BluetoothHost>*
+ bluetooth() {
+ return &bluetooth_;
+ }
+ ConnectionHolder<mojom::BootPhaseMonitorInstance,
+ mojom::BootPhaseMonitorHost>*
+ boot_phase_monitor() {
return &boot_phase_monitor_;
}
- InstanceHolder<mojom::CastReceiverInstance>* cast_receiver() {
+ ConnectionHolder<mojom::CastReceiverInstance>* cast_receiver() {
return &cast_receiver_;
}
- InstanceHolder<mojom::CertStoreInstance>* cert_store() {
+ ConnectionHolder<mojom::CertStoreInstance, mojom::CertStoreHost>*
+ cert_store() {
return &cert_store_;
}
- InstanceHolder<mojom::ClipboardInstance>* clipboard() { return &clipboard_; }
- InstanceHolder<mojom::CrashCollectorInstance>* crash_collector() {
+ ConnectionHolder<mojom::ClipboardInstance, mojom::ClipboardHost>*
+ clipboard() {
+ return &clipboard_;
+ }
+ ConnectionHolder<mojom::CrashCollectorInstance, mojom::CrashCollectorHost>*
+ crash_collector() {
return &crash_collector_;
}
- InstanceHolder<mojom::EnterpriseReportingInstance>* enterprise_reporting() {
+ ConnectionHolder<mojom::EnterpriseReportingInstance,
+ mojom::EnterpriseReportingHost>*
+ enterprise_reporting() {
return &enterprise_reporting_;
}
- InstanceHolder<mojom::FileSystemInstance>* file_system() {
+ ConnectionHolder<mojom::FileSystemInstance, mojom::FileSystemHost>*
+ file_system() {
return &file_system_;
}
- InstanceHolder<mojom::ImeInstance>* ime() { return &ime_; }
- InstanceHolder<mojom::IntentHelperInstance>* intent_helper() {
+ ConnectionHolder<mojom::ImeInstance, mojom::ImeHost>* ime() { return &ime_; }
+ ConnectionHolder<mojom::IntentHelperInstance, mojom::IntentHelperHost>*
+ intent_helper() {
return &intent_helper_;
}
- InstanceHolder<mojom::KioskInstance>* kiosk() { return &kiosk_; }
- InstanceHolder<mojom::LockScreenInstance>* lock_screen() {
+ ConnectionHolder<mojom::KioskInstance, mojom::KioskHost>* kiosk() {
+ return &kiosk_;
+ }
+ ConnectionHolder<mojom::LockScreenInstance>* lock_screen() {
return &lock_screen_;
}
- InstanceHolder<mojom::MetricsInstance>* metrics() { return &metrics_; }
- InstanceHolder<mojom::MidisInstance>* midis() { return &midis_; }
- InstanceHolder<mojom::NetInstance>* net() { return &net_; }
- InstanceHolder<mojom::NotificationsInstance>* notifications() {
+ ConnectionHolder<mojom::MetricsInstance, mojom::MetricsHost>* metrics() {
+ return &metrics_;
+ }
+ ConnectionHolder<mojom::MidisInstance, mojom::MidisHost>* midis() {
+ return &midis_;
+ }
+ ConnectionHolder<mojom::NetInstance, mojom::NetHost>* net() { return &net_; }
+ ConnectionHolder<mojom::NotificationsInstance, mojom::NotificationsHost>*
+ notifications() {
return &notifications_;
}
- InstanceHolder<mojom::ObbMounterInstance>* obb_mounter() {
+ ConnectionHolder<mojom::ObbMounterInstance, mojom::ObbMounterHost>*
+ obb_mounter() {
return &obb_mounter_;
}
- InstanceHolder<mojom::OemCryptoInstance>* oemcrypto() { return &oemcrypto_; }
- InstanceHolder<mojom::PolicyInstance>* policy() { return &policy_; }
- InstanceHolder<mojom::PowerInstance>* power() { return &power_; }
- InstanceHolder<mojom::PrintInstance>* print() { return &print_; }
- InstanceHolder<mojom::ProcessInstance>* process() { return &process_; }
- InstanceHolder<mojom::RotationLockInstance>* rotation_lock() {
+ ConnectionHolder<mojom::OemCryptoInstance, mojom::OemCryptoHost>*
+ oemcrypto() {
+ return &oemcrypto_;
+ }
+ ConnectionHolder<mojom::PolicyInstance, mojom::PolicyHost>* policy() {
+ return &policy_;
+ }
+ ConnectionHolder<mojom::PowerInstance, mojom::PowerHost>* power() {
+ return &power_;
+ }
+ ConnectionHolder<mojom::PrintInstance, mojom::PrintHost>* print() {
+ return &print_;
+ }
+ ConnectionHolder<mojom::ProcessInstance>* process() { return &process_; }
+ ConnectionHolder<mojom::RotationLockInstance>* rotation_lock() {
return &rotation_lock_;
}
- InstanceHolder<mojom::StorageManagerInstance>* storage_manager() {
+ ConnectionHolder<mojom::StorageManagerInstance>* storage_manager() {
return &storage_manager_;
}
- InstanceHolder<mojom::TracingInstance>* tracing() { return &tracing_; }
- InstanceHolder<mojom::TtsInstance>* tts() { return &tts_; }
- InstanceHolder<mojom::VideoInstance>* video() { return &video_; }
- InstanceHolder<mojom::VoiceInteractionArcHomeInstance>*
+ ConnectionHolder<mojom::TracingInstance>* tracing() { return &tracing_; }
+ ConnectionHolder<mojom::TtsInstance, mojom::TtsHost>* tts() { return &tts_; }
+ ConnectionHolder<mojom::VideoInstance, mojom::VideoHost>* video() {
+ return &video_;
+ }
+ ConnectionHolder<mojom::VoiceInteractionArcHomeInstance,
+ mojom::VoiceInteractionArcHomeHost>*
voice_interaction_arc_home() {
return &voice_interaction_arc_home_;
}
- InstanceHolder<mojom::VoiceInteractionFrameworkInstance>*
+ ConnectionHolder<mojom::VoiceInteractionFrameworkInstance,
+ mojom::VoiceInteractionFrameworkHost>*
voice_interaction_framework() {
return &voice_interaction_framework_;
}
- InstanceHolder<mojom::VolumeMounterInstance>* volume_mounter() {
+ ConnectionHolder<mojom::VolumeMounterInstance>* volume_mounter() {
return &volume_mounter_;
}
- InstanceHolder<mojom::WallpaperInstance>* wallpaper() { return &wallpaper_; }
+ ConnectionHolder<mojom::WallpaperInstance, mojom::WallpaperHost>*
+ wallpaper() {
+ return &wallpaper_;
+ }
private:
- InstanceHolder<mojom::AccessibilityHelperInstance> accessibility_helper_;
- InstanceHolder<mojom::AppInstance> app_;
- InstanceHolder<mojom::AudioInstance> audio_;
- InstanceHolder<mojom::AuthInstance> auth_;
- InstanceHolder<mojom::BluetoothInstance> bluetooth_;
- InstanceHolder<mojom::BootPhaseMonitorInstance> boot_phase_monitor_;
- InstanceHolder<mojom::CastReceiverInstance> cast_receiver_;
- InstanceHolder<mojom::CertStoreInstance> cert_store_;
- InstanceHolder<mojom::ClipboardInstance> clipboard_;
- InstanceHolder<mojom::CrashCollectorInstance> crash_collector_;
- InstanceHolder<mojom::EnterpriseReportingInstance> enterprise_reporting_;
- InstanceHolder<mojom::FileSystemInstance> file_system_;
- InstanceHolder<mojom::ImeInstance> ime_;
- InstanceHolder<mojom::IntentHelperInstance> intent_helper_;
- InstanceHolder<mojom::KioskInstance> kiosk_;
- InstanceHolder<mojom::LockScreenInstance> lock_screen_;
- InstanceHolder<mojom::MetricsInstance> metrics_;
- InstanceHolder<mojom::MidisInstance> midis_;
- InstanceHolder<mojom::NetInstance> net_;
- InstanceHolder<mojom::NotificationsInstance> notifications_;
- InstanceHolder<mojom::ObbMounterInstance> obb_mounter_;
- InstanceHolder<mojom::OemCryptoInstance> oemcrypto_;
- InstanceHolder<mojom::PolicyInstance> policy_;
- InstanceHolder<mojom::PowerInstance> power_;
- InstanceHolder<mojom::PrintInstance> print_;
- InstanceHolder<mojom::ProcessInstance> process_;
- InstanceHolder<mojom::RotationLockInstance> rotation_lock_;
- InstanceHolder<mojom::StorageManagerInstance> storage_manager_;
- InstanceHolder<mojom::TracingInstance> tracing_;
- InstanceHolder<mojom::TtsInstance> tts_;
- InstanceHolder<mojom::VideoInstance> video_;
- InstanceHolder<mojom::VoiceInteractionArcHomeInstance>
+ ConnectionHolder<mojom::AccessibilityHelperInstance,
+ mojom::AccessibilityHelperHost>
+ accessibility_helper_;
+ ConnectionHolder<mojom::AppInstance, mojom::AppHost> app_;
+ ConnectionHolder<mojom::AudioInstance, mojom::AudioHost> audio_;
+ ConnectionHolder<mojom::AuthInstance, mojom::AuthHost> auth_;
+ ConnectionHolder<mojom::BackupSettingsInstance> backup_settings_;
+ ConnectionHolder<mojom::BluetoothInstance, mojom::BluetoothHost> bluetooth_;
+ ConnectionHolder<mojom::BootPhaseMonitorInstance, mojom::BootPhaseMonitorHost>
+ boot_phase_monitor_;
+ ConnectionHolder<mojom::CastReceiverInstance> cast_receiver_;
+ ConnectionHolder<mojom::CertStoreInstance, mojom::CertStoreHost> cert_store_;
+ ConnectionHolder<mojom::ClipboardInstance, mojom::ClipboardHost> clipboard_;
+ ConnectionHolder<mojom::CrashCollectorInstance, mojom::CrashCollectorHost>
+ crash_collector_;
+ ConnectionHolder<mojom::EnterpriseReportingInstance,
+ mojom::EnterpriseReportingHost>
+ enterprise_reporting_;
+ ConnectionHolder<mojom::FileSystemInstance, mojom::FileSystemHost>
+ file_system_;
+ ConnectionHolder<mojom::ImeInstance, mojom::ImeHost> ime_;
+ ConnectionHolder<mojom::IntentHelperInstance, mojom::IntentHelperHost>
+ intent_helper_;
+ ConnectionHolder<mojom::KioskInstance, mojom::KioskHost> kiosk_;
+ ConnectionHolder<mojom::LockScreenInstance> lock_screen_;
+ ConnectionHolder<mojom::MetricsInstance, mojom::MetricsHost> metrics_;
+ ConnectionHolder<mojom::MidisInstance, mojom::MidisHost> midis_;
+ ConnectionHolder<mojom::NetInstance, mojom::NetHost> net_;
+ ConnectionHolder<mojom::NotificationsInstance, mojom::NotificationsHost>
+ notifications_;
+ ConnectionHolder<mojom::ObbMounterInstance, mojom::ObbMounterHost>
+ obb_mounter_;
+ ConnectionHolder<mojom::OemCryptoInstance, mojom::OemCryptoHost> oemcrypto_;
+ ConnectionHolder<mojom::PolicyInstance, mojom::PolicyHost> policy_;
+ ConnectionHolder<mojom::PowerInstance, mojom::PowerHost> power_;
+ ConnectionHolder<mojom::PrintInstance, mojom::PrintHost> print_;
+ ConnectionHolder<mojom::ProcessInstance> process_;
+ ConnectionHolder<mojom::RotationLockInstance> rotation_lock_;
+ ConnectionHolder<mojom::StorageManagerInstance> storage_manager_;
+ ConnectionHolder<mojom::TracingInstance> tracing_;
+ ConnectionHolder<mojom::TtsInstance, mojom::TtsHost> tts_;
+ ConnectionHolder<mojom::VideoInstance, mojom::VideoHost> video_;
+ ConnectionHolder<mojom::VoiceInteractionArcHomeInstance,
+ mojom::VoiceInteractionArcHomeHost>
voice_interaction_arc_home_;
- InstanceHolder<mojom::VoiceInteractionFrameworkInstance>
+ ConnectionHolder<mojom::VoiceInteractionFrameworkInstance,
+ mojom::VoiceInteractionFrameworkHost>
voice_interaction_framework_;
- InstanceHolder<mojom::VolumeMounterInstance> volume_mounter_;
- InstanceHolder<mojom::WallpaperInstance> wallpaper_;
+ ConnectionHolder<mojom::VolumeMounterInstance> volume_mounter_;
+ ConnectionHolder<mojom::WallpaperInstance, mojom::WallpaperHost> wallpaper_;
DISALLOW_COPY_AND_ASSIGN(ArcBridgeService);
};
diff --git a/chromium/components/arc/arc_data_remover_unittest.cc b/chromium/components/arc/arc_data_remover_unittest.cc
index 175026bc8a3..d2ea11ea977 100644
--- a/chromium/components/arc/arc_data_remover_unittest.cc
+++ b/chromium/components/arc/arc_data_remover_unittest.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "base/bind.h"
+#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
#include "chromeos/cryptohome/cryptohome_parameters.h"
#include "chromeos/dbus/dbus_thread_manager.h"
diff --git a/chromium/components/arc/arc_features.cc b/chromium/components/arc/arc_features.cc
index cc3b2a84871..3ce91e5d263 100644
--- a/chromium/components/arc/arc_features.cc
+++ b/chromium/components/arc/arc_features.cc
@@ -14,12 +14,12 @@ const base::Feature kBootCompletedBroadcastFeature {
// Controls experimental native bridge feature for ARC.
const base::Feature kNativeBridgeExperimentFeature {
- "ArcNativeBridgeExperiment", base::FEATURE_DISABLED_BY_DEFAULT
+ "ArcNativeBridgeExperiment", base::FEATURE_ENABLED_BY_DEFAULT
};
// Controls ARC VPN integration.
// When enabled, Chrome traffic will be routed through VPNs connected in
// Android apps.
-const base::Feature kVpnFeature{"ArcVpn", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kVpnFeature{"ArcVpn", base::FEATURE_ENABLED_BY_DEFAULT};
} // namespace arc
diff --git a/chromium/components/arc/arc_instance_mode.cc b/chromium/components/arc/arc_instance_mode.cc
index 3f6b67c1f96..de0439afd68 100644
--- a/chromium/components/arc/arc_instance_mode.cc
+++ b/chromium/components/arc/arc_instance_mode.cc
@@ -4,14 +4,17 @@
#include "components/arc/arc_instance_mode.h"
+#include <string>
+
#include "base/logging.h"
namespace arc {
+namespace {
-std::ostream& operator<<(std::ostream& os, ArcInstanceMode mode) {
+std::string ArcInstanceModeToString(ArcInstanceMode mode) {
#define MAP_MODE(name) \
case ArcInstanceMode::name: \
- return os << #name
+ return #name
switch (mode) {
MAP_MODE(MINI_INSTANCE);
@@ -22,7 +25,19 @@ std::ostream& operator<<(std::ostream& os, ArcInstanceMode mode) {
// Some compilers report an error even if all values of an enum-class are
// covered exhaustively in a switch statement.
NOTREACHED() << "Invalid value " << static_cast<int>(mode);
- return os;
+ return std::string();
+}
+
+} // namespace
+
+std::ostream& operator<<(std::ostream& os, ArcInstanceMode mode) {
+ return os << ArcInstanceModeToString(mode);
+}
+
+std::ostream& operator<<(std::ostream& os,
+ base::Optional<ArcInstanceMode> mode) {
+ return os << (mode.has_value() ? ArcInstanceModeToString(mode.value())
+ : "(nullopt)");
}
} // namespace arc
diff --git a/chromium/components/arc/arc_instance_mode.h b/chromium/components/arc/arc_instance_mode.h
index 86b3d0b5428..5f97a74cceb 100644
--- a/chromium/components/arc/arc_instance_mode.h
+++ b/chromium/components/arc/arc_instance_mode.h
@@ -7,6 +7,8 @@
#include <ostream>
+#include "base/optional.h"
+
namespace arc {
enum class ArcInstanceMode {
@@ -20,6 +22,8 @@ enum class ArcInstanceMode {
// Stringified output for logging purpose.
std::ostream& operator<<(std::ostream& os, ArcInstanceMode mode);
+std::ostream& operator<<(std::ostream& os,
+ base::Optional<ArcInstanceMode> mode);
} // namespace arc
diff --git a/chromium/components/arc/arc_prefs.cc b/chromium/components/arc/arc_prefs.cc
index 6aad8315032..5f4fc858c54 100644
--- a/chromium/components/arc/arc_prefs.cc
+++ b/chromium/components/arc/arc_prefs.cc
@@ -47,7 +47,7 @@ const char kArcSetNotificationsEnabledDeferred[] =
const char kArcSignedIn[] = "arc.signedin";
// A preference that indicates an ARC comaptible filesystem was chosen for
// the user directory (i.e., the user finished required migration.)
-extern const char kArcCompatibleFilesystemChosen[] =
+const char kArcCompatibleFilesystemChosen[] =
"arc.compatible_filesystem.chosen";
// A preference that indicates that user accepted Voice Interaction Value Prop.
const char kArcVoiceInteractionValuePropAccepted[] =
@@ -64,11 +64,6 @@ const char kVoiceInteractionEnabled[] = "settings.voice_interaction.enabled";
// screen).
const char kVoiceInteractionContextEnabled[] =
"settings.voice_interaction.context.enabled";
-// A preference indicating whether voice interaction settings have been read
-// from ARC. This synchronization only happens when user goes through the flow
-// to set up voice interaction.
-const char kVoiceInteractionPrefSynced[] =
- "settings.voice_interaction.context.synced";
void RegisterProfilePrefs(PrefRegistrySimple* registry) {
// TODO(dspaid): Implement a mechanism to allow this to sync on first boot
@@ -99,7 +94,6 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry) {
registry->RegisterBooleanPref(kSmsConnectEnabled, true);
registry->RegisterBooleanPref(kVoiceInteractionContextEnabled, false);
registry->RegisterBooleanPref(kVoiceInteractionEnabled, false);
- registry->RegisterBooleanPref(kVoiceInteractionPrefSynced, false);
}
} // namespace prefs
diff --git a/chromium/components/arc/arc_prefs.h b/chromium/components/arc/arc_prefs.h
index b3608afc4e7..16c37e3aa6d 100644
--- a/chromium/components/arc/arc_prefs.h
+++ b/chromium/components/arc/arc_prefs.h
@@ -31,7 +31,6 @@ ARC_EXPORT extern const char kEcryptfsMigrationStrategy[];
ARC_EXPORT extern const char kSmsConnectEnabled[];
ARC_EXPORT extern const char kVoiceInteractionEnabled[];
ARC_EXPORT extern const char kVoiceInteractionContextEnabled[];
-ARC_EXPORT extern const char kVoiceInteractionPrefSynced[];
void RegisterProfilePrefs(PrefRegistrySimple* registry);
diff --git a/chromium/components/arc/arc_session.cc b/chromium/components/arc/arc_session.cc
index 9a7b6dcff7b..d5c887a1136 100644
--- a/chromium/components/arc/arc_session.cc
+++ b/chromium/components/arc/arc_session.cc
@@ -4,686 +4,10 @@
#include "components/arc/arc_session.h"
-#include <fcntl.h>
-#include <grp.h>
-#include <poll.h>
-#include <unistd.h>
-
-#include <string>
-#include <utility>
-
-#include "base/files/file_util.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/sys_info.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/task_scheduler/task_traits.h"
-#include "base/threading/thread_checker.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "chromeos/chromeos_switches.h"
-#include "chromeos/cryptohome/cryptohome_parameters.h"
-#include "chromeos/dbus/dbus_method_call_status.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/session_manager_client.h"
-#include "components/arc/arc_bridge_host_impl.h"
-#include "components/arc/arc_features.h"
-#include "components/user_manager/user_manager.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/named_platform_handle.h"
-#include "mojo/edk/embedder/named_platform_handle_utils.h"
-#include "mojo/edk/embedder/outgoing_broker_client_invitation.h"
-#include "mojo/edk/embedder/platform_channel_pair.h"
-#include "mojo/edk/embedder/platform_channel_utils_posix.h"
-#include "mojo/edk/embedder/platform_handle_vector.h"
-#include "mojo/edk/embedder/scoped_platform_handle.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "components/arc/arc_session_impl.h"
namespace arc {
-namespace {
-
-using StartArcInstanceResult =
- chromeos::SessionManagerClient::StartArcInstanceResult;
-
-// This is called when StopArcInstance D-Bus method completes. Since we have the
-// ArcInstanceStopped() callback and are notified if StartArcInstance fails, we
-// don't need to do anything when StopArcInstance completes.
-void DoNothingInstanceStopped(bool) {}
-
-chromeos::SessionManagerClient* GetSessionManagerClient() {
- // If the DBusThreadManager or the SessionManagerClient aren't available,
- // there isn't much we can do. This should only happen when running tests.
- if (!chromeos::DBusThreadManager::IsInitialized() ||
- !chromeos::DBusThreadManager::Get() ||
- !chromeos::DBusThreadManager::Get()->GetSessionManagerClient())
- return nullptr;
- return chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
-}
-
-// Creates a pipe. Returns true on success, otherwise false.
-// On success, |read_fd| will be set to the fd of the read side, and
-// |write_fd| will be set to the one of write side.
-bool CreatePipe(base::ScopedFD* read_fd, base::ScopedFD* write_fd) {
- int fds[2];
- if (pipe2(fds, O_NONBLOCK | O_CLOEXEC) < 0) {
- PLOG(ERROR) << "pipe2()";
- return false;
- }
-
- read_fd->reset(fds[0]);
- write_fd->reset(fds[1]);
- return true;
-}
-
-// Waits until |raw_socket_fd| is readable.
-// The operation may be cancelled originally triggered by user interaction to
-// disable ARC, or ARC instance is unexpectedly stopped (e.g. crash).
-// To notify such a situation, |raw_cancel_fd| is also passed to here, and the
-// write side will be closed in such a case.
-bool WaitForSocketReadable(int raw_socket_fd, int raw_cancel_fd) {
- struct pollfd fds[2] = {
- {raw_socket_fd, POLLIN, 0}, {raw_cancel_fd, POLLIN, 0},
- };
-
- if (HANDLE_EINTR(poll(fds, arraysize(fds), -1)) <= 0) {
- PLOG(ERROR) << "poll()";
- return false;
- }
-
- if (fds[1].revents) {
- // Notified that Stop() is invoked. Cancel the Mojo connecting.
- VLOG(1) << "Stop() was called during ConnectMojo()";
- return false;
- }
-
- DCHECK(fds[0].revents);
- return true;
-}
-
-// TODO(hidehiko): Refactor more to make this class unittest-able, for at least
-// state-machine part.
-class ArcSessionImpl : public ArcSession,
- public chromeos::SessionManagerClient::Observer {
- public:
- // The possible states of the session. In the normal flow, the state changes
- // in the following sequence:
- //
- // NOT_STARTED
- // Start() ->
- // STARTING_INSTANCE
- // -> OnInstanceStarted() ->
- // CONNECTING_MOJO
- // ConnectMojo() -> OnMojoConnected() ->
- // RUNNING
- //
- // Also, StartForLoginScreen() may start ARC instance with
- // |login_screen_instance_requested_| set to |true|. In that case, the state
- // changes like the following:
- //
- // NOT_STARTED
- // StartForLoginScreen() ->
- // STARTING_INSTANCE
- // -> OnInstanceStarted() ->
- // RUNNING_FOR_LOGIN_SCREEN
- //
- // Start() can also be used at both STARTING_INSTANCE and
- // RUNNING_FOR_LOGIN_SCREEN to turn the instance for login screen into a
- // fully functional one.
- //
- // Regardless of whether the instance is for login screen or not, at any
- // state, Stop() can be called. It may not immediately stop the instance,
- // but will eventually stop it. The actual stop will be notified via
- // ArcSession::Observer::OnSessionStopped().
- //
- // When Stop() is called, it makes various behavior based on the current
- // phase.
- //
- // NOT_STARTED:
- // Do nothing. Immediately transition to the STOPPED state.
- // STARTING_INSTANCE:
- // The ARC instance is starting via SessionManager. Stop() just sets the
- // flag and return. On the main task completion, a callback will run on the
- // thread, and the flag is checked at the beginning of them. This should
- // work under the assumption that the main tasks do not block indefinitely.
- // In its callback, it checks if ARC instance is successfully started or
- // not. In case of success, a request to stop the ARC instance is sent to
- // SessionManager. Its completion will be notified via ArcInstanceStopped.
- // Otherwise, it just turns into STOPPED state.
- // CONNECTING_MOJO:
- // The main task runs on TaskScheduler's thread, but it is a blocking call.
- // So, Stop() sends a request to cancel the blocking by closing the pipe
- // whose read side is also polled. Then, in its callback, similar to
- // STARTING_INSTANCE, a request to stop the ARC instance is sent to
- // SessionManager, and ArcInstanceStopped handles remaining procedure.
- // RUNNING_FOR_LOGIN_SCREEN:
- // RUNNING:
- // There is no more callback which runs on normal flow, so Stop() requests
- // to stop the ARC instance via SessionManager.
- //
- // Another trigger to change the state coming from outside of this class
- // is an event ArcInstanceStopped() sent from SessionManager, when ARC
- // instace unexpectedly terminates. ArcInstanceStopped() turns the state into
- // STOPPED immediately.
- //
- // In NOT_STARTED or STOPPED state, the instance can be safely destructed.
- // Specifically, in STOPPED state, there may be inflight operations or
- // pending callbacks. Though, what they do is just do-nothing conceptually
- // and they can be safely ignored.
- //
- // Note: Order of constants below matters. Please make sure to sort them
- // in chronological order.
- enum class State {
- // ARC is not yet started.
- NOT_STARTED,
-
- // The request to start or resume the instance has been sent.
- STARTING_INSTANCE,
-
- // The instance is set up, but only a handful of processes NOT including
- // arcbridgeservice (i.e. mojo endpoint) are running.
- RUNNING_FOR_LOGIN_SCREEN,
-
- // The instance has started. Waiting for it to connect to the IPC bridge.
- CONNECTING_MOJO,
-
- // The instance is fully set up.
- RUNNING,
-
- // ARC is terminated.
- STOPPED,
- };
-
- explicit ArcSessionImpl(ArcBridgeService* arc_bridge_service);
- ~ArcSessionImpl() override;
-
- // ArcSession overrides:
- void StartForLoginScreen() override;
- bool IsForLoginScreen() override;
- void Start() override;
- bool IsRunning() override;
- void Stop() override;
- bool IsStopRequested() override;
- void OnShutdown() override;
-
- private:
- // DBus callback for StartArcInstance().
- void OnInstanceStarted(bool instance_is_for_login_screen,
- StartArcInstanceResult result,
- const std::string& container_instance_id,
- base::ScopedFD socket_fd);
-
- // Synchronously accepts a connection on |socket_fd| and then processes the
- // connected socket's file descriptor.
- static mojo::ScopedMessagePipeHandle ConnectMojo(
- mojo::edk::ScopedPlatformHandle socket_fd,
- base::ScopedFD cancel_fd);
- void OnMojoConnected(mojo::ScopedMessagePipeHandle server_pipe);
-
- // Request to stop ARC instance via DBus.
- void StopArcInstance();
-
- // chromeos::SessionManagerClient::Observer:
- void ArcInstanceStopped(bool clean,
- const std::string& container_instance_id) override;
-
- // Completes the termination procedure. Note that calling this may end up with
- // deleting |this| because the function calls observers' OnSessionStopped().
- void OnStopped(ArcStopReason reason);
-
- // Sends a StartArcInstance D-Bus request to session_manager.
- static void SendStartArcInstanceDBusMessage(
- bool instance_is_for_login_screen,
- const chromeos::SessionManagerClient::StartArcInstanceCallback& cb);
-
- // Checks whether a function runs on the thread where the instance is
- // created.
- THREAD_CHECKER(thread_checker_);
-
- // Owned by ArcServiceManager.
- ArcBridgeService* const arc_bridge_service_;
-
- // The state of the session.
- State state_ = State::NOT_STARTED;
-
- // When Stop() is called, this flag is set.
- bool stop_requested_ = false;
-
- // When StartForLoginScreen() is called, this flag is set. After
- // that, when Start() is called to resume the boot, the flag is unset.
- bool login_screen_instance_requested_ = false;
-
- // Container instance id passed from session_manager.
- // Should be available only after OnInstanceStarted().
- std::string container_instance_id_;
-
- // In CONNECTING_MOJO state, this is set to the write side of the pipe
- // to notify cancelling of the procedure.
- base::ScopedFD accept_cancel_pipe_;
-
- // Mojo endpoint.
- std::unique_ptr<mojom::ArcBridgeHost> arc_bridge_host_;
-
- // WeakPtrFactory to use callbacks.
- base::WeakPtrFactory<ArcSessionImpl> weak_factory_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ArcSessionImpl);
-};
-
-ArcSessionImpl::ArcSessionImpl(ArcBridgeService* arc_bridge_service)
- : arc_bridge_service_(arc_bridge_service), weak_factory_(this) {
- chromeos::SessionManagerClient* client = GetSessionManagerClient();
- if (client == nullptr)
- return;
- client->AddObserver(this);
-}
-
-ArcSessionImpl::~ArcSessionImpl() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DCHECK(state_ == State::NOT_STARTED || state_ == State::STOPPED);
- chromeos::SessionManagerClient* client = GetSessionManagerClient();
- if (client == nullptr)
- return;
- client->RemoveObserver(this);
-}
-
-void ArcSessionImpl::Start() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- // Start() can be called either for starting ARC from scratch or for
- // resuming an existing one. Start() must be able to start a fully
- // functional instance from all of |state_| up to and including
- // RUNNING_FOR_LOGIN_SCREEN.
- DCHECK_GE(State::RUNNING_FOR_LOGIN_SCREEN, state_);
-
- // Flip the flag now so that callback functions like OnInstanceStarted()
- // can do the right thing.
- login_screen_instance_requested_ = false;
-
- if (state_ == State::NOT_STARTED) {
- // An instance for login screen does not exist. Start a new one from
- // scratch.
- VLOG(2) << "Starting ARC session";
- state_ = State::STARTING_INSTANCE;
- SendStartArcInstanceDBusMessage(
- false /* instance_is_for_login_screen */,
- base::Bind(&ArcSessionImpl::OnInstanceStarted,
- weak_factory_.GetWeakPtr(),
- false /* instance_is_for_login_screen */));
-
- } else if (state_ == State::STARTING_INSTANCE) {
- VLOG(2) << "Requested to resume an existing ARC instance";
- // OnInstanceStarted() will start a fully featured instance.
- } else if (state_ == State::RUNNING_FOR_LOGIN_SCREEN) {
- VLOG(2) << "Resuming an existing ARC instance";
- state_ = State::STARTING_INSTANCE;
- SendStartArcInstanceDBusMessage(
- false /* instance_is_for_login_screen */,
- base::Bind(&ArcSessionImpl::OnInstanceStarted,
- weak_factory_.GetWeakPtr(),
- false /* instance_is_for_login_screen */));
- }
-}
-
-// static
-void ArcSessionImpl::SendStartArcInstanceDBusMessage(
- bool instance_is_for_login_screen,
- const chromeos::SessionManagerClient::StartArcInstanceCallback& cb) {
- chromeos::SessionManagerClient* session_manager_client =
- chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
- const bool native_bridge_experiment =
- base::FeatureList::IsEnabled(arc::kNativeBridgeExperimentFeature);
- if (instance_is_for_login_screen) {
- session_manager_client->StartArcInstance(
- chromeos::SessionManagerClient::ArcStartupMode::LOGIN_SCREEN,
- // All variables below except |cb| will be ignored.
- cryptohome::Identification(), false, false,
- native_bridge_experiment, cb);
- return;
- }
-
- user_manager::UserManager* user_manager = user_manager::UserManager::Get();
- DCHECK(user_manager->GetPrimaryUser());
- const cryptohome::Identification cryptohome_id(
- user_manager->GetPrimaryUser()->GetAccountId());
-
- const bool skip_boot_completed_broadcast =
- !base::FeatureList::IsEnabled(arc::kBootCompletedBroadcastFeature);
-
- // We only enable /vendor/priv-app when voice interaction is enabled because
- // voice interaction service apk would be bundled in this location.
- const bool scan_vendor_priv_app =
- chromeos::switches::IsVoiceInteractionEnabled();
-
- session_manager_client->StartArcInstance(
- chromeos::SessionManagerClient::ArcStartupMode::FULL, cryptohome_id,
- skip_boot_completed_broadcast, scan_vendor_priv_app,
- native_bridge_experiment, cb);
-}
-
-void ArcSessionImpl::OnInstanceStarted(bool instance_is_for_login_screen,
- StartArcInstanceResult result,
- const std::string& container_instance_id,
- base::ScopedFD socket_fd) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DCHECK_EQ(state_, State::STARTING_INSTANCE);
-
- bool resumed = false;
- if (!container_instance_id_.empty()) {
- // |container_instance_id_| has already been initialized when the instance
- // for login screen was started.
- DCHECK(container_instance_id.empty());
- DCHECK(!instance_is_for_login_screen);
- resumed = true;
- } else {
- container_instance_id_ = container_instance_id;
- }
-
- if (stop_requested_) {
- if (result == StartArcInstanceResult::SUCCESS) {
- // The ARC instance has started to run. Request to stop.
- StopArcInstance();
- return;
- }
- OnStopped(ArcStopReason::SHUTDOWN);
- return;
- }
-
- if (result != StartArcInstanceResult::SUCCESS) {
- LOG(ERROR) << "Failed to start ARC instance";
- OnStopped(result == StartArcInstanceResult::LOW_FREE_DISK_SPACE
- ? ArcStopReason::LOW_DISK_SPACE
- : ArcStopReason::GENERIC_BOOT_FAILURE);
- return;
- }
-
- if (instance_is_for_login_screen) {
- VLOG(2) << "ARC instance for login screen is successfully started.";
- if (login_screen_instance_requested_) {
- state_ = State::RUNNING_FOR_LOGIN_SCREEN;
- } else {
- // Start() has been called.
- VLOG(2) << "Resuming an existing ARC instance";
- state_ = State::STARTING_INSTANCE;
- SendStartArcInstanceDBusMessage(
- false /* instance_is_for_login_screen */,
- base::Bind(&ArcSessionImpl::OnInstanceStarted,
- weak_factory_.GetWeakPtr(),
- false /* instance_is_for_login_screen */));
- }
- return;
- }
-
- VLOG(2) << "ARC instance is successfully "
- << (resumed ? "resumed" : "started") << ". Connecting Mojo...";
- state_ = State::CONNECTING_MOJO;
-
- // Prepare a pipe so that AcceptInstanceConnection can be interrupted on
- // Stop().
- base::ScopedFD cancel_fd;
- if (!CreatePipe(&cancel_fd, &accept_cancel_pipe_)) {
- StopArcInstance();
- return;
- }
-
- // For production, |socket_fd| passed from session_manager is either a valid
- // socket or a valid file descriptor (/dev/null). For testing, |socket_fd|
- // might be invalid.
- mojo::edk::PlatformHandle raw_handle(socket_fd.release());
- raw_handle.needs_connection = true;
-
- mojo::edk::ScopedPlatformHandle mojo_socket_fd(raw_handle);
- base::PostTaskWithTraitsAndReplyWithResult(
- FROM_HERE, {base::MayBlock()},
- base::Bind(&ArcSessionImpl::ConnectMojo, base::Passed(&mojo_socket_fd),
- base::Passed(&cancel_fd)),
- base::Bind(&ArcSessionImpl::OnMojoConnected, weak_factory_.GetWeakPtr()));
-}
-
-// static
-mojo::ScopedMessagePipeHandle ArcSessionImpl::ConnectMojo(
- mojo::edk::ScopedPlatformHandle socket_fd,
- base::ScopedFD cancel_fd) {
- if (!WaitForSocketReadable(socket_fd.get().handle, cancel_fd.get())) {
- VLOG(1) << "Mojo connection was cancelled.";
- return mojo::ScopedMessagePipeHandle();
- }
-
- mojo::edk::ScopedPlatformHandle scoped_fd;
- if (!mojo::edk::ServerAcceptConnection(socket_fd.get(), &scoped_fd,
- /* check_peer_user = */ false) ||
- !scoped_fd.is_valid()) {
- return mojo::ScopedMessagePipeHandle();
- }
-
- // Hardcode pid 0 since it is unused in mojo.
- const base::ProcessHandle kUnusedChildProcessHandle = 0;
- mojo::edk::PlatformChannelPair channel_pair;
- mojo::edk::OutgoingBrokerClientInvitation invitation;
-
- std::string token = mojo::edk::GenerateRandomToken();
- mojo::ScopedMessagePipeHandle pipe = invitation.AttachMessagePipe(token);
-
- invitation.Send(
- kUnusedChildProcessHandle,
- mojo::edk::ConnectionParams(mojo::edk::TransportProtocol::kLegacy,
- channel_pair.PassServerHandle()));
-
- mojo::edk::ScopedPlatformHandleVectorPtr handles(
- new mojo::edk::PlatformHandleVector{
- channel_pair.PassClientHandle().release()});
-
- // We need to send the length of the message as a single byte, so make sure it
- // fits.
- DCHECK_LT(token.size(), 256u);
- uint8_t message_length = static_cast<uint8_t>(token.size());
- struct iovec iov[] = {{&message_length, sizeof(message_length)},
- {const_cast<char*>(token.c_str()), token.size()}};
- ssize_t result = mojo::edk::PlatformChannelSendmsgWithHandles(
- scoped_fd.get(), iov, sizeof(iov) / sizeof(iov[0]), handles->data(),
- handles->size());
- if (result == -1) {
- PLOG(ERROR) << "sendmsg";
- return mojo::ScopedMessagePipeHandle();
- }
-
- return pipe;
-}
-
-void ArcSessionImpl::OnMojoConnected(
- mojo::ScopedMessagePipeHandle server_pipe) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DCHECK_EQ(state_, State::CONNECTING_MOJO);
- accept_cancel_pipe_.reset();
-
- if (stop_requested_) {
- StopArcInstance();
- return;
- }
-
- if (!server_pipe.is_valid()) {
- LOG(ERROR) << "Invalid pipe";
- StopArcInstance();
- return;
- }
-
- mojom::ArcBridgeInstancePtr instance;
- instance.Bind(mojo::InterfacePtrInfo<mojom::ArcBridgeInstance>(
- std::move(server_pipe), 0u));
- arc_bridge_host_ = std::make_unique<ArcBridgeHostImpl>(arc_bridge_service_,
- std::move(instance));
-
- VLOG(0) << "ARC ready.";
- state_ = State::RUNNING;
-}
-
-void ArcSessionImpl::Stop() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- VLOG(2) << "Stopping ARC session is requested.";
-
- // For second time or later, just do nothing.
- // It is already in the stopping phase.
- if (stop_requested_)
- return;
-
- stop_requested_ = true;
- arc_bridge_host_.reset();
- switch (state_) {
- case State::NOT_STARTED:
- OnStopped(ArcStopReason::SHUTDOWN);
- return;
-
- case State::STARTING_INSTANCE:
- // Before starting the ARC instance, we do nothing here.
- // At some point, a callback will be invoked on UI thread,
- // and stopping procedure will be run there.
- // On Chrome shutdown, it is not the case because the message loop is
- // already stopped here. Practically, it is not a problem because;
- // - On starting instance, the container instance can be leaked.
- // Practically it is not problematic because the session manager will
- // clean it up.
- return;
-
- case State::RUNNING_FOR_LOGIN_SCREEN:
- // An ARC instance for login screen is running. Request to stop it.
- StopArcInstance();
- return;
-
- case State::CONNECTING_MOJO:
- // Mojo connection is being waited on TaskScheduler's thread.
- // Request to cancel it. Following stopping procedure will run
- // in its callback.
- accept_cancel_pipe_.reset();
- return;
-
- case State::RUNNING:
- // Now ARC instance is running. Request to stop it.
- StopArcInstance();
- return;
-
- case State::STOPPED:
- // The instance is already stopped. Do nothing.
- return;
- }
-}
-
-void ArcSessionImpl::StopArcInstance() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DCHECK(state_ == State::STARTING_INSTANCE ||
- state_ == State::RUNNING_FOR_LOGIN_SCREEN ||
- state_ == State::CONNECTING_MOJO || state_ == State::RUNNING);
-
- VLOG(2) << "Requesting session_manager to stop ARC instance";
-
- // When the instance is not for login screen, change the |state_| in
- // ArcInstanceStopped().
- chromeos::SessionManagerClient* session_manager_client =
- chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
- session_manager_client->StopArcInstance(
- base::Bind(&DoNothingInstanceStopped));
-}
-
-void ArcSessionImpl::ArcInstanceStopped(
- bool clean,
- const std::string& container_instance_id) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- VLOG(1) << "Notified that ARC instance is stopped "
- << (clean ? "cleanly" : "uncleanly");
-
- if (container_instance_id != container_instance_id_) {
- VLOG(1) << "Container instance id mismatch. Do nothing."
- << container_instance_id << " vs " << container_instance_id_;
- return;
- }
-
- // Release |container_instance_id_| to avoid duplicate invocation situation.
- container_instance_id_.clear();
-
- // In case that crash happens during before the Mojo channel is connected,
- // unlock the TaskScheduler's thread.
- accept_cancel_pipe_.reset();
-
- ArcStopReason reason;
- if (stop_requested_) {
- // If the ARC instance is stopped after its explicit request,
- // return SHUTDOWN.
- reason = ArcStopReason::SHUTDOWN;
- } else if (clean) {
- // If the ARC instance is stopped, but it is not explicitly requested,
- // then this is triggered by some failure during the starting procedure.
- // Return GENERIC_BOOT_FAILURE for the case.
- reason = ArcStopReason::GENERIC_BOOT_FAILURE;
- } else {
- // Otherwise, this is caused by CRASH occured inside of the ARC instance.
- reason = ArcStopReason::CRASH;
- }
- OnStopped(reason);
-}
-
-void ArcSessionImpl::StartForLoginScreen() {
- DCHECK_EQ(State::NOT_STARTED, state_);
-
- VLOG(2) << "Starting ARC session for login screen";
- login_screen_instance_requested_ = true;
- state_ = State::STARTING_INSTANCE;
- SendStartArcInstanceDBusMessage(
- true /* instance_is_for_login_screen */,
- base::Bind(&ArcSessionImpl::OnInstanceStarted, weak_factory_.GetWeakPtr(),
- true /* instance_is_for_login_screen */));
-}
-
-bool ArcSessionImpl::IsForLoginScreen() {
- return login_screen_instance_requested_;
-}
-
-bool ArcSessionImpl::IsRunning() {
- return state_ == State::RUNNING;
-}
-
-bool ArcSessionImpl::IsStopRequested() {
- return stop_requested_;
-}
-
-void ArcSessionImpl::OnStopped(ArcStopReason reason) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- // OnStopped() should be called once per instance.
- DCHECK_NE(state_, State::STOPPED);
- VLOG(2) << "ARC session is stopped.";
- const bool was_running = IsRunning();
- arc_bridge_host_.reset();
- state_ = State::STOPPED;
- for (auto& observer : observer_list_)
- observer.OnSessionStopped(reason, was_running);
-}
-
-void ArcSessionImpl::OnShutdown() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- stop_requested_ = true;
- if (state_ == State::STOPPED)
- return;
-
- // Here, the message loop is already stopped, and the Chrome will be soon
- // shutdown. Thus, it is not necessary to take care about restarting case.
- // If ArcSession is waiting for mojo connection, cancels it.
- accept_cancel_pipe_.reset();
-
- // Stops the ARC instance to let it graceful shutdown.
- // Note that this may fail if ARC container is not actually running, but
- // ignore an error as described below.
- if (state_ == State::STARTING_INSTANCE ||
- state_ == State::RUNNING_FOR_LOGIN_SCREEN ||
- state_ == State::CONNECTING_MOJO || state_ == State::RUNNING) {
- StopArcInstance();
- }
-
- // Directly set to the STOPPED state by OnStopped(). Note that calling
- // StopArcInstance() may not work well. At least, because the UI thread is
- // already stopped here, ArcInstanceStopped() callback cannot be invoked.
- OnStopped(ArcStopReason::SHUTDOWN);
-}
-
-} // namespace
-
ArcSession::ArcSession() = default;
ArcSession::~ArcSession() = default;
@@ -698,7 +22,8 @@ void ArcSession::RemoveObserver(Observer* observer) {
// static
std::unique_ptr<ArcSession> ArcSession::Create(
ArcBridgeService* arc_bridge_service) {
- return std::make_unique<ArcSessionImpl>(arc_bridge_service);
+ return std::make_unique<ArcSessionImpl>(
+ ArcSessionImpl::CreateDelegate(arc_bridge_service));
}
} // namespace arc
diff --git a/chromium/components/arc/arc_session.h b/chromium/components/arc/arc_session.h
index be033514b65..6e303c93e75 100644
--- a/chromium/components/arc/arc_session.h
+++ b/chromium/components/arc/arc_session.h
@@ -9,6 +9,8 @@
#include "base/macros.h"
#include "base/observer_list.h"
+#include "base/optional.h"
+#include "components/arc/arc_instance_mode.h"
#include "components/arc/arc_stop_reason.h"
namespace arc {
@@ -18,7 +20,7 @@ class ArcBridgeService;
// Starts the ARC instance and bootstraps the bridge connection.
// Clients should implement the Delegate to be notified upon communications
// being available.
-// The instance can be safely removed 1) before Start*() is called, or 2) after
+// The instance can be safely removed 1) before Start() is called, or 2) after
// OnSessionStopped() is called.
// The number of instances must be at most one. Otherwise, ARC instances will
// conflict.
@@ -42,27 +44,20 @@ class ArcSession {
ArcBridgeService* arc_bridge_service);
virtual ~ArcSession();
- // Starts an instance for login screen. The instance is not a fully functional
- // one.
- virtual void StartForLoginScreen() = 0;
+ // Starts an instance in the |request_mode|. Start(FULL_INSTANCE) should
+ // not be called twice or more. When Start(MINI_INSTANCE) was called then
+ // Start(FULL_INSTANCE) is called, it upgrades the mini instance to a full
+ // instance.
+ virtual void Start(ArcInstanceMode request_mode) = 0;
- // Returns true if StartForLoginScreen() has been called but Start() hasn't.
- virtual bool IsForLoginScreen() = 0;
-
- // Starts and bootstraps a connection with the instance. Start() should not
- // be called twice or more. When StartForLoginScreen() has already been
- // called, Start() turns the mini instance to a fully functional one.
- virtual void Start() = 0;
-
- // Requests to stop the currently-running instance whether or not it is for
- // login screen.
+ // Requests to stop the currently-running instance regardless of its mode.
// The completion is notified via OnSessionStopped() of the Observer.
virtual void Stop() = 0;
- // Returns true if this instance is fully set up successfully, and running.
- // Currently, this means, this is a fully functional instance, and
- // Mojo connection is already connected successfully.
- virtual bool IsRunning() = 0;
+ // Returns the current target mode, in which eventually this instance is
+ // running.
+ // If the instance is not yet started, this returns nullopt.
+ virtual base::Optional<ArcInstanceMode> GetTargetMode() = 0;
// Returns true if Stop() has been called already.
virtual bool IsStopRequested() = 0;
diff --git a/chromium/components/arc/arc_session_impl.cc b/chromium/components/arc/arc_session_impl.cc
new file mode 100644
index 00000000000..d01edde3a38
--- /dev/null
+++ b/chromium/components/arc/arc_session_impl.cc
@@ -0,0 +1,637 @@
+// 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 "components/arc/arc_session_impl.h"
+
+#include <fcntl.h>
+#include <poll.h>
+#include <unistd.h>
+
+#include <utility>
+#include <vector>
+
+#include "base/location.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/task_scheduler/task_traits.h"
+#include "chromeos/chromeos_switches.h"
+#include "chromeos/cryptohome/cryptohome_parameters.h"
+#include "chromeos/dbus/dbus_method_call_status.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "components/arc/arc_bridge_host_impl.h"
+#include "components/arc/arc_features.h"
+#include "components/user_manager/user_manager.h"
+#include "mojo/edk/embedder/embedder.h"
+#include "mojo/edk/embedder/named_platform_handle.h"
+#include "mojo/edk/embedder/named_platform_handle_utils.h"
+#include "mojo/edk/embedder/outgoing_broker_client_invitation.h"
+#include "mojo/edk/embedder/platform_channel_pair.h"
+#include "mojo/edk/embedder/platform_channel_utils_posix.h"
+#include "mojo/edk/embedder/scoped_platform_handle.h"
+#include "mojo/public/cpp/bindings/binding.h"
+
+namespace arc {
+
+namespace {
+
+using StartArcInstanceResult =
+ chromeos::SessionManagerClient::StartArcInstanceResult;
+
+chromeos::SessionManagerClient* GetSessionManagerClient() {
+ // If the DBusThreadManager or the SessionManagerClient aren't available,
+ // there isn't much we can do. This should only happen when running tests.
+ if (!chromeos::DBusThreadManager::IsInitialized() ||
+ !chromeos::DBusThreadManager::Get() ||
+ !chromeos::DBusThreadManager::Get()->GetSessionManagerClient()) {
+ return nullptr;
+ }
+ return chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
+}
+
+// Creates a pipe. Returns true on success, otherwise false.
+// On success, |read_fd| will be set to the fd of the read side, and
+// |write_fd| will be set to the one of write side.
+bool CreatePipe(base::ScopedFD* read_fd, base::ScopedFD* write_fd) {
+ int fds[2];
+ if (pipe2(fds, O_NONBLOCK | O_CLOEXEC) < 0) {
+ PLOG(ERROR) << "pipe2()";
+ return false;
+ }
+
+ read_fd->reset(fds[0]);
+ write_fd->reset(fds[1]);
+ return true;
+}
+
+// Waits until |raw_socket_fd| is readable.
+// The operation may be cancelled originally triggered by user interaction to
+// disable ARC, or ARC instance is unexpectedly stopped (e.g. crash).
+// To notify such a situation, |raw_cancel_fd| is also passed to here, and the
+// write side will be closed in such a case.
+bool WaitForSocketReadable(int raw_socket_fd, int raw_cancel_fd) {
+ struct pollfd fds[2] = {
+ {raw_socket_fd, POLLIN, 0}, {raw_cancel_fd, POLLIN, 0},
+ };
+
+ if (HANDLE_EINTR(poll(fds, arraysize(fds), -1)) <= 0) {
+ PLOG(ERROR) << "poll()";
+ return false;
+ }
+
+ if (fds[1].revents) {
+ // Notified that Stop() is invoked. Cancel the Mojo connecting.
+ VLOG(1) << "Stop() was called during ConnectMojo()";
+ return false;
+ }
+
+ DCHECK(fds[0].revents);
+ return true;
+}
+
+// Returns the ArcStopReason corresponding to the ARC instance staring failure.
+ArcStopReason GetArcStopReason(StartArcInstanceResult result,
+ bool stop_requested) {
+ if (stop_requested)
+ return ArcStopReason::SHUTDOWN;
+
+ switch (result) {
+ case StartArcInstanceResult::SUCCESS:
+ NOTREACHED();
+ break;
+ case StartArcInstanceResult::UNKNOWN_ERROR:
+ return ArcStopReason::GENERIC_BOOT_FAILURE;
+ case StartArcInstanceResult::LOW_FREE_DISK_SPACE:
+ return ArcStopReason::LOW_DISK_SPACE;
+ }
+
+ NOTREACHED();
+ return ArcStopReason::GENERIC_BOOT_FAILURE;
+}
+
+// Real Delegate implementation to connect Mojo.
+class ArcSessionDelegateImpl : public ArcSessionImpl::Delegate {
+ public:
+ explicit ArcSessionDelegateImpl(ArcBridgeService* arc_bridge_service);
+ ~ArcSessionDelegateImpl() override = default;
+
+ // ArcSessionImpl::Delegate override.
+ base::ScopedFD ConnectMojo(base::ScopedFD socket_fd,
+ ConnectMojoCallback callback) override;
+
+ private:
+ // Synchronously accepts a connection on |socket_fd| and then processes the
+ // connected socket's file descriptor. This is designed to run on a
+ // blocking thread.
+ static mojo::ScopedMessagePipeHandle ConnectMojoInternal(
+ mojo::edk::ScopedPlatformHandle socket_fd,
+ base::ScopedFD cancel_fd);
+
+ // Called when Mojo connection is established or canceled.
+ // In case of cancel or error, |server_pipe| is invalid.
+ void OnMojoConnected(ConnectMojoCallback callback,
+ mojo::ScopedMessagePipeHandle server_pipe);
+
+ // Owned by ArcServiceManager.
+ ArcBridgeService* const arc_bridge_service_;
+
+ // WeakPtrFactory to use callbacks.
+ base::WeakPtrFactory<ArcSessionDelegateImpl> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ArcSessionDelegateImpl);
+};
+
+ArcSessionDelegateImpl::ArcSessionDelegateImpl(
+ ArcBridgeService* arc_bridge_service)
+ : arc_bridge_service_(arc_bridge_service), weak_factory_(this) {}
+
+base::ScopedFD ArcSessionDelegateImpl::ConnectMojo(
+ base::ScopedFD socket_fd,
+ ConnectMojoCallback callback) {
+ // Prepare a pipe so that AcceptInstanceConnection can be interrupted on
+ // Stop().
+ base::ScopedFD cancel_fd;
+ base::ScopedFD return_fd;
+ if (!CreatePipe(&cancel_fd, &return_fd)) {
+ LOG(ERROR) << "Failed to create a pipe to cancel accept()";
+ return base::ScopedFD();
+ }
+
+ // For production, |socket_fd| passed from session_manager is either a valid
+ // socket or a valid file descriptor (/dev/null). For testing, |socket_fd|
+ // might be invalid.
+ mojo::edk::PlatformHandle raw_handle(socket_fd.release());
+ raw_handle.needs_connection = true;
+
+ mojo::edk::ScopedPlatformHandle mojo_socket_fd(raw_handle);
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {base::MayBlock()},
+ base::BindOnce(&ArcSessionDelegateImpl::ConnectMojoInternal,
+ std::move(mojo_socket_fd), std::move(cancel_fd)),
+ base::BindOnce(&ArcSessionDelegateImpl::OnMojoConnected,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
+ return return_fd;
+}
+
+// static
+mojo::ScopedMessagePipeHandle ArcSessionDelegateImpl::ConnectMojoInternal(
+ mojo::edk::ScopedPlatformHandle socket_fd,
+ base::ScopedFD cancel_fd) {
+ if (!WaitForSocketReadable(socket_fd.get().handle, cancel_fd.get())) {
+ VLOG(1) << "Mojo connection was cancelled.";
+ return mojo::ScopedMessagePipeHandle();
+ }
+
+ mojo::edk::ScopedPlatformHandle scoped_fd;
+ if (!mojo::edk::ServerAcceptConnection(socket_fd, &scoped_fd,
+ /* check_peer_user = */ false) ||
+ !scoped_fd.is_valid()) {
+ return mojo::ScopedMessagePipeHandle();
+ }
+
+ // Hardcode pid 0 since it is unused in mojo.
+ const base::ProcessHandle kUnusedChildProcessHandle = 0;
+ mojo::edk::PlatformChannelPair channel_pair;
+ mojo::edk::OutgoingBrokerClientInvitation invitation;
+
+ std::string token = mojo::edk::GenerateRandomToken();
+ mojo::ScopedMessagePipeHandle pipe = invitation.AttachMessagePipe(token);
+
+ invitation.Send(
+ kUnusedChildProcessHandle,
+ mojo::edk::ConnectionParams(mojo::edk::TransportProtocol::kLegacy,
+ channel_pair.PassServerHandle()));
+
+ std::vector<mojo::edk::ScopedPlatformHandle> handles;
+ handles.emplace_back(channel_pair.PassClientHandle());
+
+ // We need to send the length of the message as a single byte, so make sure it
+ // fits.
+ DCHECK_LT(token.size(), 256u);
+ uint8_t message_length = static_cast<uint8_t>(token.size());
+ struct iovec iov[] = {{&message_length, sizeof(message_length)},
+ {const_cast<char*>(token.c_str()), token.size()}};
+ ssize_t result = mojo::edk::PlatformChannelSendmsgWithHandles(
+ scoped_fd, iov, sizeof(iov) / sizeof(iov[0]), handles);
+ if (result == -1) {
+ PLOG(ERROR) << "sendmsg";
+ return mojo::ScopedMessagePipeHandle();
+ }
+
+ return pipe;
+}
+
+void ArcSessionDelegateImpl::OnMojoConnected(
+ ConnectMojoCallback callback,
+ mojo::ScopedMessagePipeHandle server_pipe) {
+ if (!server_pipe.is_valid()) {
+ LOG(ERROR) << "Invalid pipe";
+ std::move(callback).Run(nullptr);
+ return;
+ }
+
+ mojom::ArcBridgeInstancePtr instance;
+ instance.Bind(mojo::InterfacePtrInfo<mojom::ArcBridgeInstance>(
+ std::move(server_pipe), 0u));
+ std::move(callback).Run(std::make_unique<ArcBridgeHostImpl>(
+ arc_bridge_service_, std::move(instance)));
+}
+
+} // namespace
+
+// static
+std::unique_ptr<ArcSessionImpl::Delegate> ArcSessionImpl::CreateDelegate(
+ ArcBridgeService* arc_bridge_service) {
+ return std::make_unique<ArcSessionDelegateImpl>(arc_bridge_service);
+}
+
+ArcSessionImpl::ArcSessionImpl(std::unique_ptr<Delegate> delegate)
+ : delegate_(std::move(delegate)), weak_factory_(this) {
+ chromeos::SessionManagerClient* client = GetSessionManagerClient();
+ if (client == nullptr)
+ return;
+ client->AddObserver(this);
+}
+
+ArcSessionImpl::~ArcSessionImpl() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(state_ == State::NOT_STARTED || state_ == State::STOPPED);
+ chromeos::SessionManagerClient* client = GetSessionManagerClient();
+ if (client == nullptr)
+ return;
+ client->RemoveObserver(this);
+}
+
+void ArcSessionImpl::Start(ArcInstanceMode request_mode) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ target_mode_ = request_mode;
+ switch (request_mode) {
+ case ArcInstanceMode::MINI_INSTANCE:
+ StartMiniInstance();
+ return;
+ case ArcInstanceMode::FULL_INSTANCE:
+ StartFullInstance();
+ return;
+ }
+
+ NOTREACHED();
+}
+
+void ArcSessionImpl::StartMiniInstance() {
+ DCHECK_EQ(State::NOT_STARTED, state_);
+
+ VLOG(2) << "Starting ARC mini instance";
+ state_ = State::STARTING_MINI_INSTANCE;
+ SendStartArcInstanceDBusMessage(
+ target_mode_.value(),
+ base::BindOnce(&ArcSessionImpl::OnMiniInstanceStarted,
+ weak_factory_.GetWeakPtr()));
+}
+
+void ArcSessionImpl::OnMiniInstanceStarted(
+ chromeos::SessionManagerClient::StartArcInstanceResult result,
+ const std::string& container_instance_id,
+ base::ScopedFD socket_fd) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK_EQ(state_, State::STARTING_MINI_INSTANCE);
+
+ if (result != StartArcInstanceResult::SUCCESS) {
+ LOG(ERROR) << "Failed to start ARC instance";
+ OnStopped(GetArcStopReason(result, stop_requested_));
+ return;
+ }
+
+ DCHECK(!container_instance_id.empty());
+ container_instance_id_ = container_instance_id;
+ VLOG(2) << "ARC mini instance is successfully started: "
+ << container_instance_id_;
+
+ if (stop_requested_) {
+ // The ARC instance has started to run. Request to stop.
+ StopArcInstance();
+ return;
+ }
+
+ state_ = State::RUNNING_MINI_INSTANCE;
+
+ if (target_mode_ == ArcInstanceMode::FULL_INSTANCE) {
+ // Start(FULL_INSTANCE) has been called during the D-Bus call.
+ StartFullInstance();
+ }
+}
+
+void ArcSessionImpl::StartFullInstance() {
+ // StartFullInstance() can be called either for starting ARC from scratch or
+ // for upgrading to an existing one. StartFullInstance() must be able to
+ // start a fully functional instance from all of |state_| up to and including
+ // RUNNING_MINI_INSTANCE.
+ switch (state_) {
+ case State::NOT_STARTED:
+ // A mini instance does not exist. Start a new one from scratch.
+ VLOG(2) << "Starting ARC session";
+ state_ = State::STARTING_FULL_INSTANCE;
+ SendStartArcInstanceDBusMessage(
+ target_mode_.value(),
+ base::BindOnce(&ArcSessionImpl::OnFullInstanceStarted,
+ weak_factory_.GetWeakPtr()));
+ break;
+ case State::STARTING_MINI_INSTANCE:
+ VLOG(2) << "Requested to upgrade a starting ARC mini instance";
+ // OnMiniInstanceStarted() will restart a full instance.
+ break;
+ case State::RUNNING_MINI_INSTANCE:
+ VLOG(2) << "Upgrading an existing ARC mini instance";
+ state_ = State::STARTING_FULL_INSTANCE;
+ SendStartArcInstanceDBusMessage(
+ target_mode_.value(),
+ base::BindOnce(&ArcSessionImpl::OnFullInstanceStarted,
+ weak_factory_.GetWeakPtr()));
+ break;
+ case State::STARTING_FULL_INSTANCE:
+ case State::CONNECTING_MOJO:
+ case State::RUNNING_FULL_INSTANCE:
+ case State::STOPPED:
+ // These mean Start(FULL_INSTANCE) is called twice or called after
+ // stopped, which are invalid operations.
+ NOTREACHED();
+ break;
+ }
+}
+
+void ArcSessionImpl::OnFullInstanceStarted(
+ chromeos::SessionManagerClient::StartArcInstanceResult result,
+ const std::string& container_instance_id,
+ base::ScopedFD socket_fd) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK_EQ(state_, State::STARTING_FULL_INSTANCE);
+
+ if (result != StartArcInstanceResult::SUCCESS) {
+ LOG(ERROR) << "Failed to start ARC instance";
+ OnStopped(GetArcStopReason(result, stop_requested_));
+ return;
+ }
+
+ if (container_instance_id.empty()) {
+ // This was upgrade request.
+ VLOG(2) << "ARC instance is successfully upgraded.";
+ DCHECK(!container_instance_id_.empty());
+ } else {
+ // This was a request to start a full instance from scratch.
+ container_instance_id_ = container_instance_id;
+ VLOG(2) << "ARC instance is successfully started: "
+ << container_instance_id_;
+ }
+
+ if (stop_requested_) {
+ // The ARC instance has started to run. Request to stop.
+ StopArcInstance();
+ return;
+ }
+
+ VLOG(2) << "Connecting mojo...";
+ state_ = State::CONNECTING_MOJO;
+ accept_cancel_pipe_ = delegate_->ConnectMojo(
+ std::move(socket_fd), base::BindOnce(&ArcSessionImpl::OnMojoConnected,
+ weak_factory_.GetWeakPtr()));
+ if (!accept_cancel_pipe_.is_valid()) {
+ // Failed to post a task to accept() the request.
+ StopArcInstance();
+ return;
+ }
+}
+
+// static
+void ArcSessionImpl::SendStartArcInstanceDBusMessage(
+ ArcInstanceMode target_mode,
+ chromeos::SessionManagerClient::StartArcInstanceCallback callback) {
+ chromeos::SessionManagerClient* session_manager_client =
+ chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
+ const bool native_bridge_experiment =
+ base::FeatureList::IsEnabled(arc::kNativeBridgeExperimentFeature);
+ if (target_mode == ArcInstanceMode::MINI_INSTANCE) {
+ session_manager_client->StartArcInstance(
+ chromeos::SessionManagerClient::ArcStartupMode::LOGIN_SCREEN,
+ // All variables below except |callback| will be ignored.
+ cryptohome::Identification(), false, false, native_bridge_experiment,
+ std::move(callback));
+ return;
+ }
+ DCHECK_EQ(ArcInstanceMode::FULL_INSTANCE, target_mode);
+
+ user_manager::UserManager* user_manager = user_manager::UserManager::Get();
+ DCHECK(user_manager->GetPrimaryUser());
+ const cryptohome::Identification cryptohome_id(
+ user_manager->GetPrimaryUser()->GetAccountId());
+
+ const bool skip_boot_completed_broadcast =
+ !base::FeatureList::IsEnabled(arc::kBootCompletedBroadcastFeature);
+
+ // We only enable /vendor/priv-app when voice interaction is enabled because
+ // voice interaction service apk would be bundled in this location.
+ const bool scan_vendor_priv_app =
+ chromeos::switches::IsVoiceInteractionEnabled();
+
+ session_manager_client->StartArcInstance(
+ chromeos::SessionManagerClient::ArcStartupMode::FULL, cryptohome_id,
+ skip_boot_completed_broadcast, scan_vendor_priv_app,
+ native_bridge_experiment, std::move(callback));
+}
+
+void ArcSessionImpl::OnMojoConnected(
+ std::unique_ptr<mojom::ArcBridgeHost> arc_bridge_host) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK_EQ(state_, State::CONNECTING_MOJO);
+ accept_cancel_pipe_.reset();
+
+ if (stop_requested_) {
+ StopArcInstance();
+ return;
+ }
+
+ if (!arc_bridge_host.get()) {
+ LOG(ERROR) << "Invalid pipe.";
+ StopArcInstance();
+ return;
+ }
+ arc_bridge_host_ = std::move(arc_bridge_host);
+
+ VLOG(0) << "ARC ready.";
+ state_ = State::RUNNING_FULL_INSTANCE;
+}
+
+void ArcSessionImpl::Stop() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ VLOG(2) << "Stopping ARC session is requested.";
+
+ // For second time or later, just do nothing.
+ // It is already in the stopping phase.
+ if (stop_requested_)
+ return;
+
+ stop_requested_ = true;
+ arc_bridge_host_.reset();
+ switch (state_) {
+ case State::NOT_STARTED:
+ OnStopped(ArcStopReason::SHUTDOWN);
+ return;
+
+ case State::STARTING_MINI_INSTANCE:
+ case State::STARTING_FULL_INSTANCE:
+ // Before starting the ARC instance, we do nothing here.
+ // At some point, a callback will be invoked on UI thread,
+ // and stopping procedure will be run there.
+ // On Chrome shutdown, it is not the case because the message loop is
+ // already stopped here. Practically, it is not a problem because;
+ // - On starting instance, the container instance can be leaked.
+ // Practically it is not problematic because the session manager will
+ // clean it up.
+ return;
+
+ case State::RUNNING_MINI_INSTANCE:
+ case State::RUNNING_FULL_INSTANCE:
+ // An ARC {mini,full} instance is running. Request to stop it.
+ StopArcInstance();
+ return;
+
+ case State::CONNECTING_MOJO:
+ // Mojo connection is being waited on TaskScheduler's thread.
+ // Request to cancel it. Following stopping procedure will run
+ // in its callback.
+ accept_cancel_pipe_.reset();
+ return;
+
+ case State::STOPPED:
+ // The instance is already stopped. Do nothing.
+ return;
+ }
+}
+
+void ArcSessionImpl::StopArcInstance() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(state_ == State::STARTING_MINI_INSTANCE ||
+ state_ == State::RUNNING_MINI_INSTANCE ||
+ state_ == State::STARTING_FULL_INSTANCE ||
+ state_ == State::CONNECTING_MOJO ||
+ state_ == State::RUNNING_FULL_INSTANCE);
+
+ VLOG(2) << "Requesting session_manager to stop ARC instance";
+
+ // When the instance is full instance, change the |state_| in
+ // ArcInstanceStopped().
+ chromeos::SessionManagerClient* session_manager_client =
+ chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
+ // Since we have the ArcInstanceStopped() callback, we don't need to do
+ // anything when StopArcInstance completes.
+ session_manager_client->StopArcInstance(
+ chromeos::EmptyVoidDBusMethodCallback());
+}
+
+void ArcSessionImpl::ArcInstanceStopped(
+ bool clean,
+ const std::string& container_instance_id) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ VLOG(1) << "Notified that ARC instance is stopped "
+ << (clean ? "cleanly" : "uncleanly");
+
+ if (container_instance_id != container_instance_id_) {
+ VLOG(1) << "Container instance id mismatch. Do nothing."
+ << container_instance_id << " vs " << container_instance_id_;
+ return;
+ }
+
+ // Release |container_instance_id_| to avoid duplicate invocation situation.
+ container_instance_id_.clear();
+
+ // In case that crash happens during before the Mojo channel is connected,
+ // unlock the TaskScheduler's thread.
+ accept_cancel_pipe_.reset();
+
+ ArcStopReason reason;
+ if (stop_requested_) {
+ // If the ARC instance is stopped after its explicit request,
+ // return SHUTDOWN.
+ reason = ArcStopReason::SHUTDOWN;
+ } else if (clean) {
+ // If the ARC instance is stopped, but it is not explicitly requested,
+ // then this is triggered by some failure during the starting procedure.
+ // Return GENERIC_BOOT_FAILURE for the case.
+ reason = ArcStopReason::GENERIC_BOOT_FAILURE;
+ } else {
+ // Otherwise, this is caused by CRASH occured inside of the ARC instance.
+ reason = ArcStopReason::CRASH;
+ }
+ OnStopped(reason);
+}
+
+base::Optional<ArcInstanceMode> ArcSessionImpl::GetTargetMode() {
+ return target_mode_;
+}
+
+bool ArcSessionImpl::IsStopRequested() {
+ return stop_requested_;
+}
+
+void ArcSessionImpl::OnStopped(ArcStopReason reason) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ // OnStopped() should be called once per instance.
+ DCHECK_NE(state_, State::STOPPED);
+ VLOG(2) << "ARC session is stopped.";
+ const bool was_running = (state_ == State::RUNNING_FULL_INSTANCE);
+ arc_bridge_host_.reset();
+ state_ = State::STOPPED;
+ for (auto& observer : observer_list_)
+ observer.OnSessionStopped(reason, was_running);
+}
+
+void ArcSessionImpl::OnShutdown() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ stop_requested_ = true;
+ if (state_ == State::STOPPED)
+ return;
+
+ // Here, the message loop is already stopped, and the Chrome will be soon
+ // shutdown. Thus, it is not necessary to take care about restarting case.
+ // If ArcSession is waiting for mojo connection, cancels it.
+ accept_cancel_pipe_.reset();
+
+ // Stops the ARC instance to let it graceful shutdown.
+ // Note that this may fail if ARC container is not actually running, but
+ // ignore an error as described below.
+ if (state_ == State::STARTING_MINI_INSTANCE ||
+ state_ == State::RUNNING_MINI_INSTANCE ||
+ state_ == State::STARTING_FULL_INSTANCE ||
+ state_ == State::CONNECTING_MOJO ||
+ state_ == State::RUNNING_FULL_INSTANCE) {
+ StopArcInstance();
+ }
+
+ // Directly set to the STOPPED state by OnStopped(). Note that calling
+ // StopArcInstance() may not work well. At least, because the UI thread is
+ // already stopped here, ArcInstanceStopped() callback cannot be invoked.
+ OnStopped(ArcStopReason::SHUTDOWN);
+}
+
+std::ostream& operator<<(std::ostream& os, ArcSessionImpl::State state) {
+#define MAP_STATE(name) \
+ case ArcSessionImpl::State::name: \
+ return os << #name
+
+ switch (state) {
+ MAP_STATE(NOT_STARTED);
+ MAP_STATE(STARTING_MINI_INSTANCE);
+ MAP_STATE(RUNNING_MINI_INSTANCE);
+ MAP_STATE(STARTING_FULL_INSTANCE);
+ MAP_STATE(CONNECTING_MOJO);
+ MAP_STATE(RUNNING_FULL_INSTANCE);
+ MAP_STATE(STOPPED);
+ }
+#undef MAP_STATE
+
+ // Some compilers report an error even if all values of an enum-class are
+ // covered exhaustively in a switch statement.
+ NOTREACHED() << "Invalid value " << static_cast<int>(state);
+ return os;
+}
+
+} // namespace arc
diff --git a/chromium/components/arc/arc_session_impl.h b/chromium/components/arc/arc_session_impl.h
new file mode 100644
index 00000000000..d52a52f5bbd
--- /dev/null
+++ b/chromium/components/arc/arc_session_impl.h
@@ -0,0 +1,242 @@
+// 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 COMPONENTS_ARC_ARC_SESSION_IMPL_H_
+#define COMPONENTS_ARC_ARC_SESSION_IMPL_H_
+
+#include <memory>
+#include <ostream>
+#include <string>
+
+#include "base/callback.h"
+#include "base/files/scoped_file.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "base/threading/thread_checker.h"
+#include "chromeos/dbus/session_manager_client.h"
+#include "components/arc/arc_instance_mode.h"
+#include "components/arc/arc_session.h"
+
+namespace arc {
+
+namespace mojom {
+class ArcBridgeHost;
+} // namespace mojom
+
+class ArcSessionImpl : public ArcSession,
+ public chromeos::SessionManagerClient::Observer {
+ public:
+ // The possible states of the session. Expected state changes are as follows.
+ //
+ // 1) Starting MINI_INSTANCE.
+ // NOT_STARTED
+ // -> StartMiniInstance() ->
+ // STARTING_MINI_INSTANCE
+ // -> OnMiniInstanceStarted() ->
+ // RUNNING_MINI_INSTANCE.
+ //
+ // 2) Starting FULL_INSTANCE.
+ // NOT_STARTED
+ // -> StartFullInstance() ->
+ // STARTING_FULL_INSTANCE
+ // -> OnFullInstanceStarted() ->
+ // CONNECTING_MOJO
+ // -> OnMojoConnected() ->
+ // RUNNING_FULL_INSTANCE
+ //
+ // 3) Upgrading from a MINI_INSTANCE to FULL_INSTANCE.
+ // RUNNING_MINI_INSTANCE
+ // -> StartFullInstance() ->
+ // STARTING_FULL_INSTANCE
+ // -> ... (remaining is as same as (2)).
+ //
+ // Note that, if Start(FULL_INSTANCE) is called during STARTING_MINI_INSTANCE
+ // state, the state change to STARTING_FULL_INSTANCE is suspended until
+ // the state becomes RUNNING_MINI_INSTANCE.
+ //
+ // At any state, Stop() can be called. It may not immediately stop the
+ // instance, but will eventually stop it. The actual stop will be notified
+ // via ArcSession::Observer::OnSessionStopped().
+ //
+ // When Stop() is called, it makes various behavior based on the current
+ // phase.
+ //
+ // NOT_STARTED:
+ // Do nothing. Immediately transition to the STOPPED state.
+ // STARTING_{MINI,FULL}_INSTANCE:
+ // The ARC instance is starting via SessionManager. Stop() just sets the
+ // flag and return. On the main task completion, a callback will run on the
+ // thread, and the flag is checked at the beginning of them. This should
+ // work under the assumption that the main tasks do not block indefinitely.
+ // In its callback, it checks if ARC instance is successfully started or
+ // not. In case of success, a request to stop the ARC instance is sent to
+ // SessionManager. Its completion will be notified via ArcInstanceStopped.
+ // Otherwise, it just turns into STOPPED state.
+ // CONNECTING_MOJO:
+ // The main task runs on TaskScheduler's thread, but it is a blocking call.
+ // So, Stop() sends a request to cancel the blocking by closing the pipe
+ // whose read side is also polled. Then, in its callback, similar to
+ // STARTING_{MINI,FULL}_INSTANCE, a request to stop the ARC instance is
+ // sent to SessionManager, and ArcInstanceStopped handles remaining
+ // procedure.
+ // RUNNING_{MINI,FULL}_INSTANCE:
+ // There is no more callback which runs on normal flow, so Stop() requests
+ // to stop the ARC instance via SessionManager.
+ //
+ // Another trigger to change the state coming from outside of this class
+ // is an event ArcInstanceStopped() sent from SessionManager, when ARC
+ // instace unexpectedly terminates. ArcInstanceStopped() turns the state into
+ // STOPPED immediately.
+ //
+ // In NOT_STARTED or STOPPED state, the instance can be safely destructed.
+ // Specifically, in STOPPED state, there may be inflight operations or
+ // pending callbacks. Though, what they do is just do-nothing conceptually
+ // and they can be safely ignored.
+ //
+ // Note: Order of constants below matters. Please make sure to sort them
+ // in chronological order.
+ enum class State {
+ // ARC is not yet started.
+ NOT_STARTED,
+
+ // The request to start a mini instance has been sent.
+ STARTING_MINI_INSTANCE,
+
+ // The instance is set up, but only a handful of processes NOT including
+ // arcbridgeservice (i.e. mojo endpoint) are running.
+ RUNNING_MINI_INSTANCE,
+
+ // The request to start or upgrade to a full instance has been sent.
+ STARTING_FULL_INSTANCE,
+
+ // The instance has started. Waiting for it to connect to the IPC bridge.
+ CONNECTING_MOJO,
+
+ // The instance is fully set up.
+ RUNNING_FULL_INSTANCE,
+
+ // ARC is terminated.
+ STOPPED,
+ };
+
+ // Delegate interface to emulate ArcBridgeHost mojo connection establishment.
+ class Delegate {
+ public:
+ // Used for ConnectMojo completion callback.
+ using ConnectMojoCallback =
+ base::OnceCallback<void(std::unique_ptr<mojom::ArcBridgeHost>)>;
+
+ virtual ~Delegate() = default;
+
+ // Connects ArcBridgeHost via |socket_fd|, and invokes |callback| with
+ // connected ArcBridgeHost instance if succeeded (or nullptr if failed).
+ // Returns a FD which cancels the current connection on close(2).
+ virtual base::ScopedFD ConnectMojo(base::ScopedFD socket_fd,
+ ConnectMojoCallback callback) = 0;
+ };
+
+ explicit ArcSessionImpl(std::unique_ptr<Delegate> delegate);
+ ~ArcSessionImpl() override;
+
+ // Returns default delegate implementation used for the production.
+ static std::unique_ptr<Delegate> CreateDelegate(
+ ArcBridgeService* arc_bridge_service);
+
+ State GetStateForTesting() { return state_; }
+
+ // ArcSession overrides:
+ void Start(ArcInstanceMode request_mode) override;
+ void Stop() override;
+ base::Optional<ArcInstanceMode> GetTargetMode() override;
+ bool IsStopRequested() override;
+ void OnShutdown() override;
+
+ private:
+ // Sends a D-Bus message to start a mini instance.
+ void StartMiniInstance();
+
+ // D-Bus callback for StartArcInstance() for a mini instance.
+ // In case of success, |container_instance_id| must not be empty, and
+ // |socket_fd| is /dev/null.
+ // TODO(hidehiko): Remove |socket_fd| from this callback.
+ void OnMiniInstanceStarted(
+ chromeos::SessionManagerClient::StartArcInstanceResult result,
+ const std::string& container_instance_id,
+ base::ScopedFD socket_fd);
+
+ // Sends a D-Bus message to start or to upgrade to a full instance.
+ void StartFullInstance();
+
+ // D-Bus callback for StartArcInstance() for a full instance.
+ // In case of success, |container_instance_id| must not be empty, if this is
+ // actually starting an instance, or empty if this is upgrade from a mini
+ // instance to a full instance.
+ // In either start or upgrade case, |socket_fd| should be a socket which
+ // shold be accept(2)ed to connect ArcBridgeService Mojo channel.
+ void OnFullInstanceStarted(
+ chromeos::SessionManagerClient::StartArcInstanceResult result,
+ const std::string& container_instance_id,
+ base::ScopedFD socket_fd);
+
+ // Called when Mojo connection is established (or canceled during the
+ // connect.)
+ void OnMojoConnected(std::unique_ptr<mojom::ArcBridgeHost> arc_bridge_host);
+
+ // Request to stop ARC instance via DBus.
+ void StopArcInstance();
+
+ // chromeos::SessionManagerClient::Observer:
+ void ArcInstanceStopped(bool clean,
+ const std::string& container_instance_id) override;
+
+ // Completes the termination procedure. Note that calling this may end up with
+ // deleting |this| because the function calls observers' OnSessionStopped().
+ void OnStopped(ArcStopReason reason);
+
+ // Sends a StartArcInstance D-Bus request to session_manager.
+ static void SendStartArcInstanceDBusMessage(
+ ArcInstanceMode target_mode,
+ chromeos::SessionManagerClient::StartArcInstanceCallback callback);
+
+ // Checks whether a function runs on the thread where the instance is
+ // created.
+ THREAD_CHECKER(thread_checker_);
+
+ // Delegate implementation.
+ std::unique_ptr<Delegate> delegate_;
+
+ // The state of the session.
+ State state_ = State::NOT_STARTED;
+
+ // When Stop() is called, this flag is set.
+ bool stop_requested_ = false;
+
+ // In which mode this instance should be running eventually.
+ // Initialized in nullopt.
+ base::Optional<ArcInstanceMode> target_mode_;
+
+ // Container instance id passed from session_manager.
+ // Should be available only after On{Mini,Full}InstanceStarted().
+ std::string container_instance_id_;
+
+ // In CONNECTING_MOJO state, this is set to the write side of the pipe
+ // to notify cancelling of the procedure.
+ base::ScopedFD accept_cancel_pipe_;
+
+ // Mojo endpoint.
+ std::unique_ptr<mojom::ArcBridgeHost> arc_bridge_host_;
+
+ // WeakPtrFactory to use callbacks.
+ base::WeakPtrFactory<ArcSessionImpl> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ArcSessionImpl);
+};
+
+// Stringified output for logging purpose.
+std::ostream& operator<<(std::ostream& os, ArcSessionImpl::State state);
+
+} // namespace arc
+
+#endif // COMPONENTS_ARC_ARC_SESSION_IMPL_H_
diff --git a/chromium/components/arc/arc_session_impl_unittest.cc b/chromium/components/arc/arc_session_impl_unittest.cc
new file mode 100644
index 00000000000..bf513ab63b7
--- /dev/null
+++ b/chromium/components/arc/arc_session_impl_unittest.cc
@@ -0,0 +1,648 @@
+// 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 <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <memory>
+#include <utility>
+
+#include "base/location.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/fake_session_manager_client.h"
+#include "components/arc/arc_session_impl.h"
+#include "components/arc/test/fake_arc_bridge_host.h"
+#include "components/signin/core/account_id/account_id.h"
+#include "components/user_manager/fake_user_manager.h"
+#include "components/user_manager/scoped_user_manager.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+namespace {
+
+constexpr char kFakeGmail[] = "user@gmail.com";
+constexpr char kFakeGmailGaiaId[] = "1234567890";
+
+class FakeDelegate : public ArcSessionImpl::Delegate {
+ public:
+ FakeDelegate() = default;
+
+ // Emulates to fail Mojo connection establishing. |callback| passed to
+ // ConnectMojo will be called with nullptr.
+ void EmulateMojoConnectionFailure() { success_ = false; }
+
+ // Suspends to complete the MojoConnection, when ConnectMojo is called.
+ // Later, when ResumeMojoConnection() is called, the passed callback will be
+ // asynchronously called.
+ void SuspendMojoConnection() { suspend_ = true; }
+
+ // Resumes the pending Mojo connection establishment. Before,
+ // SuspendMojoConnection() must be called followed by ConnectMojo().
+ // ConnectMojo's |callback| will be called asynchronously.
+ void ResumeMojoConnection() {
+ DCHECK(!pending_callback_.is_null());
+ PostCallback(std::move(pending_callback_));
+ }
+
+ // ArcSessionImpl::Delegate override:
+ base::ScopedFD ConnectMojo(base::ScopedFD socket_fd,
+ ConnectMojoCallback callback) override {
+ if (suspend_) {
+ DCHECK(pending_callback_.is_null());
+ pending_callback_ = std::move(callback);
+ } else {
+ PostCallback(std::move(callback));
+ }
+
+ // Open /dev/null as a dummy FD.
+ return base::ScopedFD(HANDLE_EINTR(open("/dev/null", O_RDONLY)));
+ }
+
+ private:
+ void PostCallback(ConnectMojoCallback callback) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ std::move(callback),
+ success_ ? std::make_unique<FakeArcBridgeHost>() : nullptr));
+ }
+
+ bool success_ = true;
+ bool suspend_ = false;
+ ConnectMojoCallback pending_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeDelegate);
+};
+
+class TestArcSessionObserver : public ArcSession::Observer {
+ public:
+ struct OnSessionStoppedArgs {
+ ArcStopReason reason;
+ bool was_running;
+ };
+
+ explicit TestArcSessionObserver(ArcSession* arc_session)
+ : arc_session_(arc_session) {
+ arc_session_->AddObserver(this);
+ }
+
+ ~TestArcSessionObserver() override { arc_session_->RemoveObserver(this); }
+
+ const base::Optional<OnSessionStoppedArgs>& on_session_stopped_args() const {
+ return on_session_stopped_args_;
+ }
+
+ // ArcSession::Observer overrides:
+ void OnSessionStopped(ArcStopReason reason, bool was_running) override {
+ on_session_stopped_args_.emplace(OnSessionStoppedArgs{reason, was_running});
+ }
+
+ private:
+ ArcSession* const arc_session_; // Not owned.
+ base::Optional<OnSessionStoppedArgs> on_session_stopped_args_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestArcSessionObserver);
+};
+
+// Custom deleter for ArcSession testing.
+struct ArcSessionDeleter {
+ void operator()(ArcSession* arc_session) {
+ // ArcSessionImpl must be in STOPPED state, if the instance is being
+ // destroyed. Calling OnShutdown() just before ensures it.
+ arc_session->OnShutdown();
+ delete arc_session;
+ }
+};
+
+class ArcSessionImplTest : public testing::Test {
+ public:
+ ArcSessionImplTest() {
+ chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
+ std::make_unique<chromeos::FakeSessionManagerClient>());
+ GetSessionManagerClient()->set_arc_available(true);
+
+ // Create a user and set it as the primary user.
+ const AccountId account_id =
+ AccountId::FromUserEmailGaiaId(kFakeGmail, kFakeGmailGaiaId);
+ const user_manager::User* user = GetUserManager()->AddUser(account_id);
+ GetUserManager()->UserLoggedIn(account_id, user->username_hash(),
+ false /* browser_restart */,
+ false /* is_child */);
+ }
+
+ ~ArcSessionImplTest() override {
+ GetUserManager()->RemoveUserFromList(
+ AccountId::FromUserEmailGaiaId(kFakeGmail, kFakeGmailGaiaId));
+ chromeos::DBusThreadManager::Shutdown();
+ }
+
+ chromeos::FakeSessionManagerClient* GetSessionManagerClient() {
+ return static_cast<chromeos::FakeSessionManagerClient*>(
+ chromeos::DBusThreadManager::Get()->GetSessionManagerClient());
+ }
+
+ user_manager::FakeUserManager* GetUserManager() {
+ return static_cast<user_manager::FakeUserManager*>(
+ user_manager::UserManager::Get());
+ }
+
+ void EmulateDBusFailure() {
+ GetSessionManagerClient()->set_arc_available(false);
+ }
+
+ std::unique_ptr<ArcSessionImpl, ArcSessionDeleter> CreateArcSession(
+ std::unique_ptr<ArcSessionImpl::Delegate> delegate = nullptr) {
+ if (!delegate)
+ delegate = std::make_unique<FakeDelegate>();
+ return std::unique_ptr<ArcSessionImpl, ArcSessionDeleter>(
+ new ArcSessionImpl(std::move(delegate)));
+ }
+
+ void SetupMiniContainer(ArcSessionImpl* arc_session,
+ TestArcSessionObserver* observer) {
+ arc_session->Start(ArcInstanceMode::MINI_INSTANCE);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(ArcSessionImpl::State::RUNNING_MINI_INSTANCE,
+ arc_session->GetStateForTesting());
+ ASSERT_FALSE(observer->on_session_stopped_args().has_value());
+ }
+
+ private:
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+ user_manager::ScopedUserManager scoped_user_manager_{
+ std::make_unique<user_manager::FakeUserManager>()};
+
+ DISALLOW_COPY_AND_ASSIGN(ArcSessionImplTest);
+};
+
+// Simple case. Starting FULL_INSTANCE will eventually start the container.
+TEST_F(ArcSessionImplTest, FullInstance_Success) {
+ auto arc_session = CreateArcSession();
+ TestArcSessionObserver observer(arc_session.get());
+ arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(ArcSessionImpl::State::RUNNING_FULL_INSTANCE,
+ arc_session->GetStateForTesting());
+ EXPECT_FALSE(observer.on_session_stopped_args().has_value());
+}
+
+// SessionManagerClient::StartArcInstance() reports an error, so that
+// the container fails to start.
+TEST_F(ArcSessionImplTest, FullInstance_DBusFail) {
+ EmulateDBusFailure();
+
+ auto arc_session = CreateArcSession();
+ TestArcSessionObserver observer(arc_session.get());
+ arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
+ ASSERT_TRUE(observer.on_session_stopped_args().has_value());
+ EXPECT_EQ(ArcStopReason::GENERIC_BOOT_FAILURE,
+ observer.on_session_stopped_args()->reason);
+ EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+}
+
+// SessionManagerClient::StartArcInstance() fails due to low disk, so that
+// the container fails to start with reporting LOW_DISK_SPACE.
+TEST_F(ArcSessionImplTest, FullInstance_LowDisk) {
+ GetSessionManagerClient()->set_low_disk(true);
+
+ auto arc_session = CreateArcSession();
+ TestArcSessionObserver observer(arc_session.get());
+ arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
+ ASSERT_TRUE(observer.on_session_stopped_args().has_value());
+ EXPECT_EQ(ArcStopReason::LOW_DISK_SPACE,
+ observer.on_session_stopped_args()->reason);
+ EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+}
+
+// Mojo connection fails, so that the container fails to start.
+TEST_F(ArcSessionImplTest, FullInstance_MojoConnectionFail) {
+ auto delegate = std::make_unique<FakeDelegate>();
+ delegate->EmulateMojoConnectionFailure();
+
+ auto arc_session = CreateArcSession(std::move(delegate));
+ TestArcSessionObserver observer(arc_session.get());
+ arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
+ ASSERT_TRUE(observer.on_session_stopped_args().has_value());
+ EXPECT_EQ(ArcStopReason::GENERIC_BOOT_FAILURE,
+ observer.on_session_stopped_args()->reason);
+ EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+}
+
+// Starting mini container success case.
+TEST_F(ArcSessionImplTest, MiniInstance_Success) {
+ auto arc_session = CreateArcSession();
+ TestArcSessionObserver observer(arc_session.get());
+ arc_session->Start(ArcInstanceMode::MINI_INSTANCE);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(ArcSessionImpl::State::RUNNING_MINI_INSTANCE,
+ arc_session->GetStateForTesting());
+ EXPECT_FALSE(observer.on_session_stopped_args().has_value());
+}
+
+// SessionManagerClient::StartArcInstance() reports an error, so that
+// the container fails to start as a mini container.
+TEST_F(ArcSessionImplTest, MiniInstance_DBusFail) {
+ EmulateDBusFailure();
+
+ auto arc_session = CreateArcSession();
+ TestArcSessionObserver observer(arc_session.get());
+ arc_session->Start(ArcInstanceMode::MINI_INSTANCE);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
+ ASSERT_TRUE(observer.on_session_stopped_args().has_value());
+ EXPECT_EQ(ArcStopReason::GENERIC_BOOT_FAILURE,
+ observer.on_session_stopped_args()->reason);
+ EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+}
+
+// SessionManagerClient::StartArcInstance() reports an error due to low disk,
+// so that the container fails to start as a mini container with reporting
+// LOW_DISK_SPACE.
+TEST_F(ArcSessionImplTest, MiniInstance_LowDisk) {
+ GetSessionManagerClient()->set_low_disk(true);
+
+ auto arc_session = CreateArcSession();
+ TestArcSessionObserver observer(arc_session.get());
+ arc_session->Start(ArcInstanceMode::MINI_INSTANCE);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
+ ASSERT_TRUE(observer.on_session_stopped_args().has_value());
+ EXPECT_EQ(ArcStopReason::LOW_DISK_SPACE,
+ observer.on_session_stopped_args()->reason);
+ EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+}
+
+// Upgrading a mini container to a full container. Success case.
+TEST_F(ArcSessionImplTest, Upgrade_Success) {
+ // Set up. Start a mini instance.
+ auto arc_session = CreateArcSession();
+ TestArcSessionObserver observer(arc_session.get());
+ ASSERT_NO_FATAL_FAILURE(SetupMiniContainer(arc_session.get(), &observer));
+
+ // Then, upgrade to a full instance.
+ arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(ArcSessionImpl::State::RUNNING_FULL_INSTANCE,
+ arc_session->GetStateForTesting());
+ EXPECT_FALSE(observer.on_session_stopped_args().has_value());
+}
+
+// SessionManagerClient::StartArcInstance() reports an error for upgrading
+// case, then the upgrading fails.
+TEST_F(ArcSessionImplTest, Upgrade_DBusFail) {
+ // Set up. Start a mini instance.
+ auto arc_session = CreateArcSession();
+ TestArcSessionObserver observer(arc_session.get());
+ ASSERT_NO_FATAL_FAILURE(SetupMiniContainer(arc_session.get(), &observer));
+
+ // Hereafter, let SessionManagerClient::StartArcInstance() fail.
+ EmulateDBusFailure();
+
+ // Then upgrade, which should fail.
+ arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
+ ASSERT_TRUE(observer.on_session_stopped_args().has_value());
+ EXPECT_EQ(ArcStopReason::GENERIC_BOOT_FAILURE,
+ observer.on_session_stopped_args()->reason);
+ EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+}
+
+// Mojo connection fails on upgrading. Then, the upgrade fails.
+TEST_F(ArcSessionImplTest, Upgrade_MojoConnectionFail) {
+ // Let Mojo connection fail.
+ auto delegate = std::make_unique<FakeDelegate>();
+ delegate->EmulateMojoConnectionFailure();
+
+ // Set up. Start mini instance.
+ auto arc_session = CreateArcSession(std::move(delegate));
+ TestArcSessionObserver observer(arc_session.get());
+ // Starting mini instance should succeed, because it is not related to
+ // Mojo connection.
+ ASSERT_NO_FATAL_FAILURE(SetupMiniContainer(arc_session.get(), &observer));
+
+ // Upgrade should fail, due to Mojo connection fail set above.
+ arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
+ ASSERT_TRUE(observer.on_session_stopped_args().has_value());
+ EXPECT_EQ(ArcStopReason::GENERIC_BOOT_FAILURE,
+ observer.on_session_stopped_args()->reason);
+ EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+}
+
+// Calling StartArcInstance() during STARTING_MINI_INSTANCE should eventually
+// succeed to run a full container.
+TEST_F(ArcSessionImplTest, Upgrade_StartingMiniInstance) {
+ auto arc_session = CreateArcSession();
+ TestArcSessionObserver observer(arc_session.get());
+ arc_session->Start(ArcInstanceMode::MINI_INSTANCE);
+ ASSERT_EQ(ArcSessionImpl::State::STARTING_MINI_INSTANCE,
+ arc_session->GetStateForTesting());
+
+ // Before moving forward to RUNNING_MINI_INSTANCE, start upgrading it.
+ arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+
+ // The state should not immediately switch to STARTING_FULL_INSTANCE, yet.
+ EXPECT_EQ(ArcSessionImpl::State::STARTING_MINI_INSTANCE,
+ arc_session->GetStateForTesting());
+
+ // Complete the upgrade procedure.
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(ArcSessionImpl::State::RUNNING_FULL_INSTANCE,
+ arc_session->GetStateForTesting());
+ EXPECT_FALSE(observer.on_session_stopped_args().has_value());
+}
+
+// Testing stop during START_MINI_INSTANCE.
+TEST_F(ArcSessionImplTest, Stop_StartingMiniInstance) {
+ auto arc_session = CreateArcSession();
+ TestArcSessionObserver observer(arc_session.get());
+ arc_session->Start(ArcInstanceMode::MINI_INSTANCE);
+ ASSERT_EQ(ArcSessionImpl::State::STARTING_MINI_INSTANCE,
+ arc_session->GetStateForTesting());
+
+ arc_session->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
+ ASSERT_TRUE(observer.on_session_stopped_args().has_value());
+ EXPECT_EQ(ArcStopReason::SHUTDOWN,
+ observer.on_session_stopped_args()->reason);
+ EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+}
+
+// Testing stop during RUNNING_MINI_INSTANCE.
+TEST_F(ArcSessionImplTest, Stop_RunningMiniInstance) {
+ auto arc_session = CreateArcSession();
+ TestArcSessionObserver observer(arc_session.get());
+ arc_session->Start(ArcInstanceMode::MINI_INSTANCE);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(ArcSessionImpl::State::RUNNING_MINI_INSTANCE,
+ arc_session->GetStateForTesting());
+
+ arc_session->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
+ ASSERT_TRUE(observer.on_session_stopped_args().has_value());
+ EXPECT_EQ(ArcStopReason::SHUTDOWN,
+ observer.on_session_stopped_args()->reason);
+ EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+}
+
+// Testing stop during STARTING_FULL_INSTANCE.
+TEST_F(ArcSessionImplTest, Stop_StartingFullInstance) {
+ auto arc_session = CreateArcSession();
+ TestArcSessionObserver observer(arc_session.get());
+ arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ ASSERT_EQ(ArcSessionImpl::State::STARTING_FULL_INSTANCE,
+ arc_session->GetStateForTesting());
+
+ arc_session->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
+ ASSERT_TRUE(observer.on_session_stopped_args().has_value());
+ EXPECT_EQ(ArcStopReason::SHUTDOWN,
+ observer.on_session_stopped_args()->reason);
+ EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+}
+
+// Testing stop during CONNECTING_MOJO.
+TEST_F(ArcSessionImplTest, Stop_ConnectingMojo) {
+ // Let Mojo connection suspend.
+ auto delegate = std::make_unique<FakeDelegate>();
+ delegate->SuspendMojoConnection();
+ auto* delegate_ptr = delegate.get();
+ auto arc_session = CreateArcSession(std::move(delegate));
+ TestArcSessionObserver observer(arc_session.get());
+ arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(ArcSessionImpl::State::CONNECTING_MOJO,
+ arc_session->GetStateForTesting());
+
+ arc_session->Stop();
+ delegate_ptr->ResumeMojoConnection();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
+ ASSERT_TRUE(observer.on_session_stopped_args().has_value());
+ EXPECT_EQ(ArcStopReason::SHUTDOWN,
+ observer.on_session_stopped_args()->reason);
+ EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+}
+
+// Testing stop during RUNNING_FULL_INSTANCE.
+TEST_F(ArcSessionImplTest, Stop_RunningFullInstance) {
+ auto arc_session = CreateArcSession();
+ TestArcSessionObserver observer(arc_session.get());
+ arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(ArcSessionImpl::State::RUNNING_FULL_INSTANCE,
+ arc_session->GetStateForTesting());
+
+ arc_session->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
+ ASSERT_TRUE(observer.on_session_stopped_args().has_value());
+ EXPECT_EQ(ArcStopReason::SHUTDOWN,
+ observer.on_session_stopped_args()->reason);
+ EXPECT_TRUE(observer.on_session_stopped_args()->was_running);
+}
+
+// Testing stop during STARTING_FULL_INSTANCE for upgrade.
+TEST_F(ArcSessionImplTest, Stop_StartingFullInstanceForUpgrade) {
+ auto arc_session = CreateArcSession();
+ TestArcSessionObserver observer(arc_session.get());
+ // Start mini container.
+ ASSERT_NO_FATAL_FAILURE(SetupMiniContainer(arc_session.get(), &observer));
+
+ // Then upgrade.
+ arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ ASSERT_EQ(ArcSessionImpl::State::STARTING_FULL_INSTANCE,
+ arc_session->GetStateForTesting());
+
+ // Request to stop during STARTING_FULL_INSTANCE state.
+ arc_session->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
+ ASSERT_TRUE(observer.on_session_stopped_args().has_value());
+ EXPECT_EQ(ArcStopReason::SHUTDOWN,
+ observer.on_session_stopped_args()->reason);
+ EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+}
+
+// Testing stop during CONNECTING_MOJO for upgrade.
+TEST_F(ArcSessionImplTest, Stop_ConnectingMojoForUpgrade) {
+ // Let Mojo connection suspend.
+ auto delegate = std::make_unique<FakeDelegate>();
+ delegate->SuspendMojoConnection();
+ auto* delegate_ptr = delegate.get();
+ auto arc_session = CreateArcSession(std::move(delegate));
+ TestArcSessionObserver observer(arc_session.get());
+ // Start mini container.
+ ASSERT_NO_FATAL_FAILURE(SetupMiniContainer(arc_session.get(), &observer));
+
+ // Then upgrade. This should suspend at Mojo connection.
+ arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(ArcSessionImpl::State::CONNECTING_MOJO,
+ arc_session->GetStateForTesting());
+
+ // Request to stop, then resume the Mojo connection.
+ arc_session->Stop();
+ delegate_ptr->ResumeMojoConnection();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
+ ASSERT_TRUE(observer.on_session_stopped_args().has_value());
+ EXPECT_EQ(ArcStopReason::SHUTDOWN,
+ observer.on_session_stopped_args()->reason);
+ EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+}
+
+// Testing stop during RUNNING_FULL_INSTANCE after upgrade.
+TEST_F(ArcSessionImplTest, Stop_RunningFullInstanceForUpgrade) {
+ auto arc_session = CreateArcSession();
+ TestArcSessionObserver observer(arc_session.get());
+ // Start mini container.
+ ASSERT_NO_FATAL_FAILURE(SetupMiniContainer(arc_session.get(), &observer));
+
+ // And upgrade successfully.
+ arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(ArcSessionImpl::State::RUNNING_FULL_INSTANCE,
+ arc_session->GetStateForTesting());
+
+ // Then request to stop.
+ arc_session->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
+ ASSERT_TRUE(observer.on_session_stopped_args().has_value());
+ EXPECT_EQ(ArcStopReason::SHUTDOWN,
+ observer.on_session_stopped_args()->reason);
+ EXPECT_TRUE(observer.on_session_stopped_args()->was_running);
+}
+
+// Testing stop during STARTING_MINI_INSTANCE with upgrade request.
+TEST_F(ArcSessionImplTest,
+ Stop_StartingFullInstanceForUpgradeDuringMiniInstanceStart) {
+ auto arc_session = CreateArcSession();
+ TestArcSessionObserver observer(arc_session.get());
+ arc_session->Start(ArcInstanceMode::MINI_INSTANCE);
+ ASSERT_EQ(ArcSessionImpl::State::STARTING_MINI_INSTANCE,
+ arc_session->GetStateForTesting());
+
+ // Request to upgrade during starting mini container.
+ arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ // Then, the state should stay at STARTING_MINI_INSTANCE.
+ ASSERT_EQ(ArcSessionImpl::State::STARTING_MINI_INSTANCE,
+ arc_session->GetStateForTesting());
+
+ // Request to stop.
+ arc_session->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
+ ASSERT_TRUE(observer.on_session_stopped_args().has_value());
+ EXPECT_EQ(ArcStopReason::SHUTDOWN,
+ observer.on_session_stopped_args()->reason);
+ EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+}
+
+// Stop is requested, but at the same time
+// SessionManagerClient::StartArcInstance() reports an error. Then, it should
+// be handled as regular SHUTDOWN, because graceful shutdown itself is
+// difficult and sometimes reports unexpected error although it succeeds.
+TEST_F(ArcSessionImplTest, Stop_ConflictWithFailure) {
+ // Let SessionManagerClient::StartArcInstance() fail.
+ EmulateDBusFailure();
+
+ auto arc_session = CreateArcSession();
+ TestArcSessionObserver observer(arc_session.get());
+ arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ ASSERT_EQ(ArcSessionImpl::State::STARTING_FULL_INSTANCE,
+ arc_session->GetStateForTesting());
+
+ arc_session->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
+ ASSERT_TRUE(observer.on_session_stopped_args().has_value());
+ // Even if D-Bus reports an error, if Stop() is invoked, it will be handled
+ // as clean shutdown.
+ EXPECT_EQ(ArcStopReason::SHUTDOWN,
+ observer.on_session_stopped_args()->reason);
+ EXPECT_FALSE(observer.on_session_stopped_args()->was_running);
+}
+
+// Emulating crash.
+TEST_F(ArcSessionImplTest, ArcStopInstance) {
+ auto arc_session = CreateArcSession();
+ TestArcSessionObserver observer(arc_session.get());
+ arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(ArcSessionImpl::State::RUNNING_FULL_INSTANCE,
+ arc_session->GetStateForTesting());
+
+ // Deliver the ArcInstanceStopped D-Bus signal.
+ auto* session_manager_client = GetSessionManagerClient();
+ session_manager_client->NotifyArcInstanceStopped(
+ false /* meaning crash */,
+ session_manager_client->container_instance_id());
+
+ EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
+ ASSERT_TRUE(observer.on_session_stopped_args().has_value());
+ EXPECT_EQ(ArcStopReason::CRASH, observer.on_session_stopped_args()->reason);
+ EXPECT_TRUE(observer.on_session_stopped_args()->was_running);
+}
+
+// ArcStopInstance for the *previous* ARC container may be reported
+// to the current instance in very racy timing.
+// Unrelated ArcStopInstance signal should be ignored.
+TEST_F(ArcSessionImplTest, ArcStopInstance_WrongContainerInstanceId) {
+ auto arc_session = CreateArcSession();
+ arc_session->Start(ArcInstanceMode::FULL_INSTANCE);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(ArcSessionImpl::State::RUNNING_FULL_INSTANCE,
+ arc_session->GetStateForTesting());
+
+ // Deliver the ArcInstanceStopped D-Bus signal.
+ auto* session_manager_client = GetSessionManagerClient();
+ session_manager_client->NotifyArcInstanceStopped(false /* meaning crash */,
+ "dummy instance id");
+
+ // The signal should be ignored.
+ EXPECT_EQ(ArcSessionImpl::State::RUNNING_FULL_INSTANCE,
+ arc_session->GetStateForTesting());
+}
+
+} // namespace
+} // namespace arc
diff --git a/chromium/components/arc/arc_session_runner.cc b/chromium/components/arc/arc_session_runner.cc
index 2eed49d1d1a..1e3eccbcfe6 100644
--- a/chromium/components/arc/arc_session_runner.cc
+++ b/chromium/components/arc/arc_session_runner.cc
@@ -5,6 +5,8 @@
#include "components/arc/arc_session_runner.h"
#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/optional.h"
#include "base/task_runner.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "components/arc/arc_util.h"
@@ -26,6 +28,45 @@ chromeos::SessionManagerClient* GetSessionManagerClient() {
return chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
}
+void RecordInstanceCrashUma(ArcContainerLifetimeEvent sample) {
+ UMA_HISTOGRAM_ENUMERATION("Arc.ContainerLifetimeEvent", sample,
+ ArcContainerLifetimeEvent::COUNT);
+}
+
+void RecordInstanceRestartAfterCrashUma(size_t restart_after_crash_count) {
+ UMA_HISTOGRAM_COUNTS_100("Arc.ContainerRestartAfterCrashCount",
+ restart_after_crash_count);
+}
+
+// Gets an ArcContainerLifetimeEvent value to record. Returns nullopt when no
+// UMA recording is needed.
+base::Optional<ArcContainerLifetimeEvent> GetArcContainerLifetimeEvent(
+ size_t restart_after_crash_count,
+ ArcStopReason stop_reason,
+ bool was_running) {
+ // Record UMA only when this is the first non-early crash. This has to be
+ // done before checking other conditions. Otherwise, an early crash after
+ // container restart might be recorded. Each CONTAINER_STARTED event can
+ // be paired up to one non-START event.
+ if (restart_after_crash_count)
+ return base::nullopt;
+
+ switch (stop_reason) {
+ case ArcStopReason::SHUTDOWN:
+ case ArcStopReason::LOW_DISK_SPACE:
+ // We don't record these events.
+ return base::nullopt;
+ case ArcStopReason::GENERIC_BOOT_FAILURE:
+ return ArcContainerLifetimeEvent::CONTAINER_FAILED_TO_START;
+ case ArcStopReason::CRASH:
+ return was_running ? ArcContainerLifetimeEvent::CONTAINER_CRASHED
+ : ArcContainerLifetimeEvent::CONTAINER_CRASHED_EARLY;
+ }
+
+ NOTREACHED();
+ return base::nullopt;
+}
+
// Returns true if restart is needed for given conditions.
bool IsRestartNeeded(base::Optional<ArcInstanceMode> target_mode,
ArcStopReason stop_reason,
@@ -60,15 +101,17 @@ bool IsRestartNeeded(base::Optional<ArcInstanceMode> target_mode,
return false;
}
-std::ostream& operator<<(std::ostream& os,
- base::Optional<ArcInstanceMode> mode) {
- return mode.has_value() ? (os << mode.value()) : (os << "(nullopt)");
-}
-
// Returns true if the request to start/upgrade ARC instance is allowed
// operation.
bool IsRequestAllowed(const base::Optional<ArcInstanceMode>& current_mode,
ArcInstanceMode request_mode) {
+ if (request_mode == ArcInstanceMode::MINI_INSTANCE &&
+ ShouldArcOnlyStartAfterLogin()) {
+ // Skip starting ARC for now. We'll have another chance to start the full
+ // instance after the user logs in.
+ return false;
+ }
+
if (!current_mode.has_value()) {
// This is a request to start a new ARC instance (either mini instance
// or full instance).
@@ -87,10 +130,28 @@ bool IsRequestAllowed(const base::Optional<ArcInstanceMode>& current_mode,
return false;
}
+// Returns true if OnSessionStopped() should be called to notify observers.
+bool ShouldNotifyOnSessionStopped(
+ const base::Optional<ArcInstanceMode>& target_mode) {
+ DCHECK(target_mode.has_value());
+
+ switch (target_mode.value()) {
+ case ArcInstanceMode::MINI_INSTANCE:
+ return false;
+ case ArcInstanceMode::FULL_INSTANCE:
+ return true;
+ }
+
+ NOTREACHED() << "Unexpeceted |target_mode|: "
+ << static_cast<int>(target_mode.value());
+ return false;
+}
+
} // namespace
ArcSessionRunner::ArcSessionRunner(const ArcSessionFactory& factory)
: restart_delay_(kDefaultRestartDelay),
+ restart_after_crash_count_(0),
factory_(factory),
weak_ptr_factory_(this) {
chromeos::SessionManagerClient* client = GetSessionManagerClient();
@@ -205,18 +266,15 @@ void ArcSessionRunner::StartArcSession() {
if (!arc_session_) {
arc_session_ = factory_.Run();
arc_session_->AddObserver(this);
+ // Record the UMA only when |restart_after_crash_count_| is zero to avoid
+ // recording an auto-restart-then-crash loop. Such a crash loop is recorded
+ // separately with RecordInstanceRestartAfterCrashUma().
+ if (!restart_after_crash_count_)
+ RecordInstanceCrashUma(ArcContainerLifetimeEvent::CONTAINER_STARTING);
} else {
- DCHECK(arc_session_->IsForLoginScreen());
- }
-
- switch (target_mode_.value()) {
- case ArcInstanceMode::MINI_INSTANCE:
- arc_session_->StartForLoginScreen();
- break;
- case ArcInstanceMode::FULL_INSTANCE:
- arc_session_->Start();
- break;
+ DCHECK_EQ(ArcInstanceMode::MINI_INSTANCE, arc_session_->GetTargetMode());
}
+ arc_session_->Start(target_mode_.value());
}
void ArcSessionRunner::RestartArcSession() {
@@ -237,13 +295,29 @@ void ArcSessionRunner::OnSessionStopped(ArcStopReason stop_reason,
// The observers should be agnostic to the existence of the limited-purpose
// instance.
- const bool notify_observers = !arc_session_->IsForLoginScreen();
+ const bool notify_observers =
+ ShouldNotifyOnSessionStopped(arc_session_->GetTargetMode());
arc_session_->RemoveObserver(this);
arc_session_.reset();
+ const base::Optional<ArcContainerLifetimeEvent> uma_to_record =
+ GetArcContainerLifetimeEvent(restart_after_crash_count_, stop_reason,
+ was_running);
+ if (uma_to_record.has_value())
+ RecordInstanceCrashUma(uma_to_record.value());
+
const bool restarting =
IsRestartNeeded(target_mode_, stop_reason, was_running);
+
+ if (restarting && stop_reason == ArcStopReason::CRASH) {
+ ++restart_after_crash_count_;
+ } else {
+ // The session ended. Record the restart count.
+ RecordInstanceRestartAfterCrashUma(restart_after_crash_count_);
+ restart_after_crash_count_ = 0;
+ }
+
if (restarting) {
// There was a previous invocation and it crashed for some reason. Try
// starting ARC instance later again.
@@ -262,17 +336,12 @@ void ArcSessionRunner::OnSessionStopped(ArcStopReason stop_reason,
}
void ArcSessionRunner::EmitLoginPromptVisibleCalled() {
- if (ShouldArcOnlyStartAfterLogin()) {
- // Skip starting ARC for now. We'll have another chance to start the full
- // instance after the user logs in.
- return;
- }
-
// Since 'login-prompt-visible' Upstart signal starts all Upstart jobs the
- // container may depend on such as cras, EmitLoginPromptVisibleCalled() is the
- // safe place to start the container for login screen.
+ // instance may depend on such as cras, EmitLoginPromptVisibleCalled() is the
+ // safe place to start a mini instance.
DCHECK(!arc_session_);
- RequestStart(ArcInstanceMode::MINI_INSTANCE);
+ if (IsArcAvailable())
+ RequestStart(ArcInstanceMode::MINI_INSTANCE);
}
} // namespace arc
diff --git a/chromium/components/arc/arc_session_runner.h b/chromium/components/arc/arc_session_runner.h
index 97703bbaf8a..5db59916480 100644
--- a/chromium/components/arc/arc_session_runner.h
+++ b/chromium/components/arc/arc_session_runner.h
@@ -21,6 +21,25 @@
namespace arc {
+// These enums are used to define the buckets for an enumerated UMA histogram
+// and need to be synced with tools/metrics/histograms/enums.xml. This enum
+// class should also be treated as append-only.
+enum class ArcContainerLifetimeEvent {
+ // Note: "container" here means "instance". Outside Chromium, like UMA
+ // dashboard, we use the former term.
+
+ // Chrome asked session_manager to start an ARC instance (of any kind). We
+ // record this as a baseline.
+ CONTAINER_STARTING = 0,
+ // The instance failed to start or exited unexpectedly.
+ CONTAINER_FAILED_TO_START = 1,
+ // The instance crashed before establishing an IPC connection to Chrome.
+ CONTAINER_CRASHED_EARLY = 2,
+ // The instance crashed after establishing the connection.
+ CONTAINER_CRASHED = 3,
+ COUNT
+};
+
// Accept requests to start/stop ARC instance. Also supports automatic
// restarting on unexpected ARC instance crash.
class ArcSessionRunner : public ArcSession::Observer,
@@ -47,7 +66,8 @@ class ArcSessionRunner : public ArcSession::Observer,
// This is the factory interface to inject ArcSession instance
// for testing purpose.
- using ArcSessionFactory = base::Callback<std::unique_ptr<ArcSession>()>;
+ using ArcSessionFactory =
+ base::RepeatingCallback<std::unique_ptr<ArcSession>()>;
explicit ArcSessionRunner(const ArcSessionFactory& factory);
~ArcSessionRunner() override;
@@ -102,6 +122,7 @@ class ArcSessionRunner : public ArcSession::Observer,
// to finish tearing down in case it is still in the process of stopping.
base::TimeDelta restart_delay_;
base::OneShotTimer restart_timer_;
+ size_t restart_after_crash_count_; // for UMA recording.
// Factory to inject a fake ArcSession instance for testing.
ArcSessionFactory factory_;
diff --git a/chromium/components/arc/arc_session_runner_unittest.cc b/chromium/components/arc/arc_session_runner_unittest.cc
index 627c8cee9af..8a531e88dc3 100644
--- a/chromium/components/arc/arc_session_runner_unittest.cc
+++ b/chromium/components/arc/arc_session_runner_unittest.cc
@@ -8,13 +8,16 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback_helpers.h"
+#include "base/command_line.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
+#include "base/test/histogram_tester.h"
#include "base/test/scoped_task_environment.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/fake_session_manager_client.h"
#include "components/arc/arc_session_runner.h"
+#include "components/arc/arc_util.h"
#include "components/arc/test/fake_arc_session.h"
#include "mojo/public/cpp/system/message_pipe.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -23,6 +26,15 @@ namespace arc {
namespace {
+constexpr int kContainerStarting =
+ static_cast<int>(ArcContainerLifetimeEvent::CONTAINER_STARTING);
+constexpr int kContainerFailedToStart =
+ static_cast<int>(ArcContainerLifetimeEvent::CONTAINER_FAILED_TO_START);
+constexpr int kContainerCrashedEarly =
+ static_cast<int>(ArcContainerLifetimeEvent::CONTAINER_CRASHED_EARLY);
+constexpr int kContainerCrashed =
+ static_cast<int>(ArcContainerLifetimeEvent::CONTAINER_CRASHED);
+
class DoNothingObserver : public ArcSessionRunner::Observer {
public:
void OnSessionStopped(ArcStopReason reason, bool restarting) override {
@@ -160,7 +172,7 @@ TEST_F(ArcSessionRunnerTest, Basic) {
arc_session_runner()->RequestStart(ArcInstanceMode::FULL_INSTANCE);
ASSERT_TRUE(arc_session());
- EXPECT_TRUE(arc_session()->IsRunning());
+ EXPECT_TRUE(arc_session()->is_running());
arc_session_runner()->RequestStop();
EXPECT_FALSE(arc_session());
@@ -176,7 +188,7 @@ TEST_F(ArcSessionRunnerTest, StopMidStartup) {
arc_session_runner()->RequestStart(ArcInstanceMode::FULL_INSTANCE);
ASSERT_TRUE(arc_session());
- EXPECT_FALSE(arc_session()->IsRunning());
+ EXPECT_FALSE(arc_session()->is_running());
arc_session_runner()->RequestStop();
EXPECT_FALSE(arc_session());
@@ -191,7 +203,7 @@ TEST_F(ArcSessionRunnerTest, StopMidStartup_MiniInstance) {
arc_session_runner()->RequestStart(ArcInstanceMode::MINI_INSTANCE);
ASSERT_TRUE(arc_session());
- EXPECT_FALSE(arc_session()->IsRunning());
+ EXPECT_FALSE(arc_session()->is_running());
arc_session_runner()->RequestStop();
EXPECT_FALSE(arc_session());
@@ -229,7 +241,7 @@ TEST_F(ArcSessionRunnerTest, BootFailure_MiniInstance) {
ResetArcSessionFactory(base::Bind(FakeArcSession::Create));
arc_session_runner()->RequestStart(ArcInstanceMode::FULL_INSTANCE);
ASSERT_TRUE(arc_session());
- EXPECT_TRUE(arc_session()->IsRunning());
+ EXPECT_TRUE(arc_session()->is_running());
}
// Similary, CRASH should do same for GENERIC_BOOT_FAILURE case, because
@@ -254,11 +266,11 @@ TEST_F(ArcSessionRunnerTest, Upgrade) {
arc_session_runner()->RequestStart(ArcInstanceMode::MINI_INSTANCE);
ASSERT_TRUE(arc_session());
- EXPECT_FALSE(arc_session()->IsRunning());
+ EXPECT_FALSE(arc_session()->is_running());
arc_session_runner()->RequestStart(ArcInstanceMode::FULL_INSTANCE);
ASSERT_TRUE(arc_session());
- EXPECT_TRUE(arc_session()->IsRunning());
+ EXPECT_TRUE(arc_session()->is_running());
}
// We expect mini instance starts to run if EmitLoginPromptVisible signal is
@@ -266,11 +278,24 @@ TEST_F(ArcSessionRunnerTest, Upgrade) {
TEST_F(ArcSessionRunnerTest, EmitLoginPromptVisible) {
EXPECT_FALSE(arc_session());
+ SetArcAvailableCommandLineForTesting(base::CommandLine::ForCurrentProcess());
+
chromeos::DBusThreadManager::Get()
->GetSessionManagerClient()
->EmitLoginPromptVisible();
ASSERT_TRUE(arc_session());
- EXPECT_FALSE(arc_session()->IsRunning());
+ EXPECT_FALSE(arc_session()->is_running());
+}
+
+// We expect mini instance does not start on EmitLoginPromptVisible when ARC
+// is not available.
+TEST_F(ArcSessionRunnerTest, EmitLoginPromptVisible_NoOp) {
+ EXPECT_FALSE(arc_session());
+
+ chromeos::DBusThreadManager::Get()
+ ->GetSessionManagerClient()
+ ->EmitLoginPromptVisible();
+ EXPECT_FALSE(arc_session());
}
// If the instance is stopped, it should be re-started.
@@ -280,7 +305,7 @@ TEST_F(ArcSessionRunnerTest, Restart) {
arc_session_runner()->RequestStart(ArcInstanceMode::FULL_INSTANCE);
ASSERT_TRUE(arc_session());
- EXPECT_TRUE(arc_session()->IsRunning());
+ EXPECT_TRUE(arc_session()->is_running());
// Simulate a connection loss.
ASSERT_TRUE(arc_session());
@@ -290,7 +315,7 @@ TEST_F(ArcSessionRunnerTest, Restart) {
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(restarting_called());
ASSERT_TRUE(arc_session());
- EXPECT_TRUE(arc_session()->IsRunning());
+ EXPECT_TRUE(arc_session()->is_running());
arc_session_runner()->RequestStop();
EXPECT_FALSE(arc_session());
@@ -302,7 +327,7 @@ TEST_F(ArcSessionRunnerTest, GracefulStop) {
arc_session_runner()->RequestStart(ArcInstanceMode::FULL_INSTANCE);
ASSERT_TRUE(arc_session());
- EXPECT_TRUE(arc_session()->IsRunning());
+ EXPECT_TRUE(arc_session()->is_running());
// Graceful stop.
arc_session_runner()->RequestStop();
@@ -318,7 +343,7 @@ TEST_F(ArcSessionRunnerTest, Shutdown) {
arc_session_runner()->RequestStart(ArcInstanceMode::FULL_INSTANCE);
ASSERT_TRUE(arc_session());
- EXPECT_TRUE(arc_session()->IsRunning());
+ EXPECT_TRUE(arc_session()->is_running());
// Simulate shutdown.
arc_session_runner()->OnShutdown();
@@ -345,4 +370,121 @@ TEST_F(ArcSessionRunnerTest, RemoveUnknownObserver) {
arc_session_runner()->RemoveObserver(&do_nothing_observer);
}
+// Tests UMA recording on mini instance -> full instance -> shutdown case.
+TEST_F(ArcSessionRunnerTest, UmaRecording_StartUpgradeShutdown) {
+ base::HistogramTester tester;
+
+ arc_session_runner()->RequestStart(ArcInstanceMode::MINI_INSTANCE);
+ tester.ExpectUniqueSample("Arc.ContainerLifetimeEvent", kContainerStarting,
+ 1 /* count of the sample */);
+
+ // Boot continue should not increase the count.
+ arc_session_runner()->RequestStart(ArcInstanceMode::FULL_INSTANCE);
+ tester.ExpectUniqueSample("Arc.ContainerLifetimeEvent", kContainerStarting,
+ 1);
+
+ // "0" should be recorded as a restart count on shutdown.
+ arc_session_runner()->OnShutdown();
+ tester.ExpectUniqueSample("Arc.ContainerRestartAfterCrashCount",
+ 0 /* sample */, 1 /* count of the sample */);
+}
+
+// Tests UMA recording on full instance -> shutdown case.
+TEST_F(ArcSessionRunnerTest, UmaRecording_StartShutdown) {
+ base::HistogramTester tester;
+
+ arc_session_runner()->RequestStart(ArcInstanceMode::FULL_INSTANCE);
+ tester.ExpectUniqueSample("Arc.ContainerLifetimeEvent", kContainerStarting,
+ 1);
+ // "0" should be recorded as a restart count on shutdown.
+ arc_session_runner()->OnShutdown();
+ tester.ExpectUniqueSample("Arc.ContainerRestartAfterCrashCount", 0, 1);
+}
+
+// Tests UMA recording on mini instance -> full instance -> crash -> shutdown
+// case.
+TEST_F(ArcSessionRunnerTest, UmaRecording_CrashTwice) {
+ base::HistogramTester tester;
+
+ arc_session_runner()->SetRestartDelayForTesting(base::TimeDelta());
+ EXPECT_FALSE(arc_session());
+
+ arc_session_runner()->RequestStart(ArcInstanceMode::MINI_INSTANCE);
+ tester.ExpectUniqueSample("Arc.ContainerLifetimeEvent", kContainerStarting,
+ 1);
+ arc_session_runner()->RequestStart(ArcInstanceMode::FULL_INSTANCE);
+
+ // Stop the instance with CRASH.
+ arc_session()->StopWithReason(ArcStopReason::CRASH);
+ tester.ExpectBucketCount("Arc.ContainerLifetimeEvent", kContainerCrashed, 1);
+ tester.ExpectTotalCount("Arc.ContainerLifetimeEvent", 2);
+
+ // Restart the instance, then crash the instance again. The second CRASH
+ // should not affect Arc.ContainerLifetimeEvent.
+ base::RunLoop().RunUntilIdle();
+ arc_session()->StopWithReason(ArcStopReason::CRASH);
+ tester.ExpectBucketCount("Arc.ContainerLifetimeEvent", kContainerCrashed, 1);
+ tester.ExpectTotalCount("Arc.ContainerLifetimeEvent", 2);
+
+ // However, "2" should be recorded as a restart count on shutdown.
+ base::RunLoop().RunUntilIdle();
+ arc_session_runner()->OnShutdown();
+ tester.ExpectUniqueSample("Arc.ContainerRestartAfterCrashCount", 2, 1);
+}
+
+// Tests UMA recording on mini instance -> crash -> shutdown case.
+TEST_F(ArcSessionRunnerTest, UmaRecording_CrashMini) {
+ base::HistogramTester tester;
+
+ arc_session_runner()->RequestStart(ArcInstanceMode::MINI_INSTANCE);
+ tester.ExpectUniqueSample("Arc.ContainerLifetimeEvent", kContainerStarting,
+ 1);
+
+ // Stop the instance with CRASH.
+ arc_session()->StopWithReason(ArcStopReason::CRASH);
+ tester.ExpectBucketCount("Arc.ContainerLifetimeEvent", kContainerCrashedEarly,
+ 1);
+ tester.ExpectTotalCount("Arc.ContainerLifetimeEvent", 2);
+
+ // In this case, no restart happened. "0" should be recorded.
+ arc_session_runner()->OnShutdown();
+ tester.ExpectUniqueSample("Arc.ContainerRestartAfterCrashCount", 0, 1);
+}
+
+// Tests UMA recording on mini instance -> boot fail -> shutdown case.
+TEST_F(ArcSessionRunnerTest, UmaRecording_BootFail) {
+ base::HistogramTester tester;
+
+ arc_session_runner()->RequestStart(ArcInstanceMode::MINI_INSTANCE);
+ tester.ExpectUniqueSample("Arc.ContainerLifetimeEvent", kContainerStarting,
+ 1);
+
+ arc_session()->StopWithReason(ArcStopReason::GENERIC_BOOT_FAILURE);
+ tester.ExpectBucketCount("Arc.ContainerLifetimeEvent",
+ kContainerFailedToStart, 1);
+ tester.ExpectTotalCount("Arc.ContainerLifetimeEvent", 2);
+
+ // No restart happened. "0" should be recorded.
+ arc_session_runner()->OnShutdown();
+ tester.ExpectUniqueSample("Arc.ContainerRestartAfterCrashCount", 0, 1);
+}
+
+// Tests UMA recording on full instance -> low disk -> shutdown case.
+TEST_F(ArcSessionRunnerTest, UmaRecording_LowDisk) {
+ base::HistogramTester tester;
+
+ arc_session_runner()->RequestStart(ArcInstanceMode::FULL_INSTANCE);
+ tester.ExpectUniqueSample("Arc.ContainerLifetimeEvent", kContainerStarting,
+ 1);
+
+ // We don't record UMA for LOW_DISK_SPACE.
+ arc_session()->StopWithReason(ArcStopReason::LOW_DISK_SPACE);
+ tester.ExpectUniqueSample("Arc.ContainerLifetimeEvent", kContainerStarting,
+ 1);
+
+ // No restart happened. "0" should be recorded.
+ arc_session_runner()->OnShutdown();
+ tester.ExpectUniqueSample("Arc.ContainerRestartAfterCrashCount", 0, 1);
+}
+
} // namespace arc
diff --git a/chromium/components/arc/arc_stop_reason.h b/chromium/components/arc/arc_stop_reason.h
index df104439e7a..bdf08e1fa80 100644
--- a/chromium/components/arc/arc_stop_reason.h
+++ b/chromium/components/arc/arc_stop_reason.h
@@ -15,8 +15,9 @@ enum class ArcStopReason {
SHUTDOWN,
// Errors occurred during the ARC instance boot. This includes any failures
- // before the instance is actually attempted to be started, and also
- // failures on bootstrapping IPC channels with Android.
+ // before the instance is actually attempted to be started (e.g.
+ // session_manager failed to fork/exec the instance), and also a "clean"
+ // (non crashy) but unexpected container shutdown.
GENERIC_BOOT_FAILURE,
// The device is critically low on disk space.
diff --git a/chromium/components/arc/arc_util.cc b/chromium/components/arc/arc_util.cc
index 83436fe2d1e..f0033f4751b 100644
--- a/chromium/components/arc/arc_util.cc
+++ b/chromium/components/arc/arc_util.cc
@@ -172,6 +172,11 @@ bool IsArcAllowedForUser(const user_manager::User* user) {
return false;
}
+ if (user->GetType() == user_manager::USER_TYPE_CHILD) {
+ VLOG(1) << "ARC usage by Child users is prohibited";
+ return false;
+ }
+
return true;
}
diff --git a/chromium/components/arc/arc_util_unittest.cc b/chromium/components/arc/arc_util_unittest.cc
index 51b8a41b6da..bc476adefa3 100644
--- a/chromium/components/arc/arc_util_unittest.cc
+++ b/chromium/components/arc/arc_util_unittest.cc
@@ -14,6 +14,7 @@
#include "base/test/scoped_feature_list.h"
#include "components/signin/core/account_id/account_id.h"
#include "components/user_manager/fake_user_manager.h"
+#include "components/user_manager/scoped_user_manager.h"
#include "components/user_manager/user.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/aura_constants.h"
@@ -42,32 +43,11 @@ class ScopedArcFeature {
DISALLOW_COPY_AND_ASSIGN(ScopedArcFeature);
};
-// Helper to enable user_manager::FakeUserManager while it is in scope.
-// TODO(xiyuan): Remove after ScopedUserManagerEnabler is moved to user_manager.
-class ScopedUserManager {
- public:
- explicit ScopedUserManager(user_manager::UserManager* user_manager)
- : user_manager_(user_manager) {
- DCHECK(!user_manager::UserManager::IsInitialized());
- user_manager->Initialize();
- }
- ~ScopedUserManager() {
- DCHECK_EQ(user_manager::UserManager::Get(), user_manager_);
- user_manager_->Shutdown();
- user_manager_->Destroy();
- }
-
- private:
- user_manager::UserManager* const user_manager_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedUserManager);
-};
-
// Fake user that can be created with a specified type.
class FakeUser : public user_manager::User {
public:
explicit FakeUser(user_manager::UserType user_type)
- : User(AccountId::FromUserEmail("user@test.com")),
+ : User(AccountId::FromUserEmailGaiaId("user@test.com", "1234567890")),
user_type_(user_type) {}
~FakeUser() override = default;
@@ -203,8 +183,10 @@ TEST_F(ArcUtilTest, IsArcAppWindow) {
}
TEST_F(ArcUtilTest, IsArcAllowedForUser) {
- user_manager::FakeUserManager fake_user_manager;
- ScopedUserManager scoped_user_manager(&fake_user_manager);
+ user_manager::FakeUserManager* fake_user_manager =
+ new user_manager::FakeUserManager();
+ user_manager::ScopedUserManager scoped_user_manager(
+ base::WrapUnique(fake_user_manager));
struct {
user_manager::UserType user_type;
@@ -215,7 +197,7 @@ TEST_F(ArcUtilTest, IsArcAllowedForUser) {
{user_manager::USER_TYPE_PUBLIC_ACCOUNT, false},
{user_manager::USER_TYPE_SUPERVISED, false},
{user_manager::USER_TYPE_KIOSK_APP, false},
- {user_manager::USER_TYPE_CHILD, true},
+ {user_manager::USER_TYPE_CHILD, false},
{user_manager::USER_TYPE_ARC_KIOSK_APP, true},
{user_manager::USER_TYPE_ACTIVE_DIRECTORY, true},
};
@@ -227,12 +209,13 @@ TEST_F(ArcUtilTest, IsArcAllowedForUser) {
// An ephemeral user is a logged in user but unknown to UserManager when
// ephemeral policy is set.
- fake_user_manager.SetEphemeralUsersEnabled(true);
- fake_user_manager.UserLoggedIn(AccountId::FromUserEmail("test@test.com"),
- "test@test.com-hash", false);
- const user_manager::User* ephemeral_user = fake_user_manager.GetActiveUser();
+ fake_user_manager->SetEphemeralUsersEnabled(true);
+ fake_user_manager->UserLoggedIn(
+ AccountId::FromUserEmailGaiaId("test@test.com", "9876543210"),
+ "test@test.com-hash", false /* browser_restart */, false /* is_child */);
+ const user_manager::User* ephemeral_user = fake_user_manager->GetActiveUser();
ASSERT_TRUE(ephemeral_user);
- ASSERT_TRUE(fake_user_manager.IsUserCryptohomeDataEphemeral(
+ ASSERT_TRUE(fake_user_manager->IsUserCryptohomeDataEphemeral(
ephemeral_user->GetAccountId()));
// Ephemeral user is not allowed for ARC.
diff --git a/chromium/components/arc/audio/arc_audio_bridge.cc b/chromium/components/arc/audio/arc_audio_bridge.cc
index 880acb390ae..72a8106d695 100644
--- a/chromium/components/arc/audio/arc_audio_bridge.cc
+++ b/chromium/components/arc/audio/arc_audio_bridge.cc
@@ -45,7 +45,8 @@ ArcAudioBridge* ArcAudioBridge::GetForBrowserContext(
ArcAudioBridge::ArcAudioBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service)
- : arc_bridge_service_(bridge_service), binding_(this) {
+ : arc_bridge_service_(bridge_service) {
+ arc_bridge_service_->audio()->SetHost(this);
arc_bridge_service_->audio()->AddObserver(this);
if (chromeos::CrasAudioHandler::IsInitialized()) {
cras_audio_handler_ = chromeos::CrasAudioHandler::Get();
@@ -57,19 +58,15 @@ ArcAudioBridge::~ArcAudioBridge() {
if (cras_audio_handler_)
cras_audio_handler_->RemoveAudioObserver(this);
arc_bridge_service_->audio()->RemoveObserver(this);
+ arc_bridge_service_->audio()->SetHost(nullptr);
}
-void ArcAudioBridge::OnInstanceReady() {
- mojom::AudioInstance* audio_instance =
- ARC_GET_INSTANCE_FOR_METHOD(arc_bridge_service_->audio(), Init);
- DCHECK(audio_instance); // the instance on ARC side is too old.
- mojom::AudioHostPtr host_proxy;
- binding_.Bind(mojo::MakeRequest(&host_proxy));
- audio_instance->Init(std::move(host_proxy));
+void ArcAudioBridge::OnConnectionReady() {
+ // TODO(hidehiko): Replace with ConnectionHolder::IsConnected().
available_ = true;
}
-void ArcAudioBridge::OnInstanceClosed() {
+void ArcAudioBridge::OnConnectionClosed() {
available_ = false;
}
diff --git a/chromium/components/arc/audio/arc_audio_bridge.h b/chromium/components/arc/audio/arc_audio_bridge.h
index 7938f6f57e0..ab068f6c29b 100644
--- a/chromium/components/arc/audio/arc_audio_bridge.h
+++ b/chromium/components/arc/audio/arc_audio_bridge.h
@@ -10,9 +10,8 @@
#include "base/macros.h"
#include "chromeos/audio/cras_audio_handler.h"
#include "components/arc/common/audio.mojom.h"
-#include "components/arc/instance_holder.h"
+#include "components/arc/connection_observer.h"
#include "components/keyed_service/core/keyed_service.h"
-#include "mojo/public/cpp/bindings/binding.h"
namespace content {
class BrowserContext;
@@ -23,7 +22,7 @@ namespace arc {
class ArcBridgeService;
class ArcAudioBridge : public KeyedService,
- public InstanceHolder<mojom::AudioInstance>::Observer,
+ public ConnectionObserver<mojom::AudioInstance>,
public mojom::AudioHost,
public chromeos::CrasAudioHandler::AudioObserver {
public:
@@ -35,9 +34,9 @@ class ArcAudioBridge : public KeyedService,
ArcBridgeService* bridge_service);
~ArcAudioBridge() override;
- // InstanceHolder<mojom::AudioInstance>::Observer overrides.
- void OnInstanceReady() override;
- void OnInstanceClosed() override;
+ // ConnectionObserver<mojom::AudioInstance> overrides.
+ void OnConnectionReady() override;
+ void OnConnectionClosed() override;
// mojom::AudioHost overrides.
void ShowVolumeControls() override;
@@ -54,8 +53,6 @@ class ArcAudioBridge : public KeyedService,
ArcBridgeService* const arc_bridge_service_; // Owned by ArcServiceManager.
- mojo::Binding<mojom::AudioHost> binding_;
-
chromeos::CrasAudioHandler* cras_audio_handler_ = nullptr;
int volume_ = 0; // Volume range: 0-100.
diff --git a/chromium/components/arc/bluetooth/bluetooth_type_converters_unittest.cc b/chromium/components/arc/bluetooth/bluetooth_type_converters_unittest.cc
index 9ed5d7e531a..213c8f0efdf 100644
--- a/chromium/components/arc/bluetooth/bluetooth_type_converters_unittest.cc
+++ b/chromium/components/arc/bluetooth/bluetooth_type_converters_unittest.cc
@@ -58,15 +58,15 @@ size_t GetDepthOfMojoAttribute(
bluez::BluetoothServiceAttributeValueBlueZ CreateDeepBlueZSequenceAttribute(
size_t depth) {
if (depth > 0u) {
- std::unique_ptr<bluez::BluetoothServiceAttributeValueBlueZ::Sequence>
- sequence(new bluez::BluetoothServiceAttributeValueBlueZ::Sequence());
+ auto sequence = std::make_unique<
+ bluez::BluetoothServiceAttributeValueBlueZ::Sequence>();
sequence->push_back(CreateDeepBlueZSequenceAttribute(depth - 1));
return bluez::BluetoothServiceAttributeValueBlueZ(std::move(sequence));
} else {
return bluez::BluetoothServiceAttributeValueBlueZ(
bluez::BluetoothServiceAttributeValueBlueZ::UINT, sizeof(uint16_t),
- base::WrapUnique(new base::Value(3)));
+ std::make_unique<base::Value>(3));
}
}
@@ -81,420 +81,392 @@ size_t GetDepthOfBlueZAttribute(
return depth;
}
+std::string ValueToJson(const base::Value& value) {
+ std::string json;
+ base::JSONWriter::Write(value, &json);
+ return json;
+}
+
} // namespace
namespace mojo {
-TEST(BluetoothTypeConvertorTest, ConvertMojoBluetoothAddressFromString) {
- arc::mojom::BluetoothAddressPtr addressMojo =
+TEST(BluetoothTypeConverterTest, ConvertMojoBluetoothAddressFromString) {
+ arc::mojom::BluetoothAddressPtr address_mojo =
arc::mojom::BluetoothAddress::From(std::string(kAddressStr));
- EXPECT_EQ(kAddressSize, addressMojo->address.size());
- for (size_t i = 0; i < kAddressSize; i++) {
- EXPECT_EQ(kAddressArray[i], addressMojo->address[i]);
- }
+ EXPECT_EQ(kAddressSize, address_mojo->address.size());
+ for (size_t i = 0; i < kAddressSize; i++)
+ EXPECT_EQ(kAddressArray[i], address_mojo->address[i]);
}
-TEST(BluetoothTypeConvertorTest, ConvertMojoBluetoothAddressToString) {
- arc::mojom::BluetoothAddressPtr addressMojo =
+TEST(BluetoothTypeConverterTest, ConvertMojoBluetoothAddressToString) {
+ arc::mojom::BluetoothAddressPtr address_mojo =
arc::mojom::BluetoothAddress::New();
- for (size_t i = 0; i < kAddressSize - 1; i++) {
- addressMojo->address.push_back(kAddressArray[i]);
- }
- EXPECT_EQ(std::string(kInvalidAddressStr), addressMojo->To<std::string>());
+ // Test address is shorter than expected (invalid address).
+ for (size_t i = 0; i < kAddressSize - 1; i++)
+ address_mojo->address.push_back(kAddressArray[i]);
+ EXPECT_EQ(kInvalidAddressStr, address_mojo->To<std::string>());
+
+ // Test success case.
+ address_mojo->address.push_back(kAddressArray[kAddressSize - 1]);
+ EXPECT_EQ(kAddressStr, address_mojo->To<std::string>());
+
+ // Test address is longer than expected (invalid address).
+ address_mojo->address.push_back(kFillerByte);
+ EXPECT_EQ(kInvalidAddressStr, address_mojo->To<std::string>());
+}
+
+TEST(BluetoothTypeConverterTest,
+ ConvertMojoValueAttributeToBlueZAttribute_NullType) {
+ auto mojo = arc::mojom::BluetoothSdpAttribute::New();
+ mojo->type = bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE;
+ mojo->type_size = 0;
+
+ auto blue_z = mojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
- addressMojo->address.push_back(kAddressArray[kAddressSize - 1]);
- EXPECT_EQ(std::string(kAddressStr), addressMojo->To<std::string>());
+ EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE,
+ blue_z.type());
+ EXPECT_EQ(0u, blue_z.size());
+ EXPECT_EQ(base::Value::Type::NONE, blue_z.value().type());
+}
- addressMojo->address.push_back(kFillerByte);
+TEST(BluetoothTypeConverterTest,
+ ConvertMojoValueAttributeToBlueZAttribute_BoolType) {
+ auto mojo = arc::mojom::BluetoothSdpAttribute::New();
+ mojo->type = bluez::BluetoothServiceAttributeValueBlueZ::BOOL;
+ mojo->type_size = static_cast<uint32_t>(sizeof(bool));
+ mojo->json_value = ValueToJson(base::Value(true));
- EXPECT_EQ(std::string(kInvalidAddressStr), addressMojo->To<std::string>());
+ auto blue_z = mojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
+
+ EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::BOOL, blue_z.type());
+ EXPECT_EQ(sizeof(bool), blue_z.size());
+ ASSERT_EQ(base::Value::Type::BOOLEAN, blue_z.value().type());
+ EXPECT_TRUE(blue_z.value().GetBool());
}
+TEST(BluetoothTypeConverterTest,
+ ConvertMojoValueAttributeToBlueZAttribute_UintType) {
+ constexpr uint16_t kValue = 10;
+ auto mojo = arc::mojom::BluetoothSdpAttribute::New();
+ mojo->type = bluez::BluetoothServiceAttributeValueBlueZ::UINT;
+ mojo->type_size = static_cast<uint32_t>(sizeof(kValue));
+ mojo->json_value = ValueToJson(base::Value(static_cast<int>(kValue)));
+
+ auto blue_z = mojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
-TEST(BluetoothTypeConvertorTest, ConvertMojoValueAttributeToBlueZAttribute) {
- // Construct Mojo attribute with NULLTYPE value.
- auto nulltypeAttributeMojo = arc::mojom::BluetoothSdpAttribute::New();
- nulltypeAttributeMojo->type =
- bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE;
- nulltypeAttributeMojo->type_size = 0;
+ EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UINT, blue_z.type());
+ EXPECT_EQ(sizeof(kValue), blue_z.size());
+ ASSERT_EQ(base::Value::Type::INTEGER, blue_z.value().type());
+ EXPECT_EQ(kValue, static_cast<uint16_t>(blue_z.value().GetInt()));
+}
- auto nulltypeAttributeBlueZ =
- nulltypeAttributeMojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
+TEST(BluetoothTypeConverterTest,
+ ConvertMojoValueAttributeToBlueZAttribute_IntType) {
+ constexpr int16_t kValue = 20;
+ auto mojo = arc::mojom::BluetoothSdpAttribute::New();
+ mojo->type = bluez::BluetoothServiceAttributeValueBlueZ::INT;
+ mojo->type_size = static_cast<uint32_t>(sizeof(kValue));
+ mojo->json_value = ValueToJson(base::Value(static_cast<int>(kValue)));
- EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE,
- nulltypeAttributeBlueZ.type());
- EXPECT_EQ(0u, nulltypeAttributeBlueZ.size());
- EXPECT_EQ(base::Value::Type::NONE, nulltypeAttributeBlueZ.value().GetType());
-
- // Construct Mojo attribute with TYPE_BOOLEAN value.
- bool valueBool = true;
- auto boolAttributeMojo = arc::mojom::BluetoothSdpAttribute::New();
- boolAttributeMojo->type = bluez::BluetoothServiceAttributeValueBlueZ::BOOL;
- boolAttributeMojo->type_size = static_cast<uint32_t>(sizeof(valueBool));
- std::string json;
- base::JSONWriter::Write(base::Value(valueBool), &json);
- boolAttributeMojo->json_value = std::move(json);
- auto boolAttributeBlueZ =
- boolAttributeMojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
-
- EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::BOOL,
- boolAttributeBlueZ.type());
- EXPECT_EQ(sizeof(valueBool), boolAttributeBlueZ.size());
- EXPECT_EQ(base::Value::Type::BOOLEAN, boolAttributeBlueZ.value().GetType());
- EXPECT_TRUE(boolAttributeBlueZ.value().GetAsBoolean(&valueBool));
- EXPECT_TRUE(valueBool);
-
- // Construct Mojo attribute with TYPE_UINT value.
- uint16_t valueUint16 = 10;
- int valueUint16AsInt = 0;
- auto uintAttributeMojo = arc::mojom::BluetoothSdpAttribute::New();
- uintAttributeMojo->type = bluez::BluetoothServiceAttributeValueBlueZ::UINT;
- uintAttributeMojo->type_size = static_cast<uint32_t>(sizeof(valueUint16));
- json.clear();
- base::JSONWriter::Write(base::Value(static_cast<int>(valueUint16)), &json);
- uintAttributeMojo->json_value = std::move(json);
-
- auto uintAttributeBlueZ =
- uintAttributeMojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
-
- EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UINT,
- uintAttributeBlueZ.type());
- EXPECT_EQ(sizeof(valueUint16), uintAttributeBlueZ.size());
- EXPECT_EQ(base::Value::Type::INTEGER, uintAttributeBlueZ.value().GetType());
- EXPECT_TRUE(uintAttributeBlueZ.value().GetAsInteger(&valueUint16AsInt));
- EXPECT_EQ(valueUint16, static_cast<uint16_t>(valueUint16AsInt));
-
- // Construct Mojo attribute with TYPE_INT value.
- int16_t valueInt16 = 20;
- int valueInt16AsInt = 0;
- auto intAttributeMojo = arc::mojom::BluetoothSdpAttribute::New();
- intAttributeMojo->type = bluez::BluetoothServiceAttributeValueBlueZ::INT;
- intAttributeMojo->type_size = static_cast<uint32_t>(sizeof(valueInt16));
- json.clear();
- base::JSONWriter::Write(base::Value(static_cast<int>(valueInt16)), &json);
- intAttributeMojo->json_value = std::move(json);
-
- auto intAttributeBlueZ =
- intAttributeMojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
-
- EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::INT,
- intAttributeBlueZ.type());
- EXPECT_EQ(sizeof(valueInt16), intAttributeBlueZ.size());
- EXPECT_EQ(base::Value::Type::INTEGER, intAttributeBlueZ.value().GetType());
- EXPECT_TRUE(intAttributeBlueZ.value().GetAsInteger(&valueInt16AsInt));
- EXPECT_EQ(valueInt16, static_cast<int16_t>(valueInt16AsInt));
+ auto blue_z = mojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
+ EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::INT, blue_z.type());
+ EXPECT_EQ(sizeof(kValue), blue_z.size());
+ ASSERT_EQ(base::Value::Type::INTEGER, blue_z.value().type());
+ EXPECT_EQ(kValue, static_cast<int16_t>(blue_z.value().GetInt()));
+}
+
+TEST(BluetoothTypeConverterTest,
+ ConvertMojoValueAttributeToBlueZAttribute_UuidType) {
// Construct Mojo attribute with TYPE_UUID.
- std::string expectedUUID("00000000-0000-1000-8000-00805f9b34fb");
- std::string actualUUID;
- auto uuidAttributeMojo = arc::mojom::BluetoothSdpAttribute::New();
- uuidAttributeMojo->type = bluez::BluetoothServiceAttributeValueBlueZ::UUID;
+ constexpr char kValue[] = "00000000-0000-1000-8000-00805f9b34fb";
+ auto mojo = arc::mojom::BluetoothSdpAttribute::New();
+ mojo->type = bluez::BluetoothServiceAttributeValueBlueZ::UUID;
// UUIDs are all stored in string form, but it can be converted to one of
// UUID16, UUID32 and UUID128.
- uuidAttributeMojo->type_size = static_cast<uint32_t>(sizeof(uint16_t));
- json.clear();
- base::JSONWriter::Write(base::Value(expectedUUID), &json);
- uuidAttributeMojo->json_value = std::move(json);
+ mojo->type_size = static_cast<uint32_t>(sizeof(uint16_t));
+ mojo->json_value = ValueToJson(base::Value(kValue));
- auto uuidAttributeBlueZ =
- uuidAttributeMojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
+ auto blue_z = mojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
- EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UUID,
- uuidAttributeBlueZ.type());
- EXPECT_EQ(sizeof(uint16_t), uuidAttributeBlueZ.size());
- EXPECT_EQ(base::Value::Type::STRING, uuidAttributeBlueZ.value().GetType());
- EXPECT_TRUE(uuidAttributeBlueZ.value().GetAsString(&actualUUID));
- EXPECT_EQ(expectedUUID, actualUUID);
+ EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UUID, blue_z.type());
+ EXPECT_EQ(sizeof(uint16_t), blue_z.size());
+ ASSERT_EQ(base::Value::Type::STRING, blue_z.value().type());
+ EXPECT_EQ(kValue, blue_z.value().GetString());
+}
+TEST(BluetoothTypeConverterTest,
+ ConvertMojoValueAttributeToBlueZAttribute_StringType) {
// Construct Mojo attribute with TYPE_STRING. TYPE_URL is the same case as
// TYPE_STRING.
- std::string expectedString("Some SDP service");
- std::string actualString;
- auto stringAttributeMojo = arc::mojom::BluetoothSdpAttribute::New();
- stringAttributeMojo->type =
- bluez::BluetoothServiceAttributeValueBlueZ::STRING;
- stringAttributeMojo->type_size =
- static_cast<uint32_t>(expectedString.length());
- json.clear();
- base::JSONWriter::Write(base::Value(expectedString), &json);
- stringAttributeMojo->json_value = std::move(json);
-
- auto stringAttributeBlueZ =
- stringAttributeMojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
-
- EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::STRING,
- stringAttributeBlueZ.type());
- EXPECT_EQ(expectedString.length(), stringAttributeBlueZ.size());
- EXPECT_EQ(base::Value::Type::STRING, stringAttributeBlueZ.value().GetType());
- EXPECT_TRUE(stringAttributeBlueZ.value().GetAsString(&actualString));
- EXPECT_EQ(expectedString, actualString);
+ constexpr char kValue[] = "Some SDP service";
+ constexpr size_t kValueSize = sizeof(kValue) - 1; // Subtract '\0' size.
+ auto mojo = arc::mojom::BluetoothSdpAttribute::New();
+ mojo->type = bluez::BluetoothServiceAttributeValueBlueZ::STRING;
+ // Subtract '\0'-terminate size.
+ mojo->type_size = static_cast<uint32_t>(kValueSize);
+ mojo->json_value = ValueToJson(base::Value(kValue));
+
+ auto blue_z = mojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
+
+ EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::STRING, blue_z.type());
+ EXPECT_EQ(kValueSize, blue_z.size());
+ ASSERT_EQ(base::Value::Type::STRING, blue_z.value().type());
+ EXPECT_EQ(kValue, blue_z.value().GetString());
}
-TEST(BluetoothTypeConvertorTest, ConvertMojoSequenceAttributeToBlueZAttribute) {
- // Create an UUID value.
- std::string l2capUUID("00000100-0000-1000-8000-00805f9b34fb");
- auto valueUUID = arc::mojom::BluetoothSdpAttribute::New();
- valueUUID->type = bluez::BluetoothServiceAttributeValueBlueZ::UUID;
- valueUUID->type_size = static_cast<uint32_t>(sizeof(uint16_t));
- std::string json;
- base::JSONWriter::Write(base::Value(l2capUUID), &json);
- valueUUID->json_value = std::move(json);
-
- // Create an UINT value.
- uint16_t l2capChannel = 3;
- auto valueUint16 = arc::mojom::BluetoothSdpAttribute::New();
- valueUint16->type = bluez::BluetoothServiceAttributeValueBlueZ::UINT;
- valueUint16->type_size = static_cast<uint32_t>(sizeof(l2capChannel));
- json.clear();
- base::JSONWriter::Write(base::Value(static_cast<int>(l2capChannel)), &json);
- valueUint16->json_value = std::move(json);
+TEST(BluetoothTypeConverterTest, ConvertMojoSequenceAttributeToBlueZAttribute) {
+ constexpr char kL2capUuid[] = "00000100-0000-1000-8000-00805f9b34fb";
+ constexpr uint16_t kL2capChannel = 3;
// Create a sequence with the above two values.
- auto sequenceMojo = arc::mojom::BluetoothSdpAttribute::New();
- sequenceMojo->type = bluez::BluetoothServiceAttributeValueBlueZ::SEQUENCE;
- sequenceMojo->sequence.push_back(std::move(valueUUID));
- sequenceMojo->sequence.push_back(std::move(valueUint16));
- sequenceMojo->type_size = sequenceMojo->sequence.size();
- sequenceMojo->json_value = base::nullopt;
+ auto sequence_mojo = arc::mojom::BluetoothSdpAttribute::New();
+ sequence_mojo->type = bluez::BluetoothServiceAttributeValueBlueZ::SEQUENCE;
+ {
+ // Create an UUID value.
+ auto value_uuid = arc::mojom::BluetoothSdpAttribute::New();
+ value_uuid->type = bluez::BluetoothServiceAttributeValueBlueZ::UUID;
+ value_uuid->type_size = static_cast<uint32_t>(sizeof(uint16_t));
+ value_uuid->json_value = ValueToJson(base::Value(kL2capUuid));
+ sequence_mojo->sequence.push_back(std::move(value_uuid));
+ }
+ {
+ // Create an UINT value.
+ auto value_channel = arc::mojom::BluetoothSdpAttribute::New();
+ value_channel->type = bluez::BluetoothServiceAttributeValueBlueZ::UINT;
+ value_channel->type_size = static_cast<uint32_t>(sizeof(kL2capChannel));
+ value_channel->json_value =
+ ValueToJson(base::Value(static_cast<int>(kL2capChannel)));
+ sequence_mojo->sequence.push_back(std::move(value_channel));
+ }
+ sequence_mojo->type_size = sequence_mojo->sequence.size();
+ sequence_mojo->json_value = base::nullopt;
- auto sequenceBlueZ =
- sequenceMojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
+ auto sequence_blue_z =
+ sequence_mojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::SEQUENCE,
- sequenceBlueZ.type());
- EXPECT_EQ(sequenceMojo->sequence.size(), sequenceBlueZ.sequence().size());
-
- const auto& sequence = sequenceBlueZ.sequence();
- std::string uuid;
- EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UUID,
- sequence.at(0).type());
- EXPECT_EQ(sizeof(uint16_t), sequence.at(0).size());
- EXPECT_TRUE(sequence.at(0).value().GetAsString(&uuid));
- EXPECT_EQ(l2capUUID, uuid);
-
- int channel;
- EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UINT,
- sequence.at(1).type());
- EXPECT_EQ(sizeof(l2capChannel), sequence.at(1).size());
- EXPECT_TRUE(sequence.at(1).value().GetAsInteger(&channel));
- EXPECT_EQ(l2capChannel, static_cast<uint16_t>(channel));
+ sequence_blue_z.type());
+ EXPECT_EQ(sequence_mojo->sequence.size(), sequence_blue_z.sequence().size());
+
+ const auto& sequence = sequence_blue_z.sequence();
+ ASSERT_EQ(2u, sequence.size());
+ {
+ const auto& blue_z = sequence[0];
+ EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UUID, blue_z.type());
+ EXPECT_EQ(sizeof(uint16_t), blue_z.size());
+ ASSERT_EQ(base::Value::Type::STRING, blue_z.value().type());
+ EXPECT_EQ(kL2capUuid, blue_z.value().GetString());
+ }
+
+ {
+ const auto& blue_z = sequence[1];
+ EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UINT, blue_z.type());
+ EXPECT_EQ(sizeof(kL2capChannel), blue_z.size());
+ ASSERT_EQ(base::Value::Type::INTEGER, blue_z.value().type());
+ EXPECT_EQ(kL2capChannel, static_cast<uint16_t>(blue_z.value().GetInt()));
+ }
}
-TEST(BluetoothTypeConvertorTest,
+TEST(BluetoothTypeConverterTest,
ConvertInvalidMojoValueAttributeToBlueZAttribute) {
// Create a Mojo attribute without value defined.
- auto valueNoData = arc::mojom::BluetoothSdpAttribute::New();
- valueNoData->type = bluez::BluetoothServiceAttributeValueBlueZ::UINT;
- valueNoData->type_size = static_cast<uint32_t>(sizeof(uint32_t));
- valueNoData->json_value = base::nullopt;
+ auto mojo = arc::mojom::BluetoothSdpAttribute::New();
+ mojo->type = bluez::BluetoothServiceAttributeValueBlueZ::UINT;
+ mojo->type_size = static_cast<uint32_t>(sizeof(uint32_t));
+ mojo->json_value = base::nullopt;
- auto valueNoDataBlueZ =
- valueNoData.To<bluez::BluetoothServiceAttributeValueBlueZ>();
+ auto blue_z = mojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE,
- valueNoDataBlueZ.type());
- EXPECT_EQ(0u, valueNoDataBlueZ.size());
- EXPECT_EQ(base::Value::Type::NONE, valueNoDataBlueZ.value().GetType());
+ blue_z.type());
+ EXPECT_EQ(0u, blue_z.size());
+ EXPECT_EQ(base::Value::Type::NONE, blue_z.value().type());
}
-TEST(BluetoothTypeConvertorTest,
- ConvertInvalidMojoSequenceAttributeToBlueZAttribute) {
+TEST(BluetoothTypeConverterTest,
+ ConvertInvalidMojoSequenceAttributeToBlueZAttribute_NoData) {
// Create a Mojo attribute with an empty sequence.
- auto sequenceNoData = arc::mojom::BluetoothSdpAttribute::New();
- sequenceNoData->type = bluez::BluetoothServiceAttributeValueBlueZ::SEQUENCE;
- sequenceNoData->type_size = 0;
- sequenceNoData->json_value = base::nullopt;
+ auto mojo = arc::mojom::BluetoothSdpAttribute::New();
+ mojo->type = bluez::BluetoothServiceAttributeValueBlueZ::SEQUENCE;
+ mojo->type_size = 0;
+ mojo->json_value = base::nullopt;
- auto sequenceNoDataBlueZ =
- sequenceNoData.To<bluez::BluetoothServiceAttributeValueBlueZ>();
+ auto blue_z = mojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE,
- sequenceNoDataBlueZ.type());
- EXPECT_EQ(0u, sequenceNoDataBlueZ.size());
- EXPECT_EQ(base::Value::Type::NONE, sequenceNoDataBlueZ.value().GetType());
+ blue_z.type());
+ EXPECT_EQ(0u, blue_z.size());
+ EXPECT_EQ(base::Value::Type::NONE, blue_z.value().type());
+}
+TEST(BluetoothTypeConverterTest,
+ ConvertInvalidMojoSequenceAttributeToBlueZAttribute_TooDeep) {
// Create a Mojo attribute with the depth = arc::kBluetoothSDPMaxDepth + 3.
- auto sequenceTooDeepMojo =
- CreateDeepMojoSequenceAttribute(arc::kBluetoothSDPMaxDepth + 3);
- auto sequenceTooDeepBlueZ =
- sequenceTooDeepMojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
+ auto mojo = CreateDeepMojoSequenceAttribute(arc::kBluetoothSDPMaxDepth + 3);
+
+ auto blue_z = mojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::SEQUENCE,
- sequenceTooDeepBlueZ.type());
- EXPECT_EQ(1u, sequenceTooDeepBlueZ.size());
- EXPECT_EQ(arc::kBluetoothSDPMaxDepth,
- GetDepthOfBlueZAttribute(sequenceTooDeepBlueZ));
+ blue_z.type());
+ EXPECT_EQ(1u, blue_z.size());
+ EXPECT_EQ(arc::kBluetoothSDPMaxDepth, GetDepthOfBlueZAttribute(blue_z));
}
-TEST(BluetoothTypeConvertorTest, ConvertBlueZValueAttributeToMojoAttribute) {
+TEST(BluetoothTypeConverterTest,
+ ConvertBlueZValueAttributeToMojoAttribute_NullType) {
// Check NULL type.
- auto nulltypeAttributeBlueZ = bluez::BluetoothServiceAttributeValueBlueZ();
+ auto blue_z = bluez::BluetoothServiceAttributeValueBlueZ();
- auto nulltypeAttributeMojo =
- ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(nulltypeAttributeBlueZ);
+ auto mojo = ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(blue_z);
- EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE,
- nulltypeAttributeMojo->type);
- EXPECT_EQ(0u, nulltypeAttributeMojo->type_size);
- {
- ASSERT_TRUE(nulltypeAttributeMojo->json_value.has_value());
- auto value =
- base::JSONReader::Read(nulltypeAttributeMojo->json_value.value());
- ASSERT_TRUE(value);
- EXPECT_TRUE(value->is_none());
- }
+ EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE, mojo->type);
+ EXPECT_EQ(0u, mojo->type_size);
+ ASSERT_TRUE(mojo->json_value.has_value());
+ auto value = base::JSONReader::Read(mojo->json_value.value());
+ ASSERT_TRUE(value);
+ EXPECT_TRUE(value->is_none());
+}
+
+TEST(BluetoothTypeConverterTest,
+ ConvertBlueZValueAttributeToMojoAttribute_UintType) {
// Check integer types (INT, UINT).
- uint16_t valueUint16 = 10;
- auto uintAttributeBlueZ = bluez::BluetoothServiceAttributeValueBlueZ(
- bluez::BluetoothServiceAttributeValueBlueZ::UINT, sizeof(valueUint16),
- std::make_unique<base::Value>(static_cast<int>(valueUint16)));
+ constexpr uint16_t kValue = 10;
+ auto blue_z = bluez::BluetoothServiceAttributeValueBlueZ(
+ bluez::BluetoothServiceAttributeValueBlueZ::UINT, sizeof(kValue),
+ std::make_unique<base::Value>(static_cast<int>(kValue)));
- auto uintAttributeMojo =
- ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(uintAttributeBlueZ);
+ auto mojo = ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(blue_z);
- EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UINT,
- uintAttributeMojo->type);
- EXPECT_EQ(sizeof(valueUint16), uintAttributeMojo->type_size);
- {
- ASSERT_TRUE(uintAttributeMojo->json_value.has_value());
- auto value = base::JSONReader::Read(uintAttributeMojo->json_value.value());
- ASSERT_TRUE(value);
- ASSERT_TRUE(value->is_int());
- EXPECT_EQ(valueUint16, static_cast<uint16_t>(value->GetInt()));
- }
+ EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UINT, mojo->type);
+ EXPECT_EQ(sizeof(kValue), mojo->type_size);
+
+ ASSERT_TRUE(mojo->json_value.has_value());
+ auto value = base::JSONReader::Read(mojo->json_value.value());
+ ASSERT_TRUE(value);
+ ASSERT_TRUE(value->is_int());
+ EXPECT_EQ(kValue, static_cast<uint16_t>(value->GetInt()));
+}
+TEST(BluetoothTypeConverterTest,
+ ConvertBlueZValueAttributeToMojoAttribute_BoolType) {
// Check bool type.
- bool valueBool = false;
- auto boolAttributeBlueZ = bluez::BluetoothServiceAttributeValueBlueZ(
+ auto blue_z = bluez::BluetoothServiceAttributeValueBlueZ(
bluez::BluetoothServiceAttributeValueBlueZ::BOOL, sizeof(bool),
- std::make_unique<base::Value>(valueBool));
+ std::make_unique<base::Value>(false));
- auto boolAttributeMojo =
- ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(boolAttributeBlueZ);
+ auto mojo = ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(blue_z);
- EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::BOOL,
- boolAttributeMojo->type);
- EXPECT_EQ(static_cast<uint32_t>(sizeof(valueBool)),
- boolAttributeMojo->type_size);
- {
- ASSERT_TRUE(boolAttributeMojo->json_value.has_value());
- auto value = base::JSONReader::Read(boolAttributeMojo->json_value.value());
- ASSERT_TRUE(value);
- ASSERT_TRUE(value->is_bool());
- EXPECT_FALSE(value->GetBool());
- }
+ EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::BOOL, mojo->type);
+ EXPECT_EQ(static_cast<uint32_t>(sizeof(bool)), mojo->type_size);
+ ASSERT_TRUE(mojo->json_value.has_value());
+ auto value = base::JSONReader::Read(mojo->json_value.value());
+ ASSERT_TRUE(value);
+ ASSERT_TRUE(value->is_bool());
+ EXPECT_FALSE(value->GetBool());
+}
+
+TEST(BluetoothTypeConverterTest,
+ ConvertBlueZValueAttributeToMojoAttribute_UuidType) {
// Check UUID type.
- std::string valueUUID("00000100-0000-1000-8000-00805f9b34fb");
- auto uuidAttributeBlueZ = bluez::BluetoothServiceAttributeValueBlueZ(
+ constexpr char kValue[] = "00000100-0000-1000-8000-00805f9b34fb";
+ auto blue_z = bluez::BluetoothServiceAttributeValueBlueZ(
bluez::BluetoothServiceAttributeValueBlueZ::UUID, sizeof(uint16_t),
- std::make_unique<base::Value>(valueUUID));
+ std::make_unique<base::Value>(kValue));
- auto uuidAttributeMojo =
- ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(uuidAttributeBlueZ);
+ auto mojo = ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(blue_z);
- EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UUID,
- uuidAttributeMojo->type);
- EXPECT_EQ(static_cast<uint32_t>(sizeof(uint16_t)),
- uuidAttributeMojo->type_size);
- {
- ASSERT_TRUE(uuidAttributeMojo->json_value.has_value());
- auto value = base::JSONReader::Read(uuidAttributeMojo->json_value.value());
- ASSERT_TRUE(value);
- ASSERT_TRUE(value->is_string());
- EXPECT_EQ(valueUUID, value->GetString());
- }
+ EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UUID, mojo->type);
+ EXPECT_EQ(static_cast<uint32_t>(sizeof(uint16_t)), mojo->type_size);
+
+ ASSERT_TRUE(mojo->json_value.has_value());
+ auto value = base::JSONReader::Read(mojo->json_value.value());
+ ASSERT_TRUE(value);
+ ASSERT_TRUE(value->is_string());
+ EXPECT_EQ(kValue, value->GetString());
+}
+TEST(BluetoothTypeConverterTest,
+ ConvertBlueZValueAttributeToMojoAttribute_StringType) {
// Check string types (STRING, URL).
- std::string valueString("Some Service Name");
- auto stringAttributeBlueZ = bluez::BluetoothServiceAttributeValueBlueZ(
- bluez::BluetoothServiceAttributeValueBlueZ::STRING, valueString.length(),
- std::make_unique<base::Value>(valueString));
-
- auto stringAttributeMojo =
- ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(stringAttributeBlueZ);
-
- EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::STRING,
- stringAttributeMojo->type);
- EXPECT_EQ(static_cast<uint32_t>(valueString.length()),
- stringAttributeMojo->type_size);
- {
- ASSERT_TRUE(stringAttributeMojo->json_value.has_value());
- auto value =
- base::JSONReader::Read(stringAttributeMojo->json_value.value());
- ASSERT_TRUE(value);
- ASSERT_TRUE(value->is_string());
- EXPECT_EQ(valueString, value->GetString());
- }
+ constexpr char kValue[] = "Some Service Name";
+ constexpr size_t kValueSize = sizeof(kValue) - 1; // Subtract '\0' size.
+ auto blue_z = bluez::BluetoothServiceAttributeValueBlueZ(
+ bluez::BluetoothServiceAttributeValueBlueZ::STRING, kValueSize,
+ std::make_unique<base::Value>(kValue));
+
+ auto mojo = ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(blue_z);
+
+ EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::STRING, mojo->type);
+ EXPECT_EQ(static_cast<uint32_t>(kValueSize), mojo->type_size);
+
+ ASSERT_TRUE(mojo->json_value.has_value());
+ auto value = base::JSONReader::Read(mojo->json_value.value());
+ ASSERT_TRUE(value);
+ ASSERT_TRUE(value->is_string());
+ EXPECT_EQ(kValue, value->GetString());
}
-TEST(BluetoothTypeConvertorTest, ConvertBlueZSequenceAttributeToMojoAttribute) {
- std::string l2capUUID("00000100-0000-1000-8000-00805f9b34fb");
- uint16_t l2capChannel = 3;
+TEST(BluetoothTypeConverterTest, ConvertBlueZSequenceAttributeToMojoAttribute) {
+ constexpr char kL2capUuid[] = "00000100-0000-1000-8000-00805f9b34fb";
+ constexpr uint16_t kL2capChannel = 3;
- std::unique_ptr<bluez::BluetoothServiceAttributeValueBlueZ::Sequence>
- sequence(new bluez::BluetoothServiceAttributeValueBlueZ::Sequence());
+ auto sequence =
+ std::make_unique<bluez::BluetoothServiceAttributeValueBlueZ::Sequence>();
sequence->push_back(bluez::BluetoothServiceAttributeValueBlueZ(
bluez::BluetoothServiceAttributeValueBlueZ::UUID, sizeof(uint16_t),
- std::make_unique<base::Value>(l2capUUID)));
+ std::make_unique<base::Value>(kL2capUuid)));
sequence->push_back(bluez::BluetoothServiceAttributeValueBlueZ(
bluez::BluetoothServiceAttributeValueBlueZ::UINT, sizeof(uint16_t),
- std::make_unique<base::Value>(l2capChannel)));
-
- auto sequenceBlueZ =
- bluez::BluetoothServiceAttributeValueBlueZ(std::move(sequence));
+ std::make_unique<base::Value>(kL2capChannel)));
- ASSERT_EQ(2u, sequenceBlueZ.sequence().size());
+ auto blue_z = bluez::BluetoothServiceAttributeValueBlueZ(std::move(sequence));
+ ASSERT_EQ(2u, blue_z.sequence().size());
- auto sequenceMojo =
- ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(sequenceBlueZ);
+ auto sequence_mojo = ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(blue_z);
EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::SEQUENCE,
- sequenceMojo->type);
- EXPECT_EQ(static_cast<uint32_t>(sequenceBlueZ.size()),
- sequenceMojo->type_size);
- EXPECT_EQ(sequenceMojo->type_size, sequenceMojo->sequence.size());
-
- EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UUID,
- sequenceMojo->sequence[0]->type);
- EXPECT_EQ(static_cast<uint32_t>(sizeof(uint16_t)),
- sequenceMojo->sequence[0]->type_size);
+ sequence_mojo->type);
+ EXPECT_EQ(static_cast<uint32_t>(blue_z.size()), sequence_mojo->type_size);
+ EXPECT_EQ(sequence_mojo->type_size, sequence_mojo->sequence.size());
+
{
- ASSERT_TRUE(sequenceMojo->sequence[0]->json_value.has_value());
- auto value =
- base::JSONReader::Read(sequenceMojo->sequence[0]->json_value.value());
+ const auto& mojo = sequence_mojo->sequence[0];
+ EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UUID, mojo->type);
+ EXPECT_EQ(static_cast<uint32_t>(sizeof(uint16_t)), mojo->type_size);
+
+ ASSERT_TRUE(mojo->json_value.has_value());
+ auto value = base::JSONReader::Read(mojo->json_value.value());
ASSERT_TRUE(value);
ASSERT_TRUE(value->is_string());
- EXPECT_EQ(l2capUUID, value->GetString());
+ EXPECT_EQ(kL2capUuid, value->GetString());
}
- EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UINT,
- sequenceMojo->sequence[1]->type);
- EXPECT_EQ(static_cast<uint32_t>(sizeof(uint16_t)),
- sequenceMojo->sequence[1]->type_size);
{
- ASSERT_TRUE(sequenceMojo->sequence[1]->json_value.has_value());
- auto value =
- base::JSONReader::Read(sequenceMojo->sequence[1]->json_value.value());
+ const auto& mojo = sequence_mojo->sequence[1];
+ EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::UINT, mojo->type);
+ EXPECT_EQ(static_cast<uint32_t>(sizeof(uint16_t)), mojo->type_size);
+ ASSERT_TRUE(mojo->json_value.has_value());
+ auto value = base::JSONReader::Read(mojo->json_value.value());
ASSERT_TRUE(value);
ASSERT_TRUE(value->is_int());
- EXPECT_EQ(l2capChannel, static_cast<uint16_t>(value->GetInt()));
+ EXPECT_EQ(kL2capChannel, static_cast<uint16_t>(value->GetInt()));
}
}
-TEST(BluetoothTypeConvertorTest,
- ConvertDeepBlueZSequenceAttributeToBlueZAttribute) {
- bluez::BluetoothServiceAttributeValueBlueZ sequenceBlueZ =
+TEST(BluetoothTypeConverterTest,
+ ConvertInvalidBlueZSequenceAttributeToBlueZAttribute_TooDeep) {
+ bluez::BluetoothServiceAttributeValueBlueZ blue_z =
CreateDeepBlueZSequenceAttribute(arc::kBluetoothSDPMaxDepth + 3);
- auto sequenceMojo =
- ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(sequenceBlueZ);
+ auto mojo = ConvertTo<arc::mojom::BluetoothSdpAttributePtr>(blue_z);
- EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::SEQUENCE,
- sequenceMojo->type);
- EXPECT_EQ((uint32_t)1, sequenceMojo->type_size);
- EXPECT_EQ(arc::kBluetoothSDPMaxDepth, GetDepthOfMojoAttribute(sequenceMojo));
+ EXPECT_EQ(bluez::BluetoothServiceAttributeValueBlueZ::SEQUENCE, mojo->type);
+ EXPECT_EQ(1u, mojo->type_size);
+ EXPECT_EQ(arc::kBluetoothSDPMaxDepth, GetDepthOfMojoAttribute(mojo));
}
} // namespace mojo
diff --git a/chromium/components/arc/clipboard/arc_clipboard_bridge.cc b/chromium/components/arc/clipboard/arc_clipboard_bridge.cc
index 7517dab7cb8..2c05eb1c088 100644
--- a/chromium/components/arc/clipboard/arc_clipboard_bridge.cc
+++ b/chromium/components/arc/clipboard/arc_clipboard_bridge.cc
@@ -150,25 +150,15 @@ ArcClipboardBridge* ArcClipboardBridge::GetForBrowserContext(
ArcClipboardBridge::ArcClipboardBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service)
: arc_bridge_service_(bridge_service),
- binding_(this),
event_originated_at_instance_(false) {
- arc_bridge_service_->clipboard()->AddObserver(this);
+ arc_bridge_service_->clipboard()->SetHost(this);
ui::ClipboardMonitor::GetInstance()->AddObserver(this);
}
ArcClipboardBridge::~ArcClipboardBridge() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
ui::ClipboardMonitor::GetInstance()->RemoveObserver(this);
- arc_bridge_service_->clipboard()->RemoveObserver(this);
-}
-
-void ArcClipboardBridge::OnInstanceReady() {
- mojom::ClipboardInstance* clipboard_instance =
- ARC_GET_INSTANCE_FOR_METHOD(arc_bridge_service_->clipboard(), Init);
- DCHECK(clipboard_instance);
- mojom::ClipboardHostPtr host_proxy;
- binding_.Bind(mojo::MakeRequest(&host_proxy));
- clipboard_instance->Init(std::move(host_proxy));
+ arc_bridge_service_->clipboard()->SetHost(nullptr);
}
void ArcClipboardBridge::OnClipboardDataChanged() {
diff --git a/chromium/components/arc/clipboard/arc_clipboard_bridge.h b/chromium/components/arc/clipboard/arc_clipboard_bridge.h
index 053ae8bb374..35b92f17c3c 100644
--- a/chromium/components/arc/clipboard/arc_clipboard_bridge.h
+++ b/chromium/components/arc/clipboard/arc_clipboard_bridge.h
@@ -10,9 +10,7 @@
#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "components/arc/common/clipboard.mojom.h"
-#include "components/arc/instance_holder.h"
#include "components/keyed_service/core/keyed_service.h"
-#include "mojo/public/cpp/bindings/binding.h"
#include "ui/base/clipboard/clipboard_observer.h"
namespace content {
@@ -23,11 +21,9 @@ namespace arc {
class ArcBridgeService;
-class ArcClipboardBridge
- : public KeyedService,
- public ui::ClipboardObserver,
- public InstanceHolder<mojom::ClipboardInstance>::Observer,
- public mojom::ClipboardHost {
+class ArcClipboardBridge : public KeyedService,
+ public ui::ClipboardObserver,
+ public mojom::ClipboardHost {
public:
// Returns singleton instance for the given BrowserContext,
// or nullptr if the browser |context| is not allowed to use ARC.
@@ -38,9 +34,6 @@ class ArcClipboardBridge
ArcBridgeService* bridge_service);
~ArcClipboardBridge() override;
- // InstanceHolder<mojom::ClipboardInstance>::Observer overrides.
- void OnInstanceReady() override;
-
// ClipboardObserver overrides.
void OnClipboardDataChanged() override;
@@ -52,7 +45,6 @@ class ArcClipboardBridge
private:
ArcBridgeService* const arc_bridge_service_; // Owned by ArcServiceManager.
- mojo::Binding<mojom::ClipboardHost> binding_;
bool event_originated_at_instance_;
diff --git a/chromium/components/arc/common/BUILD.gn b/chromium/components/arc/common/BUILD.gn
new file mode 100644
index 00000000000..a60852bbab1
--- /dev/null
+++ b/chromium/components/arc/common/BUILD.gn
@@ -0,0 +1,76 @@
+# 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.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+if (is_chromeos) {
+ mojom("common") {
+ sources = [
+ "accessibility_helper.mojom",
+ "app.mojom",
+ "arc_bridge.mojom",
+ "audio.mojom",
+ "auth.mojom",
+ "backup_settings.mojom",
+ "bitmap.mojom",
+ "bluetooth.mojom",
+ "boot_phase_monitor.mojom",
+ "cast_receiver.mojom",
+ "cert_store.mojom",
+ "clipboard.mojom",
+ "crash_collector.mojom",
+ "enterprise_reporting.mojom",
+ "file_system.mojom",
+ "gfx.mojom",
+ "ime.mojom",
+ "intent_helper.mojom",
+ "kiosk.mojom",
+ "lock_screen.mojom",
+ "metrics.mojom",
+ "midis.mojom",
+ "net.mojom",
+ "notifications.mojom",
+ "obb_mounter.mojom",
+ "oemcrypto.mojom",
+ "oemcrypto_daemon.mojom",
+ "policy.mojom",
+ "power.mojom",
+ "print.mojom",
+ "process.mojom",
+ "rotation_lock.mojom",
+ "scale_factor.mojom",
+ "storage_manager.mojom",
+ "tracing.mojom",
+ "tts.mojom",
+ "voice_interaction_arc_home.mojom",
+ "voice_interaction_framework.mojom",
+ "volume_mounter.mojom",
+ "wallpaper.mojom",
+ ]
+
+ public_deps = [
+ ":media",
+ "//mojo/common:common_custom_types",
+ "//ui/gfx/geometry/mojo",
+ ]
+ }
+}
+
+# Media related mojo interfaces. There are used by
+# //services/ui/public/interfaces. We have this separate mojom target to avoid
+# pulling in unnecessary interfaces,
+mojom("media") {
+ sources = [
+ "protected_buffer_manager.mojom",
+ "video.mojom",
+ "video_common.mojom",
+ "video_decode_accelerator.mojom",
+ "video_encode_accelerator.mojom",
+ ]
+
+ public_deps = [
+ "//mojo/common:common_custom_types",
+ "//ui/gfx/geometry/mojo",
+ ]
+}
diff --git a/chromium/components/arc/common/DEPS b/chromium/components/arc/common/DEPS
new file mode 100644
index 00000000000..04dd5ab2b11
--- /dev/null
+++ b/chromium/components/arc/common/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+media/video/video_encode_accelerator.h",
+]
diff --git a/chromium/components/arc/common/accessibility_helper.mojom b/chromium/components/arc/common/accessibility_helper.mojom
index 7cc1327546c..9e6eebabe90 100644
--- a/chromium/components/arc/common/accessibility_helper.mojom
+++ b/chromium/components/arc/common/accessibility_helper.mojom
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Next MinVersion: 9
+// Next MinVersion: 10
module arc.mojom;
-import "screen_rect.mojom";
+import "gfx.mojom";
// For future maintainers, each of the below enums were hand picked
// from their equivalents in the Android source. Keep them in the
@@ -211,20 +211,20 @@ struct AccessibilityRangeInfoData {
// AccessibilityNodeInfoData is a struct to contain info of
// AccessibilityNodeInfo in Android.
struct AccessibilityNodeInfoData {
- ScreenRect bounds_in_screen;
- [MinVersion=1]int32 id;
- [MinVersion=1]map<AccessibilityBooleanProperty, bool>? boolean_properties;
- [MinVersion=1]map<AccessibilityStringProperty, string>? string_properties;
- [MinVersion=1]map<AccessibilityIntProperty, int32>? int_properties;
+ Rect bounds_in_screen;
+ [MinVersion=1] int32 id;
+ [MinVersion=1] map<AccessibilityBooleanProperty, bool>? boolean_properties;
+ [MinVersion=1] map<AccessibilityStringProperty, string>? string_properties;
+ [MinVersion=1] map<AccessibilityIntProperty, int32>? int_properties;
[MinVersion=1]
map<AccessibilityIntListProperty, array<int32>>? int_list_properties;
- [MinVersion=3]map<AccessibilityStringListProperty, array<string>>?
+ [MinVersion=3] map<AccessibilityStringListProperty, array<string>>?
string_list_properties;
- [MinVersion=5]map<AccessibilityStringProperty, array<SpanEntry>>?
+ [MinVersion=5] map<AccessibilityStringProperty, array<SpanEntry>>?
spannable_string_properties;
- [MinVersion=5]AccessibilityCollectionInfoData? collection_info;
- [MinVersion=5]AccessibilityCollectionItemInfoData? collection_item_info;
- [MinVersion=5]AccessibilityRangeInfoData? range_info;
+ [MinVersion=5] AccessibilityCollectionInfoData? collection_info;
+ [MinVersion=5] AccessibilityCollectionItemInfoData? collection_item_info;
+ [MinVersion=5] AccessibilityRangeInfoData? range_info;
};
// Filters the event type (and implicitly the data) sent by the ARC
@@ -241,7 +241,7 @@ enum AccessibilityFilterType {
ALL,
// Send complete subtrees for root nodes with whitelisted package names.
- [MinVersion=2]WHITELISTED_PACKAGE_NAME
+ [MinVersion=2] WHITELISTED_PACKAGE_NAME
};
// AccessibilityEventData is a struct to contain info of
@@ -253,16 +253,16 @@ struct AccessibilityEventData {
array<AccessibilityNodeInfoData> node_data;
// notification_key is set only for an event on an Android notification.
- [MinVersion=6]string? notification_key;
+ [MinVersion=6] string? notification_key;
// window_id where this event is dispatched for. While this window_id matches
// with AccessibilityNodeInfo.getWindowId now, do not expect that it always
// matches with it.
- [MinVersion=6]int32 window_id;
+ [MinVersion=6] int32 window_id;
// Task associated with this event (usually the front task when this event
// gets dispatched).
- [MinVersion=8]int32 task_id;
+ [MinVersion=8] int32 task_id;
};
// AccessibilityActionData is a struct to contain info of AccessibilityAction in
@@ -277,7 +277,7 @@ struct AccessibilityActionData {
int32 custom_action_id;
// window_id where the action is performed on.
- [MinVersion=6]int32 window_id;
+ [MinVersion=6] int32 window_id;
};
// Next method ID: 2
@@ -290,28 +290,32 @@ interface AccessibilityHelperHost {
OnAccessibilityEvent@1(AccessibilityEventData event_data);
};
-// Next method ID: 7
+// Next method ID: 8
interface AccessibilityHelperInstance {
- Init@0(AccessibilityHelperHost host);
+ // DEPRECATED: Please use Init@7 instead.
+ InitDeprecated@0(AccessibilityHelperHost host);
+
+ // Establishes full-duplex communication with the host.
+ [MinVersion=9] Init@7(AccessibilityHelperHost host) => ();
PerformActionDeprecated@1(int32 id, AccessibilityActionType action);
// Set a filter on the event types received.
SetFilter@2(AccessibilityFilterType filter_type);
- [MinVersion=3]PerformActionDeprecated2@3(AccessibilityActionData action_data);
+ [MinVersion=3] PerformActionDeprecated2@3(AccessibilityActionData action_data);
// Perform an action on a node requested by a Chrome client.
- [MinVersion=4]PerformAction@4(AccessibilityActionData action_data)
+ [MinVersion=4] PerformAction@4(AccessibilityActionData action_data)
=> (bool result);
// Sets the package to use ChromeVox (true) or TalkBack (false). Returns true
// if the request was processed.
- [MinVersion=7]SetNativeChromeVoxArcSupportDeprecated@5(
+ [MinVersion=7] SetNativeChromeVoxArcSupportDeprecated@5(
string package_name, bool enabled) => (bool processed);
// Sets the focused window's package to use ChromeVox (true) or TalkBack
// (false).
- [MinVersion=8]SetNativeChromeVoxArcSupportForFocusedWindow@6(
+ [MinVersion=8] SetNativeChromeVoxArcSupportForFocusedWindow@6(
bool enabled) => (bool processed);
};
diff --git a/chromium/components/arc/common/app.mojom b/chromium/components/arc/common/app.mojom
index 48b66bb8baf..c00f4c4e838 100644
--- a/chromium/components/arc/common/app.mojom
+++ b/chromium/components/arc/common/app.mojom
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// Next MinVersion: 24
+// Next MinVersion: 27
module arc.mojom;
+import "gfx.mojom";
import "scale_factor.mojom";
-import "screen_rect.mojom";
// Describes OrientationLock request.
// Note: ChromeOS currently assumes the internal panel is always landscape.
@@ -55,6 +55,8 @@ struct ArcPackageInfo {
int64 last_backup_time;
bool sync; // true if package installation should be synced
[MinVersion=11] bool system; // true if package is system package.
+ // true if package registers VPNService intent.
+ [MinVersion=25] bool vpn_provider;
};
// Describes ARC app shortcut.
@@ -89,7 +91,8 @@ struct AppDiscoveryResult {
[MinVersion=22] string? package_name;
};
-// Describes the status of an app discovery request.
+// Describes the status of an app discovery request, including completed
+// states and all possible anomalies.
[Extensible]
enum AppDiscoveryRequestState {
// Request handled successfully.
@@ -97,7 +100,37 @@ enum AppDiscoveryRequestState {
// Request canceled when a newer request is sent.
CANCELED = 1,
// Request failed due to any communication error or Play Store internal error.
- ERROR = 2,
+ ERROR_DEPRECATED = 2,
+
+ // All possible reasons of ending a request:
+ // PlayStoreProxyService is not available.
+ PLAY_STORE_PROXY_NOT_AVAILABLE = 3,
+ // It fails to cancel the previous request.
+ FAILED_TO_CALL_CANCEL = 4,
+ // It fails to call findApps API.
+ FAILED_TO_CALL_FINDAPPS = 5,
+ // It comes with invalid parameters.
+ REQUEST_HAS_INVALID_PARAMS = 6,
+ // It times out.
+ REQUEST_TIMEOUT = 7,
+ // At least one result returned from Phonesky has an unmatched request code.
+ PHONESKY_RESULT_REQUEST_CODE_UNMATCHED = 8,
+ // At least one result returned from Phonesky has an unmatched session id.
+ PHONESKY_RESULT_SESSION_ID_UNMATCHED = 9,
+ // Phonesky returns with an unmatched request code.
+ PHONESKY_REQUEST_REQUEST_CODE_UNMATCHED = 10,
+ // The app discovery service is not available.
+ PHONESKY_APP_DISCOVERY_NOT_AVAILABLE = 11,
+ // The installed Phonesky version doesn't support app discovery.
+ PHONESKY_VERSION_NOT_SUPPORTED = 12,
+ // It gets an unexpected exception from Phonesky.
+ PHONESKY_UNEXPECTED_EXCEPTION = 13,
+ // The Phonesky app discovery service thinks it's malformed.
+ PHONESKY_MALFORMED_QUERY = 14,
+ // An internal error happens in Phonesky while processing the request.
+ PHONESKY_INTERNAL_ERROR = 15,
+ // At least one result returned with invalid app data.
+ PHONESKY_RESULT_INVALID_DATA = 16,
};
// Next method ID: 18
@@ -186,12 +219,16 @@ interface AppHost {
};
// TODO(lhchavez): Migrate all request/response messages to Mojo.
-// Next method ID: 21
+// Next method ID: 22
interface AppInstance {
- Init@0(AppHost host_ptr);
+ // DEPRECATED: Please use Init@21 instead.
+ InitDeprecated@0(AppHost host_ptr);
+
+ // Establishes full-duplex communication with the host.
+ [MinVersion=26] Init@21(AppHost host_ptr) => ();
[MinVersion=1] CanHandleResolutionDeprecated@4(
- string package_name, string activity, ScreenRect dimension) =>
+ string package_name, string activity, Rect dimension) =>
(bool can_handle);
// Closes the the given task.
@@ -205,7 +242,7 @@ interface AppInstance {
[MinVersion=8] InstallPackage@11(ArcPackageInfo arcPackageInfo);
LaunchAppDeprecated@1(string package_name, string activity,
- [MinVersion=1] ScreenRect? dimension_on_screen);
+ [MinVersion=1] Rect? dimension_on_screen);
// Sends a request to ARC to launch an ARC app defined by |package_name| and
// |activity|, which cannot be empty.
@@ -213,7 +250,7 @@ interface AppInstance {
int64 display_id);
[MinVersion=9] LaunchIntentDeprecated@12(string intent_uri,
- ScreenRect? dimension_on_screen);
+ Rect? dimension_on_screen);
// Sends a request to ARC to launch an intent. The intent is encoded as a URI
// string. See Intent.toUri().
@@ -244,11 +281,11 @@ interface AppInstance {
[MinVersion=4] SetTaskActive@7(int32 task_id);
[MinVersion=5] ShowPackageInfoDeprecated@9(string package_name,
- ScreenRect dimension_on_screen);
+ Rect dimension_on_screen);
[MinVersion=10] ShowPackageInfoOnPageDeprecated@15(string package_name,
ShowPackageInfoPage page,
- ScreenRect dimension_on_screen);
+ Rect dimension_on_screen);
// Sends a request to ARC to show package info for given package on the
// specified page.
diff --git a/chromium/components/arc/common/app.typemap b/chromium/components/arc/common/app.typemap
deleted file mode 100644
index 83cac7b5174..00000000000
--- a/chromium/components/arc/common/app.typemap
+++ /dev/null
@@ -1,15 +0,0 @@
-# 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.
-
-mojom = "//components/arc/common/app.mojom"
-public_headers = [
- "//ui/gfx/geometry/rect.h",
-]
-traits_headers = [ "//components/arc/common/app_struct_traits.h" ]
-sources = [
- "//components/arc/common/app_struct_traits.cc"
-]
-type_mappings = [
- "arc.mojom.ScreenRect=gfx::Rect"
-]
diff --git a/chromium/components/arc/common/app_struct_traits.cc b/chromium/components/arc/common/app_struct_traits.cc
deleted file mode 100644
index 46c8ac0a22c..00000000000
--- a/chromium/components/arc/common/app_struct_traits.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// 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 "components/arc/common/app_struct_traits.h"
-
-namespace mojo {
-
-bool StructTraits<arc::mojom::ScreenRectDataView, gfx::Rect>::Read(
- arc::mojom::ScreenRectDataView data,
- gfx::Rect* out) {
- if (data.right() < data.left() || data.bottom() < data.top())
- return false;
-
- out->SetRect(data.left(), data.top(), data.right() - data.left(),
- data.bottom() - data.top());
- return true;
-}
-
-} // namespace mojo
diff --git a/chromium/components/arc/common/app_struct_traits.h b/chromium/components/arc/common/app_struct_traits.h
deleted file mode 100644
index e0ada3d9e8c..00000000000
--- a/chromium/components/arc/common/app_struct_traits.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// 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.
-
-#ifndef COMPONENTS_ARC_COMMON_APP_STRUCT_TRAITS_H_
-#define COMPONENTS_ARC_COMMON_APP_STRUCT_TRAITS_H_
-
-#include "components/arc/common/app.mojom.h"
-#include "ui/gfx/geometry/rect.h"
-
-namespace mojo {
-
-template <>
-struct StructTraits<arc::mojom::ScreenRectDataView, gfx::Rect> {
- static int32_t left(const gfx::Rect& p) { return p.x(); }
- static int32_t top(const gfx::Rect& p) { return p.y(); }
- static int32_t right(const gfx::Rect& p) { return p.right(); }
- static int32_t bottom(const gfx::Rect& p) { return p.bottom(); }
- static bool Read(arc::mojom::ScreenRectDataView data, gfx::Rect* out);
-};
-
-} // namespace mojo
-
-#endif // COMPONENTS_ARC_COMMON_APP_STRUCT_TRAITS_H_
diff --git a/chromium/components/arc/common/arc_bridge.mojom b/chromium/components/arc/common/arc_bridge.mojom
index e8f613983c2..297c99a3a37 100644
--- a/chromium/components/arc/common/arc_bridge.mojom
+++ b/chromium/components/arc/common/arc_bridge.mojom
@@ -8,6 +8,7 @@ import "accessibility_helper.mojom";
import "app.mojom";
import "audio.mojom";
import "auth.mojom";
+import "backup_settings.mojom";
import "bluetooth.mojom";
import "boot_phase_monitor.mojom";
import "cast_receiver.mojom";
@@ -40,9 +41,9 @@ import "voice_interaction_framework.mojom";
import "volume_mounter.mojom";
import "wallpaper.mojom";
-// Next MinVersion: 33
+// Next MinVersion: 34
// Deprecated method IDs: 101, 105
-// Next method ID: 138
+// Next method ID: 139
interface ArcBridgeHost {
// Keep the entries alphabetical. In order to do so without breaking
// compatibility with the ARC instance, explicitly assign each interface a
@@ -61,6 +62,9 @@ interface ArcBridgeHost {
// Notifies Chrome that the AuthInstance interface is ready.
[MinVersion=1] OnAuthInstanceReady@106(AuthInstance instance_ptr);
+ // Notifies Chrome that the BackupSettingsInstance interface is ready.
+ [MinVersion=33] OnBackupSettingsInstanceReady@138(BackupSettingsInstance instance_ptr);
+
// Notifies Chrome that the BluetoothInstance interface is ready.
[MinVersion=9] OnBluetoothInstanceReady@113(BluetoothInstance instance_ptr);
diff --git a/chromium/components/arc/common/arc_gfx_struct_traits.cc b/chromium/components/arc/common/arc_gfx_struct_traits.cc
new file mode 100644
index 00000000000..20858df1123
--- /dev/null
+++ b/chromium/components/arc/common/arc_gfx_struct_traits.cc
@@ -0,0 +1,28 @@
+// 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 "components/arc/common/arc_gfx_struct_traits.h"
+
+namespace mojo {
+
+bool StructTraits<arc::mojom::RectDataView, gfx::Rect>::Read(
+ arc::mojom::RectDataView data,
+ gfx::Rect* out) {
+ if (data.right() < data.left() || data.bottom() < data.top())
+ return false;
+
+ out->SetRect(data.left(), data.top(), data.right() - data.left(),
+ data.bottom() - data.top());
+ return true;
+}
+
+bool StructTraits<arc::mojom::RangeDataView, gfx::Range>::Read(
+ arc::mojom::RangeDataView data,
+ gfx::Range* out) {
+ out->set_start(data.start());
+ out->set_end(data.end());
+ return true;
+}
+
+} // namespace mojo
diff --git a/chromium/components/arc/ime/arc_ime_struct_traits.h b/chromium/components/arc/common/arc_gfx_struct_traits.h
index 91a7addffde..02c4edf9023 100644
--- a/chromium/components/arc/ime/arc_ime_struct_traits.h
+++ b/chromium/components/arc/common/arc_gfx_struct_traits.h
@@ -2,32 +2,33 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_ARC_IME_ARC_IME_STRUCT_TRAITS_H_
-#define COMPONENTS_ARC_IME_ARC_IME_STRUCT_TRAITS_H_
+#ifndef COMPONENTS_ARC_COMMON_ARC_GFX_STRUCT_TRAITS_H_
+#define COMPONENTS_ARC_COMMON_ARC_GFX_STRUCT_TRAITS_H_
-#include "components/arc/common/ime.mojom.h"
+#include "components/arc/common/gfx.mojom.h"
#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/range/range.h"
namespace mojo {
template <>
-struct StructTraits<arc::mojom::CursorRectDataView, gfx::Rect> {
+struct StructTraits<arc::mojom::RectDataView, gfx::Rect> {
static int32_t left(const gfx::Rect& r) { return r.x(); }
static int32_t top(const gfx::Rect& r) { return r.y(); }
static int32_t right(const gfx::Rect& r) { return r.right(); }
static int32_t bottom(const gfx::Rect& r) { return r.bottom(); }
- static bool Read(arc::mojom::CursorRectDataView data, gfx::Rect* out);
+ static bool Read(arc::mojom::RectDataView data, gfx::Rect* out);
};
template <>
-struct StructTraits<arc::mojom::TextRangeDataView, gfx::Range> {
+struct StructTraits<arc::mojom::RangeDataView, gfx::Range> {
static uint32_t start(const gfx::Range& r) { return r.start(); }
static uint32_t end(const gfx::Range& r) { return r.end(); }
- static bool Read(arc::mojom::TextRangeDataView data, gfx::Range* out);
+ static bool Read(arc::mojom::RangeDataView data, gfx::Range* out);
};
} // namespace mojo
-#endif // COMPONENTS_ARC_IME_ARC_IME_STRUCT_TRAITS_H_
+#endif // COMPONENTS_ARC_COMMON_ARC_GFX_STRUCT_TRAITS_H_
diff --git a/chromium/components/arc/common/audio.mojom b/chromium/components/arc/common/audio.mojom
index 07e2b2eace3..eceb20e4cdf 100644
--- a/chromium/components/arc/common/audio.mojom
+++ b/chromium/components/arc/common/audio.mojom
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Next MinVersion: 4
+// Next MinVersion: 5
module arc.mojom;
@@ -24,10 +24,13 @@ interface AudioHost {
[MinVersion=3] OnSystemVolumeUpdateRequest@1(int32 percent);
};
-// Next method ID: 3
+// Next method ID: 4
interface AudioInstance {
+ // DEPRECATED: Please use Init@3 instead.
+ [MinVersion=1] InitDeprecated@1(AudioHost host);
+
// Establishes full-duplex communication with the host.
- [MinVersion=1] Init@1(AudioHost host);
+ [MinVersion=4] Init@3(AudioHost host) => ();
// Notify plug states of headphone, microphone, etc. Each switch state is
// represented by the corresponding bit, if the bit is set then the switch
diff --git a/chromium/components/arc/common/auth.mojom b/chromium/components/arc/common/auth.mojom
index bee59b6c84c..54334bc9bae 100644
--- a/chromium/components/arc/common/auth.mojom
+++ b/chromium/components/arc/common/auth.mojom
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Next MinVersion: 12
+// Next MinVersion: 13
module arc.mojom;
@@ -184,10 +184,13 @@ interface AuthHost {
[MinVersion=9] ReportAccountCheckStatus@9(AccountCheckStatus status);
};
-// Next Method ID: 2
+// Next Method ID: 3
interface AuthInstance {
+ // DEPRECATED: Please use Init@2 instead.
+ InitDeprecated@0(AuthHost host_ptr);
+
// Establishes full-duplex communication with the host.
- Init@0(AuthHost host_ptr);
+ [MinVersion=12] Init@2(AuthHost host_ptr) => ();
// Callback from RequestAccountInfo. This cannot be a normal callback since
// the result can sometimes take a few minutes in some cases (Kiosk mode),
diff --git a/chromium/components/arc/common/backup_settings.mojom b/chromium/components/arc/common/backup_settings.mojom
new file mode 100644
index 00000000000..4ebb2ce2e09
--- /dev/null
+++ b/chromium/components/arc/common/backup_settings.mojom
@@ -0,0 +1,16 @@
+// 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.
+//
+// Next MinVersion: 1
+
+module arc.mojom;
+
+// Controls the setting entries for the ARC backup and restore feature.
+// Next method ID: 1
+interface BackupSettingsInstance {
+ // Enables or disables the backup feature as specified by the |enabled|
+ // parameter. The |managed| parameter indicates whether or not this setting
+ // is managed by the enterprise policy.
+ SetBackupEnabled@0(bool enabled, bool managed);
+};
diff --git a/chromium/components/arc/common/bluetooth.mojom b/chromium/components/arc/common/bluetooth.mojom
index f6e41c9f561..f22585f8ec1 100644
--- a/chromium/components/arc/common/bluetooth.mojom
+++ b/chromium/components/arc/common/bluetooth.mojom
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Next MinVersion: 7
+// Next MinVersion: 8
module arc.mojom;
@@ -403,9 +403,13 @@ interface BluetoothHost {
=> (BluetoothGattStatus status);
};
-// Next Method ID: 18
+// Next Method ID: 19
interface BluetoothInstance {
- Init@0(BluetoothHost host_ptr);
+ // DEPRECATED: Please use Init@18 instead.
+ InitDeprecated@0(BluetoothHost host_ptr);
+
+ // Establishes full-duplex communication with the host.
+ [MinVersion=7] Init@18(BluetoothHost host_ptr) => ();
OnAdapterProperties@1(BluetoothStatus status,
array<BluetoothProperty> properties);
diff --git a/chromium/components/arc/common/bluetooth.typemap b/chromium/components/arc/common/bluetooth.typemap
index fc86d17a20e..b59c8707820 100644
--- a/chromium/components/arc/common/bluetooth.typemap
+++ b/chromium/components/arc/common/bluetooth.typemap
@@ -6,6 +6,9 @@ public_headers = [
"//device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.h",
]
traits_headers = [ "//components/arc/bluetooth/bluetooth_struct_traits.h" ]
+sources = [
+ "//components/arc/bluetooth/bluetooth_struct_traits.cc",
+]
deps = [
"//device/bluetooth",
]
diff --git a/chromium/components/arc/common/boot_phase_monitor.mojom b/chromium/components/arc/common/boot_phase_monitor.mojom
index e642f2656da..045270f3e1f 100644
--- a/chromium/components/arc/common/boot_phase_monitor.mojom
+++ b/chromium/components/arc/common/boot_phase_monitor.mojom
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// Next MinVersion: 1
+// Next MinVersion: 2
module arc.mojom;
@@ -12,8 +12,11 @@ interface BootPhaseMonitorHost {
OnBootCompleted@0();
};
-// Next method ID: 1
+// Next method ID: 2
interface BootPhaseMonitorInstance {
+ // DEPRECATED: Please use Init@1 instead.
+ InitDeprecated@0(BootPhaseMonitorHost host_ptr);
+
// Establishes full-duplex communication with the host.
- Init@0(BootPhaseMonitorHost host_ptr);
+ [MinVersion=1] Init@1(BootPhaseMonitorHost host_ptr) => ();
};
diff --git a/chromium/components/arc/common/cert_store.mojom b/chromium/components/arc/common/cert_store.mojom
index 6af522bd9bb..eabf6b13731 100644
--- a/chromium/components/arc/common/cert_store.mojom
+++ b/chromium/components/arc/common/cert_store.mojom
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Next MinVersion: 2
+
//
// CertStoreHost is modeled after Android keymaster interface
// hardware/libhardware/include/hardware/keymaster2.h
@@ -106,10 +108,13 @@ interface CertStoreHost {
Abort@5(uint64 operation_handle) => (KeymasterError error);
};
-// Next method ID: 3
+// Next method ID: 4
interface CertStoreInstance {
+ // DEPRECATED: Please use Init@3 instead.
+ InitDeprecated@0(CertStoreHost host_ptr);
+
// Establishes full-duplex communication with the host.
- Init@0(CertStoreHost host_ptr);
+ [MinVersion=1] Init@3(CertStoreHost host_ptr) => ();
// Informs the key permissions are changed: only listed packages are allowed
// to use exposed certificates.
diff --git a/chromium/components/arc/common/clipboard.mojom b/chromium/components/arc/common/clipboard.mojom
index d10183e1a26..db8d434e6f6 100644
--- a/chromium/components/arc/common/clipboard.mojom
+++ b/chromium/components/arc/common/clipboard.mojom
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Next MinVersion: 3
module arc.mojom;
@@ -10,7 +11,6 @@ module arc.mojom;
// either a |blob| or a |text|.
// Value for |ClipRepresentation|.
-// Next MinVersion: 1
// Next ID: 2
union ClipValue {
// For images and other opaque structures.
@@ -20,7 +20,6 @@ union ClipValue {
};
// One possible representation of the |ClipData|: |mime_type| + its |value|.
-// Next MinVersion: 1
// Next ID: 2
struct ClipRepresentation {
// The mime type.
@@ -30,7 +29,6 @@ struct ClipRepresentation {
};
// The |ClipData| to transfer.
-// Next MinVersion: 1
// Next ID: 1
struct ClipData {
// A |ClipData| could have multiple representations.
@@ -38,7 +36,6 @@ struct ClipData {
array<ClipRepresentation> representations@0;
};
-// Next MinVersion: 2
// Next method ID: 4
// IDs to be removed 18 weeks after being up revved: 0, 1
interface ClipboardHost {
@@ -61,12 +58,14 @@ interface ClipboardHost {
[MinVersion=1] GetClipContent@3() => (ClipData data);
};
-// Next MinVersion: 2
-// Next method ID: 3
+// Next method ID: 4
// IDs to be removed 18 weeks after being up revved: 1
interface ClipboardInstance {
+ // DEPRECATED: Please use Init@3 instead.
+ InitDeprecated@0(ClipboardHost host_ptr);
+
// Establishes full-duplex communication with the host.
- Init@0(ClipboardHost host_ptr);
+ [MinVersion=2] Init@3(ClipboardHost host_ptr) => ();
// Passes the result of ClipboardHost.GetTextContentDeprecated().
OnGetTextContentDeprecated@1(string returned_text);
diff --git a/chromium/components/arc/common/crash_collector.mojom b/chromium/components/arc/common/crash_collector.mojom
index b61963cfcba..fb827b89f3f 100644
--- a/chromium/components/arc/common/crash_collector.mojom
+++ b/chromium/components/arc/common/crash_collector.mojom
@@ -2,8 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Next MinVersion: 3
+
module arc.mojom;
+// Next Method ID: 2
interface CrashCollectorHost {
// Sends a dump for a non-native crash of the given |type|. The host reads
// the dump from |pipe|, or rejects the dump by closing |pipe|. Note that
@@ -17,6 +20,11 @@ interface CrashCollectorHost {
string cpu_abi);
};
+// Next Method ID: 2
interface CrashCollectorInstance {
- Init@0(CrashCollectorHost host_ptr);
+ // DEPRECATED: Please use Init@1 instead.
+ InitDeprecated@0(CrashCollectorHost host_ptr);
+
+ // Establishes full-duplex communication with the host.
+ [MinVersion=2] Init@1(CrashCollectorHost host_ptr) => ();
};
diff --git a/chromium/components/arc/common/enterprise_reporting.mojom b/chromium/components/arc/common/enterprise_reporting.mojom
index 0ad1ffab2a5..3130ee9fc54 100644
--- a/chromium/components/arc/common/enterprise_reporting.mojom
+++ b/chromium/components/arc/common/enterprise_reporting.mojom
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// Next MinVersion: 2
+// Next MinVersion: 3
module arc.mojom;
// Enumerates the states that management can be in for a user.
@@ -25,10 +25,13 @@ interface EnterpriseReportingHost {
ReportManagementState@0(ManagementState state);
};
-// Next method ID: 2
+// Next method ID: 3
interface EnterpriseReportingInstance {
+ // DEPRECATED: Please use Init@2 instead.
+ InitDeprecated@0(EnterpriseReportingHost host_ptr);
+
// Establishes full-duplex communication with the host.
- Init@0(EnterpriseReportingHost host_ptr);
+ [MinVersion=2] Init@2(EnterpriseReportingHost host_ptr) => ();
// Requests that a JSON status blob be generated and passed to the
// host.
diff --git a/chromium/components/arc/common/file_system.mojom b/chromium/components/arc/common/file_system.mojom
index dae4ef28a45..b3c2ef235b1 100644
--- a/chromium/components/arc/common/file_system.mojom
+++ b/chromium/components/arc/common/file_system.mojom
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// Next MinVersion: 7
+// Next MinVersion: 8
module arc.mojom;
@@ -73,7 +73,7 @@ interface FileSystemHost {
[MinVersion=6] OpenFileToRead@4(string url) => (handle? fd);
};
-// Next method ID: 10
+// Next method ID: 11
interface FileSystemInstance {
// Notes about Android Documents Provider:
//
@@ -140,8 +140,11 @@ interface FileSystemInstance {
[MinVersion=5] GetRecentDocuments@9(string authority, string root_id) =>
(array<Document>? documents);
+ // DEPRECATED: Please use Init@10 instead.
+ [MinVersion=3] InitDeprecated@5(FileSystemHost host_ptr);
+
// Establishes full-duplex communication with the host.
- [MinVersion=3] Init@5(FileSystemHost host_ptr);
+ [MinVersion=7] Init@10(FileSystemHost host_ptr) => ();
// Asks the ContentResolver to get a FD to read the file specified by the
// URL.
diff --git a/chromium/components/arc/common/file_system.typemap b/chromium/components/arc/common/file_system.typemap
index cb71bf2d616..e21e8490f6a 100644
--- a/chromium/components/arc/common/file_system.typemap
+++ b/chromium/components/arc/common/file_system.typemap
@@ -8,4 +8,7 @@ public_deps = [
"//storage/browser",
]
traits_headers = [ "//components/arc/file_system/file_system_struct_traits.h" ]
+sources = [
+ "//components/arc/file_system/file_system_struct_traits.cc",
+]
type_mappings = [ "arc.mojom.ChangeType=storage::WatcherManager::ChangeType" ]
diff --git a/chromium/components/arc/common/gfx.mojom b/chromium/components/arc/common/gfx.mojom
new file mode 100644
index 00000000000..aaf58a27b7e
--- /dev/null
+++ b/chromium/components/arc/common/gfx.mojom
@@ -0,0 +1,28 @@
+// 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.
+
+// Defines structs (and its related type mappings) related gfx.
+// Eventually, we may want to migrate mojom files under ui/gfx.
+// However, currently there is no well developed roll mechanism, so
+// API diverge can be more problematic, unfortunately. So, instead of sharing,
+// defines structs by ourselves.
+
+module arc.mojom;
+
+// Represents a rectangle. Note that the wire format is different from
+// the one defined in geometry.mojom in ui/gfx for backward compatibility.
+struct Rect {
+ int32 left;
+ int32 top;
+ int32 right;
+ int32 bottom;
+};
+
+// Represents a range in a text. It is an open interval [start, end).
+struct Range {
+ // Start offset in UTF-16 index.
+ uint32 start;
+ // End offset in UTF-16 index.
+ uint32 end;
+};
diff --git a/chromium/components/arc/common/ime.typemap b/chromium/components/arc/common/gfx.typemap
index 141f4ad18ce..be462bc0ab5 100644
--- a/chromium/components/arc/common/ime.typemap
+++ b/chromium/components/arc/common/gfx.typemap
@@ -2,19 +2,24 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-mojom = "//components/arc/common/ime.mojom"
+mojom = "//components/arc/common/gfx.mojom"
+
public_headers = [
"//ui/gfx/geometry/rect.h",
"//ui/gfx/range/range.h",
]
+
deps = [
"//ui/gfx",
]
-traits_headers = [ "//components/arc/ime/arc_ime_struct_traits.h" ]
+
+traits_headers = [ "//components/arc/common/arc_gfx_struct_traits.h" ]
+
sources = [
- "//components/arc/ime/arc_ime_struct_traits.cc",
+ "//components/arc/common/arc_gfx_struct_traits.cc",
]
+
type_mappings = [
- "arc.mojom.CursorRect=::gfx::Rect[move_only]",
- "arc.mojom.TextRange=::gfx::Range[move_only]",
+ "arc.mojom.Rect=::gfx::Rect",
+ "arc.mojom.Range=::gfx::Range",
]
diff --git a/chromium/components/arc/common/ime.mojom b/chromium/components/arc/common/ime.mojom
index fd945302c3c..1dd59177d38 100644
--- a/chromium/components/arc/common/ime.mojom
+++ b/chromium/components/arc/common/ime.mojom
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Next MinVersion: 6
+// Next MinVersion: 7
module arc.mojom;
-import "screen_rect.mojom";
+import "gfx.mojom";
// Represents the type of text input field currently focused.
[Extensible]
@@ -24,25 +24,6 @@ enum TextInputType {
DATETIME,
};
-// TODO(yhanada): Switch to use gfx.mojom.Rect. See crbug.com/723224.
-// Represents the text insertion points in the container screen coordinates.
-struct CursorRect {
- int32 left;
- int32 top;
- int32 right;
- int32 bottom;
-};
-
-// TODO(yhanada): Switch to use gfx.mojom.Range. See crbug.com/723224.
-// Represents the range in the text. It is an open interval [start, end).
-[MinVersion=5]
-struct TextRange {
- // Start offset in UTF-16 index.
- uint32 start;
- // End offset in UTF-16 index.
- uint32 end;
-};
-
// Represents a single segment of text currently composed by IME.
struct CompositionSegment {
// Start offset of the segment in UTF-16 index.
@@ -59,7 +40,7 @@ interface ImeHost {
OnTextInputTypeChanged@0(TextInputType type);
// Notifies Chrome that the cursor poisition has changed.
- OnCursorRectChanged@1(CursorRect rect);
+ OnCursorRectChanged@1(Rect rect);
// Notifies Chrome that the current composition is canceled.
[MinVersion=1] OnCancelComposition@2();
@@ -74,18 +55,22 @@ interface ImeHost {
// into this method because Chrome OS IME tries to retrieve these information
// synchronously, so we need to update them all at once to keep consistency.
[MinVersion=5] OnCursorRectChangedWithSurroundingText@4(
- CursorRect rect, // The cursor position.
- TextRange text_range, // The range of |text_in_range| in the current
+ Rect rect, // The cursor position.
+ Range text_range, // The range of |text_in_range| in the current
// text in the editor.
string text_in_range, // The text around the cursor.
- TextRange selection_range // The range of the selected text
+ Range selection_range // The range of the selected text
// in the current text in the editor.
);
};
-// Next method ID: 6
+// Next method ID: 7
interface ImeInstance {
- Init@0(ImeHost host_ptr);
+ // DEPRECATED: Please use Init@6 instead.
+ InitDeprecated@0(ImeHost host_ptr);
+
+ // Establishes full-duplex communication with the host.
+ [MinVersion=6] Init@6(ImeHost host_ptr) => ();
// Sets composition text and attributes requested by the host IME.
SetCompositionText@1(string text, array<CompositionSegment> segments);
@@ -100,7 +85,7 @@ interface ImeInstance {
// |new_bounds| Represents a ChromeOS virtual keyboard bounds in ChromeOS
// screen coordinate, physical pixel as a unit.
// When all members are zero value, virtual keyboard is being hidden.
- [MinVersion=3] OnKeyboardBoundsChanging@4(ScreenRect new_bounds);
+ [MinVersion=3] OnKeyboardBoundsChanging@4(Rect new_bounds);
// Deletes current selection plus the specified number of char16 values
// before and after selection or caret.
diff --git a/chromium/components/arc/common/intent_helper.mojom b/chromium/components/arc/common/intent_helper.mojom
index e62874f6669..4cc56de151d 100644
--- a/chromium/components/arc/common/intent_helper.mojom
+++ b/chromium/components/arc/common/intent_helper.mojom
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// Next MinVersion: 19
+// Next MinVersion: 20
module arc.mojom;
@@ -82,9 +82,9 @@ struct UrlWithMimeType {
string mime_type;
};
-// Describes a specific page in chrome://settings.
+// Describes a specific page in chrome://, about:blank, about:downloads and about:history.
[Extensible]
-enum SettingsPage {
+enum ChromePage {
MULTIDEVICE,
MAIN,
POWER,
@@ -92,9 +92,34 @@ enum SettingsPage {
DATETIME,
DISPLAY,
WIFI,
- LANGUAGE,
+ LANGUAGES,
PRIVACY,
HELP,
+ ACCOUNTS,
+ APPEARANCE,
+ AUTOFILL,
+ BLUETOOTHDEVICES,
+ CHANGEPICTURE,
+ CLEARBROWSERDATA,
+ CLOUDPRINTERS,
+ CUPSPRINTERS,
+ DOWNLOADS,
+ KEYBOARDOVERLAY,
+ LOCKSCREEN,
+ MANAGEACCESSIBILITY,
+ NETWORKSTYPEVPN,
+ ONSTARTUP,
+ PASSWORDS,
+ POINTEROVERLAY,
+ RESET,
+ SEARCH,
+ STORAGE,
+ SYNCSETUP,
+ ABOUTBLANK,
+ ABOUTDOWNLOADS,
+ ABOUTHISTORY,
+
+ LAST = ABOUTHISTORY,
};
// Handles intents from ARC in Chrome.
@@ -126,12 +151,12 @@ interface IntentHelperHost {
// Opens the volume control.
[MinVersion=16] OpenVolumeControl@6();
- // Opens the specified settings page in the Chrome browser.
- [MinVersion=17] OnOpenChromeSettings@7([MinVersion=18] SettingsPage page);
+ // Opens the specified Chrome page in the Chrome browser.
+ [MinVersion=17] OnOpenChromePage@7([MinVersion=18] ChromePage page);
};
// Sends intents to ARC on behalf of Chrome.
-// Next method ID: 13
+// Next method ID: 14
interface IntentHelperInstance {
// Sets the given package as a preferred package. The next time an ACTION_VIEW
// intent is sent with a URL that requires disambiguation, instead of opening
@@ -154,8 +179,11 @@ interface IntentHelperInstance {
ActivityName activity,
ActionType action_type);
+ // DEPRECATED: Please use Init@13 instead.
+ InitDeprecated@0(IntentHelperHost host_ptr);
+
// Establishes full-duplex communication with the host.
- Init@0(IntentHelperHost host_ptr);
+ [MinVersion=19] Init@13(IntentHelperHost host_ptr) => ();
// DEPRECATED. Use FileSystemInstance.OpenFileToRead() instead.
[MinVersion=15] OpenFileToReadDeprecated@12(string url) => (handle? fd);
diff --git a/chromium/components/arc/common/kiosk.mojom b/chromium/components/arc/common/kiosk.mojom
index f2903b380e8..39beb508f79 100644
--- a/chromium/components/arc/common/kiosk.mojom
+++ b/chromium/components/arc/common/kiosk.mojom
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// Next MinVersion: 1
+// Next MinVersion: 2
module arc.mojom;
@@ -20,10 +20,11 @@ interface KioskHost {
OnMaintenanceSessionFinished@1(int32 session_id, bool succeeded);
};
-// Next method ID: 1
+// Next method ID: 2
interface KioskInstance {
+ // DEPRECATED: Please use Init@1 instead.
+ InitDeprecated@0(KioskHost host_ptr);
+
// Establishes full-duplex communication with the host.
- // |host_ptr| is the MessagePipe endpoint that is bound to the
- // KioskHost binding.
- Init@0(KioskHost host_ptr);
+ [MinVersion=1] Init@1(KioskHost host_ptr) => ();
};
diff --git a/chromium/components/arc/common/metrics.mojom b/chromium/components/arc/common/metrics.mojom
index d1c997a52a1..4f98a2b6513 100644
--- a/chromium/components/arc/common/metrics.mojom
+++ b/chromium/components/arc/common/metrics.mojom
@@ -1,7 +1,7 @@
// 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.
-// Next MinVersion: 2
+// Next MinVersion: 3
module arc.mojom;
@@ -46,7 +46,11 @@ interface MetricsHost {
[MinVersion=1] BootType boot_type);
};
-// Next method ID: 1
+// Next method ID: 2
interface MetricsInstance {
- Init@0(MetricsHost host_ptr);
+ // DEPRECATED: Please use Init@1 instead.
+ InitDeprecated@0(MetricsHost host_ptr);
+
+ // Establishes full-duplex communication with the host.
+ [MinVersion=2] Init@1(MetricsHost host_ptr) => ();
};
diff --git a/chromium/components/arc/common/midis.mojom b/chromium/components/arc/common/midis.mojom
index 3342f21bc8b..bea75fb0287 100644
--- a/chromium/components/arc/common/midis.mojom
+++ b/chromium/components/arc/common/midis.mojom
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Next MinVersion: 2
+
// This file defines the mojo interface between Android, Chrome and the
// Chrome OS daemon for the MIDI implementation used in ARC.
@@ -66,7 +68,11 @@ interface MidisHost {
// MidisInstance is implemented in the ARC MIDI JNI code that
// runs in Android and handles the Android side of the ArcBridge connection.
-// Next Method ID: 1
+// Next Method ID: 2
interface MidisInstance {
- Init@0(MidisHost host_ptr);
+ // DEPRECATED: Please use Init@1 instead.
+ InitDeprecated@0(MidisHost host_ptr);
+
+ // Establishes full-duplex communication with the host.
+ [MinVersion=1] Init@1(MidisHost host_ptr) => ();
};
diff --git a/chromium/components/arc/common/net.mojom b/chromium/components/arc/common/net.mojom
index c29a96e594c..d162a242564 100644
--- a/chromium/components/arc/common/net.mojom
+++ b/chromium/components/arc/common/net.mojom
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Next MinVersion: 8
+// Next MinVersion: 9
module arc.mojom;
@@ -162,6 +162,7 @@ struct AndroidVpnConfiguration {
array<string> domains@8;
};
+// Next Method ID: 13
interface NetHost {
// Sends a request to get enabled / disabled status of WiFi.
GetWifiEnabledState@1() => (bool is_enabled);
@@ -210,9 +211,13 @@ interface NetHost {
[MinVersion=7] AndroidVpnStateChanged@12(ConnectionStateType state);
};
+// Next Method ID: 7
interface NetInstance {
+ // DEPRECATED: Please use Init@6 instead.
+ InitDeprecated@0(NetHost host_ptr);
+
// Establishes full-duplex communication with the host.
- Init@0(NetHost host_ptr);
+ [MinVersion=8] Init@6(NetHost host_ptr) => ();
// Notifies the instance of a WiFI AP scan being completed.
[MinVersion=1] ScanCompleted@1();
diff --git a/chromium/components/arc/common/notifications.mojom b/chromium/components/arc/common/notifications.mojom
index ae9a48cc9d8..b63bde26697 100644
--- a/chromium/components/arc/common/notifications.mojom
+++ b/chromium/components/arc/common/notifications.mojom
@@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// Next MinVersion: 11
+// Next MinVersion: 15
module arc.mojom;
import "bitmap.mojom";
+import "gfx.mojom";
// These values must be matched with the NOTIFICATION_EVENT_* constants in
// com.android.server.ArcNotificationListenerService.
@@ -55,6 +56,12 @@ enum ArcNotificationExpandState {
EXPANDED = 2,
};
+[Extensible, MinVersion=12]
+enum ArcNotificationRemoteInputState {
+ CLOSED = 0,
+ OPENED = 1,
+};
+
// These values represent what shows in an ARC custom notification.
[Extensible, MinVersion=11]
enum ArcNotificationShownContents {
@@ -120,6 +127,14 @@ struct ArcNotificationData {
// Flag for what shows in a notification.
[MinVersion=11]
ArcNotificationShownContents shown_contents;
+ [MinVersion=12]
+ ArcNotificationRemoteInputState remote_input_state;
+ // Indicates a rect for which Android wants to handle swipe events for by
+ // itself. The coordinates in this Rect are in Android pixels and represent
+ // a sub-rectangle of the notification, with the origin being the top left
+ // of the notification.
+ [MinVersion=14]
+ Rect? swipe_input_rect;
};
[MinVersion=2]
@@ -137,9 +152,11 @@ struct ArcToastData {
string? dismiss_text;
};
+// Next Method ID: 6
interface NotificationsHost {
// Tells the Chrome that a notification is posted (created or updated) on
- // Android.
+ // Android. If you know that the notification exists, please consider to use
+ // OnNotificationUpdate instead.
// |notification_data| is the data of notification (id, texts, icon and ...).
OnNotificationPosted@0(ArcNotificationData notification_data);
@@ -154,12 +171,20 @@ interface NotificationsHost {
[MinVersion=2]
// Hides the visible toast immediately, or cancels the scheduled one.
OnToastCancelled@3(ArcToastData data);
+
+ [MinVersion=13]
+ // Notifies that an existing notiication is updated on Android.
+ OnNotificationUpdated@5(ArcNotificationData notification_data);
};
+// Next Method ID: 6
// TODO(lhchavez): Migrate all request/response messages to Mojo.
interface NotificationsInstance {
+ // DEPRECATED: Please use Init@5 instead.
+ InitDeprecated@0(NotificationsHost host_ptr);
+
// Establishes full-duplex communication with the host.
- Init@0(NotificationsHost host_ptr);
+ [MinVersion=14] Init@5(NotificationsHost host_ptr) => ();
// Sends an event from Chrome notification UI to Android.
// |event| is a type of occured event.
diff --git a/chromium/components/arc/common/obb_mounter.mojom b/chromium/components/arc/common/obb_mounter.mojom
index d47dcb6168b..d3659753320 100644
--- a/chromium/components/arc/common/obb_mounter.mojom
+++ b/chromium/components/arc/common/obb_mounter.mojom
@@ -2,8 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Next MinVersion: 2
+
module arc.mojom;
+// Next Method ID: 2
interface ObbMounterHost {
// Mounts the specified OBB file to the target path, the owner GID will be set
// to the specified value.
@@ -15,6 +18,11 @@ interface ObbMounterHost {
UnmountObb@1(string target_path) => (bool success);
};
+// Next Method ID: 2
interface ObbMounterInstance {
- Init@0(ObbMounterHost host_ptr);
+ // DEPRECATED: Please use Init@1 instead.
+ InitDeprecated@0(ObbMounterHost host_ptr);
+
+ // Establishes full-duplex communication with the host.
+ [MinVersion=1] Init@1(ObbMounterHost host_ptr) => ();
};
diff --git a/chromium/components/arc/common/oemcrypto.mojom b/chromium/components/arc/common/oemcrypto.mojom
index b228cd0b8e7..9d43e224e5c 100644
--- a/chromium/components/arc/common/oemcrypto.mojom
+++ b/chromium/components/arc/common/oemcrypto.mojom
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Next MinVersion: 2
+
// The original version of this file lives in the Chromium repository at:
// src/components/arc/common/oemcrypto.mojom
@@ -225,7 +227,11 @@ interface OemCryptoHost {
// OemCryptoInstance is implemented in the liboemcrypto.so library that runs in
// Android and handles the Android side of the ArcBridge connection.
-// Next Method ID: 1
+// Next Method ID: 2
interface OemCryptoInstance {
- Init@0(OemCryptoHost host_ptr);
+ // DEPRECATED: Please use Init@1 instead.
+ InitDeprecated@0(OemCryptoHost host_ptr);
+
+ // Establishes full-duplex communication with the host.
+ [MinVersion=1] Init@1(OemCryptoHost host_ptr) => ();
};
diff --git a/chromium/components/arc/common/oemcrypto_daemon.mojom b/chromium/components/arc/common/oemcrypto_daemon.mojom
index 5b2b7827eaa..b75db2d4efb 100644
--- a/chromium/components/arc/common/oemcrypto_daemon.mojom
+++ b/chromium/components/arc/common/oemcrypto_daemon.mojom
@@ -21,5 +21,5 @@ import "protected_buffer_manager.mojom";
// Next Method ID: 1
interface OemCryptoHostDaemon {
Connect@0(arc.mojom.OemCryptoService& oemcryptor,
- media.mojom.ProtectedBufferManager protected_buffer_manager);
+ arc.mojom.ProtectedBufferManager protected_buffer_manager);
};
diff --git a/chromium/components/arc/common/policy.mojom b/chromium/components/arc/common/policy.mojom
index 742d0e710cc..08294b4cabd 100644
--- a/chromium/components/arc/common/policy.mojom
+++ b/chromium/components/arc/common/policy.mojom
@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// Next MinVersion: 2
+// Next MinVersion: 3
module arc.mojom;
+// Next Method ID: 2
interface PolicyHost {
// Get policies from Chrome OS, as JSON-encoded dictionary with the policies'
// names as keys and their values as values. The list of possible policies can
@@ -19,9 +20,13 @@ interface PolicyHost {
[MinVersion=1] ReportCompliance@1(string request) => (string response);
};
+// Next Method ID: 3
interface PolicyInstance {
+ // DEPRECATED: Please use Init@2 instead.
+ InitDeprecated@0(PolicyHost host_ptr);
+
// Establishes full-duplex communication with the host.
- Init@0(PolicyHost host_ptr);
+ [MinVersion=2] Init@2(PolicyHost host_ptr) => ();
// Indicates some policies have changed
OnPolicyUpdated@1();
diff --git a/chromium/components/arc/common/power.mojom b/chromium/components/arc/common/power.mojom
index f2fc4d87de9..048f8c63ba8 100644
--- a/chromium/components/arc/common/power.mojom
+++ b/chromium/components/arc/common/power.mojom
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Next min version: 4
+// Next MinVersion: 5
module arc.mojom;
@@ -33,10 +33,13 @@ interface PowerHost {
[MinVersion=3] OnScreenBrightnessUpdateRequest@3(double percent);
};
-// Next method ID: 5
+// Next method ID: 6
interface PowerInstance {
+ // DEPRECATED: Please use Init@5 instead.
+ InitDeprecated@0(PowerHost host_ptr);
+
// Establishes full-duplex communication with the host.
- Init@0(PowerHost host_ptr);
+ [MinVersion=4] Init@5(PowerHost host_ptr) => ();
// Alerts the instance to a change in interactive state.
[MinVersion=1] SetInteractive@1(bool enabled);
diff --git a/chromium/components/arc/common/print.mojom b/chromium/components/arc/common/print.mojom
index c72a7898726..3f03b7ff82c 100644
--- a/chromium/components/arc/common/print.mojom
+++ b/chromium/components/arc/common/print.mojom
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// Next MinVersion: 1
+// Next MinVersion: 2
module arc.mojom;
@@ -11,8 +11,11 @@ interface PrintHost {
Print@0(handle file);
};
-// Next method ID: 1
+// Next method ID: 2
interface PrintInstance {
+ // DEPRECATED: Please use Init@1 instead.
+ InitDeprecated@0(PrintHost host_ptr);
+
// Establishes full-duplex communication with the host.
- Init@0(PrintHost host_ptr);
+ [MinVersion=1] Init@1(PrintHost host_ptr) => ();
};
diff --git a/chromium/components/arc/common/protected_buffer_manager.mojom b/chromium/components/arc/common/protected_buffer_manager.mojom
index b226ea3d347..298f6d3bbf2 100644
--- a/chromium/components/arc/common/protected_buffer_manager.mojom
+++ b/chromium/components/arc/common/protected_buffer_manager.mojom
@@ -5,7 +5,7 @@
// The original version of this file lives in the Chromium repository at:
// src/components/arc/common/protected_buffer_manager.mojom
-module media.mojom;
+module arc.mojom;
// This interface is exposed by the GPU process for translating dummy handles
// for secure buffers into a usable shared memory handle. The output of a
diff --git a/chromium/components/arc/common/screen_rect.mojom b/chromium/components/arc/common/screen_rect.mojom
deleted file mode 100644
index baafbcdd70e..00000000000
--- a/chromium/components/arc/common/screen_rect.mojom
+++ /dev/null
@@ -1,13 +0,0 @@
-// 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.
-
-module arc.mojom;
-
-// Represents a rectangle to specify screen coordinates.
-struct ScreenRect {
- int32 left;
- int32 top;
- int32 right;
- int32 bottom;
-};
diff --git a/chromium/components/arc/common/tts.mojom b/chromium/components/arc/common/tts.mojom
index 4b7f044db11..b013a1b2c21 100644
--- a/chromium/components/arc/common/tts.mojom
+++ b/chromium/components/arc/common/tts.mojom
@@ -1,7 +1,7 @@
// 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.
-// Next MinVersion: 1
+// Next MinVersion: 2
module arc.mojom;
@@ -30,10 +30,13 @@ interface TtsHost {
string error_msg);
};
-// Next Method ID: 3
+// Next Method ID: 4
interface TtsInstance {
+ // DEPRECATED: Please use Init@3 instead.
+ InitDeprecated@0(TtsHost host_ptr);
+
// Establishes full-duplex communication with the host.
- Init@0(TtsHost host_ptr);
+ [MinVersion=1] Init@3(TtsHost host_ptr) => ();
// Sends an utterance to Android for synthesis.
Speak@1(TtsUtterance utterance);
diff --git a/chromium/components/arc/common/typemaps.gni b/chromium/components/arc/common/typemaps.gni
index 8902a9b60cb..62c81904348 100644
--- a/chromium/components/arc/common/typemaps.gni
+++ b/chromium/components/arc/common/typemaps.gni
@@ -3,14 +3,12 @@
# found in the LICENSE file.
typemaps = [
- "//components/arc/common/app.typemap",
"//components/arc/common/bitmap.typemap",
"//components/arc/common/bluetooth.typemap",
"//components/arc/common/file_system.typemap",
- "//components/arc/common/ime.typemap",
+ "//components/arc/common/gfx.typemap",
"//components/arc/common/intent_helper.typemap",
"//components/arc/common/video_common.typemap",
"//components/arc/common/video_encode_accelerator.typemap",
- "//components/arc/common/voice_interaction_framework.typemap",
"//components/arc/common/volume_mounter.typemap",
]
diff --git a/chromium/components/arc/common/video.mojom b/chromium/components/arc/common/video.mojom
index 42755ada236..9b048960057 100644
--- a/chromium/components/arc/common/video.mojom
+++ b/chromium/components/arc/common/video.mojom
@@ -2,12 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Next MinVersion: 6
+
module arc.mojom;
import "video_decode_accelerator.mojom";
import "video_encode_accelerator.mojom";
-// Next MinVersion: 5
// Deprecated method IDs: 0
// Next method ID: 2
interface VideoHost {
@@ -19,15 +20,16 @@ interface VideoHost {
string token);
};
-// Next MinVersion: 1
-// Next method ID: 1
+// Next method ID: 2
interface VideoInstance {
+ // DEPRECATED: Please use Init@1 instead.
+ InitDeprecated@0(VideoHost host_ptr);
+
// Establishes full-duplex communication with the host.
- Init@0(VideoHost host_ptr);
+ [MinVersion=5] Init@1(VideoHost host_ptr) => ();
};
-// Next MinVersion: 2
-// Next method ID: 3
+// Next method ID: 2
interface VideoAcceleratorFactory {
CreateDecodeAccelerator@0(VideoDecodeAccelerator& decoder);
diff --git a/chromium/components/arc/video_accelerator/video_accelerator_struct_traits.cc b/chromium/components/arc/common/video_accelerator_struct_traits.cc
index 91028274dba..a0061dc0324 100644
--- a/chromium/components/arc/video_accelerator/video_accelerator_struct_traits.cc
+++ b/chromium/components/arc/common/video_accelerator_struct_traits.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/arc/video_accelerator/video_accelerator_struct_traits.h"
+#include "components/arc/common/video_accelerator_struct_traits.h"
namespace mojo {
diff --git a/chromium/components/arc/video_accelerator/video_accelerator_struct_traits.h b/chromium/components/arc/common/video_accelerator_struct_traits.h
index c7e8d3b174a..8c1ff484697 100644
--- a/chromium/components/arc/video_accelerator/video_accelerator_struct_traits.h
+++ b/chromium/components/arc/common/video_accelerator_struct_traits.h
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_ARC_VIDEO_ACCELERATOR_VIDEO_ACCELERATOR_STRUCT_TRAITS_H_
-#define COMPONENTS_ARC_VIDEO_ACCELERATOR_VIDEO_ACCELERATOR_STRUCT_TRAITS_H_
+#ifndef COMPONENTS_ARC_COMMON_VIDEO_ACCELERATOR_STRUCT_TRAITS_H_
+#define COMPONENTS_ARC_COMMON_VIDEO_ACCELERATOR_STRUCT_TRAITS_H_
#include "components/arc/common/video_decode_accelerator.mojom.h"
-#include "components/arc/video_accelerator/video_accelerator.h"
+#include "components/arc/video_accelerator/video_frame_plane.h"
#include "ui/gfx/geometry/size.h"
namespace mojo {
@@ -43,4 +43,4 @@ struct StructTraits<arc::mojom::SizeDataView, gfx::Size> {
};
} // namespace mojo
-#endif // COMPONENTS_ARC_VIDEO_ACCELERATOR_VIDEO_ACCELERATOR_STRUCT_TRAITS_H_
+#endif // COMPONENTS_ARC_COMMON_VIDEO_ACCELERATOR_STRUCT_TRAITS_H_
diff --git a/chromium/components/arc/common/video_common.typemap b/chromium/components/arc/common/video_common.typemap
index 04e082d329e..3bc56045ac0 100644
--- a/chromium/components/arc/common/video_common.typemap
+++ b/chromium/components/arc/common/video_common.typemap
@@ -4,13 +4,15 @@
mojom = "//components/arc/common/video_common.mojom"
public_headers = [
- "//components/arc/video_accelerator/video_accelerator.h",
+ "//components/arc/video_accelerator/video_frame_plane.h",
"//ui/gfx/geometry/size.h",
]
-traits_headers =
- [ "//components/arc/video_accelerator/video_accelerator_struct_traits.h" ]
+traits_headers = [ "//components/arc/common/video_accelerator_struct_traits.h" ]
sources = [
- "//components/arc/video_accelerator/video_accelerator_struct_traits.cc",
+ "//components/arc/common/video_accelerator_struct_traits.cc",
+]
+deps = [
+ "//ui/gfx/geometry",
]
type_mappings = [
"arc.mojom.VideoFramePlane=arc::VideoFramePlane[move_only]",
diff --git a/chromium/components/arc/common/video_decode_accelerator.mojom b/chromium/components/arc/common/video_decode_accelerator.mojom
index bb732f96caa..530759453b8 100644
--- a/chromium/components/arc/common/video_decode_accelerator.mojom
+++ b/chromium/components/arc/common/video_decode_accelerator.mojom
@@ -40,6 +40,7 @@ struct VideoFormat {
uint32 crop_height;
};
+// Next MinVersion: 2
struct VideoDecodeAcceleratorConfig {
// Deprecated. This config struct is used for decoder only.
enum DeviceTypeDeprecated {
@@ -51,11 +52,12 @@ struct VideoDecodeAcceleratorConfig {
DeviceTypeDeprecated device_type_deprecated;
uint32 num_input_buffers;
uint32 input_pixel_format;
+ [MinVersion=1] bool secure_mode;
};
-// Next MinVersion: 4
+// Next MinVersion: 5
// Deprecated method IDs: 2, 7
-// Next method ID: 10
+// Next method ID: 11
interface VideoDecodeAccelerator {
enum Result {
SUCCESS = 0,
@@ -70,6 +72,10 @@ interface VideoDecodeAccelerator {
Initialize@8(VideoDecodeAcceleratorConfig config,
VideoDecodeClient client) => (Result result);
+ [MinVersion=4]
+ AllocateProtectedBuffer@10(PortType port, uint32 index, handle handle_fd,
+ uint64 size) => (bool result);
+
BindSharedMemory@1(PortType port, uint32 index, handle ashmem_fd,
uint32 offset, uint32 length);
diff --git a/chromium/components/arc/common/video_encode_accelerator.mojom b/chromium/components/arc/common/video_encode_accelerator.mojom
index 2aaf61e541b..9278f3b0310 100644
--- a/chromium/components/arc/common/video_encode_accelerator.mojom
+++ b/chromium/components/arc/common/video_encode_accelerator.mojom
@@ -59,7 +59,10 @@ enum VideoCodecProfile {
THEORAPROFILE_MIN = 23,
THEORAPROFILE_ANY = THEORAPROFILE_MIN,
THEORAPROFILE_MAX = THEORAPROFILE_ANY,
- VIDEO_CODEC_PROFILE_MAX = THEORAPROFILE_ANY,
+ AV1PROFILE_MIN = 24,
+ AV1PROFILE_PROFILE0 = AV1PROFILE_MIN,
+ AV1PROFILE_MAX = AV1PROFILE_PROFILE0,
+ VIDEO_CODEC_PROFILE_MAX = AV1PROFILE_PROFILE0,
};
// Specification of an encoding profile supported by an encoder.
@@ -72,7 +75,7 @@ struct VideoEncodeProfile {
// Video encoder IPC interface.
// Next MinVersion: 1
-// Next Method ID: 5
+// Next Method ID: 6
interface VideoEncodeAccelerator {
// The input buffer storage type.
@@ -162,6 +165,14 @@ interface VideoEncodeAccelerator {
// |framerate| is the requested new framerate, in frames per second.
RequestEncodingParametersChange@4(uint32 bitrate,
uint32 framerate);
+
+ // Flushes the encoder: all pending inputs will be encoded and all bitstreams
+ // handed back to the client. The client should not invoke Flush() or
+ // Encode() before the previous Flush() is finished.
+ // Callback:
+ // Called with |true| if Flush() is complete; with |false| if Flush() is
+ // canceled.
+ Flush@5() => (bool flush_done);
};
// Interface for clients that use VideoEncodeAccelerator. These callbacks will
diff --git a/chromium/components/arc/common/video_encode_accelerator.typemap b/chromium/components/arc/common/video_encode_accelerator.typemap
index 61b8db22915..a7453766a3f 100644
--- a/chromium/components/arc/common/video_encode_accelerator.typemap
+++ b/chromium/components/arc/common/video_encode_accelerator.typemap
@@ -5,11 +5,12 @@
mojom = "//components/arc/common/video_encode_accelerator.mojom"
public_headers = [ "//media/video/video_encode_accelerator.h" ]
public_deps = [
- "//media",
+ "//media/gpu",
]
-traits_headers = [ "//components/arc/video_accelerator/video_encode_accelerator_struct_traits.h" ]
+traits_headers =
+ [ "//components/arc/common/video_encode_accelerator_struct_traits.h" ]
sources = [
- "//components/arc/video_accelerator/video_encode_accelerator_struct_traits.cc",
+ "//components/arc/common/video_encode_accelerator_struct_traits.cc",
]
type_mappings = [
"arc.mojom.VideoEncodeAccelerator.Error=media::VideoEncodeAccelerator::Error",
diff --git a/chromium/components/arc/video_accelerator/video_encode_accelerator_struct_traits.cc b/chromium/components/arc/common/video_encode_accelerator_struct_traits.cc
index 9b3c6456045..d1fee57cb23 100644
--- a/chromium/components/arc/video_accelerator/video_encode_accelerator_struct_traits.cc
+++ b/chromium/components/arc/common/video_encode_accelerator_struct_traits.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/arc/video_accelerator/video_encode_accelerator_struct_traits.h"
+#include "components/arc/common/video_encode_accelerator_struct_traits.h"
namespace mojo {
@@ -116,6 +116,7 @@ CHECK_PROFILE_ENUM(DOLBYVISION_MAX);
CHECK_PROFILE_ENUM(THEORAPROFILE_MIN);
CHECK_PROFILE_ENUM(THEORAPROFILE_ANY);
CHECK_PROFILE_ENUM(THEORAPROFILE_MAX);
+CHECK_PROFILE_ENUM(AV1PROFILE_PROFILE0);
CHECK_PROFILE_ENUM(VIDEO_CODEC_PROFILE_MAX);
#undef CHECK_PROFILE_ENUM
@@ -157,6 +158,7 @@ bool EnumTraits<arc::mojom::VideoCodecProfile, media::VideoCodecProfile>::
case arc::mojom::VideoCodecProfile::DOLBYVISION_PROFILE5:
case arc::mojom::VideoCodecProfile::DOLBYVISION_PROFILE7:
case arc::mojom::VideoCodecProfile::THEORAPROFILE_ANY:
+ case arc::mojom::VideoCodecProfile::AV1PROFILE_PROFILE0:
*output = static_cast<media::VideoCodecProfile>(input);
return true;
}
diff --git a/chromium/components/arc/video_accelerator/video_encode_accelerator_struct_traits.h b/chromium/components/arc/common/video_encode_accelerator_struct_traits.h
index c3b39e1f371..060b2ad4277 100644
--- a/chromium/components/arc/video_accelerator/video_encode_accelerator_struct_traits.h
+++ b/chromium/components/arc/common/video_encode_accelerator_struct_traits.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_ARC_VIDEO_ACCELERATOR_VIDEO_ENCODE_ACCELERATOR_STRUCT_TRAITS_H_
-#define COMPONENTS_ARC_VIDEO_ACCELERATOR_VIDEO_ENCODE_ACCELERATOR_STRUCT_TRAITS_H_
+#ifndef COMPONENTS_ARC_COMMON_VIDEO_ENCODE_ACCELERATOR_STRUCT_TRAITS_H_
+#define COMPONENTS_ARC_COMMON_VIDEO_ENCODE_ACCELERATOR_STRUCT_TRAITS_H_
#include "components/arc/common/video_encode_accelerator.mojom.h"
#include "media/video/video_encode_accelerator.h"
@@ -65,4 +65,4 @@ struct StructTraits<arc::mojom::VideoEncodeProfileDataView,
} // namespace mojo
-#endif // COMPONENTS_ARC_VIDEO_ACCELERATOR_VIDEO_ENCODE_ACCELERATOR_STRUCT_TRAITS_H_
+#endif // COMPONENTS_ARC_COMMON_VIDEO_ENCODE_ACCELERATOR_STRUCT_TRAITS_H_
diff --git a/chromium/components/arc/common/voice_interaction_arc_home.mojom b/chromium/components/arc/common/voice_interaction_arc_home.mojom
index 4db7ffffbd9..ebe7be2e898 100644
--- a/chromium/components/arc/common/voice_interaction_arc_home.mojom
+++ b/chromium/components/arc/common/voice_interaction_arc_home.mojom
@@ -2,19 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// Next MinVersion: 3
+// Next MinVersion: 4
module arc.mojom;
+import "gfx.mojom";
import "mojo/common/string16.mojom";
-import "screen_rect.mojom";
-
-// Represents the start and end unicode char indices of the selected
-// portion of the text [start, end).
-struct TextSelection {
- int32 start_selection;
- int32 end_selection;
-};
// Represents view structure to be passed to ARC. The view
// structure is synthesized from the AXStructure, which
@@ -24,7 +17,7 @@ struct TextSelection {
// AccessibilitySnapshotNode.java used in Android Chromium.
struct VoiceInteractionStructure {
// Geometry of the view in pixels
- ScreenRect rect;
+ Rect rect;
// Text of the view.
mojo.common.mojom.String16 text;
@@ -39,7 +32,7 @@ struct VoiceInteractionStructure {
bool line_through;
// Selected portion of the text.
- TextSelection? selection;
+ Range? selection;
// Fake Android view class name of the element. Each node is assigned
// a closest approximation of Android's views.
@@ -67,7 +60,11 @@ interface VoiceInteractionArcHomeHost {
};
// Connects with ArcHome.
-// Next method ID: 1
+// Next method ID: 2
interface VoiceInteractionArcHomeInstance {
- Init@0(VoiceInteractionArcHomeHost host_ptr);
+ // DEPRECATED: Please use Init@1 instead.
+ InitDeprecated@0(VoiceInteractionArcHomeHost host_ptr);
+
+ // Establishes full-duplex communication with the host.
+ [MinVersion=3] Init@1(VoiceInteractionArcHomeHost host_ptr) => ();
};
diff --git a/chromium/components/arc/common/voice_interaction_framework.mojom b/chromium/components/arc/common/voice_interaction_framework.mojom
index 53e33f53b6c..2aedfa1fea7 100644
--- a/chromium/components/arc/common/voice_interaction_framework.mojom
+++ b/chromium/components/arc/common/voice_interaction_framework.mojom
@@ -2,11 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// Next MinVersion: 13
+// Next MinVersion: 14
module arc.mojom;
-import "screen_rect.mojom";
+import "gfx.mojom";
+
+// There is another copy of the VoiceInteractionState definition in
+// //ash/public/interfaces/voice_interaction_controller.mojom
+// Please also update the other one if you change it.
+// The duplicate definition is because we do not use extensible widely
+// (crbug.com/731893).
[Extensible]
enum VoiceInteractionState {
@@ -17,21 +23,12 @@ enum VoiceInteractionState {
// Handles voice interaction queries from Android.
// Next method ID: 6
-// Deprecated method ID: 0
+// Deprecated method ID: 0, 2, 3, 4
interface VoiceInteractionFrameworkHost {
// Returns a fullscreen screenshot of the primary display.
// |data| represents the image encoded in JPEG format.
[MinVersion=1]CaptureFullscreen@1() => (array<uint8> data);
- // Notifies the host that the metalayer has closed or could not open.
- [MinVersion=2]OnMetalayerClosed@2();
-
- // Enables/disables screenshot taking.
- [MinVersion=3]SetMetalayerEnabled@3(bool enabled);
-
- // Notifies Chrome whether voice interaction session is running.
- [MinVersion=6]SetVoiceInteractionRunning@4(bool running);
-
// Notifies Chrome the state of voice interaction session.
[MinVersion=8]SetVoiceInteractionState@5(VoiceInteractionState state);
};
@@ -49,10 +46,14 @@ struct VoiceInteractionStatus {
};
// Connects with Android system server.
-// Next method ID: 11
+// Next method ID: 12
// Deprecated method ID: 4
interface VoiceInteractionFrameworkInstance {
- Init@0(VoiceInteractionFrameworkHost host_ptr);
+ // DEPRECATED: Please use Init@11 instead.
+ InitDeprecated@0(VoiceInteractionFrameworkHost host_ptr);
+
+ // Establishes full-duplex communication with the host.
+ [MinVersion=13] Init@11(VoiceInteractionFrameworkHost host_ptr) => ();
// Starts the voice interaction session in container.
// |homescreen_is_active| is true if the session was invoked when homescreen is active.
@@ -64,7 +65,7 @@ interface VoiceInteractionFrameworkInstance {
// Starts the voice interaction session in container, with a screen region
// selected.
- [MinVersion=1] StartVoiceInteractionSessionForRegion@2(ScreenRect region);
+ [MinVersion=1] StartVoiceInteractionSessionForRegion@2(Rect region);
// Shows/hides the metalayer in the container.
[MinVersion=1] SetMetalayerVisibility@3([MinVersion=2] bool visible);
diff --git a/chromium/components/arc/common/voice_interaction_framework.typemap b/chromium/components/arc/common/voice_interaction_framework.typemap
deleted file mode 100644
index 825471951f7..00000000000
--- a/chromium/components/arc/common/voice_interaction_framework.typemap
+++ /dev/null
@@ -1,13 +0,0 @@
-# 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.
-
-mojom = "//components/arc/common/voice_interaction_framework.mojom"
-public_headers = [ "//ash/public/cpp/voice_interaction_state.h" ]
-public_deps = [
- "//ash/public/cpp:ash_public_cpp",
-]
-traits_headers =
- [ "//components/arc/voice_interaction/voice_interaction_struct_traits.h" ]
-sources = []
-type_mappings = [ "arc.mojom.VoiceInteractionState=ash::VoiceInteractionState" ]
diff --git a/chromium/components/arc/common/volume_mounter.typemap b/chromium/components/arc/common/volume_mounter.typemap
index 6198166d87e..0b905728284 100644
--- a/chromium/components/arc/common/volume_mounter.typemap
+++ b/chromium/components/arc/common/volume_mounter.typemap
@@ -3,14 +3,16 @@
# found in the LICENSE file.
mojom = "//components/arc/common/volume_mounter.mojom"
-public_headers = [ "//chromeos/disks/disk_mount_manager.h" ]
+public_headers = [
+ "//chromeos/chromeos_export.h",
+ "//chromeos/dbus/cros_disks_client.h",
+ "//chromeos/dbus/dbus_client_implementation_type.h",
+ "//chromeos/disks/disk_mount_manager.h",
+]
traits_headers = [ "//components/arc/volume_mounter/volume_mounter_traits.h" ]
sources = [
"//components/arc/volume_mounter/volume_mounter_traits.cc",
]
-deps = [
- "//chromeos",
-]
type_mappings = [
"arc.mojom.DeviceType=chromeos::DeviceType",
"arc.mojom.MountEvent=chromeos::disks::DiskMountManager::MountEvent",
diff --git a/chromium/components/arc/common/wallpaper.mojom b/chromium/components/arc/common/wallpaper.mojom
index d2dd78dc52f..3048e4560a7 100644
--- a/chromium/components/arc/common/wallpaper.mojom
+++ b/chromium/components/arc/common/wallpaper.mojom
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// Next MinVersion: 3
+// Next MinVersion: 4
module arc.mojom;
// Handles wallpaper calls from ARC in Chrome.
-// Next method ID:3
+// Next method ID: 3
interface WallpaperHost {
// Gets current wallpaper encoded in PNG and send it back to ARC.
GetWallpaper@0() => (array<uint8> wallpaper);
@@ -21,10 +21,13 @@ interface WallpaperHost {
};
// Connects with container side to publish wallpaper related intents.
-// Next method ID:3
+// Next method ID: 4
interface WallpaperInstance {
- // Establishes communication with the container side.
- Init@0(WallpaperHost host_ptr);
+ // DEPRECATED: Please use Init@3 instead.
+ InitDeprecated@0(WallpaperHost host_ptr);
+
+ // Establishes full-duplex communication with the host.
+ [MinVersion=3] Init@3(WallpaperHost host_ptr) => ();
// Notifies ArcWallpaperManagerService that wallpaper is changed.
[MinVersion=1] OnWallpaperChanged@1([MinVersion=2] int32 wallpaper_id);
diff --git a/chromium/components/arc/connection_holder.h b/chromium/components/arc/connection_holder.h
new file mode 100644
index 00000000000..72cd6478cc3
--- /dev/null
+++ b/chromium/components/arc/connection_holder.h
@@ -0,0 +1,386 @@
+// Copyright 2015 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 COMPONENTS_ARC_CONNECTION_HOLDER_H_
+#define COMPONENTS_ARC_CONNECTION_HOLDER_H_
+
+#include <memory>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/macros.h"
+#include "base/observer_list.h"
+#include "base/threading/thread_checker.h"
+#include "components/arc/connection_notifier.h"
+#include "components/arc/connection_observer.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/interface_ptr.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+
+// A macro to call
+// ConnectionHolder<T>::GetInstanceForVersionDoNotCallDirectly(). In order to
+// avoid exposing method names from within the Mojo bindings, we will rely on
+// stringification and the fact that the method min versions have a consistent
+// naming scheme.
+#define ARC_GET_INSTANCE_FOR_METHOD(holder, method_name) \
+ (holder)->GetInstanceForVersionDoNotCallDirectly( \
+ std::remove_pointer<decltype( \
+ holder)>::type::Instance::k##method_name##MinVersion, \
+ #method_name)
+
+namespace arc {
+
+namespace internal {
+
+// Small helper to implement HasInit<> trait below.
+// Note that only Check() declaration is needed.
+// - If InstanceType::Init exists, Check(InstanceType()) would return
+// std::true_type, because 1) the template param is successfully substituted,
+// and 2) Check(...) is weaker than the template's so there is no overload
+// conflict.
+// - If not, Check(InstanceType()) would return std::false_type, because
+// template param substitution is failed, but it won't be compile error
+// thanks to SFINAE, thus Check(...) is the only candidate.
+struct HasInitImpl {
+ template <typename InstanceType>
+ static auto Check(InstanceType* v)
+ -> decltype(&InstanceType::Init, std::true_type());
+ static std::false_type Check(...);
+};
+
+// Type trait to return whether InstanceType has Init() or not.
+template <typename InstanceType>
+using HasInit =
+ decltype(HasInitImpl::Check(static_cast<InstanceType*>(nullptr)));
+
+// Same as above, but for InstanceType::InitDeprecated.
+struct HasInitDeprecatedImpl {
+ template <typename InstanceType>
+ static auto Check(InstanceType* v)
+ -> decltype(&InstanceType::InitDeprecated, std::true_type());
+ static std::false_type Check(...);
+};
+
+// Type trait to return whether InstanceType has InitDeprecated() or not.
+template <typename InstanceType>
+using HasInitDeprecated =
+ decltype(HasInitDeprecatedImpl::Check(static_cast<InstanceType*>(nullptr)));
+
+// Templates to count the number of arguments in a function. This is used to
+// distinguish between interfaces that do not declare an Init() method, a
+// one-argument (single-duplex) Init() and the two-argument (full-duplex)
+// Init().
+// TODO(crbug.com/750563): Simplify the templates once InitDeprecated() is
+// removed.
+template <typename Signature>
+struct CountInitArgsImpl;
+
+template <typename R, typename Receiver, typename... Args>
+struct CountInitArgsImpl<R (Receiver::*)(Args...)> {
+ static constexpr size_t value = sizeof...(Args);
+};
+
+template <class T>
+struct Void {
+ typedef void type;
+};
+
+template <typename T, typename U = void>
+struct CountInitArgs {
+ static constexpr size_t value = 0;
+};
+
+template <typename T>
+struct CountInitArgs<T, typename Void<decltype(&T::Init)>::type> {
+ static constexpr size_t value = CountInitArgsImpl<decltype(&T::Init)>::value;
+};
+
+// Full duplex Mojo connection holder implementation.
+// InstanceType and HostType are Mojo interface types (arc::mojom::XxxInstance,
+// and arc::mojom::XxxHost respectively).
+template <typename InstanceType, typename HostType>
+class ConnectionHolderImpl {
+ public:
+ explicit ConnectionHolderImpl(ConnectionNotifier* connection_notifier)
+ : connection_notifier_(connection_notifier), weak_ptr_factory_(this) {}
+
+ InstanceType* instance() { return instance_; }
+ uint32_t instance_version() const { return instance_version_; }
+
+ // Returns true if |binding_| is set.
+ bool IsConnected() const { return binding_.get(); }
+
+ // Sets (or resets if |host| is nullptr) the host.
+ void SetHost(HostType* host) {
+ // Some tests overwrite host, now. It is safe iff the |instance_| is
+ // not yet set.
+ // TODO(hidehiko): Make check more strict.
+ DCHECK(host == nullptr || host_ == nullptr || instance_ == nullptr);
+
+ if (host_ == host)
+ return;
+
+ host_ = host;
+ OnChanged();
+ }
+
+ // Sets (or resets if |instance| is nullptr) the instance.
+ void SetInstance(InstanceType* instance,
+ uint32_t version = InstanceType::version_) {
+ DCHECK(instance == nullptr || instance_ == nullptr);
+
+ // Note: This can be called with nullptr even if |instance_| is still
+ // nullptr for just in case clean up purpose. No-op in such a case.
+ if (instance == instance_)
+ return;
+
+ instance_ = instance;
+ instance_version_ = version;
+ OnChanged();
+ }
+
+ private:
+ // Called when |instance_| or |host_| is updated from null to non-null or
+ // from non-null to null.
+ void OnChanged() {
+ if (instance_ && host_) {
+ // When both get ready, start connection.
+ // TODO(crbug.com/750563): Fix the race issue.
+ binding_ = std::make_unique<mojo::Binding<HostType>>(host_);
+ mojo::InterfacePtr<HostType> host_proxy;
+ binding_->Bind(mojo::MakeRequest(&host_proxy));
+ // Note: because the callback will be destroyed with |binding_|,
+ // base::Unretained() can be safely used.
+ binding_->set_connection_error_handler(base::BindOnce(
+ &mojo::Binding<HostType>::Close, base::Unretained(binding_.get())));
+
+ // Call the appropriate version of Init().
+ CallInstanceInit<InstanceType>(std::move(host_proxy),
+ HasInitDeprecated<InstanceType>());
+ } else if (binding_.get()) {
+ // Otherwise, the connection is closed. If it was connected,
+ // reset the host binding and notify.
+ binding_.reset();
+ connection_notifier_->NotifyConnectionClosed();
+ }
+ }
+
+ // Dispatches the correct version of Init(). The template type is needed
+ // because std::enable_if<> needs to depend on a template parameter in order
+ // for SFINAE to work. The second parameter (std::true_type or
+ // std::false_type) refers to whether InstanceType::DeprecatedInit() exists.
+ template <class T>
+ typename std::enable_if<CountInitArgs<T>::value == 2, void>::type
+ CallInstanceInit(mojo::InterfacePtr<HostType> host_proxy, std::true_type) {
+ if (instance_version_ < InstanceType::kInitMinVersion) {
+ // The instance is too old to know about the new Init() version. For now,
+ // call the deprecated version for backwards-compatibility.
+ // TODO(crbug.com/750563): Deprecate this version.
+ CallInstanceInitDeprecated(std::move(host_proxy),
+ HasInitDeprecated<InstanceType>());
+ return;
+ }
+
+ instance_->Init(std::move(host_proxy),
+ base::BindOnce(&ConnectionHolderImpl::OnConnectionReady,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+
+ template <class T>
+ typename std::enable_if<CountInitArgs<T>::value == 2, void>::type
+ CallInstanceInit(mojo::InterfacePtr<HostType> host_proxy, std::false_type) {
+ instance_->Init(std::move(host_proxy),
+ base::BindOnce(&ConnectionHolderImpl::OnConnectionReady,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+
+ // TODO(crbug.com/750563): Deprecate this version.
+ template <class T>
+ typename std::enable_if<CountInitArgs<T>::value == 1, void>::type
+ CallInstanceInit(mojo::InterfacePtr<HostType> host_proxy, ...) {
+ instance_->Init(std::move(host_proxy));
+ OnConnectionReady();
+ }
+
+ void CallInstanceInitDeprecated(mojo::InterfacePtr<HostType> host_proxy,
+ std::true_type) {
+ instance_->InitDeprecated(std::move(host_proxy));
+ OnConnectionReady();
+ }
+
+ void CallInstanceInitDeprecated(mojo::InterfacePtr<HostType> host_proxy,
+ std::false_type) {
+ // If InitDeprecated does not exists, ARC container must support
+ // Init() with callback, already. Thus, this should not be called.
+ NOTREACHED();
+ }
+
+ // Notifies all the observers that the connection is ready.
+ void OnConnectionReady() { connection_notifier_->NotifyConnectionReady(); }
+
+ // This class does not have ownership. The pointers should be managed by the
+ // caller.
+ ConnectionNotifier* const connection_notifier_;
+ InstanceType* instance_ = nullptr;
+ uint32_t instance_version_ = 0;
+ HostType* host_ = nullptr;
+
+ // Created when both |instance_| and |host_| ptr are set.
+ std::unique_ptr<mojo::Binding<HostType>> binding_;
+
+ base::WeakPtrFactory<ConnectionHolderImpl> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ConnectionHolderImpl);
+};
+
+// Single direction Mojo connection holder implementation.
+// (HostType == void means single direction).
+// InstanceType should be Mojo interface type (arc::mojom::XxxInstance).
+template <typename InstanceType>
+class ConnectionHolderImpl<InstanceType, void> {
+ public:
+ // InstanceType must not have Init() method, which should be for a
+ // full-duplex connection.
+ static_assert(!HasInit<InstanceType>::value,
+ "Full duplex ConnectionHolderImpl should be used instead");
+
+ explicit ConnectionHolderImpl(ConnectionNotifier* connection_notifier)
+ : connection_notifier_(connection_notifier) {}
+
+ InstanceType* instance() { return instance_; }
+ uint32_t instance_version() const { return instance_version_; }
+
+ // For single direction connection, when Instance proxy is obtained,
+ // it means connected.
+ bool IsConnected() const { return instance_; }
+
+ void SetHost(void* unused) {
+ static_assert(!sizeof(*this),
+ "ConnectionHolder::SetHost for single direction connection "
+ "is called unexpectedly.");
+ NOTREACHED();
+ }
+
+ // Sets (or resets if |instance| is nullptr) the instance.
+ void SetInstance(InstanceType* instance,
+ uint32_t version = InstanceType::version_) {
+ DCHECK(instance == nullptr || instance_ == nullptr);
+
+ // Note: This can be called with nullptr even if |instance_| is still
+ // nullptr for just in case clean up purpose. No-op in such a case.
+ if (instance == instance_)
+ return;
+
+ instance_ = instance;
+ instance_version_ = version;
+
+ // There is nothing more than setting in this case. Notify observers.
+ if (instance_)
+ connection_notifier_->NotifyConnectionReady();
+ else
+ connection_notifier_->NotifyConnectionClosed();
+ }
+
+ private:
+ // This class does not have ownership. The pointers should be managed by the
+ // caller.
+ ConnectionNotifier* const connection_notifier_;
+ InstanceType* instance_ = nullptr;
+ uint32_t instance_version_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(ConnectionHolderImpl);
+};
+
+} // namespace internal
+
+// Holds a Mojo connection. This also allows for listening for state changes
+// for the particular connection.
+// InstanceType and HostType should be Mojo interface type
+// (arc::mojom::XxxInstance and arc::mojom::XxxHost respectively).
+// If HostType is void, it is single direction Mojo connection, so it only
+// looks at Instance pointer.
+// Otherwise, it is full duplex Mojo connection. When both Instance and Host
+// pointers are set, it calls Instance::Init() method to pass Host pointer
+// to the ARC container.
+template <typename InstanceType, typename HostType = void>
+class ConnectionHolder {
+ public:
+ using Observer = ConnectionObserver<InstanceType>;
+ using Instance = InstanceType;
+
+ ConnectionHolder() = default;
+
+ // Returns true if the Mojo interface is ready at least for its version 0
+ // interface. Use an Observer if you want to be notified when this is ready.
+ // This can only be called on the thread that this class was created on.
+ bool IsConnected() const { return impl_.IsConnected(); }
+
+ // Gets the Mojo interface that's intended to call for
+ // |method_name_for_logging|, but only if its reported version is at least
+ // |min_version|. Returns nullptr if the connection is either not ready or
+ // the instance does not have the requested version, and logs appropriately.
+ // This function should not be called directly. Instead, use the
+ // ARC_GET_INSTANCE_FOR_METHOD() macro.
+ InstanceType* GetInstanceForVersionDoNotCallDirectly(
+ uint32_t min_version,
+ const char method_name_for_logging[]) {
+ if (!impl_.IsConnected()) {
+ VLOG(1) << "Instance " << InstanceType::Name_ << " not available.";
+ return nullptr;
+ }
+ if (impl_.instance_version() < min_version) {
+ LOG(ERROR) << "Instance for " << InstanceType::Name_
+ << "::" << method_name_for_logging
+ << " version mismatch. Expected " << min_version << " got "
+ << impl_.instance_version();
+ return nullptr;
+ }
+ return impl_.instance();
+ }
+
+ // Adds or removes observers. This can only be called on the thread that this
+ // class was created on. RemoveObserver does nothing if |observer| is not in
+ // the list.
+ void AddObserver(Observer* observer) {
+ connection_notifier_.AddObserver(observer);
+ if (impl_.IsConnected())
+ connection_notifier_.NotifyConnectionReady();
+ }
+
+ void RemoveObserver(Observer* observer) {
+ connection_notifier_.RemoveObserver(observer);
+ }
+
+ // Sets |host|. This can be called in both cases; on ready, or on closed.
+ // Passing nullptr to |host| means closing.
+ // This must not be called if HostType is void (i.e. single direciton
+ // connection).
+ void SetHost(HostType* host) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ impl_.SetHost(host);
+ }
+
+ // Sets |instance| with |version|.
+ // This can be called in both case; on ready, and on closed.
+ // Passing nullptr to |instance| means closing.
+ void SetInstance(InstanceType* instance,
+ uint32_t version = InstanceType::Version_) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ impl_.SetInstance(instance, version);
+ }
+
+ private:
+ THREAD_CHECKER(thread_checker_);
+ internal::ConnectionNotifier connection_notifier_;
+ internal::ConnectionHolderImpl<InstanceType, HostType> impl_{
+ &connection_notifier_};
+
+ DISALLOW_COPY_AND_ASSIGN(ConnectionHolder);
+};
+
+} // namespace arc
+
+#endif // COMPONENTS_ARC_CONNECTION_HOLDER_H_
diff --git a/chromium/components/arc/connection_notifier.cc b/chromium/components/arc/connection_notifier.cc
new file mode 100644
index 00000000000..b3b1e17aab0
--- /dev/null
+++ b/chromium/components/arc/connection_notifier.cc
@@ -0,0 +1,39 @@
+// 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 "components/arc/connection_notifier.h"
+
+#include "components/arc/connection_observer.h"
+
+namespace arc {
+namespace internal {
+
+ConnectionNotifier::ConnectionNotifier() = default;
+
+ConnectionNotifier::~ConnectionNotifier() = default;
+
+void ConnectionNotifier::AddObserver(ConnectionObserverBase* observer) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ observer_list_.AddObserver(observer);
+}
+
+void ConnectionNotifier::RemoveObserver(ConnectionObserverBase* observer) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ observer_list_.RemoveObserver(observer);
+}
+
+void ConnectionNotifier::NotifyConnectionReady() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ for (auto& observer : observer_list_)
+ observer.OnConnectionReady();
+}
+
+void ConnectionNotifier::NotifyConnectionClosed() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ for (auto& observer : observer_list_)
+ observer.OnConnectionClosed();
+}
+
+} // namespace internal
+} // namespace arc
diff --git a/chromium/components/arc/connection_notifier.h b/chromium/components/arc/connection_notifier.h
new file mode 100644
index 00000000000..05a9cac2d30
--- /dev/null
+++ b/chromium/components/arc/connection_notifier.h
@@ -0,0 +1,43 @@
+// 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 COMPONENTS_ARC_CONNECTION_NOTIFIER_H_
+#define COMPONENTS_ARC_CONNECTION_NOTIFIER_H_
+
+#include "base/macros.h"
+#include "base/observer_list.h"
+#include "base/threading/thread_checker.h"
+
+namespace arc {
+namespace internal {
+
+class ConnectionObserverBase;
+
+// Manages events related to connection. Designed to be used only by
+// ConnectionHolder.
+class ConnectionNotifier {
+ public:
+ ConnectionNotifier();
+ ~ConnectionNotifier();
+
+ void AddObserver(ConnectionObserverBase* observer);
+ void RemoveObserver(ConnectionObserverBase* observer);
+
+ // Notifies observers that connection gets ready.
+ void NotifyConnectionReady();
+
+ // Notifies observers that connection is closed.
+ void NotifyConnectionClosed();
+
+ private:
+ THREAD_CHECKER(thread_checker_);
+ base::ObserverList<ConnectionObserverBase> observer_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(ConnectionNotifier);
+};
+
+} // namespace internal
+} // namespace arc
+
+#endif // COMPONENTS_ARC_CONNECTION_NOTIFIER_H_
diff --git a/chromium/components/arc/connection_observer.h b/chromium/components/arc/connection_observer.h
new file mode 100644
index 00000000000..a3eaaa7dd40
--- /dev/null
+++ b/chromium/components/arc/connection_observer.h
@@ -0,0 +1,38 @@
+// 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 COMPONENTS_ARC_CONNECTION_OBSERVER_H_
+#define COMPONENTS_ARC_CONNECTION_OBSERVER_H_
+
+namespace arc {
+namespace internal {
+
+// Observer to listen events for connection.
+class ConnectionObserverBase {
+ public:
+ // Called once the connection is ready.
+ // TODO(hidehiko): Currently, this means Instance is ready.
+ // Later, this will be called when Instance::Init() is completed
+ // for ARC full-duplex mojo connection.
+ virtual void OnConnectionReady() {}
+
+ // Called once the connection is closed.
+ // Currently, this means Instance is closed.
+ virtual void OnConnectionClosed() {}
+
+ protected:
+ virtual ~ConnectionObserverBase() = default;
+};
+
+} // namespace internal
+
+// Observer to listen events for connection for specific type.
+// This is for type safeness to prevent listening events of unexpected mojo
+// connection.
+template <typename InstanceType>
+class ConnectionObserver : public internal::ConnectionObserverBase {};
+
+} // namespace arc
+
+#endif // COMPONENTS_ARC_CONNECTION_OBSERVER_H_
diff --git a/chromium/components/arc/crash_collector/arc_crash_collector_bridge.cc b/chromium/components/arc/crash_collector/arc_crash_collector_bridge.cc
index 90912eaf743..a84bb8261cc 100644
--- a/chromium/components/arc/crash_collector/arc_crash_collector_bridge.cc
+++ b/chromium/components/arc/crash_collector/arc_crash_collector_bridge.cc
@@ -81,21 +81,12 @@ ArcCrashCollectorBridge* ArcCrashCollectorBridge::GetForBrowserContext(
ArcCrashCollectorBridge::ArcCrashCollectorBridge(
content::BrowserContext* context,
ArcBridgeService* bridge_service)
- : arc_bridge_service_(bridge_service), binding_(this) {
- arc_bridge_service_->crash_collector()->AddObserver(this);
+ : arc_bridge_service_(bridge_service) {
+ arc_bridge_service_->crash_collector()->SetHost(this);
}
ArcCrashCollectorBridge::~ArcCrashCollectorBridge() {
- arc_bridge_service_->crash_collector()->RemoveObserver(this);
-}
-
-void ArcCrashCollectorBridge::OnInstanceReady() {
- mojom::CrashCollectorHostPtr host_ptr;
- binding_.Bind(mojo::MakeRequest(&host_ptr));
- auto* instance =
- ARC_GET_INSTANCE_FOR_METHOD(arc_bridge_service_->crash_collector(), Init);
- DCHECK(instance);
- instance->Init(std::move(host_ptr));
+ arc_bridge_service_->crash_collector()->SetHost(nullptr);
}
void ArcCrashCollectorBridge::DumpCrash(const std::string& type,
diff --git a/chromium/components/arc/crash_collector/arc_crash_collector_bridge.h b/chromium/components/arc/crash_collector/arc_crash_collector_bridge.h
index 17cf7850c8b..9da78baf6e7 100644
--- a/chromium/components/arc/crash_collector/arc_crash_collector_bridge.h
+++ b/chromium/components/arc/crash_collector/arc_crash_collector_bridge.h
@@ -9,9 +9,7 @@
#include "base/macros.h"
#include "components/arc/common/crash_collector.mojom.h"
-#include "components/arc/instance_holder.h"
#include "components/keyed_service/core/keyed_service.h"
-#include "mojo/public/cpp/bindings/binding.h"
namespace content {
class BrowserContext;
@@ -24,7 +22,6 @@ class ArcBridgeService;
// Relays dumps for non-native ARC crashes to the crash reporter in Chrome OS.
class ArcCrashCollectorBridge
: public KeyedService,
- public InstanceHolder<mojom::CrashCollectorInstance>::Observer,
public mojom::CrashCollectorHost {
public:
// Returns singleton instance for the given BrowserContext,
@@ -37,9 +34,6 @@ class ArcCrashCollectorBridge
~ArcCrashCollectorBridge() override;
- // InstanceHolder<mojom::CrashCollectorInstance>::Observer overrides.
- void OnInstanceReady() override;
-
// mojom::CrashCollectorHost overrides.
void DumpCrash(const std::string& type, mojo::ScopedHandle pipe) override;
@@ -50,8 +44,6 @@ class ArcCrashCollectorBridge
private:
ArcBridgeService* const arc_bridge_service_; // Owned by ArcServiceManager.
- mojo::Binding<mojom::CrashCollectorHost> binding_;
-
std::string device_;
std::string board_;
std::string cpu_abi_;
diff --git a/chromium/components/arc/ime/arc_ime_bridge_impl.cc b/chromium/components/arc/ime/arc_ime_bridge_impl.cc
index 304788b5ce1..6e4840ff284 100644
--- a/chromium/components/arc/ime/arc_ime_bridge_impl.cc
+++ b/chromium/components/arc/ime/arc_ime_bridge_impl.cc
@@ -76,20 +76,12 @@ std::vector<mojom::CompositionSegmentPtr> ConvertSegments(
ArcImeBridgeImpl::ArcImeBridgeImpl(Delegate* delegate,
ArcBridgeService* bridge_service)
- : binding_(this), delegate_(delegate), bridge_service_(bridge_service) {
- bridge_service_->ime()->AddObserver(this);
+ : delegate_(delegate), bridge_service_(bridge_service) {
+ bridge_service_->ime()->SetHost(this);
}
ArcImeBridgeImpl::~ArcImeBridgeImpl() {
- bridge_service_->ime()->RemoveObserver(this);
-}
-
-void ArcImeBridgeImpl::OnInstanceReady() {
- auto* instance = ARC_GET_INSTANCE_FOR_METHOD(bridge_service_->ime(), Init);
- DCHECK(instance);
- mojom::ImeHostPtr host_proxy;
- binding_.Bind(mojo::MakeRequest(&host_proxy));
- instance->Init(std::move(host_proxy));
+ bridge_service_->ime()->SetHost(nullptr);
}
void ArcImeBridgeImpl::SendSetCompositionText(
@@ -145,7 +137,7 @@ void ArcImeBridgeImpl::OnTextInputTypeChanged(mojom::TextInputType type) {
delegate_->OnTextInputTypeChanged(ConvertTextInputType(type));
}
-void ArcImeBridgeImpl::OnCursorRectChanged(gfx::Rect rect) {
+void ArcImeBridgeImpl::OnCursorRectChanged(const gfx::Rect& rect) {
delegate_->OnCursorRectChanged(rect);
}
@@ -158,10 +150,10 @@ void ArcImeBridgeImpl::ShowImeIfNeeded() {
}
void ArcImeBridgeImpl::OnCursorRectChangedWithSurroundingText(
- gfx::Rect rect,
- gfx::Range text_range,
+ const gfx::Rect& rect,
+ const gfx::Range& text_range,
const std::string& text_in_range,
- gfx::Range selection_range) {
+ const gfx::Range& selection_range) {
delegate_->OnCursorRectChangedWithSurroundingText(
rect, text_range, base::UTF8ToUTF16(text_in_range), selection_range);
}
diff --git a/chromium/components/arc/ime/arc_ime_bridge_impl.h b/chromium/components/arc/ime/arc_ime_bridge_impl.h
index ad26b7e7752..dbac40f7d8e 100644
--- a/chromium/components/arc/ime/arc_ime_bridge_impl.h
+++ b/chromium/components/arc/ime/arc_ime_bridge_impl.h
@@ -11,8 +11,6 @@
#include "base/strings/string16.h"
#include "components/arc/common/ime.mojom.h"
#include "components/arc/ime/arc_ime_bridge.h"
-#include "components/arc/instance_holder.h"
-#include "mojo/public/cpp/bindings/binding.h"
#include "ui/base/ime/text_input_type.h"
#include "ui/gfx/geometry/rect.h"
@@ -26,16 +24,11 @@ class ArcBridgeService;
// This class encapsulates the detail of IME related IPC between
// Chromium and the ARC container.
-class ArcImeBridgeImpl : public ArcImeBridge,
- public mojom::ImeHost,
- public InstanceHolder<mojom::ImeInstance>::Observer {
+class ArcImeBridgeImpl : public ArcImeBridge, public mojom::ImeHost {
public:
ArcImeBridgeImpl(Delegate* delegate, ArcBridgeService* bridge_service);
~ArcImeBridgeImpl() override;
- // InstanceHolder<mojom::ImeInstance>::Observer overrides:
- void OnInstanceReady() override;
-
// ArcImeBridge overrides:
void SendSetCompositionText(const ui::CompositionText& composition) override;
void SendConfirmCompositionText() override;
@@ -45,17 +38,16 @@ class ArcImeBridgeImpl : public ArcImeBridge,
// mojom::ImeHost overrides:
void OnTextInputTypeChanged(mojom::TextInputType type) override;
- void OnCursorRectChanged(gfx::Rect rect) override;
+ void OnCursorRectChanged(const gfx::Rect& rect) override;
void OnCancelComposition() override;
void ShowImeIfNeeded() override;
void OnCursorRectChangedWithSurroundingText(
- gfx::Rect rect,
- gfx::Range text_range,
+ const gfx::Rect& rect,
+ const gfx::Range& text_range,
const std::string& text_in_range,
- gfx::Range selection_range) override;
+ const gfx::Range& selection_range) override;
private:
- mojo::Binding<mojom::ImeHost> binding_;
Delegate* const delegate_;
ArcBridgeService* const bridge_service_;
diff --git a/chromium/components/arc/ime/arc_ime_service.cc b/chromium/components/arc/ime/arc_ime_service.cc
index 775bea2d98d..bfbc3325180 100644
--- a/chromium/components/arc/ime/arc_ime_service.cc
+++ b/chromium/components/arc/ime/arc_ime_service.cc
@@ -8,11 +8,13 @@
#include "base/logging.h"
#include "base/memory/singleton.h"
+#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/arc/arc_browser_context_keyed_service_factory_base.h"
#include "components/arc/ime/arc_ime_bridge_impl.h"
#include "components/exo/shell_surface.h"
#include "components/exo/surface.h"
+#include "components/exo/wm_helper.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
@@ -465,6 +467,12 @@ bool ArcImeService::IsTextEditCommandEnabled(
return false;
}
+const std::string& ArcImeService::GetClientSourceInfo() const {
+ // TODO(yhanada): Implement this method. crbug.com/752657
+ NOTIMPLEMENTED_LOG_ONCE();
+ return base::EmptyString();
+}
+
void ArcImeService::InvalidateSurroundingTextAndSelectionRange() {
text_range_ = gfx::Range::InvalidRange();
text_in_range_ = base::string16();
diff --git a/chromium/components/arc/ime/arc_ime_service.h b/chromium/components/arc/ime/arc_ime_service.h
index 61b7ca3834c..a09b3caac2c 100644
--- a/chromium/components/arc/ime/arc_ime_service.h
+++ b/chromium/components/arc/ime/arc_ime_service.h
@@ -9,8 +9,8 @@
#include "base/macros.h"
#include "components/arc/ime/arc_ime_bridge.h"
-#include "components/exo/wm_helper.h"
#include "components/keyed_service/core/keyed_service.h"
+#include "ui/aura/client/focus_change_observer.h"
#include "ui/aura/env_observer.h"
#include "ui/aura/window_observer.h"
#include "ui/base/ime/text_input_client.h"
@@ -42,7 +42,7 @@ class ArcImeService : public KeyedService,
public ArcImeBridge::Delegate,
public aura::EnvObserver,
public aura::WindowObserver,
- public exo::WMHelper::FocusObserver,
+ public aura::client::FocusChangeObserver,
public keyboard::KeyboardControllerObserver,
public ui::TextInputClient {
public:
@@ -79,7 +79,7 @@ class ArcImeService : public KeyedService,
void OnWindowRemovingFromRootWindow(aura::Window* window,
aura::Window* new_root) override;
- // Overridden from exo::WMHelper::FocusObserver:
+ // Overridden from aura::client::FocusChangeObserver:
void OnWindowFocused(aura::Window* gained_focus,
aura::Window* lost_focus) override;
@@ -132,6 +132,7 @@ class ArcImeService : public KeyedService,
bool IsTextEditCommandEnabled(ui::TextEditCommand command) const override;
void SetTextEditCommandForNextKeyEvent(ui::TextEditCommand command) override {
}
+ const std::string& GetClientSourceInfo() const override;
private:
ui::InputMethod* GetInputMethod();
diff --git a/chromium/components/arc/ime/arc_ime_service_unittest.cc b/chromium/components/arc/ime/arc_ime_service_unittest.cc
index f980dd93a78..45353111a74 100644
--- a/chromium/components/arc/ime/arc_ime_service_unittest.cc
+++ b/chromium/components/arc/ime/arc_ime_service_unittest.cc
@@ -8,7 +8,6 @@
#include <set>
#include <utility>
-#include "base/memory/ptr_util.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "components/arc/arc_bridge_service.h"
diff --git a/chromium/components/arc/ime/arc_ime_struct_traits.cc b/chromium/components/arc/ime/arc_ime_struct_traits.cc
deleted file mode 100644
index b3ca64ac47e..00000000000
--- a/chromium/components/arc/ime/arc_ime_struct_traits.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// 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 "components/arc/ime/arc_ime_struct_traits.h"
-
-namespace mojo {
-
-bool StructTraits<arc::mojom::CursorRectDataView, gfx::Rect>::Read(
- arc::mojom::CursorRectDataView data,
- gfx::Rect* out) {
- out->set_x(data.left());
- out->set_y(data.top());
- out->set_width(data.right() - out->x());
- out->set_height(data.bottom() - out->y());
- return true;
-}
-
-bool StructTraits<arc::mojom::TextRangeDataView, gfx::Range>::Read(
- arc::mojom::TextRangeDataView data,
- gfx::Range* out) {
- out->set_start(data.start());
- out->set_end(data.end());
- return true;
-}
-
-} // namespace mojo
diff --git a/chromium/components/arc/instance_holder.h b/chromium/components/arc/instance_holder.h
deleted file mode 100644
index 48f833f4fcc..00000000000
--- a/chromium/components/arc/instance_holder.h
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2015 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 COMPONENTS_ARC_INSTANCE_HOLDER_H_
-#define COMPONENTS_ARC_INSTANCE_HOLDER_H_
-
-#include <string>
-#include <type_traits>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/observer_list.h"
-#include "base/threading/thread_checker.h"
-
-// A macro to call InstanceHolder<T>::GetInstanceForVersionDoNotCallDirectly().
-// In order to avoid exposing method names from within the Mojo bindings, we
-// will rely on stringification and the fact that the method min versions have a
-// consistent naming scheme.
-#define ARC_GET_INSTANCE_FOR_METHOD(holder, method_name) \
- (holder)->GetInstanceForVersionDoNotCallDirectly( \
- std::remove_pointer<decltype( \
- holder)>::type::Instance::k##method_name##MinVersion, \
- #method_name)
-
-namespace arc {
-
-// Holds a Mojo instance+version pair. This also allows for listening for state
-// changes for the particular instance. T should be a Mojo interface type
-// (arc::mojom::XxxInstance).
-template <typename T>
-class InstanceHolder {
- public:
- // Notifies about connection events for individual instances.
- class Observer {
- public:
- // Called once the instance is ready.
- virtual void OnInstanceReady() {}
-
- // Called when the connection to the instance is closed.
- virtual void OnInstanceClosed() {}
-
- protected:
- virtual ~Observer() = default;
- };
-
- using Instance = T;
-
- InstanceHolder() = default;
-
- // Returns true if the Mojo interface is ready at least for its version 0
- // interface. Use an Observer if you want to be notified when this is ready.
- // This can only be called on the thread that this class was created on.
- bool has_instance() const { return instance_; }
-
- // Gets the Mojo interface that's intended to call for
- // |method_name_for_logging|, but only if its reported version is at least
- // |min_version|. Returns nullptr if the instance is either not ready or does
- // not have the requested version, and logs appropriately.
- // This function should not be called directly. Instead, use the
- // ARC_GET_INSTANCE_FOR_METHOD() macro.
- T* GetInstanceForVersionDoNotCallDirectly(
- uint32_t min_version,
- const char method_name_for_logging[]) {
- if (!instance_) {
- VLOG(1) << "Instance " << T::Name_ << " not available.";
- return nullptr;
- }
- if (version_ < min_version) {
- LOG(ERROR) << "Instance for " << T::Name_
- << "::" << method_name_for_logging
- << " version mismatch. Expected " << min_version << " got "
- << version_;
- return nullptr;
- }
- return instance_;
- }
-
- // Adds or removes observers. This can only be called on the thread that this
- // class was created on. RemoveObserver does nothing if |observer| is not in
- // the list.
- void AddObserver(Observer* observer) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- observer_list_.AddObserver(observer);
-
- if (instance_)
- observer->OnInstanceReady();
- }
-
- void RemoveObserver(Observer* observer) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- observer_list_.RemoveObserver(observer);
- }
-
- // Sets |instance| with |version|.
- // This can be called in both case; on ready, and on closed.
- // Passing nullptr to |instance| means closing.
- void SetInstance(T* instance, uint32_t version = T::Version_) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DCHECK(instance == nullptr || instance_ == nullptr);
-
- // Note: This can be called with nullptr even if |instance_| is still
- // nullptr for just in case clean up purpose. No-op in such a case.
- if (instance == instance_)
- return;
-
- instance_ = instance;
- version_ = version;
- if (instance_) {
- for (auto& observer : observer_list_)
- observer.OnInstanceReady();
- } else {
- for (auto& observer : observer_list_)
- observer.OnInstanceClosed();
- }
- }
-
- private:
- // This class does not have ownership. The pointers should be managed by the
- // callee.
- T* instance_ = nullptr;
- uint32_t version_ = 0;
-
- THREAD_CHECKER(thread_checker_);
- base::ObserverList<Observer> observer_list_;
-
- DISALLOW_COPY_AND_ASSIGN(InstanceHolder<T>);
-};
-
-} // namespace arc
-
-#endif // COMPONENTS_ARC_INSTANCE_HOLDER_H_
diff --git a/chromium/components/arc/intent_helper/DEPS b/chromium/components/arc/intent_helper/DEPS
index e2ab3722b4c..71b171809a0 100644
--- a/chromium/components/arc/intent_helper/DEPS
+++ b/chromium/components/arc/intent_helper/DEPS
@@ -6,6 +6,7 @@ include_rules = [
"+ash/shell_delegate.h",
"+ash/wallpaper/wallpaper_controller.h",
"+components/google/core/browser",
+ "+components/url_formatter",
"+ui/base",
"+ui/gfx",
]
diff --git a/chromium/components/arc/intent_helper/activity_icon_loader.cc b/chromium/components/arc/intent_helper/activity_icon_loader.cc
index c38ec4a0723..a864bad92e3 100644
--- a/chromium/components/arc/intent_helper/activity_icon_loader.cc
+++ b/chromium/components/arc/intent_helper/activity_icon_loader.cc
@@ -65,7 +65,7 @@ mojom::IntentHelperInstance* GetInstanceForRequestActivityIcons(
auto* intent_helper_holder =
arc_service_manager->arc_bridge_service()->intent_helper();
- if (!intent_helper_holder->has_instance()) {
+ if (!intent_helper_holder->IsConnected()) {
VLOG(2) << "ARC intent helper instance is not ready.";
if (out_error_code)
*out_error_code = ActivityIconLoader::GetResult::FAILED_ARC_NOT_READY;
@@ -181,7 +181,7 @@ void ActivityIconLoader::InvalidateIcons(const std::string& package_name) {
ActivityIconLoader::GetResult ActivityIconLoader::GetActivityIcons(
const std::vector<ActivityName>& activities,
- const OnIconsReadyCallback& cb) {
+ OnIconsReadyCallback cb) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
std::unique_ptr<ActivityToIconsMap> result(new ActivityToIconsMap);
std::vector<mojom::ActivityNamePtr> activities_to_fetch;
@@ -200,7 +200,7 @@ ActivityIconLoader::GetResult ActivityIconLoader::GetActivityIcons(
if (activities_to_fetch.empty()) {
// If there's nothing to fetch, run the callback now.
- cb.Run(std::move(result));
+ std::move(cb).Run(std::move(result));
return GetResult::SUCCEEDED_SYNC;
}
@@ -209,22 +209,24 @@ ActivityIconLoader::GetResult ActivityIconLoader::GetActivityIcons(
if (!instance) {
// The mojo channel is not yet ready (or not supported at all). Run the
// callback with |result| that could be empty.
- cb.Run(std::move(result));
+ std::move(cb).Run(std::move(result));
return error_code;
}
// Fetch icons from ARC.
instance->RequestActivityIcons(
std::move(activities_to_fetch), mojom::ScaleFactor(scale_factor_),
- base::Bind(&ActivityIconLoader::OnIconsReady,
- weak_ptr_factory_.GetWeakPtr(), base::Passed(&result), cb));
+ base::BindOnce(&ActivityIconLoader::OnIconsReady,
+ weak_ptr_factory_.GetWeakPtr(), std::move(result),
+ std::move(cb)));
return GetResult::SUCCEEDED_ASYNC;
}
void ActivityIconLoader::OnIconsResizedForTesting(
- const OnIconsReadyCallback& cb,
+ OnIconsReadyCallback cb,
std::unique_ptr<ActivityToIconsMap> result) {
- OnIconsResized(std::make_unique<ActivityToIconsMap>(), cb, std::move(result));
+ OnIconsResized(std::make_unique<ActivityToIconsMap>(), std::move(cb),
+ std::move(result));
}
void ActivityIconLoader::AddCacheEntryForTesting(const ActivityName& activity) {
@@ -247,20 +249,20 @@ bool ActivityIconLoader::HasIconsReadyCallbackRun(GetResult result) {
void ActivityIconLoader::OnIconsReady(
std::unique_ptr<ActivityToIconsMap> cached_result,
- const OnIconsReadyCallback& cb,
+ OnIconsReadyCallback cb,
std::vector<mojom::ActivityIconPtr> icons) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
base::PostTaskAndReplyWithResult(
FROM_HERE,
- base::Bind(&ResizeAndEncodeIcons, base::Passed(&icons), scale_factor_),
- base::Bind(&ActivityIconLoader::OnIconsResized,
- weak_ptr_factory_.GetWeakPtr(), base::Passed(&cached_result),
- cb));
+ base::BindOnce(&ResizeAndEncodeIcons, std::move(icons), scale_factor_),
+ base::BindOnce(&ActivityIconLoader::OnIconsResized,
+ weak_ptr_factory_.GetWeakPtr(), std::move(cached_result),
+ std::move(cb)));
}
void ActivityIconLoader::OnIconsResized(
std::unique_ptr<ActivityToIconsMap> cached_result,
- const OnIconsReadyCallback& cb,
+ OnIconsReadyCallback cb,
std::unique_ptr<ActivityToIconsMap> result) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// Update |cached_icons_|.
@@ -271,7 +273,7 @@ void ActivityIconLoader::OnIconsResized(
// Merge the results that were obtained from cache before doing IPC.
result->insert(cached_result->begin(), cached_result->end());
- cb.Run(std::move(result));
+ std::move(cb).Run(std::move(result));
}
} // namespace internal
diff --git a/chromium/components/arc/intent_helper/activity_icon_loader.h b/chromium/components/arc/intent_helper/activity_icon_loader.h
index 33ac3b70d72..3b07589fd21 100644
--- a/chromium/components/arc/intent_helper/activity_icon_loader.h
+++ b/chromium/components/arc/intent_helper/activity_icon_loader.h
@@ -66,7 +66,7 @@ class ActivityIconLoader {
using ActivityToIconsMap = std::map<ActivityName, Icons>;
using OnIconsReadyCallback =
- base::Callback<void(std::unique_ptr<ActivityToIconsMap>)>;
+ base::OnceCallback<void(std::unique_ptr<ActivityToIconsMap>)>;
ActivityIconLoader();
~ActivityIconLoader();
@@ -80,9 +80,9 @@ class ActivityIconLoader {
// locally or ARC is not ready/supported). Otherwise, the callback is run
// later asynchronously with icons fetched from ARC side.
GetResult GetActivityIcons(const std::vector<ActivityName>& activities,
- const OnIconsReadyCallback& cb);
+ OnIconsReadyCallback cb);
- void OnIconsResizedForTesting(const OnIconsReadyCallback& cb,
+ void OnIconsResizedForTesting(OnIconsReadyCallback cb,
std::unique_ptr<ActivityToIconsMap> result);
void AddCacheEntryForTesting(const ActivityName& activity);
@@ -95,13 +95,13 @@ class ActivityIconLoader {
private:
// A function called when the mojo IPC returns.
void OnIconsReady(std::unique_ptr<ActivityToIconsMap> cached_result,
- const OnIconsReadyCallback& cb,
+ OnIconsReadyCallback cb,
std::vector<mojom::ActivityIconPtr> icons);
// A function called when ResizeIcons finishes. Append items in |result| to
// |cached_icons_|.
void OnIconsResized(std::unique_ptr<ActivityToIconsMap> cached_result,
- const OnIconsReadyCallback& cb,
+ OnIconsReadyCallback cb,
std::unique_ptr<ActivityToIconsMap> result);
// The maximum scale factor the current platform supports.
diff --git a/chromium/components/arc/intent_helper/activity_icon_loader_unittest.cc b/chromium/components/arc/intent_helper/activity_icon_loader_unittest.cc
index 586897e084e..6f5cceadd45 100644
--- a/chromium/components/arc/intent_helper/activity_icon_loader_unittest.cc
+++ b/chromium/components/arc/intent_helper/activity_icon_loader_unittest.cc
@@ -118,7 +118,7 @@ TEST(ActivityIconLoaderTest, TestOnIconsResized) {
ActivityIconLoader loader;
// Call OnIconsResized() and check that the cache is properly updated.
- loader.OnIconsResizedForTesting(base::Bind(&OnIconsReady0),
+ loader.OnIconsResizedForTesting(base::BindOnce(&OnIconsReady0),
std::move(activity_to_icons));
EXPECT_EQ(3U, loader.cached_icons_for_testing().size());
EXPECT_EQ(1U, loader.cached_icons_for_testing().count(
@@ -139,7 +139,7 @@ TEST(ActivityIconLoaderTest, TestOnIconsResized) {
activity_to_icons->insert(std::make_pair(
ActivityIconLoader::ActivityName("p2", "a2"),
ActivityIconLoader::Icons(gfx::Image(), gfx::Image(), nullptr)));
- loader.OnIconsResizedForTesting(base::Bind(&OnIconsReady3),
+ loader.OnIconsResizedForTesting(base::BindOnce(&OnIconsReady3),
std::move(activity_to_icons));
EXPECT_EQ(4U, loader.cached_icons_for_testing().size());
EXPECT_EQ(1U, loader.cached_icons_for_testing().count(
diff --git a/chromium/components/arc/intent_helper/arc_intent_helper_bridge.cc b/chromium/components/arc/intent_helper/arc_intent_helper_bridge.cc
index cb841928d68..5e7e2366fff 100644
--- a/chromium/components/arc/intent_helper/arc_intent_helper_bridge.cc
+++ b/chromium/components/arc/intent_helper/arc_intent_helper_bridge.cc
@@ -4,25 +4,75 @@
#include "components/arc/intent_helper/arc_intent_helper_bridge.h"
+#include <iterator>
#include <utility>
#include "ash/new_window_controller.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "ash/wallpaper/wallpaper_controller.h"
+#include "base/logging.h"
#include "base/memory/singleton.h"
#include "base/memory/weak_ptr.h"
+#include "base/strings/string_util.h"
#include "components/arc/arc_bridge_service.h"
#include "components/arc/arc_browser_context_keyed_service_factory_base.h"
#include "components/arc/arc_service_manager.h"
#include "components/arc/audio/arc_audio_bridge.h"
+#include "components/url_formatter/url_fixer.h"
#include "ui/base/layout.h"
-#include "url/gurl.h"
+#include "url/url_constants.h"
namespace arc {
namespace {
-constexpr char kChromeUIScheme[] = "chrome";
+constexpr std::pair<mojom::ChromePage, const char*> kMapping[] = {
+ {mojom::ChromePage::MULTIDEVICE, "multidevice"},
+ {mojom::ChromePage::MAIN, ""},
+ {mojom::ChromePage::POWER, "power"},
+ {mojom::ChromePage::BLUETOOTH, "bluetoothDevices"},
+ {mojom::ChromePage::DATETIME, "dateTime"},
+ {mojom::ChromePage::DISPLAY, "display"},
+ {mojom::ChromePage::WIFI, "networks/?type=WiFi"},
+ {mojom::ChromePage::PRIVACY, "privacy"},
+ {mojom::ChromePage::HELP, "help"},
+ {mojom::ChromePage::ACCOUNTS, "accounts"},
+ {mojom::ChromePage::APPEARANCE, "appearance"},
+ {mojom::ChromePage::AUTOFILL, "autofill"},
+ {mojom::ChromePage::BLUETOOTHDEVICES, "bluetoothDevices"},
+ {mojom::ChromePage::CHANGEPICTURE, "changePicture"},
+ {mojom::ChromePage::CLEARBROWSERDATA, "clearBrowserData"},
+ {mojom::ChromePage::CLOUDPRINTERS, "cloudPrinters"},
+ {mojom::ChromePage::CUPSPRINTERS, "cupsPrinters"},
+ {mojom::ChromePage::DOWNLOADS, "downloads"},
+ {mojom::ChromePage::KEYBOARDOVERLAY, "keyboard-overlay"},
+ {mojom::ChromePage::LANGUAGES, "languages"},
+ {mojom::ChromePage::LOCKSCREEN, "lockScreen"},
+ {mojom::ChromePage::MANAGEACCESSIBILITY, "manageAccessibility"},
+ {mojom::ChromePage::NETWORKSTYPEVPN, "networks?type=VPN"},
+ {mojom::ChromePage::ONSTARTUP, "onStartup"},
+ {mojom::ChromePage::PASSWORDS, "passwords"},
+ {mojom::ChromePage::POINTEROVERLAY, "pointer-overlay"},
+ {mojom::ChromePage::RESET, "reset"},
+ {mojom::ChromePage::SEARCH, "search"},
+ {mojom::ChromePage::STORAGE, "storage"},
+ {mojom::ChromePage::SYNCSETUP, "syncSetup"},
+ {mojom::ChromePage::ABOUTBLANK, url::kAboutBlankURL},
+ {mojom::ChromePage::ABOUTDOWNLOADS, "about:downloads"},
+ {mojom::ChromePage::ABOUTHISTORY, "about:history"}};
+
+// TODO(djacobo): Propose geo: as a constant.
+constexpr const char* kArcSchemes[] = {url::kHttpScheme,
+ url::kHttpsScheme,
+ url::kContentScheme,
+ url::kFileScheme,
+ "geo",
+ url::kMailToScheme};
+
+// mojom::ChromePage::LAST returns the ammout of valid entries - 1.
+static_assert(arraysize(kMapping) ==
+ static_cast<size_t>(mojom::ChromePage::LAST) + 1,
+ "kMapping is out of sync");
class OpenUrlDelegateImpl : public ArcIntentHelperBridge::OpenUrlDelegate {
public:
@@ -77,32 +127,25 @@ KeyedServiceBaseFactory* ArcIntentHelperBridge::GetFactory() {
return ArcIntentHelperBridgeFactory::GetInstance();
}
+// static
+std::string ArcIntentHelperBridge::AppendStringToIntentHelperPackageName(
+ const std::string& to_append) {
+ return base::JoinString({kArcIntentHelperPackageName, to_append}, ".");
+}
+
ArcIntentHelperBridge::ArcIntentHelperBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service)
: context_(context),
arc_bridge_service_(bridge_service),
- binding_(this),
- open_url_delegate_(std::make_unique<OpenUrlDelegateImpl>()) {
- arc_bridge_service_->intent_helper()->AddObserver(this);
+ open_url_delegate_(std::make_unique<OpenUrlDelegateImpl>()),
+ allowed_chrome_pages_map_(std::cbegin(kMapping), std::cend(kMapping)),
+ allowed_arc_schemes_(std::cbegin(kArcSchemes), std::cend(kArcSchemes)) {
+ arc_bridge_service_->intent_helper()->SetHost(this);
}
ArcIntentHelperBridge::~ArcIntentHelperBridge() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- arc_bridge_service_->intent_helper()->RemoveObserver(this);
-}
-
-void ArcIntentHelperBridge::OnInstanceReady() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- auto* instance =
- ARC_GET_INSTANCE_FOR_METHOD(arc_bridge_service_->intent_helper(), Init);
- DCHECK(instance);
- mojom::IntentHelperHostPtr host_proxy;
- binding_.Bind(mojo::MakeRequest(&host_proxy));
- instance->Init(std::move(host_proxy));
-}
-
-void ArcIntentHelperBridge::OnInstanceClosed() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ arc_bridge_service_->intent_helper()->SetHost(nullptr);
}
void ArcIntentHelperBridge::OnIconInvalidated(const std::string& package_name) {
@@ -123,56 +166,29 @@ void ArcIntentHelperBridge::OnOpenDownloads() {
void ArcIntentHelperBridge::OnOpenUrl(const std::string& url) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- const GURL gurl(url);
- // Disallow opening chrome:// URLs.
- if (gurl.SchemeIs(kChromeUIScheme))
+ // Converts |url| to a fixed-up one and checks validity.
+ const GURL gurl(url_formatter::FixupURL(url, std::string()));
+ if (!gurl.is_valid())
return;
- open_url_delegate_->OpenUrl(gurl);
+
+ if (allowed_arc_schemes_.find(gurl.scheme()) != allowed_arc_schemes_.end())
+ open_url_delegate_->OpenUrl(gurl);
}
-void ArcIntentHelperBridge::OnOpenChromeSettings(mojom::SettingsPage page) {
+void ArcIntentHelperBridge::OnOpenChromePage(mojom::ChromePage page) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
- // Mapping from the mojom enum values to the URL components.
- const char* sub_url = nullptr;
- switch (page) {
- case mojom::SettingsPage::MULTIDEVICE:
- sub_url = "multidevice";
- break;
- case mojom::SettingsPage::MAIN:
- sub_url = "";
- break;
- case mojom::SettingsPage::POWER:
- sub_url = "power";
- break;
- case mojom::SettingsPage::BLUETOOTH:
- sub_url = "bluetoothDevices";
- break;
- case mojom::SettingsPage::DATETIME:
- sub_url = "dateTime";
- break;
- case mojom::SettingsPage::DISPLAY:
- sub_url = "display";
- break;
- case mojom::SettingsPage::WIFI:
- sub_url = "networks/?type=WiFi";
- break;
- case mojom::SettingsPage::LANGUAGE:
- sub_url = "languages";
- break;
- case mojom::SettingsPage::PRIVACY:
- sub_url = "privacy";
- break;
- case mojom::SettingsPage::HELP:
- sub_url = "help";
- break;
- }
-
- if (!sub_url) {
- LOG(ERROR) << "Invalid settings page: " << page;
+ auto it = allowed_chrome_pages_map_.find(page);
+ if (it == allowed_chrome_pages_map_.end()) {
+ LOG(WARNING) << "The requested ChromePage is invalid: "
+ << static_cast<int>(page);
return;
}
- open_url_delegate_->OpenUrl(GURL(kSettingsPageBaseUrl).Resolve(sub_url));
+
+ GURL page_gurl(it->second);
+ if (page_gurl.SchemeIs(url::kAboutScheme))
+ open_url_delegate_->OpenUrl(page_gurl);
+ else
+ open_url_delegate_->OpenUrl(GURL(kSettingsPageBaseUrl).Resolve(it->second));
}
void ArcIntentHelperBridge::OpenWallpaperPicker() {
@@ -196,9 +212,9 @@ void ArcIntentHelperBridge::OpenVolumeControl() {
ArcIntentHelperBridge::GetResult ArcIntentHelperBridge::GetActivityIcons(
const std::vector<ActivityName>& activities,
- const OnIconsReadyCallback& callback) {
+ OnIconsReadyCallback callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- return icon_loader_.GetActivityIcons(activities, callback);
+ return icon_loader_.GetActivityIcons(activities, std::move(callback));
}
bool ArcIntentHelperBridge::ShouldChromeHandleUrl(const GURL& url) {
diff --git a/chromium/components/arc/intent_helper/arc_intent_helper_bridge.h b/chromium/components/arc/intent_helper/arc_intent_helper_bridge.h
index 2fad5b12dac..9922c11922b 100644
--- a/chromium/components/arc/intent_helper/arc_intent_helper_bridge.h
+++ b/chromium/components/arc/intent_helper/arc_intent_helper_bridge.h
@@ -5,7 +5,9 @@
#ifndef COMPONENTS_ARC_INTENT_HELPER_ARC_INTENT_HELPER_BRIDGE_H_
#define COMPONENTS_ARC_INTENT_HELPER_ARC_INTENT_HELPER_BRIDGE_H_
+#include <map>
#include <memory>
+#include <set>
#include <string>
#include <vector>
@@ -13,11 +15,10 @@
#include "base/observer_list.h"
#include "base/threading/thread_checker.h"
#include "components/arc/common/intent_helper.mojom.h"
-#include "components/arc/instance_holder.h"
#include "components/arc/intent_helper/activity_icon_loader.h"
#include "components/arc/intent_helper/arc_intent_helper_observer.h"
#include "components/keyed_service/core/keyed_service.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "url/gurl.h"
class KeyedServiceBaseFactory;
@@ -33,7 +34,6 @@ class IntentFilter;
// Receives intents from ARC.
class ArcIntentHelperBridge
: public KeyedService,
- public InstanceHolder<mojom::IntentHelperInstance>::Observer,
public mojom::IntentHelperHost {
public:
// Returns singleton instance for the given BrowserContext,
@@ -44,6 +44,10 @@ class ArcIntentHelperBridge
// Returns factory for the ArcIntentHelperBridge.
static KeyedServiceBaseFactory* GetFactory();
+ // Appends '.' + |to_append| to the intent helper package name.
+ static std::string AppendStringToIntentHelperPackageName(
+ const std::string& to_append);
+
ArcIntentHelperBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service);
~ArcIntentHelperBridge() override;
@@ -52,17 +56,13 @@ class ArcIntentHelperBridge
void RemoveObserver(ArcIntentHelperObserver* observer);
bool HasObserver(ArcIntentHelperObserver* observer) const;
- // InstanceHolder<mojom::IntentHelperInstance>::Observer
- void OnInstanceReady() override;
- void OnInstanceClosed() override;
-
// mojom::IntentHelperHost
void OnIconInvalidated(const std::string& package_name) override;
void OnIntentFiltersUpdated(
std::vector<IntentFilter> intent_filters) override;
void OnOpenDownloads() override;
void OnOpenUrl(const std::string& url) override;
- void OnOpenChromeSettings(mojom::SettingsPage page) override;
+ void OnOpenChromePage(mojom::ChromePage page) override;
void OpenWallpaperPicker() override;
void SetWallpaperDeprecated(const std::vector<uint8_t>& jpeg_data) override;
void OpenVolumeControl() override;
@@ -84,7 +84,7 @@ class ArcIntentHelperBridge
internal::ActivityIconLoader::OnIconsReadyCallback;
using GetResult = internal::ActivityIconLoader::GetResult;
GetResult GetActivityIcons(const std::vector<ActivityName>& activities,
- const OnIconsReadyCallback& callback);
+ OnIconsReadyCallback callback);
// Returns true when |url| can only be handled by Chrome. Otherwise, which is
// when there might be one or more ARC apps that can handle |url|, returns
@@ -113,7 +113,6 @@ class ArcIntentHelperBridge
content::BrowserContext* const context_;
ArcBridgeService* const arc_bridge_service_; // Owned by ArcServiceManager.
- mojo::Binding<mojom::IntentHelperHost> binding_;
std::unique_ptr<OpenUrlDelegate> open_url_delegate_;
internal::ActivityIconLoader icon_loader_;
@@ -123,6 +122,13 @@ class ArcIntentHelperBridge
base::ObserverList<ArcIntentHelperObserver> observer_list_;
+ // about: and chrome://settings pages assistant requires to launch via
+ // OnOpenChromePage.
+ const std::map<mojom::ChromePage, std::string> allowed_chrome_pages_map_;
+
+ // Schemes that ARC is known to send via OnOpenUrl.
+ const std::set<std::string> allowed_arc_schemes_;
+
DISALLOW_COPY_AND_ASSIGN(ArcIntentHelperBridge);
};
diff --git a/chromium/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc b/chromium/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc
index 0a41295b955..dde660f0f8d 100644
--- a/chromium/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc
+++ b/chromium/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc
@@ -36,7 +36,11 @@ class ArcIntentHelperTest : public testing::Test {
// ArcIntentHelperBridge::OpenUrlDelegate:
void OpenUrl(const GURL& url) override { last_opened_url_ = url; }
- const GURL& last_opened_url() const { return last_opened_url_; }
+ GURL TakeLastOpenedUrl() {
+ GURL result = std::move(last_opened_url_);
+ last_opened_url_ = GURL();
+ return result;
+ }
private:
GURL last_opened_url_;
@@ -271,33 +275,181 @@ TEST_F(ArcIntentHelperTest, TestMultipleUpdate) {
// Tests that OnOpenUrl opens the URL in Chrome browser.
TEST_F(ArcIntentHelperTest, TestOnOpenUrl) {
+ instance_->OnOpenUrl("http://google.com");
+ EXPECT_EQ(GURL("http://google.com"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
instance_->OnOpenUrl("https://google.com");
EXPECT_EQ(GURL("https://google.com"),
- test_open_url_delegate_->last_opened_url());
+ test_open_url_delegate_->TakeLastOpenedUrl());
}
-// Tests that OnOpenUrl does not open URLs with the 'chrome' scheme.
+// Tests that OnOpenUrl does not open URLs with the 'chrome://' and equivalent
+// schemes like 'about:'.
TEST_F(ArcIntentHelperTest, TestOnOpenUrl_ChromeScheme) {
instance_->OnOpenUrl("chrome://www.google.com");
- EXPECT_FALSE(test_open_url_delegate_->last_opened_url().is_valid());
+ EXPECT_FALSE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid());
+
instance_->OnOpenUrl("chrome://settings");
- EXPECT_FALSE(test_open_url_delegate_->last_opened_url().is_valid());
+ EXPECT_FALSE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid());
+
+ instance_->OnOpenUrl("about:");
+ EXPECT_FALSE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid());
+
+ instance_->OnOpenUrl("about:settings");
+ EXPECT_FALSE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid());
+
+ instance_->OnOpenUrl("about:blank");
+ EXPECT_FALSE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid());
}
-// Tests that OnOpenChromeSettings opens the specified settings section in the
+// Tests that OnOpenChromePage opens the specified settings section in the
// Chrome browser.
-TEST_F(ArcIntentHelperTest, TestOnOpenChromeSettings) {
- instance_->OnOpenChromeSettings(mojom::SettingsPage::MAIN);
+TEST_F(ArcIntentHelperTest, TestOnOpenChromePage) {
+ instance_->OnOpenChromePage(mojom::ChromePage::MAIN);
EXPECT_EQ(GURL("chrome://settings"),
- test_open_url_delegate_->last_opened_url());
+ test_open_url_delegate_->TakeLastOpenedUrl());
- instance_->OnOpenChromeSettings(mojom::SettingsPage::MULTIDEVICE);
+ instance_->OnOpenChromePage(mojom::ChromePage::MULTIDEVICE);
EXPECT_EQ(GURL("chrome://settings/multidevice"),
- test_open_url_delegate_->last_opened_url());
+ test_open_url_delegate_->TakeLastOpenedUrl());
- instance_->OnOpenChromeSettings(mojom::SettingsPage::WIFI);
+ instance_->OnOpenChromePage(mojom::ChromePage::WIFI);
EXPECT_EQ(GURL("chrome://settings/networks/?type=WiFi"),
- test_open_url_delegate_->last_opened_url());
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::POWER);
+ EXPECT_EQ(GURL("chrome://settings/power"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::BLUETOOTH);
+ EXPECT_EQ(GURL("chrome://settings/bluetoothDevices"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::DATETIME);
+ EXPECT_EQ(GURL("chrome://settings/dateTime"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::DISPLAY);
+ EXPECT_EQ(GURL("chrome://settings/display"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::PRIVACY);
+ EXPECT_EQ(GURL("chrome://settings/privacy"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::HELP);
+ EXPECT_EQ(GURL("chrome://settings/help"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::ACCOUNTS);
+ EXPECT_EQ(GURL("chrome://settings/accounts"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::APPEARANCE);
+ EXPECT_EQ(GURL("chrome://settings/appearance"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::AUTOFILL);
+ EXPECT_EQ(GURL("chrome://settings/autofill"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::BLUETOOTHDEVICES);
+ EXPECT_EQ(GURL("chrome://settings/bluetoothDevices"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::CHANGEPICTURE);
+ EXPECT_EQ(GURL("chrome://settings/changePicture"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::CLEARBROWSERDATA);
+ EXPECT_EQ(GURL("chrome://settings/clearBrowserData"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::CLOUDPRINTERS);
+ EXPECT_EQ(GURL("chrome://settings/cloudPrinters"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::CUPSPRINTERS);
+ EXPECT_EQ(GURL("chrome://settings/cupsPrinters"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::DOWNLOADS);
+ EXPECT_EQ(GURL("chrome://settings/downloads"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::ABOUTDOWNLOADS);
+ EXPECT_EQ(GURL("about:downloads"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::ABOUTHISTORY);
+ EXPECT_EQ(GURL("about:history"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::KEYBOARDOVERLAY);
+ EXPECT_EQ(GURL("chrome://settings/keyboard-overlay"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::LANGUAGES);
+ EXPECT_EQ(GURL("chrome://settings/languages"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::LOCKSCREEN);
+ EXPECT_EQ(GURL("chrome://settings/lockScreen"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::MANAGEACCESSIBILITY);
+ EXPECT_EQ(GURL("chrome://settings/manageAccessibility"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::NETWORKSTYPEVPN);
+ EXPECT_EQ(GURL("chrome://settings/networks?type=VPN"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::ONSTARTUP);
+ EXPECT_EQ(GURL("chrome://settings/onStartup"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::PASSWORDS);
+ EXPECT_EQ(GURL("chrome://settings/passwords"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::POINTEROVERLAY);
+ EXPECT_EQ(GURL("chrome://settings/pointer-overlay"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::RESET);
+ EXPECT_EQ(GURL("chrome://settings/reset"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::SEARCH);
+ EXPECT_EQ(GURL("chrome://settings/search"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::STORAGE);
+ EXPECT_EQ(GURL("chrome://settings/storage"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::SYNCSETUP);
+ EXPECT_EQ(GURL("chrome://settings/syncSetup"),
+ test_open_url_delegate_->TakeLastOpenedUrl());
+
+ instance_->OnOpenChromePage(mojom::ChromePage::ABOUTBLANK);
+ EXPECT_EQ(GURL("about:blank"), test_open_url_delegate_->TakeLastOpenedUrl());
+}
+
+// Tests that AppendStringToIntentHelperPackageName works.
+TEST_F(ArcIntentHelperTest, TestAppendStringToIntentHelperPackageName) {
+ std::string package_name = ArcIntentHelperBridge::kArcIntentHelperPackageName;
+ std::string fake_activity = "this_is_a_fake_activity";
+ EXPECT_EQ(ArcIntentHelperBridge::AppendStringToIntentHelperPackageName(
+ fake_activity),
+ package_name + "." + fake_activity);
+
+ std::string empty_string = "";
+ EXPECT_EQ(ArcIntentHelperBridge::AppendStringToIntentHelperPackageName(
+ empty_string),
+ package_name + ".");
}
} // namespace arc
diff --git a/chromium/components/arc/intent_helper/intent_filter.cc b/chromium/components/arc/intent_helper/intent_filter.cc
index e8a80455f52..32fb9a143f0 100644
--- a/chromium/components/arc/intent_helper/intent_filter.cc
+++ b/chromium/components/arc/intent_helper/intent_filter.cc
@@ -115,11 +115,10 @@ bool IntentFilter::AuthorityEntry::Match(const GURL& url) const {
if (wild_) {
return base::EndsWith(url.host_piece(), host_,
base::CompareCase::INSENSITIVE_ASCII);
- } else {
- // TODO(kenobi): Not i18n-friendly. Figure out how to correctly deal with
- // IDNs.
- return host_ == base::ToLowerASCII(url.host_piece());
}
+ // TODO(kenobi): Not i18n-friendly. Figure out how to correctly deal with
+ // IDNs.
+ return host_ == base::ToLowerASCII(url.host_piece());
}
IntentFilter::PatternMatcher::PatternMatcher() = default;
diff --git a/chromium/components/arc/intent_helper/link_handler_model.cc b/chromium/components/arc/intent_helper/link_handler_model.cc
index 42002920f6f..d70fcefdbc5 100644
--- a/chromium/components/arc/intent_helper/link_handler_model.cc
+++ b/chromium/components/arc/intent_helper/link_handler_model.cc
@@ -118,8 +118,8 @@ void LinkHandlerModel::OnUrlHandlerList(
}
const ArcIntentHelperBridge::GetResult result =
intent_helper_bridge->GetActivityIcons(
- activities, base::Bind(&LinkHandlerModel::NotifyObserver,
- weak_ptr_factory_.GetWeakPtr()));
+ activities, base::BindOnce(&LinkHandlerModel::NotifyObserver,
+ weak_ptr_factory_.GetWeakPtr()));
icon_info_notified =
internal::ActivityIconLoader::HasIconsReadyCallbackRun(result);
}
diff --git a/chromium/components/arc/lock_screen/arc_lock_screen_bridge.cc b/chromium/components/arc/lock_screen/arc_lock_screen_bridge.cc
index 1be29eb72ed..5c833fd3c08 100644
--- a/chromium/components/arc/lock_screen/arc_lock_screen_bridge.cc
+++ b/chromium/components/arc/lock_screen/arc_lock_screen_bridge.cc
@@ -57,7 +57,7 @@ ArcLockScreenBridge::~ArcLockScreenBridge() {
session_manager::SessionManager::Get()->RemoveObserver(this);
}
-void ArcLockScreenBridge::OnInstanceReady() {
+void ArcLockScreenBridge::OnConnectionReady() {
SendDeviceLockedState();
}
diff --git a/chromium/components/arc/lock_screen/arc_lock_screen_bridge.h b/chromium/components/arc/lock_screen/arc_lock_screen_bridge.h
index 7c1aabe2de2..bd9476c995c 100644
--- a/chromium/components/arc/lock_screen/arc_lock_screen_bridge.h
+++ b/chromium/components/arc/lock_screen/arc_lock_screen_bridge.h
@@ -8,7 +8,7 @@
#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "components/arc/common/lock_screen.mojom.h"
-#include "components/arc/instance_holder.h"
+#include "components/arc/connection_observer.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/session_manager/core/session_manager_observer.h"
@@ -23,7 +23,7 @@ class ArcBridgeService;
// This class notifies the Chrome OS side lock screen state to the container.
class ArcLockScreenBridge
: public KeyedService,
- public InstanceHolder<mojom::LockScreenInstance>::Observer,
+ public ConnectionObserver<mojom::LockScreenInstance>,
public session_manager::SessionManagerObserver {
public:
// Returns singleton instance for the given BrowserContext,
@@ -35,8 +35,8 @@ class ArcLockScreenBridge
ArcBridgeService* bridge_service);
~ArcLockScreenBridge() override;
- // InstanceHolder<mojom::LockScreenInstance>::Observer overrides:
- void OnInstanceReady() override;
+ // ConnectionObserver<mojom::LockScreenInstance> overrides:
+ void OnConnectionReady() override;
// session_manager::SessionManagerObserver overrides.
void OnSessionStateChanged() override;
diff --git a/chromium/components/arc/metrics/arc_metrics_service.cc b/chromium/components/arc/metrics/arc_metrics_service.cc
index c1d2e3da8e2..79de7ed8d03 100644
--- a/chromium/components/arc/metrics/arc_metrics_service.cc
+++ b/chromium/components/arc/metrics/arc_metrics_service.cc
@@ -68,6 +68,11 @@ class ArcMetricsServiceFactory
} // namespace
// static
+BrowserContextKeyedServiceFactory* ArcMetricsService::GetFactory() {
+ return ArcMetricsServiceFactory::GetInstance();
+}
+
+// static
ArcMetricsService* ArcMetricsService::GetForBrowserContext(
content::BrowserContext* context) {
return ArcMetricsServiceFactory::GetForBrowserContext(context);
@@ -76,43 +81,25 @@ ArcMetricsService* ArcMetricsService::GetForBrowserContext(
ArcMetricsService::ArcMetricsService(content::BrowserContext* context,
ArcBridgeService* bridge_service)
: arc_bridge_service_(bridge_service),
- binding_(this),
process_observer_(this),
weak_ptr_factory_(this) {
- arc_bridge_service_->metrics()->AddObserver(this);
+ arc_bridge_service_->metrics()->SetHost(this);
arc_bridge_service_->process()->AddObserver(&process_observer_);
}
ArcMetricsService::~ArcMetricsService() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
arc_bridge_service_->process()->RemoveObserver(&process_observer_);
- arc_bridge_service_->metrics()->RemoveObserver(this);
-}
-
-void ArcMetricsService::OnInstanceReady() {
- VLOG(2) << "Start metrics service.";
- // Retrieve ARC start time from session manager.
- chromeos::SessionManagerClient* session_manager_client =
- chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
- session_manager_client->GetArcStartTime(
- base::BindOnce(&ArcMetricsService::OnArcStartTimeRetrieved,
- weak_ptr_factory_.GetWeakPtr()));
+ arc_bridge_service_->metrics()->SetHost(nullptr);
}
-void ArcMetricsService::OnInstanceClosed() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- VLOG(2) << "Close metrics service.";
- if (binding_.is_bound())
- binding_.Unbind();
-}
-
-void ArcMetricsService::OnProcessInstanceReady() {
+void ArcMetricsService::OnProcessConnectionReady() {
VLOG(2) << "Start updating process list.";
timer_.Start(FROM_HERE, kRequestProcessListPeriod, this,
&ArcMetricsService::RequestProcessList);
}
-void ArcMetricsService::OnProcessInstanceClosed() {
+void ArcMetricsService::OnProcessConnectionClosed() {
VLOG(2) << "Stop updating process list.";
timer_.Stop();
}
@@ -154,46 +141,26 @@ void ArcMetricsService::ParseProcessList(
}
void ArcMetricsService::OnArcStartTimeRetrieved(
+ std::vector<mojom::BootProgressEventPtr> events,
+ mojom::BootType boot_type,
base::Optional<base::TimeTicks> arc_start_time) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!arc_start_time.has_value()) {
LOG(ERROR) << "Failed to retrieve ARC start timeticks.";
return;
}
- auto* instance =
- ARC_GET_INSTANCE_FOR_METHOD(arc_bridge_service_->metrics(), Init);
- if (!instance)
- return;
+ VLOG(2) << "ARC start @" << arc_start_time.value();
- // The binding of host interface is deferred until the ARC start time is
- // retrieved here because it prevents race condition of the ARC start
- // time availability in ReportBootProgress().
- if (!binding_.is_bound()) {
- mojom::MetricsHostPtr host_ptr;
- binding_.Bind(mojo::MakeRequest(&host_ptr));
- instance->Init(std::move(host_ptr));
- }
- arc_start_time_ = arc_start_time.value();
- VLOG(2) << "ARC start @" << arc_start_time_;
-}
-
-void ArcMetricsService::ReportBootProgress(
- std::vector<mojom::BootProgressEventPtr> events,
- mojom::BootType boot_type) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (boot_type == mojom::BootType::UNKNOWN) {
- LOG(WARNING) << "boot_type is unknown. Skip recording UMA.";
- return;
- }
- int64_t arc_start_time_in_ms =
- (arc_start_time_ - base::TimeTicks()).InMilliseconds();
+ DCHECK_NE(mojom::BootType::UNKNOWN, boot_type);
const std::string suffix = BootTypeToString(boot_type);
for (const auto& event : events) {
VLOG(2) << "Report boot progress event:" << event->event << "@"
<< event->uptimeMillis;
const std::string name = "Arc." + event->event + suffix;
- const base::TimeDelta elapsed_time = base::TimeDelta::FromMilliseconds(
- event->uptimeMillis - arc_start_time_in_ms);
+ const base::TimeTicks uptime =
+ base::TimeDelta::FromMilliseconds(event->uptimeMillis) +
+ base::TimeTicks();
+ const base::TimeDelta elapsed_time = uptime - arc_start_time.value();
base::UmaHistogramCustomTimes(name, elapsed_time, kUmaMinTime, kUmaMaxTime,
kUmaNumBuckets);
if (event->event.compare(kBootProgressEnableScreen) == 0) {
@@ -204,18 +171,35 @@ void ArcMetricsService::ReportBootProgress(
}
}
+void ArcMetricsService::ReportBootProgress(
+ std::vector<mojom::BootProgressEventPtr> events,
+ mojom::BootType boot_type) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (boot_type == mojom::BootType::UNKNOWN) {
+ LOG(WARNING) << "boot_type is unknown. Skip recording UMA.";
+ return;
+ }
+
+ // Retrieve ARC start time from session manager.
+ chromeos::SessionManagerClient* session_manager_client =
+ chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
+ session_manager_client->GetArcStartTime(base::BindOnce(
+ &ArcMetricsService::OnArcStartTimeRetrieved,
+ weak_ptr_factory_.GetWeakPtr(), std::move(events), boot_type));
+}
+
ArcMetricsService::ProcessObserver::ProcessObserver(
ArcMetricsService* arc_metrics_service)
: arc_metrics_service_(arc_metrics_service) {}
ArcMetricsService::ProcessObserver::~ProcessObserver() = default;
-void ArcMetricsService::ProcessObserver::OnInstanceReady() {
- arc_metrics_service_->OnProcessInstanceReady();
+void ArcMetricsService::ProcessObserver::OnConnectionReady() {
+ arc_metrics_service_->OnProcessConnectionReady();
}
-void ArcMetricsService::ProcessObserver::OnInstanceClosed() {
- arc_metrics_service_->OnProcessInstanceClosed();
+void ArcMetricsService::ProcessObserver::OnConnectionClosed() {
+ arc_metrics_service_->OnProcessConnectionClosed();
}
} // namespace arc
diff --git a/chromium/components/arc/metrics/arc_metrics_service.h b/chromium/components/arc/metrics/arc_metrics_service.h
index 2f1f6624cba..76ea2e803ed 100644
--- a/chromium/components/arc/metrics/arc_metrics_service.h
+++ b/chromium/components/arc/metrics/arc_metrics_service.h
@@ -14,9 +14,10 @@
#include "base/timer/timer.h"
#include "components/arc/common/metrics.mojom.h"
#include "components/arc/common/process.mojom.h"
-#include "components/arc/instance_holder.h"
+#include "components/arc/connection_observer.h"
#include "components/keyed_service/core/keyed_service.h"
-#include "mojo/public/cpp/bindings/binding.h"
+
+class BrowserContextKeyedServiceFactory;
namespace content {
class BrowserContext;
@@ -27,11 +28,12 @@ namespace arc {
class ArcBridgeService;
// Collects information from other ArcServices and send UMA metrics.
-class ArcMetricsService
- : public KeyedService,
- public InstanceHolder<mojom::MetricsInstance>::Observer,
- public mojom::MetricsHost {
+class ArcMetricsService : public KeyedService,
+ public mojom::MetricsHost {
public:
+ // Returns the factory instance for this class.
+ static BrowserContextKeyedServiceFactory* GetFactory();
+
// Returns singleton instance for the given BrowserContext,
// or nullptr if the browser |context| is not allowed to use ARC.
static ArcMetricsService* GetForBrowserContext(
@@ -41,13 +43,9 @@ class ArcMetricsService
ArcBridgeService* bridge_service);
~ArcMetricsService() override;
- // InstanceHolder<mojom::MetricsInstance>::Observer overrides.
- void OnInstanceReady() override;
- void OnInstanceClosed() override;
-
- // Implementations for InstanceHolder<mojom::ProcessInstance>::Observer.
- void OnProcessInstanceReady();
- void OnProcessInstanceClosed();
+ // Implementations for ConnectionObserver<mojom::ProcessInstance>.
+ void OnProcessConnectionReady();
+ void OnProcessConnectionClosed();
// MetricsHost overrides.
void ReportBootProgress(std::vector<mojom::BootProgressEventPtr> events,
@@ -55,16 +53,15 @@ class ArcMetricsService
private:
// Adapter to be able to also observe ProcessInstance events.
- class ProcessObserver
- : public InstanceHolder<mojom::ProcessInstance>::Observer {
+ class ProcessObserver : public ConnectionObserver<mojom::ProcessInstance> {
public:
explicit ProcessObserver(ArcMetricsService* arc_metrics_service);
~ProcessObserver() override;
private:
- // InstanceHolder<mojom::ProcessInstance>::Observer overrides.
- void OnInstanceReady() override;
- void OnInstanceClosed() override;
+ // ConnectionObserver<mojom::ProcessInstance> overrides.
+ void OnConnectionReady() override;
+ void OnConnectionClosed() override;
ArcMetricsService* arc_metrics_service_;
@@ -75,19 +72,17 @@ class ArcMetricsService
void ParseProcessList(std::vector<mojom::RunningAppProcessInfoPtr> processes);
// DBus callbacks.
- void OnArcStartTimeRetrieved(base::Optional<base::TimeTicks> arc_start_time);
+ void OnArcStartTimeRetrieved(std::vector<mojom::BootProgressEventPtr> events,
+ mojom::BootType boot_type,
+ base::Optional<base::TimeTicks> arc_start_time);
THREAD_CHECKER(thread_checker_);
ArcBridgeService* const arc_bridge_service_; // Owned by ArcServiceManager.
- mojo::Binding<mojom::MetricsHost> binding_;
-
ProcessObserver process_observer_;
base::RepeatingTimer timer_;
- base::TimeTicks arc_start_time_;
-
// Always keep this the last member of this class to make sure it's the
// first thing to be destructed.
base::WeakPtrFactory<ArcMetricsService> weak_ptr_factory_;
diff --git a/chromium/components/arc/metrics/arc_metrics_service_unittest.cc b/chromium/components/arc/metrics/arc_metrics_service_unittest.cc
new file mode 100644
index 00000000000..75fc712b10b
--- /dev/null
+++ b/chromium/components/arc/metrics/arc_metrics_service_unittest.cc
@@ -0,0 +1,228 @@
+// 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 "components/arc/metrics/arc_metrics_service.h"
+
+#include <algorithm>
+#include <array>
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "base/metrics/histogram_samples.h"
+#include "base/run_loop.h"
+#include "base/test/histogram_tester.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/fake_session_manager_client.h"
+#include "components/arc/arc_bridge_service.h"
+#include "components/arc/arc_service_manager.h"
+#include "components/arc/test/fake_arc_session.h"
+#include "components/arc/test/test_browser_context.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+namespace {
+
+// The event names the container sends to Chrome.
+constexpr std::array<const char*, 11> kBootEvents{
+ "boot_progress_start",
+ "boot_progress_preload_start",
+ "boot_progress_preload_end",
+ "boot_progress_system_run",
+ "boot_progress_pms_start",
+ "boot_progress_pms_system_scan_start",
+ "boot_progress_pms_data_scan_start",
+ "boot_progress_pms_scan_end",
+ "boot_progress_pms_ready",
+ "boot_progress_ams_ready",
+ "boot_progress_enable_screen"};
+
+ArcMetricsService* GetArcMetricsService(content::BrowserContext* context) {
+ ArcMetricsService::GetFactory()->SetTestingFactoryAndUse(
+ context,
+ [](content::BrowserContext* context) -> std::unique_ptr<KeyedService> {
+ return std::make_unique<ArcMetricsService>(
+ context, ArcServiceManager::Get()->arc_bridge_service());
+ });
+ return ArcMetricsService::GetForBrowserContext(context);
+}
+
+class ArcMetricsServiceTest : public testing::Test {
+ public:
+ ArcMetricsServiceTest()
+ : arc_service_manager_(std::make_unique<ArcServiceManager>()),
+ context_(std::make_unique<TestBrowserContext>()),
+ metrics_service_(GetArcMetricsService(context_.get())) {
+ chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
+ std::make_unique<chromeos::FakeSessionManagerClient>());
+ GetSessionManagerClient()->set_arc_available(true);
+ }
+
+ ~ArcMetricsServiceTest() override {
+ metrics_service_->Shutdown();
+ chromeos::DBusThreadManager::Shutdown();
+ }
+
+ ArcMetricsService* metrics_service() { return metrics_service_; }
+
+ protected:
+ void SetArcStartTimeInMs(uint64_t arc_start_time_in_ms) {
+ const base::TimeTicks arc_start_time =
+ base::TimeDelta::FromMilliseconds(arc_start_time_in_ms) +
+ base::TimeTicks();
+ GetSessionManagerClient()->set_arc_start_time(arc_start_time);
+ }
+
+ std::vector<mojom::BootProgressEventPtr> GetBootProgressEvents(
+ uint64_t start_in_ms,
+ uint64_t step_in_ms) {
+ std::vector<mojom::BootProgressEventPtr> events;
+ for (size_t i = 0; i < kBootEvents.size(); ++i) {
+ events.emplace_back(mojom::BootProgressEvent::New(
+ kBootEvents[i], start_in_ms + (step_in_ms * i)));
+ }
+ return events;
+ }
+
+ private:
+ chromeos::FakeSessionManagerClient* GetSessionManagerClient() {
+ return static_cast<chromeos::FakeSessionManagerClient*>(
+ chromeos::DBusThreadManager::Get()->GetSessionManagerClient());
+ }
+
+ content::TestBrowserThreadBundle thread_bundle_;
+ std::unique_ptr<ArcServiceManager> arc_service_manager_;
+ std::unique_ptr<TestBrowserContext> context_;
+
+ ArcMetricsService* const metrics_service_;
+
+ DISALLOW_COPY_AND_ASSIGN(ArcMetricsServiceTest);
+};
+
+// Tests that ReportBootProgress() actually records UMA stats.
+TEST_F(ArcMetricsServiceTest, ReportBootProgress_FirstBoot) {
+ // Start the full ARC container at t=10. Also set boot_progress_start to 10,
+ // boot_progress_preload_start to 11, and so on.
+ constexpr uint64_t kArcStartTimeMs = 10;
+ SetArcStartTimeInMs(kArcStartTimeMs);
+ std::vector<mojom::BootProgressEventPtr> events(
+ GetBootProgressEvents(kArcStartTimeMs, 1 /* step_in_ms */));
+
+ // Call ReportBootProgress() and then confirm that
+ // Arc.boot_progress_start.FirstBoot is recorded with 0 (ms),
+ // Arc.boot_progress_preload_start.FirstBoot is with 1 (ms), etc.
+ base::HistogramTester tester;
+ metrics_service()->ReportBootProgress(std::move(events),
+ mojom::BootType::FIRST_BOOT);
+ base::RunLoop().RunUntilIdle();
+ for (size_t i = 0; i < kBootEvents.size(); ++i) {
+ tester.ExpectUniqueSample(
+ std::string("Arc.") + kBootEvents[i] + ".FirstBoot", i,
+ 1 /* count of the sample */);
+ }
+ // Confirm that Arc.AndroidBootTime.FirstBoot is also recorded, and has the
+ // same value as "Arc.boot_progress_enable_screen.FirstBoot".
+ std::unique_ptr<base::HistogramSamples> samples =
+ tester.GetHistogramSamplesSinceCreation(
+ "Arc." + std::string(kBootEvents.back()) + ".FirstBoot");
+ ASSERT_TRUE(samples.get());
+ tester.ExpectUniqueSample("Arc.AndroidBootTime.FirstBoot", samples->sum(), 1);
+}
+
+// Does the same but with negative values and FIRST_BOOT_AFTER_UPDATE.
+TEST_F(ArcMetricsServiceTest, ReportBootProgress_FirstBootAfterUpdate) {
+ // Start the full ARC container at t=10. Also set boot_progress_start to 5,
+ // boot_progress_preload_start to 7, and so on. This can actually happen
+ // because the mini container can finish up to boot_progress_preload_end
+ // before the full container is started.
+ constexpr uint64_t kArcStartTimeMs = 10;
+ SetArcStartTimeInMs(kArcStartTimeMs);
+ std::vector<mojom::BootProgressEventPtr> events(
+ GetBootProgressEvents(kArcStartTimeMs - 5, 2 /* step_in_ms */));
+
+ // Call ReportBootProgress() and then confirm that
+ // Arc.boot_progress_start.FirstBoot is recorded with 0 (ms),
+ // Arc.boot_progress_preload_start.FirstBoot is with 0 (ms), etc. Unlike our
+ // performance dashboard where negative performance numbers are treated as-is,
+ // UMA treats them as zeros.
+ base::HistogramTester tester;
+ // This time, use mojom::BootType::FIRST_BOOT_AFTER_UPDATE.
+ metrics_service()->ReportBootProgress(
+ std::move(events), mojom::BootType::FIRST_BOOT_AFTER_UPDATE);
+ base::RunLoop().RunUntilIdle();
+ for (size_t i = 0; i < kBootEvents.size(); ++i) {
+ const int expected = std::max<int>(0, i * 2 - 5);
+ tester.ExpectUniqueSample(
+ std::string("Arc.") + kBootEvents[i] + ".FirstBootAfterUpdate",
+ expected, 1);
+ }
+ std::unique_ptr<base::HistogramSamples> samples =
+ tester.GetHistogramSamplesSinceCreation(
+ "Arc." + std::string(kBootEvents.back()) + ".FirstBootAfterUpdate");
+ ASSERT_TRUE(samples.get());
+ tester.ExpectUniqueSample("Arc.AndroidBootTime.FirstBootAfterUpdate",
+ samples->sum(), 1);
+}
+
+// Does the same but with REGULAR_BOOT.
+TEST_F(ArcMetricsServiceTest, ReportBootProgress_RegularBoot) {
+ constexpr uint64_t kArcStartTimeMs = 10;
+ SetArcStartTimeInMs(kArcStartTimeMs);
+ std::vector<mojom::BootProgressEventPtr> events(
+ GetBootProgressEvents(kArcStartTimeMs - 5, 2 /* step_in_ms */));
+
+ base::HistogramTester tester;
+ metrics_service()->ReportBootProgress(std::move(events),
+ mojom::BootType::REGULAR_BOOT);
+ base::RunLoop().RunUntilIdle();
+ for (size_t i = 0; i < kBootEvents.size(); ++i) {
+ const int expected = std::max<int>(0, i * 2 - 5);
+ tester.ExpectUniqueSample(
+ std::string("Arc.") + kBootEvents[i] + ".RegularBoot", expected, 1);
+ }
+ std::unique_ptr<base::HistogramSamples> samples =
+ tester.GetHistogramSamplesSinceCreation(
+ "Arc." + std::string(kBootEvents.back()) + ".RegularBoot");
+ ASSERT_TRUE(samples.get());
+ tester.ExpectUniqueSample("Arc.AndroidBootTime.RegularBoot", samples->sum(),
+ 1);
+}
+
+// Tests that no UMA is recorded when nothing is reported.
+TEST_F(ArcMetricsServiceTest, ReportBootProgress_EmptyResults) {
+ SetArcStartTimeInMs(100);
+ std::vector<mojom::BootProgressEventPtr> events; // empty
+
+ base::HistogramTester tester;
+ metrics_service()->ReportBootProgress(std::move(events),
+ mojom::BootType::FIRST_BOOT);
+ base::RunLoop().RunUntilIdle();
+ for (size_t i = 0; i < kBootEvents.size(); ++i) {
+ tester.ExpectTotalCount(std::string("Arc.") + kBootEvents[i] + ".FirstBoot",
+ 0);
+ }
+ tester.ExpectTotalCount("Arc.AndroidBootTime.FirstBoot", 0);
+}
+
+// Tests that no UMA is recorded when BootType is invalid.
+TEST_F(ArcMetricsServiceTest, ReportBootProgress_InvalidBootType) {
+ SetArcStartTimeInMs(100);
+ std::vector<mojom::BootProgressEventPtr> events(
+ GetBootProgressEvents(123, 456));
+ base::HistogramTester tester;
+ metrics_service()->ReportBootProgress(std::move(events),
+ mojom::BootType::UNKNOWN);
+ base::RunLoop().RunUntilIdle();
+ for (const std::string& suffix :
+ {".FirstBoot", ".FirstBootAfterUpdate", ".RegularBoot"}) {
+ tester.ExpectTotalCount("Arc." + (kBootEvents.front() + suffix), 0);
+ tester.ExpectTotalCount("Arc." + (kBootEvents.back() + suffix), 0);
+ tester.ExpectTotalCount("Arc.AndroidBootTime" + suffix, 0);
+ }
+}
+
+} // namespace
+} // namespace arc
diff --git a/chromium/components/arc/midis/arc_midis_bridge.cc b/chromium/components/arc/midis/arc_midis_bridge.cc
index 32bec549440..657fcc4e32b 100644
--- a/chromium/components/arc/midis/arc_midis_bridge.cc
+++ b/chromium/components/arc/midis/arc_midis_bridge.cc
@@ -49,26 +49,12 @@ ArcMidisBridge* ArcMidisBridge::GetForBrowserContext(
ArcMidisBridge::ArcMidisBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service)
- : arc_bridge_service_(bridge_service), binding_(this), weak_factory_(this) {
- arc_bridge_service_->midis()->AddObserver(this);
+ : arc_bridge_service_(bridge_service), weak_factory_(this) {
+ arc_bridge_service_->midis()->SetHost(this);
}
ArcMidisBridge::~ArcMidisBridge() {
- arc_bridge_service_->midis()->RemoveObserver(this);
-}
-
-void ArcMidisBridge::OnInstanceReady() {
- DVLOG(1) << "ArcMidisBridge::OnInstanceReady() called.";
- mojom::MidisInstance* midis_instance =
- ARC_GET_INSTANCE_FOR_METHOD(arc_bridge_service_->midis(), Init);
- DCHECK(midis_instance);
-
- DVLOG(1) << "Calling Init on the other side of MidisInstance.";
- mojom::MidisHostPtr host_proxy;
- binding_.Bind(mojo::MakeRequest(&host_proxy));
- midis_instance->Init(std::move(host_proxy));
- binding_.set_connection_error_handler(base::Bind(
- &mojo::Binding<MidisHost>::Close, base::Unretained(&binding_)));
+ arc_bridge_service_->midis()->SetHost(nullptr);
}
void ArcMidisBridge::OnBootstrapMojoConnection(
diff --git a/chromium/components/arc/midis/arc_midis_bridge.h b/chromium/components/arc/midis/arc_midis_bridge.h
index b08d0fc5a08..21bbf23c662 100644
--- a/chromium/components/arc/midis/arc_midis_bridge.h
+++ b/chromium/components/arc/midis/arc_midis_bridge.h
@@ -11,9 +11,7 @@
#include "base/macros.h"
#include "components/arc/common/midis.mojom.h"
-#include "components/arc/instance_holder.h"
#include "components/keyed_service/core/keyed_service.h"
-#include "mojo/public/cpp/bindings/binding.h"
namespace content {
class BrowserContext;
@@ -24,7 +22,6 @@ namespace arc {
class ArcBridgeService;
class ArcMidisBridge : public KeyedService,
- public InstanceHolder<mojom::MidisInstance>::Observer,
public mojom::MidisHost {
public:
// Returns singleton instance for the given BrowserContext,
@@ -35,9 +32,6 @@ class ArcMidisBridge : public KeyedService,
ArcBridgeService* bridge_service);
~ArcMidisBridge() override;
- // Overridden from InstanceHolder<mojom::MidisInstance>::Observer:
- void OnInstanceReady() override;
-
// Midis Mojo host interface
void Connect(mojom::MidisServerRequest request,
mojom::MidisClientPtr client_ptr) override;
@@ -48,7 +42,6 @@ class ArcMidisBridge : public KeyedService,
bool result);
ArcBridgeService* const arc_bridge_service_; // Owned by ArcServiceManager.
- mojo::Binding<mojom::MidisHost> binding_;
mojom::MidisHostPtr midis_host_ptr_;
// WeakPtrFactory to use for callbacks.
diff --git a/chromium/components/arc/net/arc_net_host_impl.cc b/chromium/components/arc/net/arc_net_host_impl.cc
index e6f3e4f7366..50f464a4fd4 100644
--- a/chromium/components/arc/net/arc_net_host_impl.cc
+++ b/chromium/components/arc/net/arc_net_host_impl.cc
@@ -73,14 +73,13 @@ arc::mojom::SecurityType TranslateONCWifiSecurityType(
true /* required */);
if (type == onc::wifi::kWEP_PSK)
return arc::mojom::SecurityType::WEP_PSK;
- else if (type == onc::wifi::kWEP_8021X)
+ if (type == onc::wifi::kWEP_8021X)
return arc::mojom::SecurityType::WEP_8021X;
- else if (type == onc::wifi::kWPA_PSK)
+ if (type == onc::wifi::kWPA_PSK)
return arc::mojom::SecurityType::WPA_PSK;
- else if (type == onc::wifi::kWPA_EAP)
+ if (type == onc::wifi::kWPA_EAP)
return arc::mojom::SecurityType::WPA_EAP;
- else
- return arc::mojom::SecurityType::NONE;
+ return arc::mojom::SecurityType::NONE;
}
arc::mojom::WiFiPtr TranslateONCWifi(const base::DictionaryValue* dict) {
@@ -171,7 +170,7 @@ arc::mojom::ConnectionStateType TranslateONCConnectionState(
if (connection_state == onc::connection_state::kConnected)
return arc::mojom::ConnectionStateType::CONNECTED;
- else if (connection_state == onc::connection_state::kConnecting)
+ if (connection_state == onc::connection_state::kConnecting)
return arc::mojom::ConnectionStateType::CONNECTING;
return arc::mojom::ConnectionStateType::NOT_CONNECTED;
}
@@ -362,7 +361,8 @@ ArcNetHostImpl* ArcNetHostImpl::GetForBrowserContext(
ArcNetHostImpl::ArcNetHostImpl(content::BrowserContext* context,
ArcBridgeService* bridge_service)
- : arc_bridge_service_(bridge_service), binding_(this), weak_factory_(this) {
+ : arc_bridge_service_(bridge_service), weak_factory_(this) {
+ arc_bridge_service_->net()->SetHost(this);
arc_bridge_service_->net()->AddObserver(this);
}
@@ -373,18 +373,12 @@ ArcNetHostImpl::~ArcNetHostImpl() {
GetNetworkConnectionHandler()->RemoveObserver(this);
}
arc_bridge_service_->net()->RemoveObserver(this);
+ arc_bridge_service_->net()->SetHost(nullptr);
}
-void ArcNetHostImpl::OnInstanceReady() {
+void ArcNetHostImpl::OnConnectionReady() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- mojom::NetHostPtr host;
- binding_.Bind(MakeRequest(&host));
- auto* instance =
- ARC_GET_INSTANCE_FOR_METHOD(arc_bridge_service_->net(), Init);
- DCHECK(instance);
- instance->Init(std::move(host));
-
if (chromeos::NetworkHandler::IsInitialized()) {
GetStateHandler()->AddObserver(this, FROM_HERE);
GetNetworkConnectionHandler()->AddObserver(this);
@@ -404,7 +398,7 @@ void ArcNetHostImpl::OnInstanceReady() {
}
}
-void ArcNetHostImpl::OnInstanceClosed() {
+void ArcNetHostImpl::OnConnectionClosed() {
if (!observing_network_state_)
return;
@@ -599,9 +593,8 @@ bool ArcNetHostImpl::GetNetworkPathFromGuid(const std::string& guid,
if (cached_guid_ == guid) {
*path = cached_service_path_;
return true;
- } else {
- return false;
}
+ return false;
}
void ArcNetHostImpl::ForgetNetwork(const std::string& guid,
@@ -700,21 +693,21 @@ void ArcNetHostImpl::ScanCompleted(const chromeos::DeviceState* /*unused*/) {
net_instance->ScanCompleted();
}
-void ArcNetHostImpl::GetDefaultNetwork(GetDefaultNetworkCallback callback) {
- const chromeos::NetworkState* default_network;
-
- // Expose Chrome OS VPNs to Android, but if ARC VPN is active, only expose
- // the underlying physical interface.
+const chromeos::NetworkState* ArcNetHostImpl::GetDefaultNetworkFromChrome() {
+ // If an Android VPN is connected, report the underlying physical
+ // connection only. Never tell Android about its own VPN.
+ // If a Chrome OS VPN is connected, report the Chrome OS VPN as the
+ // default connection.
if (arc_vpn_service_path_.empty()) {
- default_network = GetStateHandler()->DefaultNetwork();
- } else {
- default_network = GetStateHandler()->FirstNetworkByType(
- chromeos::NetworkTypePattern::NonVirtual());
+ return GetShillBackedNetwork(GetStateHandler()->DefaultNetwork());
}
- // Some network types are not backed by Shill; make sure to pass a Shill-
- // backed network to ARC to ensure that it can use its network connection.
- default_network = GetShillBackedNetwork(default_network);
+ return GetShillBackedNetwork(GetStateHandler()->ConnectedNetworkByType(
+ chromeos::NetworkTypePattern::NonVirtual()));
+}
+
+void ArcNetHostImpl::GetDefaultNetwork(GetDefaultNetworkCallback callback) {
+ const chromeos::NetworkState* default_network = GetDefaultNetworkFromChrome();
if (!default_network) {
VLOG(1) << "GetDefaultNetwork: no default network";
@@ -746,20 +739,10 @@ void ArcNetHostImpl::DefaultNetworkSuccessCallback(
TranslateONCConfiguration(&dictionary));
}
-void ArcNetHostImpl::DefaultNetworkChanged(
- const chromeos::NetworkState* network) {
- // If an ARC VPN is connected, the default network will point to the
- // ARC VPN but we cannot tell ARC about that. ARC needs to continue
- // believing that the current physical network is the default network.
- // The medium term fix for this is go/arc-multinet which will report
- // status for each interface separately.
- if (!arc_vpn_service_path_.empty())
- return;
+void ArcNetHostImpl::UpdateDefaultNetwork() {
+ const chromeos::NetworkState* default_network = GetDefaultNetworkFromChrome();
- const chromeos::NetworkState* shill_backed_network =
- GetShillBackedNetwork(network);
-
- if (!shill_backed_network) {
+ if (!default_network) {
VLOG(1) << "No default network";
auto* net_instance = ARC_GET_INSTANCE_FOR_METHOD(arc_bridge_service_->net(),
DefaultNetworkChanged);
@@ -768,15 +751,21 @@ void ArcNetHostImpl::DefaultNetworkChanged(
return;
}
- VLOG(1) << "New default network: " << shill_backed_network->path();
+ VLOG(1) << "New default network: " << default_network->path() << " ("
+ << default_network->type() << ")";
std::string user_id_hash = chromeos::LoginState::Get()->primary_user_hash();
GetManagedConfigurationHandler()->GetProperties(
- user_id_hash, shill_backed_network->path(),
+ user_id_hash, default_network->path(),
base::Bind(&ArcNetHostImpl::DefaultNetworkSuccessCallback,
weak_factory_.GetWeakPtr()),
base::Bind(&DefaultNetworkFailureCallback));
}
+void ArcNetHostImpl::DefaultNetworkChanged(
+ const chromeos::NetworkState* network) {
+ UpdateDefaultNetwork();
+}
+
void ArcNetHostImpl::DeviceListChanged() {
auto* net_instance = ARC_GET_INSTANCE_FOR_METHOD(arc_bridge_service_->net(),
WifiEnabledStateChanged);
@@ -961,6 +950,12 @@ void ArcNetHostImpl::DisconnectRequested(const std::string& service_path) {
void ArcNetHostImpl::NetworkConnectionStateChanged(
const chromeos::NetworkState* network) {
+ // DefaultNetworkChanged() won't be invoked if an ARC VPN is the default
+ // network and the underlying physical connection changed, so check for
+ // that condition here. This is invoked any time any service state
+ // changes.
+ UpdateDefaultNetwork();
+
const chromeos::NetworkState* shill_backed_network =
GetShillBackedNetwork(network);
if (!shill_backed_network)
@@ -979,6 +974,14 @@ void ArcNetHostImpl::NetworkConnectionStateChanged(
DisconnectArcVpn();
}
+void ArcNetHostImpl::NetworkListChanged() {
+ // This is invoked any time the list of services is reordered or changed.
+ // During the transition when a new service comes online, it will
+ // temporarily be ranked below "inferior" services. This callback
+ // informs us that shill's ordering has been updated.
+ UpdateDefaultNetwork();
+}
+
void ArcNetHostImpl::OnShuttingDown() {
DCHECK(observing_network_state_);
GetStateHandler()->RemoveObserver(this, FROM_HERE);
diff --git a/chromium/components/arc/net/arc_net_host_impl.h b/chromium/components/arc/net/arc_net_host_impl.h
index 51f6a304b7c..fdc133d97d2 100644
--- a/chromium/components/arc/net/arc_net_host_impl.h
+++ b/chromium/components/arc/net/arc_net_host_impl.h
@@ -19,9 +19,8 @@
#include "chromeos/network/network_connection_observer.h"
#include "chromeos/network/network_state_handler_observer.h"
#include "components/arc/common/net.mojom.h"
-#include "components/arc/instance_holder.h"
+#include "components/arc/connection_observer.h"
#include "components/keyed_service/core/keyed_service.h"
-#include "mojo/public/cpp/bindings/binding.h"
namespace content {
class BrowserContext;
@@ -33,7 +32,7 @@ class ArcBridgeService;
// Private implementation of ArcNetHost.
class ArcNetHostImpl : public KeyedService,
- public InstanceHolder<mojom::NetInstance>::Observer,
+ public ConnectionObserver<mojom::NetInstance>,
public chromeos::NetworkConnectionObserver,
public chromeos::NetworkStateHandlerObserver,
public mojom::NetHost {
@@ -87,17 +86,20 @@ class ArcNetHostImpl : public KeyedService,
void DefaultNetworkChanged(const chromeos::NetworkState* network) override;
void NetworkConnectionStateChanged(
const chromeos::NetworkState* network) override;
+ void NetworkListChanged() override;
void DeviceListChanged() override;
void GetDefaultNetwork(GetDefaultNetworkCallback callback) override;
// Overriden from chromeos::NetworkConnectionObserver.
void DisconnectRequested(const std::string& service_path) override;
- // Overridden from ArcBridgeService::InterfaceObserver<mojom::NetInstance>:
- void OnInstanceReady() override;
- void OnInstanceClosed() override;
+ // Overridden from ConnectionObserver<mojom::NetInstance>:
+ void OnConnectionReady() override;
+ void OnConnectionClosed() override;
private:
+ const chromeos::NetworkState* GetDefaultNetworkFromChrome();
+ void UpdateDefaultNetwork();
void DefaultNetworkSuccessCallback(const std::string& service_path,
const base::DictionaryValue& dictionary);
@@ -154,7 +156,6 @@ class ArcNetHostImpl : public KeyedService,
std::string arc_vpn_service_path_;
THREAD_CHECKER(thread_checker_);
- mojo::Binding<mojom::NetHost> binding_;
base::WeakPtrFactory<ArcNetHostImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ArcNetHostImpl);
diff --git a/chromium/components/arc/obb_mounter/arc_obb_mounter_bridge.cc b/chromium/components/arc/obb_mounter/arc_obb_mounter_bridge.cc
index 5ad2f539eb7..3764676ebf4 100644
--- a/chromium/components/arc/obb_mounter/arc_obb_mounter_bridge.cc
+++ b/chromium/components/arc/obb_mounter/arc_obb_mounter_bridge.cc
@@ -46,21 +46,12 @@ ArcObbMounterBridge* ArcObbMounterBridge::GetForBrowserContext(
ArcObbMounterBridge::ArcObbMounterBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service)
- : arc_bridge_service_(bridge_service), binding_(this) {
- arc_bridge_service_->obb_mounter()->AddObserver(this);
+ : arc_bridge_service_(bridge_service) {
+ arc_bridge_service_->obb_mounter()->SetHost(this);
}
ArcObbMounterBridge::~ArcObbMounterBridge() {
- arc_bridge_service_->obb_mounter()->RemoveObserver(this);
-}
-
-void ArcObbMounterBridge::OnInstanceReady() {
- mojom::ObbMounterInstance* obb_mounter_instance =
- ARC_GET_INSTANCE_FOR_METHOD(arc_bridge_service_->obb_mounter(), Init);
- DCHECK(obb_mounter_instance);
- mojom::ObbMounterHostPtr host_proxy;
- binding_.Bind(mojo::MakeRequest(&host_proxy));
- obb_mounter_instance->Init(std::move(host_proxy));
+ arc_bridge_service_->obb_mounter()->SetHost(nullptr);
}
void ArcObbMounterBridge::MountObb(const std::string& obb_file,
diff --git a/chromium/components/arc/obb_mounter/arc_obb_mounter_bridge.h b/chromium/components/arc/obb_mounter/arc_obb_mounter_bridge.h
index 571a83e0a62..8756ab62ebf 100644
--- a/chromium/components/arc/obb_mounter/arc_obb_mounter_bridge.h
+++ b/chromium/components/arc/obb_mounter/arc_obb_mounter_bridge.h
@@ -9,9 +9,7 @@
#include "base/macros.h"
#include "components/arc/common/obb_mounter.mojom.h"
-#include "components/arc/instance_holder.h"
#include "components/keyed_service/core/keyed_service.h"
-#include "mojo/public/cpp/bindings/binding.h"
namespace content {
class BrowserContext;
@@ -24,7 +22,6 @@ class ArcBridgeService;
// This class handles OBB mount/unmount requests from Android.
class ArcObbMounterBridge
: public KeyedService,
- public InstanceHolder<mojom::ObbMounterInstance>::Observer,
public mojom::ObbMounterHost {
public:
// Returns singleton instance for the given BrowserContext,
@@ -36,9 +33,6 @@ class ArcObbMounterBridge
ArcBridgeService* bridge_service);
~ArcObbMounterBridge() override;
- // InstanceHolder<mojom::ObbMounterInstance>::Observer overrides:
- void OnInstanceReady() override;
-
// mojom::ObbMounterHost overrides:
void MountObb(const std::string& obb_file,
const std::string& target_path,
@@ -50,8 +44,6 @@ class ArcObbMounterBridge
private:
ArcBridgeService* const arc_bridge_service_; // Owned by ArcServiceManager.
- mojo::Binding<mojom::ObbMounterHost> binding_;
-
DISALLOW_COPY_AND_ASSIGN(ArcObbMounterBridge);
};
diff --git a/chromium/components/arc/power/DEPS b/chromium/components/arc/power/DEPS
index ac7ae6d3982..2a902196e7c 100644
--- a/chromium/components/arc/power/DEPS
+++ b/chromium/components/arc/power/DEPS
@@ -1,4 +1,7 @@
include_rules = [
"+ash/shell.h",
+ "+content/public/common/service_manager_connection.h",
"+ui/display/manager/chromeos",
+ "+services/device/public",
+ "+services/service_manager/public",
]
diff --git a/chromium/components/arc/power/arc_power_bridge.cc b/chromium/components/arc/power/arc_power_bridge.cc
index ef6a083460d..b584cd6135c 100644
--- a/chromium/components/arc/power/arc_power_bridge.cc
+++ b/chromium/components/arc/power/arc_power_bridge.cc
@@ -15,6 +15,11 @@
#include "components/arc/arc_bridge_service.h"
#include "components/arc/arc_browser_context_keyed_service_factory_base.h"
#include "components/arc/arc_service_manager.h"
+#include "content/public/common/service_manager_connection.h"
+#include "services/device/public/interfaces/constants.mojom.h"
+#include "services/device/public/interfaces/wake_lock.mojom.h"
+#include "services/device/public/interfaces/wake_lock_provider.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
namespace arc {
namespace {
@@ -45,6 +50,71 @@ class ArcPowerBridgeFactory
} // namespace
+// WakeLockRequestor requests a wake lock from the device service in response
+// to wake lock requests of a given type from Android. A count is kept of
+// outstanding Android requests so that only a single actual wake lock is used.
+class ArcPowerBridge::WakeLockRequestor {
+ public:
+ WakeLockRequestor(device::mojom::WakeLockType type,
+ service_manager::Connector* connector)
+ : type_(type), connector_(connector) {}
+ ~WakeLockRequestor() = default;
+
+ // Increments the number of outstanding requests from Android and requests a
+ // wake lock from the device service if this is the only request.
+ void AddRequest() {
+ num_android_requests_++;
+ if (num_android_requests_ > 1)
+ return;
+
+ // Initialize |wake_lock_| if this is the first time we're using it.
+ if (!wake_lock_) {
+ device::mojom::WakeLockProviderPtr provider;
+ connector_->BindInterface(device::mojom::kServiceName,
+ mojo::MakeRequest(&provider));
+ provider->GetWakeLockWithoutContext(
+ type_, device::mojom::WakeLockReason::kOther, "ARC",
+ mojo::MakeRequest(&wake_lock_));
+ }
+
+ wake_lock_->RequestWakeLock();
+ }
+
+ // Decrements the number of outstanding Android requests. Cancels the device
+ // service wake lock when the request count hits zero.
+ void RemoveRequest() {
+ DCHECK_GT(num_android_requests_, 0);
+ num_android_requests_--;
+ if (num_android_requests_ >= 1)
+ return;
+
+ DCHECK(wake_lock_);
+ wake_lock_->CancelWakeLock();
+ }
+
+ // Runs the message loop until replies have been received for all pending
+ // requests on |wake_lock_|.
+ void FlushForTesting() {
+ if (wake_lock_)
+ wake_lock_.FlushForTesting();
+ }
+
+ private:
+ // Type of wake lock to request.
+ device::mojom::WakeLockType type_;
+
+ // Used to get services. Not owned.
+ service_manager::Connector* const connector_ = nullptr;
+
+ // Number of outstanding Android requests.
+ int num_android_requests_ = 0;
+
+ // Lazily initialized in response to first request.
+ device::mojom::WakeLockPtr wake_lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(WakeLockRequestor);
+};
+
// static
ArcPowerBridge* ArcPowerBridge::GetForBrowserContext(
content::BrowserContext* context) {
@@ -54,23 +124,29 @@ ArcPowerBridge* ArcPowerBridge::GetForBrowserContext(
ArcPowerBridge::ArcPowerBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service)
: arc_bridge_service_(bridge_service),
- binding_(this),
weak_ptr_factory_(this) {
+ arc_bridge_service_->power()->SetHost(this);
arc_bridge_service_->power()->AddObserver(this);
}
ArcPowerBridge::~ArcPowerBridge() {
- ReleaseAllDisplayWakeLocks();
arc_bridge_service_->power()->RemoveObserver(this);
+ arc_bridge_service_->power()->SetHost(nullptr);
}
-void ArcPowerBridge::OnInstanceReady() {
- mojom::PowerInstance* power_instance =
- ARC_GET_INSTANCE_FOR_METHOD(arc_bridge_service_->power(), Init);
- DCHECK(power_instance);
- mojom::PowerHostPtr host_proxy;
- binding_.Bind(mojo::MakeRequest(&host_proxy));
- power_instance->Init(std::move(host_proxy));
+bool ArcPowerBridge::TriggerNotifyBrightnessTimerForTesting() {
+ if (!notify_brightness_timer_.IsRunning())
+ return false;
+ notify_brightness_timer_.user_task().Run();
+ return true;
+}
+
+void ArcPowerBridge::FlushWakeLocksForTesting() {
+ for (const auto& it : wake_lock_requestors_)
+ it.second->FlushForTesting();
+}
+
+void ArcPowerBridge::OnConnectionReady() {
// TODO(mash): Support this functionality without ash::Shell access in Chrome.
if (ash::Shell::HasInstance())
ash::Shell::Get()->display_configurator()->AddObserver(this);
@@ -79,20 +155,21 @@ void ArcPowerBridge::OnInstanceReady() {
chromeos::DBusThreadManager::Get()
->GetPowerManagerClient()
->GetScreenBrightnessPercent(
- base::Bind(&ArcPowerBridge::UpdateAndroidScreenBrightness,
- weak_ptr_factory_.GetWeakPtr()));
+ base::BindOnce(&ArcPowerBridge::OnGetScreenBrightnessPercent,
+ weak_ptr_factory_.GetWeakPtr()));
}
-void ArcPowerBridge::OnInstanceClosed() {
+void ArcPowerBridge::OnConnectionClosed() {
// TODO(mash): Support this functionality without ash::Shell access in Chrome.
if (ash::Shell::HasInstance())
ash::Shell::Get()->display_configurator()->RemoveObserver(this);
chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
RemoveObserver(this);
- ReleaseAllDisplayWakeLocks();
+ wake_lock_requestors_.clear();
}
-void ArcPowerBridge::SuspendImminent() {
+void ArcPowerBridge::SuspendImminent(
+ power_manager::SuspendImminent::Reason reason) {
mojom::PowerInstance* power_instance =
ARC_GET_INSTANCE_FOR_METHOD(arc_bridge_service_->power(), Suspend);
if (!power_instance)
@@ -140,50 +217,39 @@ void ArcPowerBridge::OnPowerStateChanged(
}
void ArcPowerBridge::OnAcquireDisplayWakeLock(mojom::DisplayWakeLockType type) {
- if (!chromeos::PowerPolicyController::IsInitialized()) {
- LOG(WARNING) << "PowerPolicyController is not available";
- return;
- }
- chromeos::PowerPolicyController* controller =
- chromeos::PowerPolicyController::Get();
-
- int wake_lock_id = -1;
switch (type) {
case mojom::DisplayWakeLockType::BRIGHT:
- wake_lock_id = controller->AddScreenWakeLock(
- chromeos::PowerPolicyController::REASON_OTHER, "ARC");
+ GetWakeLockRequestor(device::mojom::WakeLockType::kPreventDisplaySleep)
+ ->AddRequest();
break;
case mojom::DisplayWakeLockType::DIM:
- wake_lock_id = controller->AddDimWakeLock(
- chromeos::PowerPolicyController::REASON_OTHER, "ARC");
+ GetWakeLockRequestor(
+ device::mojom::WakeLockType::kPreventDisplaySleepAllowDimming)
+ ->AddRequest();
break;
default:
LOG(WARNING) << "Tried to take invalid wake lock type "
<< static_cast<int>(type);
return;
}
- wake_locks_.insert(std::make_pair(type, wake_lock_id));
}
void ArcPowerBridge::OnReleaseDisplayWakeLock(mojom::DisplayWakeLockType type) {
- if (!chromeos::PowerPolicyController::IsInitialized()) {
- LOG(WARNING) << "PowerPolicyController is not available";
- return;
- }
- chromeos::PowerPolicyController* controller =
- chromeos::PowerPolicyController::Get();
-
- // From the perspective of the PowerPolicyController, all wake locks
- // of a given type are equivalent, so it doesn't matter which one
- // we pass to the controller here.
- auto it = wake_locks_.find(type);
- if (it == wake_locks_.end()) {
- LOG(WARNING) << "Tried to release wake lock of type "
- << static_cast<int>(type) << " when none were taken";
- return;
+ switch (type) {
+ case mojom::DisplayWakeLockType::BRIGHT:
+ GetWakeLockRequestor(device::mojom::WakeLockType::kPreventDisplaySleep)
+ ->RemoveRequest();
+ break;
+ case mojom::DisplayWakeLockType::DIM:
+ GetWakeLockRequestor(
+ device::mojom::WakeLockType::kPreventDisplaySleepAllowDimming)
+ ->RemoveRequest();
+ break;
+ default:
+ LOG(WARNING) << "Tried to take invalid wake lock type "
+ << static_cast<int>(type);
+ return;
}
- controller->RemoveWakeLock(it->second);
- wake_locks_.erase(it);
}
void ArcPowerBridge::IsDisplayOn(IsDisplayOnCallback callback) {
@@ -200,18 +266,32 @@ void ArcPowerBridge::OnScreenBrightnessUpdateRequest(double percent) {
->SetScreenBrightnessPercent(percent, true);
}
-void ArcPowerBridge::ReleaseAllDisplayWakeLocks() {
- if (!chromeos::PowerPolicyController::IsInitialized()) {
- LOG(WARNING) << "PowerPolicyController is not available";
- return;
- }
- chromeos::PowerPolicyController* controller =
- chromeos::PowerPolicyController::Get();
+ArcPowerBridge::WakeLockRequestor* ArcPowerBridge::GetWakeLockRequestor(
+ device::mojom::WakeLockType type) {
+ auto it = wake_lock_requestors_.find(type);
+ if (it != wake_lock_requestors_.end())
+ return it->second.get();
+
+ service_manager::Connector* connector =
+ connector_for_test_
+ ? connector_for_test_
+ : content::ServiceManagerConnection::GetForProcess()->GetConnector();
+ DCHECK(connector);
- for (const auto& it : wake_locks_) {
- controller->RemoveWakeLock(it.second);
+ it = wake_lock_requestors_
+ .emplace(type, std::make_unique<WakeLockRequestor>(type, connector))
+ .first;
+ return it->second.get();
+}
+
+void ArcPowerBridge::OnGetScreenBrightnessPercent(
+ base::Optional<double> percent) {
+ if (!percent.has_value()) {
+ LOG(ERROR)
+ << "PowerManagerClient::GetScreenBrightnessPercent reports an error";
+ return;
}
- wake_locks_.clear();
+ UpdateAndroidScreenBrightness(percent.value());
}
void ArcPowerBridge::UpdateAndroidScreenBrightness(double percent) {
diff --git a/chromium/components/arc/power/arc_power_bridge.h b/chromium/components/arc/power/arc_power_bridge.h
index 5aab1655c6f..31894c4b53b 100644
--- a/chromium/components/arc/power/arc_power_bridge.h
+++ b/chromium/components/arc/power/arc_power_bridge.h
@@ -6,19 +6,25 @@
#define COMPONENTS_ARC_POWER_ARC_POWER_BRIDGE_H_
#include <map>
+#include <memory>
#include "base/macros.h"
+#include "base/optional.h"
#include "chromeos/dbus/power_manager_client.h"
#include "components/arc/common/power.mojom.h"
-#include "components/arc/instance_holder.h"
+#include "components/arc/connection_observer.h"
#include "components/keyed_service/core/keyed_service.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "services/device/public/interfaces/wake_lock.mojom.h"
#include "ui/display/manager/chromeos/display_configurator.h"
namespace content {
class BrowserContext;
} // namespace content
+namespace service_manager {
+class Connector;
+} // namespace service_manager
+
namespace arc {
class ArcBridgeService;
@@ -26,7 +32,7 @@ class ArcBridgeService;
// ARC Power Client sets power management policy based on requests from
// ARC instances.
class ArcPowerBridge : public KeyedService,
- public InstanceHolder<mojom::PowerInstance>::Observer,
+ public ConnectionObserver<mojom::PowerInstance>,
public chromeos::PowerManagerClient::Observer,
public display::DisplayConfigurator::Observer,
public mojom::PowerHost {
@@ -39,12 +45,24 @@ class ArcPowerBridge : public KeyedService,
ArcBridgeService* bridge_service);
~ArcPowerBridge() override;
- // InstanceHolder<mojom::PowerInstance>::Observer overrides.
- void OnInstanceReady() override;
- void OnInstanceClosed() override;
+ void set_connector_for_test(service_manager::Connector* connector) {
+ connector_for_test_ = connector;
+ }
+
+ // If |notify_brightness_timer_| is set, runs it and returns true. Returns
+ // false otherwise.
+ bool TriggerNotifyBrightnessTimerForTesting() WARN_UNUSED_RESULT;
+
+ // Runs the message loop until replies have been received for all pending
+ // device service requests in |wake_lock_requestors_|.
+ void FlushWakeLocksForTesting();
+
+ // ConnectionObserver<mojom::PowerInstance> overrides.
+ void OnConnectionReady() override;
+ void OnConnectionClosed() override;
// chromeos::PowerManagerClient::Observer overrides.
- void SuspendImminent() override;
+ void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
void SuspendDone(const base::TimeDelta& sleep_duration) override;
void BrightnessChanged(int level, bool user_initiated) override;
@@ -58,15 +76,25 @@ class ArcPowerBridge : public KeyedService,
void OnScreenBrightnessUpdateRequest(double percent) override;
private:
- void ReleaseAllDisplayWakeLocks();
+ class WakeLockRequestor;
+
+ // Returns the WakeLockRequestor for |type|, creating one if needed.
+ WakeLockRequestor* GetWakeLockRequestor(device::mojom::WakeLockType type);
+
+ // Called on PowerManagerClient::GetScreenBrightnessPercent() completion.
+ void OnGetScreenBrightnessPercent(base::Optional<double> percent);
+
void UpdateAndroidScreenBrightness(double percent);
ArcBridgeService* const arc_bridge_service_; // Owned by ArcServiceManager.
- mojo::Binding<mojom::PowerHost> binding_;
- // Stores a mapping of type -> wake lock ID for all wake locks
- // held by ARC.
- std::multimap<mojom::DisplayWakeLockType, int> wake_locks_;
+ // If non-null, used instead of the process-wide connector to fetch services.
+ service_manager::Connector* connector_for_test_ = nullptr;
+
+ // Used to track Android wake lock requests and acquire and release device
+ // service wake locks as needed.
+ std::map<device::mojom::WakeLockType, std::unique_ptr<WakeLockRequestor>>
+ wake_lock_requestors_;
// Last time that the power manager notified about a brightness change.
base::TimeTicks last_brightness_changed_time_;
diff --git a/chromium/components/arc/power/arc_power_bridge_unittest.cc b/chromium/components/arc/power/arc_power_bridge_unittest.cc
new file mode 100644
index 00000000000..e592c28fa6e
--- /dev/null
+++ b/chromium/components/arc/power/arc_power_bridge_unittest.cc
@@ -0,0 +1,235 @@
+// 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 "components/arc/power/arc_power_bridge.h"
+
+#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power_manager/suspend.pb.h"
+#include "components/arc/arc_bridge_service.h"
+#include "components/arc/common/power.mojom.h"
+#include "components/arc/test/fake_power_instance.h"
+#include "content/public/common/service_manager_connection.h"
+#include "services/device/public/cpp/test/test_wake_lock_provider.h"
+#include "services/service_manager/public/cpp/test/test_connector_factory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+
+using device::mojom::WakeLockType;
+
+class ArcPowerBridgeTest : public testing::Test {
+ public:
+ // Initial screen brightness percent for the Chrome OS power manager.
+ static constexpr double kInitialBrightness = 100.0;
+
+ ArcPowerBridgeTest() {
+ chromeos::DBusThreadManager::Initialize();
+ power_manager_client_ = static_cast<chromeos::FakePowerManagerClient*>(
+ chromeos::DBusThreadManager::Get()->GetPowerManagerClient());
+ power_manager_client_->set_screen_brightness_percent(kInitialBrightness);
+
+ auto wake_lock_provider_ptr =
+ std::make_unique<device::TestWakeLockProvider>();
+ wake_lock_provider_ = wake_lock_provider_ptr.get();
+
+ connector_factory_ =
+ std::make_unique<service_manager::TestConnectorFactory>(
+ std::move(wake_lock_provider_ptr));
+ connector_ = connector_factory_->CreateConnector();
+
+ bridge_service_ = std::make_unique<ArcBridgeService>();
+ power_bridge_ = std::make_unique<ArcPowerBridge>(nullptr /* context */,
+ bridge_service_.get());
+ power_bridge_->set_connector_for_test(connector_.get());
+ CreatePowerInstance();
+ }
+
+ ~ArcPowerBridgeTest() override {
+ DestroyPowerInstance();
+ power_bridge_.reset();
+ chromeos::DBusThreadManager::Shutdown();
+ }
+
+ protected:
+ // Creates a FakePowerInstance for |bridge_service_|. This results in
+ // ArcPowerBridge::OnInstanceReady() being called.
+ void CreatePowerInstance() {
+ power_instance_ = std::make_unique<FakePowerInstance>();
+ bridge_service_->power()->SetInstance(power_instance_.get(),
+ mojom::PowerInstance::Version_);
+ }
+
+ // Destroys the FakePowerInstance. This results in
+ // ArcPowerBridge::OnInstanceClosed() being called.
+ void DestroyPowerInstance() {
+ bridge_service_->power()->SetInstance(nullptr, 0);
+ power_instance_.reset();
+ }
+
+ // Acquires or releases a display wake lock of type |type|.
+ void AcquireDisplayWakeLock(mojom::DisplayWakeLockType type) {
+ power_bridge_->OnAcquireDisplayWakeLock(type);
+ power_bridge_->FlushWakeLocksForTesting();
+ }
+ void ReleaseDisplayWakeLock(mojom::DisplayWakeLockType type) {
+ power_bridge_->OnReleaseDisplayWakeLock(type);
+ power_bridge_->FlushWakeLocksForTesting();
+ }
+
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+
+ std::unique_ptr<service_manager::TestConnectorFactory> connector_factory_;
+ std::unique_ptr<service_manager::Connector> connector_;
+ device::TestWakeLockProvider* wake_lock_provider_;
+
+ chromeos::FakePowerManagerClient* power_manager_client_; // Not owned.
+
+ std::unique_ptr<ArcBridgeService> bridge_service_;
+ std::unique_ptr<FakePowerInstance> power_instance_;
+ std::unique_ptr<ArcPowerBridge> power_bridge_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ArcPowerBridgeTest);
+};
+
+TEST_F(ArcPowerBridgeTest, SuspendAndResume) {
+ ASSERT_EQ(0, power_instance_->num_suspend());
+ ASSERT_EQ(0, power_instance_->num_resume());
+
+ // When powerd notifies Chrome that the system is about to suspend,
+ // ArcPowerBridge should notify Android and take a suspend readiness callback
+ // to defer the suspend operation.
+ power_manager_client_->SendSuspendImminent(
+ power_manager::SuspendImminent_Reason_OTHER);
+ EXPECT_EQ(1, power_instance_->num_suspend());
+ EXPECT_EQ(0, power_instance_->num_resume());
+ EXPECT_EQ(1, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
+
+ // Simulate Android acknowledging that it's ready for the system to suspend.
+ power_instance_->GetSuspendCallback().Run();
+ EXPECT_EQ(0, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
+
+ power_manager_client_->SendSuspendDone();
+ EXPECT_EQ(1, power_instance_->num_suspend());
+ EXPECT_EQ(1, power_instance_->num_resume());
+
+ // We shouldn't crash if the instance isn't ready.
+ DestroyPowerInstance();
+ power_manager_client_->SendSuspendImminent(
+ power_manager::SuspendImminent_Reason_OTHER);
+ EXPECT_EQ(0, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
+ power_manager_client_->SendSuspendDone();
+}
+
+TEST_F(ArcPowerBridgeTest, SetInteractive) {
+ power_bridge_->OnPowerStateChanged(chromeos::DISPLAY_POWER_ALL_OFF);
+ EXPECT_FALSE(power_instance_->interactive());
+
+ power_bridge_->OnPowerStateChanged(chromeos::DISPLAY_POWER_ALL_ON);
+ EXPECT_TRUE(power_instance_->interactive());
+
+ // We shouldn't crash if the instance isn't ready.
+ DestroyPowerInstance();
+ power_bridge_->OnPowerStateChanged(chromeos::DISPLAY_POWER_ALL_OFF);
+}
+
+TEST_F(ArcPowerBridgeTest, ScreenBrightness) {
+ // Let the initial GetScreenBrightnessPercent() task run.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_DOUBLE_EQ(kInitialBrightness, power_instance_->screen_brightness());
+
+ // Check that Chrome OS brightness changes are passed to Android.
+ const double kUpdatedBrightness = 45.0;
+ power_manager_client_->set_screen_brightness_percent(kUpdatedBrightness);
+ power_manager_client_->SendBrightnessChanged(kUpdatedBrightness, true);
+ EXPECT_DOUBLE_EQ(kUpdatedBrightness, power_instance_->screen_brightness());
+
+ // Requests from Android should update the Chrome OS brightness.
+ const double kAndroidBrightness = 70.0;
+ power_bridge_->OnScreenBrightnessUpdateRequest(kAndroidBrightness);
+ EXPECT_DOUBLE_EQ(kAndroidBrightness,
+ power_manager_client_->screen_brightness_percent());
+
+ // To prevent battles between Chrome OS and Android, the updated brightness
+ // shouldn't be passed to Android immediately, but it should be passed after
+ // the timer fires.
+ power_manager_client_->SendBrightnessChanged(kAndroidBrightness, true);
+ EXPECT_DOUBLE_EQ(kUpdatedBrightness, power_instance_->screen_brightness());
+ ASSERT_TRUE(power_bridge_->TriggerNotifyBrightnessTimerForTesting());
+ EXPECT_DOUBLE_EQ(kAndroidBrightness, power_instance_->screen_brightness());
+}
+
+TEST_F(ArcPowerBridgeTest, DifferentWakeLocks) {
+ AcquireDisplayWakeLock(mojom::DisplayWakeLockType::BRIGHT);
+ EXPECT_EQ(1, wake_lock_provider_->GetActiveWakeLocksOfType(
+ WakeLockType::kPreventDisplaySleep));
+ EXPECT_EQ(0, wake_lock_provider_->GetActiveWakeLocksOfType(
+ WakeLockType::kPreventDisplaySleepAllowDimming));
+
+ AcquireDisplayWakeLock(mojom::DisplayWakeLockType::DIM);
+ EXPECT_EQ(1, wake_lock_provider_->GetActiveWakeLocksOfType(
+ WakeLockType::kPreventDisplaySleep));
+ EXPECT_EQ(1, wake_lock_provider_->GetActiveWakeLocksOfType(
+ WakeLockType::kPreventDisplaySleepAllowDimming));
+
+ ReleaseDisplayWakeLock(mojom::DisplayWakeLockType::BRIGHT);
+ EXPECT_EQ(0, wake_lock_provider_->GetActiveWakeLocksOfType(
+ WakeLockType::kPreventDisplaySleep));
+ EXPECT_EQ(1, wake_lock_provider_->GetActiveWakeLocksOfType(
+ WakeLockType::kPreventDisplaySleepAllowDimming));
+
+ ReleaseDisplayWakeLock(mojom::DisplayWakeLockType::DIM);
+ EXPECT_EQ(0, wake_lock_provider_->GetActiveWakeLocksOfType(
+ WakeLockType::kPreventDisplaySleep));
+ EXPECT_EQ(0, wake_lock_provider_->GetActiveWakeLocksOfType(
+ WakeLockType::kPreventDisplaySleepAllowDimming));
+}
+
+TEST_F(ArcPowerBridgeTest, ConsolidateWakeLocks) {
+ AcquireDisplayWakeLock(mojom::DisplayWakeLockType::BRIGHT);
+ EXPECT_EQ(1, wake_lock_provider_->GetActiveWakeLocksOfType(
+ WakeLockType::kPreventDisplaySleep));
+
+ // Acquiring a second Android wake lock of the same time shouldn't result in a
+ // second device service wake lock being requested.
+ AcquireDisplayWakeLock(mojom::DisplayWakeLockType::BRIGHT);
+ EXPECT_EQ(1, wake_lock_provider_->GetActiveWakeLocksOfType(
+ WakeLockType::kPreventDisplaySleep));
+
+ ReleaseDisplayWakeLock(mojom::DisplayWakeLockType::BRIGHT);
+ EXPECT_EQ(1, wake_lock_provider_->GetActiveWakeLocksOfType(
+ WakeLockType::kPreventDisplaySleep));
+
+ // The device service wake lock should only be released when all Android wake
+ // locks have been released.
+ ReleaseDisplayWakeLock(mojom::DisplayWakeLockType::BRIGHT);
+ EXPECT_EQ(0, wake_lock_provider_->GetActiveWakeLocksOfType(
+ WakeLockType::kPreventDisplaySleep));
+}
+
+TEST_F(ArcPowerBridgeTest, ReleaseWakeLocksWhenInstanceClosed) {
+ AcquireDisplayWakeLock(mojom::DisplayWakeLockType::BRIGHT);
+ ASSERT_EQ(1, wake_lock_provider_->GetActiveWakeLocksOfType(
+ WakeLockType::kPreventDisplaySleep));
+
+ // If the instance is closed, all wake locks should be released.
+ base::RunLoop run_loop;
+ wake_lock_provider_->set_wake_lock_canceled_callback(run_loop.QuitClosure());
+ DestroyPowerInstance();
+ run_loop.Run();
+ EXPECT_EQ(0, wake_lock_provider_->GetActiveWakeLocksOfType(
+ WakeLockType::kPreventDisplaySleep));
+
+ // Check that wake locks can be requested after the instance becomes ready
+ // again.
+ CreatePowerInstance();
+ AcquireDisplayWakeLock(mojom::DisplayWakeLockType::BRIGHT);
+ EXPECT_EQ(1, wake_lock_provider_->GetActiveWakeLocksOfType(
+ WakeLockType::kPreventDisplaySleep));
+}
+
+} // namespace arc
diff --git a/chromium/components/arc/rotation_lock/arc_rotation_lock_bridge.cc b/chromium/components/arc/rotation_lock/arc_rotation_lock_bridge.cc
index c75a7d68bc5..b0816302313 100644
--- a/chromium/components/arc/rotation_lock/arc_rotation_lock_bridge.cc
+++ b/chromium/components/arc/rotation_lock/arc_rotation_lock_bridge.cc
@@ -48,20 +48,24 @@ ArcRotationLockBridge::ArcRotationLockBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service)
: arc_bridge_service_(bridge_service) {
arc_bridge_service_->rotation_lock()->AddObserver(this);
- ash::Shell::Get()->screen_orientation_controller()->AddObserver(this);
- ash::Shell::Get()->tablet_mode_controller()->AddObserver(this);
+ // TODO(mash): Support this functionality without ash::Shell access in Chrome.
+ if (ash::Shell::HasInstance()) {
+ ash::Shell::Get()->screen_orientation_controller()->AddObserver(this);
+ ash::Shell::Get()->tablet_mode_controller()->AddObserver(this);
+ }
}
ArcRotationLockBridge::~ArcRotationLockBridge() {
arc_bridge_service_->rotation_lock()->RemoveObserver(this);
- // TODO(mash): mash needs proper shutdown process.
+ // TODO(mus): mus needs proper shutdown process.
+ // TODO(mash): Support this functionality without ash::Shell access in Chrome.
if (ash::Shell::HasInstance()) {
ash::Shell::Get()->screen_orientation_controller()->RemoveObserver(this);
ash::Shell::Get()->tablet_mode_controller()->RemoveObserver(this);
}
}
-void ArcRotationLockBridge::OnInstanceReady() {
+void ArcRotationLockBridge::OnConnectionReady() {
SendRotationLockState();
}
@@ -78,6 +82,10 @@ void ArcRotationLockBridge::OnTabletModeEnded() {
}
void ArcRotationLockBridge::SendRotationLockState() {
+ // TODO(mash): Support this functionality without ash::Shell access in Chrome.
+ if (!ash::Shell::HasInstance())
+ return;
+
mojom::RotationLockInstance* rotation_lock_instance =
ARC_GET_INSTANCE_FOR_METHOD(arc_bridge_service_->rotation_lock(),
OnRotationLockStateChanged);
diff --git a/chromium/components/arc/rotation_lock/arc_rotation_lock_bridge.h b/chromium/components/arc/rotation_lock/arc_rotation_lock_bridge.h
index e501612748b..a0257402927 100644
--- a/chromium/components/arc/rotation_lock/arc_rotation_lock_bridge.h
+++ b/chromium/components/arc/rotation_lock/arc_rotation_lock_bridge.h
@@ -10,7 +10,7 @@
#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "components/arc/common/rotation_lock.mojom.h"
-#include "components/arc/instance_holder.h"
+#include "components/arc/connection_observer.h"
#include "components/keyed_service/core/keyed_service.h"
namespace content {
@@ -25,7 +25,7 @@ class ArcBridgeService;
// container.
class ArcRotationLockBridge
: public KeyedService,
- public InstanceHolder<mojom::RotationLockInstance>::Observer,
+ public ConnectionObserver<mojom::RotationLockInstance>,
public ash::TabletModeObserver,
public ash::ScreenOrientationController::Observer {
public:
@@ -38,8 +38,8 @@ class ArcRotationLockBridge
ArcBridgeService* bridge_service);
~ArcRotationLockBridge() override;
- // InstanceHolder<mojom::RotationLockInstance>::Observer:
- void OnInstanceReady() override;
+ // ConnectionObserver<mojom::RotationLockInstance>:
+ void OnConnectionReady() override;
// ash::ScreenOrientationController::Observer:
void OnUserRotationLockChanged() override;
diff --git a/chromium/components/arc/storage_manager/arc_storage_manager.cc b/chromium/components/arc/storage_manager/arc_storage_manager.cc
index b35cd7a422b..a6fb61aecb9 100644
--- a/chromium/components/arc/storage_manager/arc_storage_manager.cc
+++ b/chromium/components/arc/storage_manager/arc_storage_manager.cc
@@ -4,6 +4,7 @@
#include "components/arc/storage_manager/arc_storage_manager.h"
+#include <utility>
#include <vector>
#include "base/bind.h"
@@ -58,12 +59,12 @@ bool ArcStorageManager::OpenPrivateVolumeSettings() {
}
bool ArcStorageManager::GetApplicationsSize(
- const GetApplicationsSizeCallback& callback) {
+ GetApplicationsSizeCallback callback) {
auto* storage_manager_instance = ARC_GET_INSTANCE_FOR_METHOD(
arc_bridge_service_->storage_manager(), GetApplicationsSize);
if (!storage_manager_instance)
return false;
- storage_manager_instance->GetApplicationsSize(callback);
+ storage_manager_instance->GetApplicationsSize(std::move(callback));
return true;
}
diff --git a/chromium/components/arc/storage_manager/arc_storage_manager.h b/chromium/components/arc/storage_manager/arc_storage_manager.h
index 8ed50426690..ccad8538b92 100644
--- a/chromium/components/arc/storage_manager/arc_storage_manager.h
+++ b/chromium/components/arc/storage_manager/arc_storage_manager.h
@@ -38,8 +38,8 @@ class ArcStorageManager : public KeyedService {
// Gets storage usage of all application's APK, data, and cache size.
using GetApplicationsSizeCallback =
- base::Callback<void(bool succeeded, mojom::ApplicationsSizePtr)>;
- bool GetApplicationsSize(const GetApplicationsSizeCallback& callback);
+ base::OnceCallback<void(bool succeeded, mojom::ApplicationsSizePtr)>;
+ bool GetApplicationsSize(GetApplicationsSizeCallback callback);
// Deletes all applications' cache files.
bool DeleteApplicationsCache(const base::Callback<void()>& callback);
diff --git a/chromium/components/arc/video_accelerator/BUILD.gn b/chromium/components/arc/video_accelerator/BUILD.gn
new file mode 100644
index 00000000000..49683a08b24
--- /dev/null
+++ b/chromium/components/arc/video_accelerator/BUILD.gn
@@ -0,0 +1,25 @@
+# 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.
+
+static_library("video_accelerator") {
+ sources = [
+ "arc_video_decode_accelerator.h",
+ "chrome_arc_video_decode_accelerator.cc",
+ "chrome_arc_video_decode_accelerator.h",
+ "gpu_arc_video_decode_accelerator.cc",
+ "gpu_arc_video_decode_accelerator.h",
+ "gpu_arc_video_encode_accelerator.cc",
+ "gpu_arc_video_encode_accelerator.h",
+ "protected_buffer_manager.cc",
+ "protected_buffer_manager.h",
+ "protected_buffer_manager_proxy.cc",
+ "protected_buffer_manager_proxy.h",
+ ]
+
+ deps = [
+ "//components/arc/common:media",
+ "//media/gpu",
+ "//ui/ozone",
+ ]
+}
diff --git a/chromium/components/arc/video_accelerator/DEPS b/chromium/components/arc/video_accelerator/DEPS
index 04dd5ab2b11..be1c9c99ce2 100644
--- a/chromium/components/arc/video_accelerator/DEPS
+++ b/chromium/components/arc/video_accelerator/DEPS
@@ -1,3 +1,12 @@
include_rules = [
- "+media/video/video_encode_accelerator.h",
+ "+components/arc/common",
+ "+gpu/command_buffer/service/gpu_preferences.h",
+ "+media/video",
+ "+media/base/video_frame.h",
+ "+media/base/video_types.h",
+ "+media/gpu",
+ "+mojo/edk/embedder",
+ "+services/service_manager/public/cpp",
+ "+ui/gfx",
+ "+ui/ozone/public",
]
diff --git a/chromium/components/arc/video_accelerator/OWNERS b/chromium/components/arc/video_accelerator/OWNERS
index ef5cf841917..4e730ffd89f 100644
--- a/chromium/components/arc/video_accelerator/OWNERS
+++ b/chromium/components/arc/video_accelerator/OWNERS
@@ -1,3 +1,4 @@
-per-file *_struct_traits*.*=set noparent
-per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
-per-file *_struct_traits*.*=file://components/arc/common/ARC_SECURITY_OWNERS
+kcwu@chromium.org
+piman@chromium.org
+posciak@chromium.org
+wuchengli@chromium.org
diff --git a/chromium/components/arc/video_accelerator/arc_video_decode_accelerator.h b/chromium/components/arc/video_accelerator/arc_video_decode_accelerator.h
new file mode 100644
index 00000000000..a6d563447ef
--- /dev/null
+++ b/chromium/components/arc/video_accelerator/arc_video_decode_accelerator.h
@@ -0,0 +1,182 @@
+// 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.
+
+#ifndef COMPONENTS_ARC_VIDEO_ACCELERATOR_ARC_VIDEO_DECODE_ACCELERATOR_H_
+#define COMPONENTS_ARC_VIDEO_ACCELERATOR_ARC_VIDEO_DECODE_ACCELERATOR_H_
+
+#include <vector>
+
+#include "base/files/scoped_file.h"
+#include "components/arc/video_accelerator/video_frame_plane.h"
+
+namespace arc {
+
+enum HalPixelFormatExtension {
+ // The pixel formats defined in Android but are used here. They are defined
+ // in "system/core/include/system/graphics.h"
+ HAL_PIXEL_FORMAT_BGRA_8888 = 5,
+ HAL_PIXEL_FORMAT_YCbCr_420_888 = 0x23,
+
+ // The following formats are not defined in Android, but used in
+ // ArcVideoDecodeAccelerator to identify the input format.
+ HAL_PIXEL_FORMAT_H264 = 0x34363248,
+ HAL_PIXEL_FORMAT_VP8 = 0x00385056,
+ HAL_PIXEL_FORMAT_VP9 = 0x00395056,
+};
+
+enum PortType {
+ PORT_INPUT = 0,
+ PORT_OUTPUT = 1,
+ PORT_COUNT = 2,
+};
+
+struct BufferMetadata {
+ int64_t timestamp = 0; // in microseconds
+ uint32_t bytes_used = 0;
+};
+
+struct VideoFormat {
+ uint32_t pixel_format = 0;
+ uint32_t buffer_size = 0;
+
+ // Minimum number of buffers required to decode/encode the stream.
+ uint32_t min_num_buffers = 0;
+ uint32_t coded_width = 0;
+ uint32_t coded_height = 0;
+ uint32_t crop_left = 0;
+ uint32_t crop_width = 0;
+ uint32_t crop_top = 0;
+ uint32_t crop_height = 0;
+};
+
+// The IPC interface between Android and Chromium for video decoding. Input
+// buffers are sent from Android side and get processed in Chromium and the
+// output buffers are returned back to Android side.
+class ArcVideoDecodeAccelerator {
+ public:
+ enum Result {
+ // Note: this enum is used for UMA reporting. The existing values should not
+ // be rearranged, reused or removed and any additions should include updates
+ // to UMA reporting and histograms.xml.
+ SUCCESS = 0,
+ ILLEGAL_STATE = 1,
+ INVALID_ARGUMENT = 2,
+ UNREADABLE_INPUT = 3,
+ PLATFORM_FAILURE = 4,
+ INSUFFICIENT_RESOURCES = 5,
+ RESULT_MAX = 6,
+ };
+
+ struct Config {
+ size_t num_input_buffers = 0;
+ uint32_t input_pixel_format = 0;
+ // If true, only buffers created via AllocateProtectedBuffer() may be used.
+ bool secure_mode = false;
+ // TODO(owenlin): Add output_pixel_format. For now only the native pixel
+ // format of each VDA on Chromium is supported.
+ };
+
+ // The callbacks of the ArcVideoDecodeAccelerator. The user of this class
+ // should implement this interface.
+ class Client {
+ public:
+ virtual ~Client() {}
+
+ // Called when an asynchronous error happens. The errors in Initialize()
+ // will not be reported here, but will be indicated by a return value
+ // there.
+ virtual void OnError(Result error) = 0;
+
+ // Called when a buffer with the specified |index| and |port| has been
+ // processed and is no longer used in the accelerator. For input buffers,
+ // the Client may fill them with new content. For output buffers, indicates
+ // they are ready to be consumed by the client.
+ virtual void OnBufferDone(PortType port,
+ uint32_t index,
+ const BufferMetadata& metadata) = 0;
+
+ // Called when the output format has changed or the output format
+ // becomes available at beginning of the stream after initial parsing.
+ virtual void OnOutputFormatChanged(const VideoFormat& format) = 0;
+
+ // Called as a completion notification for Reset().
+ virtual void OnResetDone() = 0;
+
+ // Called as a completion notification for Flush().
+ virtual void OnFlushDone() = 0;
+ };
+
+ // Initializes the ArcVideoDecodeAccelerator with specific configuration. This
+ // must be called before any other methods. This call is synchronous and
+ // returns SUCCESS iff initialization is successful.
+ virtual Result Initialize(const Config& config, Client* client) = 0;
+
+ // Allocates a new protected buffer on accelerator side for the given |port|
+ // and |index|, the contents of which will be inaccessible to the client.
+ // The protected buffer will remain valid for at least as long as the resource
+ // backing the passed |handle_fd| is not released (i.e. there is at least one
+ // reference on the file backing |handle_fd|.
+ //
+ // Usable only if the accelerator has been initialized to run in secure mode.
+ // Allocation for input will create a protected buffer of at least |size|;
+ // for output, |size| is ignored, and the currently configured output format
+ // is used instead to determine the required buffer size and format.
+ virtual bool AllocateProtectedBuffer(PortType port,
+ uint32_t index,
+ base::ScopedFD handle_fd,
+ size_t size) = 0;
+
+ // Assigns a shared memory to be used for the accelerator at the specified
+ // port and index. A buffer must be successfully bound before it can be passed
+ // to the accelerator via UseBuffer(). Already bound buffers may be reused
+ // multiple times without additional bindings.
+ // Not allowed in secure_mode, where protected buffers have to be allocated
+ // instead.
+ virtual void BindSharedMemory(PortType port,
+ uint32_t index,
+ base::ScopedFD ashmem_fd,
+ off_t offset,
+ size_t length) = 0;
+
+ // Assigns a buffer to be used for the accelerator at the specified
+ // port and index. A buffer must be successfully bound before it can be
+ // passed to the accelerator via UseBuffer(). Already bound buffers may be
+ // reused multiple times without additional bindings.
+ // Not allowed in secure_mode, where protected buffers have to be allocated
+ // instead.
+ virtual void BindDmabuf(
+ PortType port,
+ uint32_t index,
+ base::ScopedFD dmabuf_fd,
+ const std::vector<::arc::VideoFramePlane>& planes) = 0;
+
+ // Passes a buffer to the accelerator. For input buffer, the accelerator
+ // will process it. For output buffer, the accelerator will output content
+ // to it.
+ // In secure mode, |port| and |index| must correspond to a protected buffer
+ // allocated using AllocateProtectedBuffer().
+ virtual void UseBuffer(PortType port,
+ uint32_t index,
+ const BufferMetadata& metadata) = 0;
+
+ // Sets the number of output buffers. When it fails, Client::OnError() will
+ // be called.
+ virtual void SetNumberOfOutputBuffers(size_t number) = 0;
+
+ // Resets the accelerator. When it is done, Client::OnResetDone() will
+ // be called. Afterwards, all buffers won't be accessed by the accelerator
+ // and there won't be more callbacks.
+ virtual void Reset() = 0;
+
+ // Flushes the accelerator. After all the output buffers pending decode have
+ // been returned to client by OnBufferDone(), Client::OnFlushDone() will be
+ // called.
+ virtual void Flush() = 0;
+
+ virtual ~ArcVideoDecodeAccelerator() {}
+};
+
+} // namespace arc
+
+#endif // COMPONENTS_ARC_VIDEO_ACCELERATOR_ARC_VIDEO_DECODE_ACCELERATOR_H_
diff --git a/chromium/components/arc/video_accelerator/chrome_arc_video_decode_accelerator.cc b/chromium/components/arc/video_accelerator/chrome_arc_video_decode_accelerator.cc
new file mode 100644
index 00000000000..38bc730733f
--- /dev/null
+++ b/chromium/components/arc/video_accelerator/chrome_arc_video_decode_accelerator.cc
@@ -0,0 +1,633 @@
+// 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 "components/arc/video_accelerator/chrome_arc_video_decode_accelerator.h"
+
+#include "base/callback_helpers.h"
+#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/numerics/safe_math.h"
+#include "base/run_loop.h"
+#include "base/unguessable_token.h"
+#include "components/arc/video_accelerator/protected_buffer_manager.h"
+#include "media/base/video_frame.h"
+#include "media/gpu/format_utils.h"
+#include "media/gpu/gpu_video_decode_accelerator_factory.h"
+
+namespace arc {
+
+namespace {
+
+// An arbitrary chosen limit of the number of buffers. The number of
+// buffers used is requested from the untrusted client side.
+const size_t kMaxBufferCount = 128;
+
+// Maximum number of concurrent ARC video clients.
+// Currently we have no way to know the resources are not enough to create more
+// VDA. Arbitrarily chosen a reasonable constant as the limit.
+const int kMaxConcurrentClients = 8;
+
+} // namespace
+
+int ChromeArcVideoDecodeAccelerator::client_count_ = 0;
+
+ChromeArcVideoDecodeAccelerator::InputRecord::InputRecord(
+ int32_t bitstream_buffer_id,
+ uint32_t buffer_index,
+ int64_t timestamp)
+ : bitstream_buffer_id(bitstream_buffer_id),
+ buffer_index(buffer_index),
+ timestamp(timestamp) {}
+
+ChromeArcVideoDecodeAccelerator::InputBufferInfo::InputBufferInfo() = default;
+
+ChromeArcVideoDecodeAccelerator::InputBufferInfo::~InputBufferInfo() {
+ if (shm_handle.OwnershipPassesToIPC())
+ shm_handle.Close();
+}
+
+ChromeArcVideoDecodeAccelerator::OutputBufferInfo::OutputBufferInfo() = default;
+
+ChromeArcVideoDecodeAccelerator::OutputBufferInfo::~OutputBufferInfo() {
+ if (!gpu_memory_buffer_handle.is_null()) {
+ for (const auto& fd : gpu_memory_buffer_handle.native_pixmap_handle.fds) {
+ // Close the fd by wrapping it in a ScopedFD and letting
+ // it fall out of scope.
+ base::ScopedFD scoped_fd(fd.fd);
+ }
+ }
+}
+
+ChromeArcVideoDecodeAccelerator::ChromeArcVideoDecodeAccelerator(
+ const gpu::GpuPreferences& gpu_preferences,
+ ProtectedBufferManager* protected_buffer_manager)
+ : arc_client_(nullptr),
+ next_bitstream_buffer_id_(0),
+ output_pixel_format_(media::PIXEL_FORMAT_UNKNOWN),
+ output_buffer_size_(0),
+ requested_num_of_output_buffers_(0),
+ gpu_preferences_(gpu_preferences),
+ protected_buffer_manager_(protected_buffer_manager) {}
+
+ChromeArcVideoDecodeAccelerator::~ChromeArcVideoDecodeAccelerator() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (vda_) {
+ client_count_--;
+ }
+}
+
+ArcVideoDecodeAccelerator::Result ChromeArcVideoDecodeAccelerator::Initialize(
+ const Config& config,
+ ArcVideoDecodeAccelerator::Client* client) {
+ auto result = InitializeTask(config, client);
+ // Report initialization status to UMA.
+ UMA_HISTOGRAM_ENUMERATION(
+ "Media.ChromeArcVideoDecodeAccelerator.InitializeResult", result,
+ RESULT_MAX);
+ return result;
+}
+
+ArcVideoDecodeAccelerator::Result
+ChromeArcVideoDecodeAccelerator::InitializeTask(
+ const Config& config,
+ ArcVideoDecodeAccelerator::Client* client) {
+ DVLOG(5) << "Initialize(input_pixel_format=" << config.input_pixel_format
+ << ", num_input_buffers=" << config.num_input_buffers << ")";
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(client);
+
+ if (arc_client_) {
+ DLOG(ERROR) << "Re-Initialize() is not allowed";
+ return ILLEGAL_STATE;
+ }
+
+ arc_client_ = client;
+
+ if (client_count_ >= kMaxConcurrentClients) {
+ LOG(WARNING) << "Reject to Initialize() due to too many clients: "
+ << client_count_;
+ return INSUFFICIENT_RESOURCES;
+ }
+
+ if (config.secure_mode && !protected_buffer_manager_) {
+ DLOG(ERROR) << "Secure mode unsupported";
+ return PLATFORM_FAILURE;
+ }
+
+ secure_mode_ = config.secure_mode;
+
+ if (config.num_input_buffers > kMaxBufferCount) {
+ DLOG(ERROR) << "Request too many buffers: " << config.num_input_buffers;
+ return INVALID_ARGUMENT;
+ }
+ input_buffer_info_.resize(config.num_input_buffers);
+
+ media::VideoDecodeAccelerator::Config vda_config;
+ switch (config.input_pixel_format) {
+ case HAL_PIXEL_FORMAT_H264:
+ vda_config.profile = media::H264PROFILE_MAIN;
+ break;
+ case HAL_PIXEL_FORMAT_VP8:
+ vda_config.profile = media::VP8PROFILE_ANY;
+ break;
+ case HAL_PIXEL_FORMAT_VP9:
+ vda_config.profile = media::VP9PROFILE_PROFILE0;
+ break;
+ default:
+ DLOG(ERROR) << "Unsupported input format: " << config.input_pixel_format;
+ return INVALID_ARGUMENT;
+ }
+ vda_config.output_mode =
+ media::VideoDecodeAccelerator::Config::OutputMode::IMPORT;
+
+ auto vda_factory = media::GpuVideoDecodeAcceleratorFactory::CreateWithNoGL();
+ vda_ = vda_factory->CreateVDA(
+ this, vda_config, gpu::GpuDriverBugWorkarounds(), gpu_preferences_);
+ if (!vda_) {
+ DLOG(ERROR) << "Failed to create VDA.";
+ return PLATFORM_FAILURE;
+ }
+
+ client_count_++;
+ DVLOG(5) << "Number of concurrent ArcVideoDecodeAccelerator clients: "
+ << client_count_;
+
+ return SUCCESS;
+}
+
+void ChromeArcVideoDecodeAccelerator::SetNumberOfOutputBuffers(size_t number) {
+ DVLOG(5) << "SetNumberOfOutputBuffers(" << number << ")";
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (!vda_) {
+ DLOG(ERROR) << "VDA not initialized";
+ return;
+ }
+
+ if (number > kMaxBufferCount) {
+ DLOG(ERROR) << "Too many buffers: " << number;
+ arc_client_->OnError(INVALID_ARGUMENT);
+ return;
+ }
+
+ std::vector<media::PictureBuffer> buffers;
+ for (size_t id = 0; id < number; ++id) {
+ // TODO(owenlin): Make sure the |coded_size| is what we want.
+ buffers.push_back(
+ media::PictureBuffer(base::checked_cast<int32_t>(id), coded_size_));
+ }
+ vda_->AssignPictureBuffers(buffers);
+
+ buffers_pending_import_.clear();
+ buffers_pending_import_.resize(number);
+}
+
+bool ChromeArcVideoDecodeAccelerator::AllocateProtectedBuffer(
+ PortType port,
+ uint32_t index,
+ base::ScopedFD handle_fd,
+ size_t size) {
+ DVLOG(5) << "port=" << port << " index=" << index
+ << " handle=" << handle_fd.get() << " size=" << size;
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ if (!secure_mode_) {
+ DLOG(ERROR) << "Not in secure mode";
+ arc_client_->OnError(INVALID_ARGUMENT);
+ return false;
+ }
+
+ if (!ValidatePortAndIndex(port, index)) {
+ arc_client_->OnError(INVALID_ARGUMENT);
+ return false;
+ }
+
+ if (port == PORT_INPUT) {
+ auto protected_shmem =
+ protected_buffer_manager_->AllocateProtectedSharedMemory(
+ std::move(handle_fd), size);
+ if (!protected_shmem) {
+ DLOG(ERROR) << "Failed allocating protected shared memory";
+ return false;
+ }
+
+ auto input_info = std::make_unique<InputBufferInfo>();
+ input_info->shm_handle = protected_shmem->shm_handle();
+ input_info->protected_buffer_handle = std::move(protected_shmem);
+ input_buffer_info_[index] = std::move(input_info);
+ } else if (port == PORT_OUTPUT) {
+ auto protected_pixmap =
+ protected_buffer_manager_->AllocateProtectedNativePixmap(
+ std::move(handle_fd),
+ media::VideoPixelFormatToGfxBufferFormat(output_pixel_format_),
+ coded_size_);
+ if (!protected_pixmap) {
+ DLOG(ERROR) << "Failed allocating a protected pixmap";
+ return false;
+ }
+ auto output_info = std::make_unique<OutputBufferInfo>();
+ output_info->gpu_memory_buffer_handle.type = gfx::NATIVE_PIXMAP;
+ output_info->gpu_memory_buffer_handle.native_pixmap_handle =
+ gfx::CloneHandleForIPC(protected_pixmap->native_pixmap_handle());
+ output_info->protected_buffer_handle = std::move(protected_pixmap);
+ buffers_pending_import_[index] = std::move(output_info);
+ }
+
+ return true;
+}
+
+void ChromeArcVideoDecodeAccelerator::BindSharedMemory(PortType port,
+ uint32_t index,
+ base::ScopedFD ashmem_fd,
+ off_t offset,
+ size_t length) {
+ DVLOG(5) << "ArcGVDA::BindSharedMemory, offset: " << offset
+ << ", length: " << length;
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ if (secure_mode_) {
+ DLOG(ERROR) << "not allowed in secure mode";
+ arc_client_->OnError(INVALID_ARGUMENT);
+ return;
+ }
+
+ if (!vda_) {
+ DLOG(ERROR) << "VDA not initialized";
+ return;
+ }
+
+ if (port != PORT_INPUT) {
+ DLOG(ERROR) << "SharedBuffer is only supported for input";
+ arc_client_->OnError(INVALID_ARGUMENT);
+ return;
+ }
+ if (!ValidatePortAndIndex(port, index)) {
+ arc_client_->OnError(INVALID_ARGUMENT);
+ return;
+ }
+
+ auto input_info = std::make_unique<InputBufferInfo>();
+ input_info->shm_handle =
+ base::SharedMemoryHandle(base::FileDescriptor(ashmem_fd.release(), true),
+ length, base::UnguessableToken::Create());
+ DCHECK(input_info->shm_handle.OwnershipPassesToIPC());
+ input_info->offset = offset;
+ input_buffer_info_[index] = std::move(input_info);
+}
+
+bool ChromeArcVideoDecodeAccelerator::VerifyDmabuf(
+ const base::ScopedFD& dmabuf_fd,
+ const std::vector<::arc::VideoFramePlane>& planes) const {
+ size_t num_planes = media::VideoFrame::NumPlanes(output_pixel_format_);
+ if (planes.size() != num_planes) {
+ DLOG(ERROR) << "Invalid number of dmabuf planes passed: " << planes.size()
+ << ", expected: " << num_planes;
+ return false;
+ }
+
+ off_t size = lseek(dmabuf_fd.get(), 0, SEEK_END);
+ lseek(dmabuf_fd.get(), 0, SEEK_SET);
+ if (size < 0) {
+ DPLOG(ERROR) << "fail to find the size of dmabuf";
+ return false;
+ }
+
+ size_t i = 0;
+ for (const auto& plane : planes) {
+ DVLOG(4) << "Plane " << i << ", offset: " << plane.offset
+ << ", stride: " << plane.stride;
+
+ size_t rows =
+ media::VideoFrame::Rows(i, output_pixel_format_, coded_size_.height());
+ base::CheckedNumeric<off_t> current_size(plane.offset);
+ current_size += base::CheckMul(plane.stride, rows);
+
+ if (!current_size.IsValid() || current_size.ValueOrDie() > size) {
+ DLOG(ERROR) << "Invalid strides/offsets";
+ return false;
+ }
+
+ ++i;
+ }
+
+ return true;
+}
+
+void ChromeArcVideoDecodeAccelerator::BindDmabuf(
+ PortType port,
+ uint32_t index,
+ base::ScopedFD dmabuf_fd,
+ const std::vector<::arc::VideoFramePlane>& planes) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ if (secure_mode_) {
+ DLOG(ERROR) << "not allowed in secure mode";
+ arc_client_->OnError(INVALID_ARGUMENT);
+ return;
+ }
+
+ if (!vda_) {
+ DLOG(ERROR) << "VDA not initialized";
+ return;
+ }
+
+ if (port != PORT_OUTPUT) {
+ DLOG(ERROR) << "Dmabuf is only supported for input";
+ arc_client_->OnError(INVALID_ARGUMENT);
+ return;
+ }
+ if (!ValidatePortAndIndex(port, index)) {
+ arc_client_->OnError(INVALID_ARGUMENT);
+ return;
+ }
+ if (!VerifyDmabuf(dmabuf_fd, planes)) {
+ arc_client_->OnError(INVALID_ARGUMENT);
+ return;
+ }
+
+#if defined(USE_OZONE)
+ auto output_info = std::make_unique<OutputBufferInfo>();
+ output_info->gpu_memory_buffer_handle.type = gfx::NATIVE_PIXMAP;
+ output_info->gpu_memory_buffer_handle.native_pixmap_handle.fds.emplace_back(
+ base::FileDescriptor(dmabuf_fd.release(), true));
+ for (const auto& plane : planes) {
+ output_info->gpu_memory_buffer_handle.native_pixmap_handle.planes
+ .emplace_back(plane.stride, plane.offset, 0, 0);
+ }
+ buffers_pending_import_[index] = std::move(output_info);
+#else
+ arc_client_->OnError(PLATFORM_FAILURE);
+#endif
+}
+
+void ChromeArcVideoDecodeAccelerator::UseBuffer(
+ PortType port,
+ uint32_t index,
+ const BufferMetadata& metadata) {
+ DVLOG(5) << "UseBuffer(port=" << port << ", index=" << index
+ << ", metadata=(bytes_used=" << metadata.bytes_used
+ << ", timestamp=" << metadata.timestamp << ")";
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (!vda_) {
+ DLOG(ERROR) << "VDA not initialized";
+ return;
+ }
+ if (!ValidatePortAndIndex(port, index)) {
+ arc_client_->OnError(INVALID_ARGUMENT);
+ return;
+ }
+ switch (port) {
+ case PORT_INPUT: {
+ auto& input_info = input_buffer_info_[index];
+ if (!input_info) {
+ DLOG(ERROR) << "Buffer not initialized";
+ arc_client_->OnError(INVALID_ARGUMENT);
+ return;
+ }
+
+ int32_t bitstream_buffer_id = next_bitstream_buffer_id_;
+ // Mask against 30 bits, to avoid (undefined) wraparound on signed
+ // integer.
+ next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF;
+
+ auto duplicated_handle = input_info->shm_handle.Duplicate();
+ if (!duplicated_handle.IsValid()) {
+ arc_client_->OnError(PLATFORM_FAILURE);
+ return;
+ }
+
+ CreateInputRecord(bitstream_buffer_id, index, metadata.timestamp);
+ vda_->Decode(
+ media::BitstreamBuffer(bitstream_buffer_id, duplicated_handle,
+ metadata.bytes_used, input_info->offset));
+ break;
+ }
+ case PORT_OUTPUT: {
+ auto& output_info = buffers_pending_import_[index];
+ if (!output_info) {
+ DLOG(ERROR) << "Buffer not initialized";
+ arc_client_->OnError(INVALID_ARGUMENT);
+ return;
+ }
+ // is_null() is false the first time the buffer is passed to the VDA.
+ // In that case, VDA needs to import the buffer first.
+ if (!output_info->gpu_memory_buffer_handle.is_null()) {
+ vda_->ImportBufferForPicture(index,
+ output_info->gpu_memory_buffer_handle);
+ // VDA takes ownership, so just clear out, don't close the handle.
+ output_info->gpu_memory_buffer_handle = gfx::GpuMemoryBufferHandle();
+ } else {
+ vda_->ReusePictureBuffer(index);
+ }
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+}
+
+void ChromeArcVideoDecodeAccelerator::Reset() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (!vda_) {
+ DLOG(ERROR) << "VDA not initialized";
+ return;
+ }
+ vda_->Reset();
+}
+
+void ChromeArcVideoDecodeAccelerator::Flush() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (!vda_) {
+ DLOG(ERROR) << "VDA not initialized";
+ return;
+ }
+ vda_->Flush();
+}
+
+void ChromeArcVideoDecodeAccelerator::ProvidePictureBuffers(
+ uint32_t requested_num_of_buffers,
+ media::VideoPixelFormat output_pixel_format,
+ uint32_t textures_per_buffer,
+ const gfx::Size& dimensions,
+ uint32_t texture_target) {
+ DVLOG(5) << "ProvidePictureBuffers("
+ << "requested_num_of_buffers=" << requested_num_of_buffers
+ << ", dimensions=" << dimensions.ToString() << ")";
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ coded_size_ = dimensions;
+
+ // By default, use an empty rect to indicate the visible rectangle is not
+ // available.
+ visible_rect_ = gfx::Rect();
+ if ((output_pixel_format_ != media::PIXEL_FORMAT_UNKNOWN) &&
+ (output_pixel_format_ != output_pixel_format)) {
+ arc_client_->OnError(PLATFORM_FAILURE);
+ return;
+ }
+ output_pixel_format_ = output_pixel_format;
+ requested_num_of_output_buffers_ = requested_num_of_buffers;
+ output_buffer_size_ =
+ media::VideoFrame::AllocationSize(output_pixel_format_, coded_size_);
+
+ NotifyOutputFormatChanged();
+}
+
+void ChromeArcVideoDecodeAccelerator::NotifyOutputFormatChanged() {
+ VideoFormat video_format;
+ switch (output_pixel_format_) {
+ case media::PIXEL_FORMAT_I420:
+ case media::PIXEL_FORMAT_YV12:
+ case media::PIXEL_FORMAT_NV12:
+ case media::PIXEL_FORMAT_NV21:
+ // HAL_PIXEL_FORMAT_YCbCr_420_888 is the flexible pixel format in Android
+ // which handles all 420 formats, with both orderings of chroma (CbCr and
+ // CrCb) as well as planar and semi-planar layouts.
+ video_format.pixel_format = HAL_PIXEL_FORMAT_YCbCr_420_888;
+ break;
+ case media::PIXEL_FORMAT_ARGB:
+ video_format.pixel_format = HAL_PIXEL_FORMAT_BGRA_8888;
+ break;
+ default:
+ DLOG(ERROR) << "Format not supported: " << output_pixel_format_;
+ arc_client_->OnError(PLATFORM_FAILURE);
+ return;
+ }
+ video_format.buffer_size = output_buffer_size_;
+ video_format.min_num_buffers = requested_num_of_output_buffers_;
+ video_format.coded_width = coded_size_.width();
+ video_format.coded_height = coded_size_.height();
+ video_format.crop_top = visible_rect_.y();
+ video_format.crop_left = visible_rect_.x();
+ video_format.crop_width = visible_rect_.width();
+ video_format.crop_height = visible_rect_.height();
+ arc_client_->OnOutputFormatChanged(video_format);
+}
+
+void ChromeArcVideoDecodeAccelerator::DismissPictureBuffer(
+ int32_t picture_buffer) {
+ // no-op
+}
+
+void ChromeArcVideoDecodeAccelerator::PictureReady(
+ const media::Picture& picture) {
+ DVLOG(5) << "PictureReady(picture_buffer_id=" << picture.picture_buffer_id()
+ << ", bitstream_buffer_id=" << picture.bitstream_buffer_id();
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ // Handle visible size change.
+ if (visible_rect_ != picture.visible_rect()) {
+ DVLOG(5) << "visible size changed: " << picture.visible_rect().ToString();
+ visible_rect_ = picture.visible_rect();
+ NotifyOutputFormatChanged();
+ }
+
+ InputRecord* input_record = FindInputRecord(picture.bitstream_buffer_id());
+ if (input_record == nullptr) {
+ DLOG(ERROR) << "Cannot find for bitstream buffer id: "
+ << picture.bitstream_buffer_id();
+ arc_client_->OnError(PLATFORM_FAILURE);
+ return;
+ }
+
+ BufferMetadata metadata;
+ metadata.timestamp = input_record->timestamp;
+ metadata.bytes_used = output_buffer_size_;
+ arc_client_->OnBufferDone(PORT_OUTPUT, picture.picture_buffer_id(), metadata);
+}
+
+void ChromeArcVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer(
+ int32_t bitstream_buffer_id) {
+ DVLOG(5) << "NotifyEndOfBitstreamBuffer(" << bitstream_buffer_id << ")";
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ InputRecord* input_record = FindInputRecord(bitstream_buffer_id);
+ if (input_record == nullptr) {
+ arc_client_->OnError(PLATFORM_FAILURE);
+ return;
+ }
+ arc_client_->OnBufferDone(PORT_INPUT, input_record->buffer_index,
+ BufferMetadata());
+}
+
+void ChromeArcVideoDecodeAccelerator::NotifyFlushDone() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ arc_client_->OnFlushDone();
+}
+
+void ChromeArcVideoDecodeAccelerator::NotifyResetDone() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ arc_client_->OnResetDone();
+}
+
+static ArcVideoDecodeAccelerator::Result ConvertErrorCode(
+ media::VideoDecodeAccelerator::Error error) {
+ switch (error) {
+ case media::VideoDecodeAccelerator::ILLEGAL_STATE:
+ return ArcVideoDecodeAccelerator::ILLEGAL_STATE;
+ case media::VideoDecodeAccelerator::INVALID_ARGUMENT:
+ return ArcVideoDecodeAccelerator::INVALID_ARGUMENT;
+ case media::VideoDecodeAccelerator::UNREADABLE_INPUT:
+ return ArcVideoDecodeAccelerator::UNREADABLE_INPUT;
+ case media::VideoDecodeAccelerator::PLATFORM_FAILURE:
+ return ArcVideoDecodeAccelerator::PLATFORM_FAILURE;
+ default:
+ DLOG(ERROR) << "Unknown error: " << error;
+ return ArcVideoDecodeAccelerator::PLATFORM_FAILURE;
+ }
+}
+
+void ChromeArcVideoDecodeAccelerator::NotifyError(
+ media::VideoDecodeAccelerator::Error error) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DLOG(ERROR) << "Error notified: " << error;
+ arc_client_->OnError(ConvertErrorCode(error));
+}
+
+void ChromeArcVideoDecodeAccelerator::CreateInputRecord(
+ int32_t bitstream_buffer_id,
+ uint32_t buffer_index,
+ int64_t timestamp) {
+ input_records_.push_front(
+ InputRecord(bitstream_buffer_id, buffer_index, timestamp));
+
+ // The same value copied from media::GpuVideoDecoder. The input record is
+ // needed when the input buffer or the corresponding output buffer are
+ // returned from VDA. However there is no guarantee how much buffers will be
+ // kept in the VDA. We kept the last |kMaxNumberOfInputRecords| in
+ // |input_records_| and drop the others.
+ const size_t kMaxNumberOfInputRecords = 128;
+ if (input_records_.size() > kMaxNumberOfInputRecords)
+ input_records_.pop_back();
+}
+
+ChromeArcVideoDecodeAccelerator::InputRecord*
+ChromeArcVideoDecodeAccelerator::FindInputRecord(int32_t bitstream_buffer_id) {
+ for (auto& record : input_records_) {
+ if (record.bitstream_buffer_id == bitstream_buffer_id)
+ return &record;
+ }
+ return nullptr;
+}
+
+bool ChromeArcVideoDecodeAccelerator::ValidatePortAndIndex(
+ PortType port,
+ uint32_t index) const {
+ switch (port) {
+ case PORT_INPUT:
+ if (index >= input_buffer_info_.size()) {
+ DLOG(ERROR) << "Invalid index: " << index;
+ return false;
+ }
+ return true;
+ case PORT_OUTPUT:
+ if (index >= buffers_pending_import_.size()) {
+ DLOG(ERROR) << "Invalid index: " << index;
+ return false;
+ }
+ return true;
+ default:
+ DLOG(ERROR) << "Invalid port: " << port;
+ return false;
+ }
+}
+
+} // namespace arc
diff --git a/chromium/components/arc/video_accelerator/chrome_arc_video_decode_accelerator.h b/chromium/components/arc/video_accelerator/chrome_arc_video_decode_accelerator.h
new file mode 100644
index 00000000000..2e19aca65a8
--- /dev/null
+++ b/chromium/components/arc/video_accelerator/chrome_arc_video_decode_accelerator.h
@@ -0,0 +1,194 @@
+// 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.
+
+#ifndef COMPONENTS_ARC_VIDEO_ACCELERATOR_CHROME_ARC_VIDEO_DECODE_ACCELERATOR_H_
+#define COMPONENTS_ARC_VIDEO_ACCELERATOR_CHROME_ARC_VIDEO_DECODE_ACCELERATOR_H_
+
+#include <list>
+#include <memory>
+#include <queue>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/threading/thread_checker.h"
+#include "components/arc/video_accelerator/arc_video_decode_accelerator.h"
+#include "gpu/command_buffer/service/gpu_preferences.h"
+#include "media/video/video_decode_accelerator.h"
+
+namespace arc {
+
+class ProtectedBufferManager;
+class ProtectedBufferHandle;
+
+// This class is executed in the GPU process. It takes decoding requests from
+// ARC via IPC channels and translates and sends those requests to an
+// implementation of media::VideoDecodeAccelerator. It also returns the decoded
+// frames back to the ARC side.
+class ChromeArcVideoDecodeAccelerator
+ : public ArcVideoDecodeAccelerator,
+ public media::VideoDecodeAccelerator::Client,
+ public base::SupportsWeakPtr<ChromeArcVideoDecodeAccelerator> {
+ public:
+ ChromeArcVideoDecodeAccelerator(
+ const gpu::GpuPreferences& gpu_preferences,
+ ProtectedBufferManager* protected_buffer_manager);
+ ~ChromeArcVideoDecodeAccelerator() override;
+
+ // Implementation of the ArcVideoDecodeAccelerator interface.
+ ArcVideoDecodeAccelerator::Result Initialize(
+ const Config& config,
+ ArcVideoDecodeAccelerator::Client* client) override;
+ void SetNumberOfOutputBuffers(size_t number) override;
+ bool AllocateProtectedBuffer(PortType port,
+ uint32_t index,
+ base::ScopedFD handle_fd,
+ size_t size) override;
+ void BindSharedMemory(PortType port,
+ uint32_t index,
+ base::ScopedFD ashmem_fd,
+ off_t offset,
+ size_t length) override;
+ void BindDmabuf(PortType port,
+ uint32_t index,
+ base::ScopedFD dmabuf_fd,
+ const std::vector<::arc::VideoFramePlane>& planes) override;
+ void UseBuffer(PortType port,
+ uint32_t index,
+ const BufferMetadata& metadata) override;
+ void Reset() override;
+ void Flush() override;
+
+ // Implementation of the VideoDecodeAccelerator::Client interface.
+ void ProvidePictureBuffers(uint32_t requested_num_of_buffers,
+ media::VideoPixelFormat output_format,
+ uint32_t textures_per_buffer,
+ const gfx::Size& dimensions,
+ uint32_t texture_target) override;
+ void DismissPictureBuffer(int32_t picture_buffer) override;
+ void PictureReady(const media::Picture& picture) override;
+ void NotifyEndOfBitstreamBuffer(int32_t bitstream_buffer_id) override;
+ void NotifyFlushDone() override;
+ void NotifyResetDone() override;
+ void NotifyError(media::VideoDecodeAccelerator::Error error) override;
+
+ private:
+ // Some information related to a bitstream buffer. The information is required
+ // when input or output buffers are returned back to the client.
+ struct InputRecord {
+ int32_t bitstream_buffer_id;
+ uint32_t buffer_index;
+ int64_t timestamp;
+
+ InputRecord(int32_t bitstream_buffer_id,
+ uint32_t buffer_index,
+ int64_t timestamp);
+ };
+
+ // The information about the shared memory used as an input buffer.
+ struct InputBufferInfo {
+ // SharedMemoryHandle for this buffer to be passed to accelerator.
+ // In non-secure mode, received via BindSharedMemory from the client,
+ // in secure mode, a handle for the SharedMemory in protected_shmem.
+ base::SharedMemoryHandle shm_handle;
+
+ // Used only in secure mode; handle to the protected buffer backing
+ // this input buffer.
+ std::unique_ptr<ProtectedBufferHandle> protected_buffer_handle;
+
+ // Offset to the payload from the beginning of the shared memory buffer.
+ off_t offset = 0;
+
+ InputBufferInfo();
+ ~InputBufferInfo();
+ };
+
+ // The information about the native pixmap used as an output buffer.
+ struct OutputBufferInfo {
+ // GpuMemoryBufferHandle for this buffer to be passed to accelerator.
+ // In non-secure mode, received via BindDmabuf from the client,
+ // in secure mode, a handle to the NativePixmap in protected_pixmap.
+ gfx::GpuMemoryBufferHandle gpu_memory_buffer_handle;
+
+ // Used only in secure mode; handle to the protected buffer backing
+ // this output buffer.
+ std::unique_ptr<ProtectedBufferHandle> protected_buffer_handle;
+
+ OutputBufferInfo();
+ ~OutputBufferInfo();
+ };
+
+ // The helper method to simplify reporting of the status returned to UMA.
+ ArcVideoDecodeAccelerator::Result InitializeTask(
+ const Config& config,
+ ArcVideoDecodeAccelerator::Client* client);
+
+ // Helper function to validate |port| and |index|.
+ bool ValidatePortAndIndex(PortType port, uint32_t index) const;
+
+ // Return true if |planes| is valid for a dmabuf |fd|.
+ bool VerifyDmabuf(const base::ScopedFD& fd,
+ const std::vector<::arc::VideoFramePlane>& planes) const;
+
+ // Creates an InputRecord for the given |bitstream_buffer_id|. The
+ // |buffer_index| is the index of the associated input buffer. The |timestamp|
+ // is the time the video frame should be displayed.
+ void CreateInputRecord(int32_t bitstream_buffer_id,
+ uint32_t buffer_index,
+ int64_t timestamp);
+
+ // Finds the InputRecord which matches to given |bitstream_buffer_id|.
+ // Returns |nullptr| if it cannot be found.
+ InputRecord* FindInputRecord(int32_t bitstream_buffer_id);
+
+ // Notify the client when output format changes.
+ void NotifyOutputFormatChanged();
+
+ // Global counter that keeps track the number of active clients (i.e., how
+ // many VDAs in use by this class).
+ // Since this class only works on the same thread, it's safe to access
+ // |client_count_| without lock.
+ static int client_count_;
+
+ std::unique_ptr<media::VideoDecodeAccelerator> vda_;
+
+ // It's safe to use the pointer here, the life cycle of the |arc_client_|
+ // is longer than this ChromeArcVideoDecodeAccelerator.
+ ArcVideoDecodeAccelerator::Client* arc_client_;
+
+ // The next ID for the bitstream buffer, started from 0.
+ int32_t next_bitstream_buffer_id_;
+
+ gfx::Size coded_size_;
+ gfx::Rect visible_rect_;
+ media::VideoPixelFormat output_pixel_format_;
+
+ // A list of most recent |kMaxNumberOfInputRecord| InputRecords.
+ // |kMaxNumberOfInputRecord| is defined in the cc file.
+ std::list<InputRecord> input_records_;
+
+ // The details of the shared memory of each input buffers.
+ std::vector<std::unique_ptr<InputBufferInfo>> input_buffer_info_;
+
+ // To keep those output buffers which have been bound by bindDmabuf() but
+ // haven't been passed to VDA yet. Will call VDA::ImportBufferForPicture()
+ // when those buffers are used for the first time.
+ std::vector<std::unique_ptr<OutputBufferInfo>> buffers_pending_import_;
+
+ THREAD_CHECKER(thread_checker_);
+ size_t output_buffer_size_;
+
+ // The minimal number of requested output buffers.
+ uint32_t requested_num_of_output_buffers_;
+
+ bool secure_mode_ = false;
+
+ gpu::GpuPreferences gpu_preferences_;
+ ProtectedBufferManager* protected_buffer_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChromeArcVideoDecodeAccelerator);
+};
+
+} // namespace arc
+
+#endif // COMPONENTS_ARC_VIDEO_ACCELERATOR_CHROME_ARC_VIDEO_DECODE_ACCELERATOR_H_
diff --git a/chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc b/chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc
new file mode 100644
index 00000000000..8020a986d10
--- /dev/null
+++ b/chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc
@@ -0,0 +1,269 @@
+// 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 "components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "components/arc/video_accelerator/chrome_arc_video_decode_accelerator.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "mojo/public/cpp/bindings/type_converter.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+
+// Make sure arc::mojom::VideoDecodeAccelerator::Result and
+// arc::ArcVideoDecodeAccelerator::Result match.
+static_assert(
+ static_cast<int>(arc::mojom::VideoDecodeAccelerator::Result::SUCCESS) ==
+ arc::ArcVideoDecodeAccelerator::SUCCESS,
+ "enum mismatch");
+static_assert(static_cast<int>(
+ arc::mojom::VideoDecodeAccelerator::Result::ILLEGAL_STATE) ==
+ arc::ArcVideoDecodeAccelerator::ILLEGAL_STATE,
+ "enum mismatch");
+static_assert(
+ static_cast<int>(
+ arc::mojom::VideoDecodeAccelerator::Result::INVALID_ARGUMENT) ==
+ arc::ArcVideoDecodeAccelerator::INVALID_ARGUMENT,
+ "enum mismatch");
+static_assert(
+ static_cast<int>(
+ arc::mojom::VideoDecodeAccelerator::Result::UNREADABLE_INPUT) ==
+ arc::ArcVideoDecodeAccelerator::UNREADABLE_INPUT,
+ "enum mismatch");
+static_assert(
+ static_cast<int>(
+ arc::mojom::VideoDecodeAccelerator::Result::PLATFORM_FAILURE) ==
+ arc::ArcVideoDecodeAccelerator::PLATFORM_FAILURE,
+ "enum mismatch");
+static_assert(
+ static_cast<int>(
+ arc::mojom::VideoDecodeAccelerator::Result::INSUFFICIENT_RESOURCES) ==
+ arc::ArcVideoDecodeAccelerator::INSUFFICIENT_RESOURCES,
+ "enum mismatch");
+
+namespace mojo {
+
+template <>
+struct TypeConverter<arc::mojom::BufferMetadataPtr, arc::BufferMetadata> {
+ static arc::mojom::BufferMetadataPtr Convert(
+ const arc::BufferMetadata& input) {
+ arc::mojom::BufferMetadataPtr result = arc::mojom::BufferMetadata::New();
+ result->timestamp = input.timestamp;
+ result->bytes_used = input.bytes_used;
+ return result;
+ }
+};
+
+template <>
+struct TypeConverter<arc::BufferMetadata, arc::mojom::BufferMetadataPtr> {
+ static arc::BufferMetadata Convert(
+ const arc::mojom::BufferMetadataPtr& input) {
+ arc::BufferMetadata result;
+ result.timestamp = input->timestamp;
+ result.bytes_used = input->bytes_used;
+ return result;
+ }
+};
+
+template <>
+struct TypeConverter<arc::mojom::VideoFormatPtr, arc::VideoFormat> {
+ static arc::mojom::VideoFormatPtr Convert(const arc::VideoFormat& input) {
+ arc::mojom::VideoFormatPtr result = arc::mojom::VideoFormat::New();
+ result->pixel_format = input.pixel_format;
+ result->buffer_size = input.buffer_size;
+ result->min_num_buffers = input.min_num_buffers;
+ result->coded_width = input.coded_width;
+ result->coded_height = input.coded_height;
+ result->crop_left = input.crop_left;
+ result->crop_width = input.crop_width;
+ result->crop_top = input.crop_top;
+ result->crop_height = input.crop_height;
+ return result;
+ }
+};
+
+template <>
+struct TypeConverter<arc::ArcVideoDecodeAccelerator::Config,
+ arc::mojom::VideoDecodeAcceleratorConfigPtr> {
+ static arc::ArcVideoDecodeAccelerator::Config Convert(
+ const arc::mojom::VideoDecodeAcceleratorConfigPtr& input) {
+ arc::ArcVideoDecodeAccelerator::Config result;
+ result.num_input_buffers = input->num_input_buffers;
+ result.input_pixel_format = input->input_pixel_format;
+ result.secure_mode = input->secure_mode;
+ return result;
+ }
+};
+
+} // namespace mojo
+
+namespace arc {
+
+GpuArcVideoDecodeAccelerator::GpuArcVideoDecodeAccelerator(
+ const gpu::GpuPreferences& gpu_preferences,
+ ProtectedBufferManager* protected_buffer_manager)
+ : gpu_preferences_(gpu_preferences),
+ accelerator_(std::make_unique<ChromeArcVideoDecodeAccelerator>(
+ gpu_preferences_,
+ protected_buffer_manager)) {}
+
+GpuArcVideoDecodeAccelerator::~GpuArcVideoDecodeAccelerator() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+}
+
+void GpuArcVideoDecodeAccelerator::OnError(
+ ArcVideoDecodeAccelerator::Result error) {
+ DVLOG(2) << "OnError " << error;
+ DCHECK_NE(error, ArcVideoDecodeAccelerator::SUCCESS);
+ DCHECK(client_);
+ client_->OnError(
+ static_cast<::arc::mojom::VideoDecodeAccelerator::Result>(error));
+}
+
+void GpuArcVideoDecodeAccelerator::OnBufferDone(
+ PortType port,
+ uint32_t index,
+ const BufferMetadata& metadata) {
+ DVLOG(2) << "OnBufferDone " << port << "," << index;
+ DCHECK(client_);
+ client_->OnBufferDone(static_cast<::arc::mojom::PortType>(port), index,
+ ::arc::mojom::BufferMetadata::From(metadata));
+}
+
+void GpuArcVideoDecodeAccelerator::OnFlushDone() {
+ DVLOG(2) << "OnFlushDone";
+ DCHECK(client_);
+ client_->OnFlushDone();
+}
+
+void GpuArcVideoDecodeAccelerator::OnResetDone() {
+ DVLOG(2) << "OnResetDone";
+ DCHECK(client_);
+ client_->OnResetDone();
+}
+
+void GpuArcVideoDecodeAccelerator::OnOutputFormatChanged(
+ const VideoFormat& format) {
+ DVLOG(2) << "OnOutputFormatChanged";
+ DCHECK(client_);
+ client_->OnOutputFormatChanged(::arc::mojom::VideoFormat::From(format));
+}
+
+void GpuArcVideoDecodeAccelerator::Initialize(
+ ::arc::mojom::VideoDecodeAcceleratorConfigPtr config,
+ ::arc::mojom::VideoDecodeClientPtr client,
+ InitializeCallback callback) {
+ DVLOG(2) << "Initialize";
+ DCHECK(!client_);
+
+ client_ = std::move(client);
+ ArcVideoDecodeAccelerator::Result result = accelerator_->Initialize(
+ config.To<ArcVideoDecodeAccelerator::Config>(), this);
+ std::move(callback).Run(
+ static_cast<::arc::mojom::VideoDecodeAccelerator::Result>(result));
+}
+
+base::ScopedFD GpuArcVideoDecodeAccelerator::UnwrapFdFromMojoHandle(
+ mojo::ScopedHandle handle) {
+ DCHECK(client_);
+ if (!handle.is_valid()) {
+ LOG(ERROR) << "handle is invalid";
+ client_->OnError(
+ ::arc::mojom::VideoDecodeAccelerator::Result::INVALID_ARGUMENT);
+ return base::ScopedFD();
+ }
+
+ base::PlatformFile platform_file;
+ MojoResult mojo_result =
+ mojo::UnwrapPlatformFile(std::move(handle), &platform_file);
+ if (mojo_result != MOJO_RESULT_OK) {
+ LOG(ERROR) << "UnwrapPlatformFile failed: " << mojo_result;
+ client_->OnError(
+ ::arc::mojom::VideoDecodeAccelerator::Result::PLATFORM_FAILURE);
+ return base::ScopedFD();
+ }
+
+ return base::ScopedFD(platform_file);
+}
+
+void GpuArcVideoDecodeAccelerator::AllocateProtectedBuffer(
+ ::arc::mojom::PortType port,
+ uint32_t index,
+ mojo::ScopedHandle handle,
+ uint64_t size,
+ AllocateProtectedBufferCallback callback) {
+ DVLOG(2) << "port=" << port << ", index=" << index << ", size=" << size;
+
+ base::ScopedFD fd = UnwrapFdFromMojoHandle(std::move(handle));
+ if (!fd.is_valid()) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ bool result = accelerator_->AllocateProtectedBuffer(
+ static_cast<PortType>(port), index, std::move(fd), size);
+
+ std::move(callback).Run(result);
+}
+
+void GpuArcVideoDecodeAccelerator::BindSharedMemory(
+ ::arc::mojom::PortType port,
+ uint32_t index,
+ mojo::ScopedHandle ashmem_handle,
+ uint32_t offset,
+ uint32_t length) {
+ DVLOG(2) << "BindSharedMemoryCallback port=" << port << ", index=" << index
+ << ", offset=" << offset << ", length=" << length;
+
+ base::ScopedFD fd = UnwrapFdFromMojoHandle(std::move(ashmem_handle));
+ if (!fd.is_valid())
+ return;
+ accelerator_->BindSharedMemory(static_cast<PortType>(port), index,
+ std::move(fd), offset, length);
+}
+
+void GpuArcVideoDecodeAccelerator::BindDmabuf(
+ ::arc::mojom::PortType port,
+ uint32_t index,
+ mojo::ScopedHandle dmabuf_handle,
+ std::vector<::arc::VideoFramePlane> planes) {
+ DVLOG(2) << "BindDmabuf port=" << port << ", index=" << index;
+
+ base::ScopedFD fd = UnwrapFdFromMojoHandle(std::move(dmabuf_handle));
+ if (!fd.is_valid())
+ return;
+
+ accelerator_->BindDmabuf(static_cast<PortType>(port), index, std::move(fd),
+ std::move(planes));
+}
+
+void GpuArcVideoDecodeAccelerator::UseBuffer(
+ ::arc::mojom::PortType port,
+ uint32_t index,
+ ::arc::mojom::BufferMetadataPtr metadata) {
+ DVLOG(2) << "UseBuffer port=" << port << ", index=" << index;
+ accelerator_->UseBuffer(static_cast<PortType>(port), index,
+ metadata.To<BufferMetadata>());
+}
+
+void GpuArcVideoDecodeAccelerator::SetNumberOfOutputBuffers(uint32_t number) {
+ DVLOG(2) << "SetNumberOfOutputBuffers number=" << number;
+ accelerator_->SetNumberOfOutputBuffers(number);
+}
+
+void GpuArcVideoDecodeAccelerator::Reset() {
+ DVLOG(2) << "Reset";
+ accelerator_->Reset();
+}
+
+void GpuArcVideoDecodeAccelerator::Flush() {
+ DVLOG(2) << "Flush";
+ accelerator_->Flush();
+}
+
+} // namespace arc
diff --git a/chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h b/chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h
new file mode 100644
index 00000000000..6be9cae26e1
--- /dev/null
+++ b/chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h
@@ -0,0 +1,88 @@
+// 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.
+
+#ifndef COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_DECODE_ACCELERATOR_H_
+#define COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_DECODE_ACCELERATOR_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/files/scoped_file.h"
+#include "base/macros.h"
+#include "base/threading/thread_checker.h"
+#include "components/arc/common/video_decode_accelerator.mojom.h"
+#include "components/arc/video_accelerator/arc_video_decode_accelerator.h"
+#include "components/arc/video_accelerator/video_frame_plane.h"
+#include "gpu/command_buffer/service/gpu_preferences.h"
+
+namespace arc {
+
+class ProtectedBufferManager;
+
+// GpuArcVideoDecodeAccelerator manages life-cycle and IPC message translation
+// for ArcVideoDecodeAccelerator.
+//
+// For each creation request from GpuArcVideoDecodeAcceleratorHost,
+// GpuArcVideoDecodeAccelerator will create a new IPC channel.
+class GpuArcVideoDecodeAccelerator
+ : public ::arc::mojom::VideoDecodeAccelerator,
+ public ArcVideoDecodeAccelerator::Client {
+ public:
+ GpuArcVideoDecodeAccelerator(
+ const gpu::GpuPreferences& gpu_preferences,
+ ProtectedBufferManager* protected_buffer_manager);
+ ~GpuArcVideoDecodeAccelerator() override;
+
+ private:
+ // ArcVideoDecodeAccelerator::Client implementation.
+ void OnError(ArcVideoDecodeAccelerator::Result error) override;
+ void OnBufferDone(PortType port,
+ uint32_t index,
+ const BufferMetadata& metadata) override;
+ void OnFlushDone() override;
+ void OnResetDone() override;
+ void OnOutputFormatChanged(const VideoFormat& format) override;
+
+ // ::arc::mojom::VideoDecodeAccelerator implementation.
+ void Initialize(::arc::mojom::VideoDecodeAcceleratorConfigPtr config,
+ ::arc::mojom::VideoDecodeClientPtr client,
+ InitializeCallback callback) override;
+
+ void AllocateProtectedBuffer(
+ ::arc::mojom::PortType port,
+ uint32_t index,
+ mojo::ScopedHandle handle,
+ uint64_t size,
+ AllocateProtectedBufferCallback callback) override;
+
+ void BindSharedMemory(::arc::mojom::PortType port,
+ uint32_t index,
+ mojo::ScopedHandle ashmem_handle,
+ uint32_t offset,
+ uint32_t length) override;
+ void BindDmabuf(::arc::mojom::PortType port,
+ uint32_t index,
+ mojo::ScopedHandle dmabuf_handle,
+ std::vector<::arc::VideoFramePlane> planes) override;
+ void UseBuffer(::arc::mojom::PortType port,
+ uint32_t index,
+ ::arc::mojom::BufferMetadataPtr metadata) override;
+ void SetNumberOfOutputBuffers(uint32_t number) override;
+ void Flush() override;
+ void Reset() override;
+
+ base::ScopedFD UnwrapFdFromMojoHandle(mojo::ScopedHandle handle);
+
+ THREAD_CHECKER(thread_checker_);
+
+ gpu::GpuPreferences gpu_preferences_;
+ std::unique_ptr<ArcVideoDecodeAccelerator> accelerator_;
+ ::arc::mojom::VideoDecodeClientPtr client_;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuArcVideoDecodeAccelerator);
+};
+
+} // namespace arc
+
+#endif // COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_DECODE_ACCELERATOR_H_
diff --git a/chromium/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc b/chromium/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc
new file mode 100644
index 00000000000..2d5e7fb1ad2
--- /dev/null
+++ b/chromium/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc
@@ -0,0 +1,257 @@
+// 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 "components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h"
+
+#include <utility>
+
+#include "base/logging.h"
+#include "base/sys_info.h"
+#include "media/base/video_types.h"
+#include "media/gpu/gpu_video_encode_accelerator_factory.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "mojo/public/cpp/bindings/type_converter.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+
+#define DVLOGF(x) DVLOG(x) << __func__ << "(): "
+
+namespace arc {
+
+namespace {
+
+// Helper class to notify client about the end of processing a video frame.
+class VideoFrameDoneNotifier {
+ public:
+ explicit VideoFrameDoneNotifier(base::OnceClosure notify_closure)
+ : notify_closure_(std::move(notify_closure)) {}
+ ~VideoFrameDoneNotifier() { std::move(notify_closure_).Run(); }
+
+ private:
+ base::OnceClosure notify_closure_;
+};
+
+} // namespace
+
+GpuArcVideoEncodeAccelerator::GpuArcVideoEncodeAccelerator(
+ const gpu::GpuPreferences& gpu_preferences)
+ : gpu_preferences_(gpu_preferences) {}
+
+GpuArcVideoEncodeAccelerator::~GpuArcVideoEncodeAccelerator() = default;
+
+// VideoEncodeAccelerator::Client implementation.
+void GpuArcVideoEncodeAccelerator::RequireBitstreamBuffers(
+ unsigned int input_count,
+ const gfx::Size& coded_size,
+ size_t output_buffer_size) {
+ DVLOGF(2) << "input_count=" << input_count
+ << ", coded_size=" << coded_size.ToString()
+ << ", output_buffer_size=" << output_buffer_size;
+ DCHECK(client_);
+ coded_size_ = coded_size;
+ client_->RequireBitstreamBuffers(input_count, coded_size, output_buffer_size);
+}
+
+void GpuArcVideoEncodeAccelerator::BitstreamBufferReady(
+ int32_t bitstream_buffer_id,
+ size_t payload_size,
+ bool key_frame,
+ base::TimeDelta timestamp) {
+ DVLOGF(2) << "id=" << bitstream_buffer_id;
+ DCHECK(client_);
+ auto iter = use_bitstream_cbs_.find(bitstream_buffer_id);
+ DCHECK(iter != use_bitstream_cbs_.end());
+ std::move(iter->second)
+ .Run(payload_size, key_frame, timestamp.InMicroseconds());
+ use_bitstream_cbs_.erase(iter);
+}
+
+void GpuArcVideoEncodeAccelerator::NotifyError(Error error) {
+ DVLOGF(2) << "error=" << error;
+ DCHECK(client_);
+ client_->NotifyError(error);
+}
+
+// ::arc::mojom::VideoEncodeAccelerator implementation.
+void GpuArcVideoEncodeAccelerator::GetSupportedProfiles(
+ GetSupportedProfilesCallback callback) {
+ std::move(callback).Run(
+ media::GpuVideoEncodeAcceleratorFactory::GetSupportedProfiles(
+ gpu_preferences_));
+}
+
+void GpuArcVideoEncodeAccelerator::Initialize(
+ VideoPixelFormat input_format,
+ const gfx::Size& visible_size,
+ VideoEncodeAccelerator::StorageType input_storage,
+ VideoCodecProfile output_profile,
+ uint32_t initial_bitrate,
+ VideoEncodeClientPtr client,
+ InitializeCallback callback) {
+ DVLOGF(2) << "visible_size=" << visible_size.ToString()
+ << ", profile=" << output_profile;
+
+ input_pixel_format_ = input_format;
+ visible_size_ = visible_size;
+ accelerator_ = media::GpuVideoEncodeAcceleratorFactory::CreateVEA(
+ input_pixel_format_, visible_size_, output_profile, initial_bitrate, this,
+ gpu_preferences_);
+ if (accelerator_ == nullptr) {
+ DLOG(ERROR) << "Failed to create a VideoEncodeAccelerator.";
+ std::move(callback).Run(false);
+ return;
+ }
+ client_ = std::move(client);
+ std::move(callback).Run(true);
+}
+
+static void DropShareMemoryAndVideoFrameDoneNotifier(
+ std::unique_ptr<base::SharedMemory> shm,
+ std::unique_ptr<VideoFrameDoneNotifier> notifier) {
+ // Just let |shm| and |notifier| fall out of scope.
+}
+
+void GpuArcVideoEncodeAccelerator::Encode(
+ mojo::ScopedHandle handle,
+ std::vector<::arc::VideoFramePlane> planes,
+ int64_t timestamp,
+ bool force_keyframe,
+ EncodeCallback callback) {
+ DVLOGF(2) << "timestamp=" << timestamp;
+ if (!accelerator_) {
+ DLOG(ERROR) << "Accelerator is not initialized.";
+ return;
+ }
+
+ auto notifier = std::make_unique<VideoFrameDoneNotifier>(std::move(callback));
+
+ if (planes.empty()) { // EOS
+ accelerator_->Encode(media::VideoFrame::CreateEOSFrame(), force_keyframe);
+ return;
+ }
+
+ base::ScopedFD fd = UnwrapFdFromMojoHandle(std::move(handle));
+ if (!fd.is_valid())
+ return;
+
+ size_t allocation_size =
+ media::VideoFrame::AllocationSize(input_pixel_format_, coded_size_);
+
+ // TODO(rockot): Pass GUIDs through Mojo. https://crbug.com/713763.
+ // TODO(rockot): This fd comes from a mojo::ScopedHandle in
+ // GpuArcVideoService::BindSharedMemory. That should be passed through,
+ // rather than pulling out the fd. https://crbug.com/713763.
+ // TODO(rockot): Pass through a real size rather than |0|.
+ base::UnguessableToken guid = base::UnguessableToken::Create();
+ base::SharedMemoryHandle shm_handle(base::FileDescriptor(fd.release(), true),
+ 0u, guid);
+ auto shm = std::make_unique<base::SharedMemory>(shm_handle, true);
+
+ base::CheckedNumeric<off_t> map_offset = planes[0].offset;
+ base::CheckedNumeric<size_t> map_size = allocation_size;
+ const uint32_t aligned_offset =
+ planes[0].offset % base::SysInfo::VMAllocationGranularity();
+ map_offset -= aligned_offset;
+ map_size += aligned_offset;
+
+ if (!map_offset.IsValid() || !map_size.IsValid()) {
+ DLOG(ERROR) << "Invalid map_offset or map_size";
+ client_->NotifyError(Error::kInvalidArgumentError);
+ return;
+ }
+ if (!shm->MapAt(map_offset.ValueOrDie(), map_size.ValueOrDie())) {
+ DLOG(ERROR) << "Failed to map memory.";
+ client_->NotifyError(Error::kPlatformFailureError);
+ return;
+ }
+
+ uint8_t* shm_memory = reinterpret_cast<uint8_t*>(shm->memory());
+ auto frame = media::VideoFrame::WrapExternalSharedMemory(
+ input_pixel_format_, coded_size_, gfx::Rect(visible_size_), visible_size_,
+ shm_memory + aligned_offset, allocation_size, shm_handle,
+ planes[0].offset, base::TimeDelta::FromMicroseconds(timestamp));
+
+ // Wrap |shm| and |notifier| in a callback and add it as a destruction
+ // observer. When the |frame| goes out of scope, it unmaps and releases
+ // the shared memory as well as notifies |client_| about the end of processing
+ // the |frame|.
+ frame->AddDestructionObserver(
+ base::Bind(&DropShareMemoryAndVideoFrameDoneNotifier, base::Passed(&shm),
+ base::Passed(&notifier)));
+
+ accelerator_->Encode(frame, force_keyframe);
+}
+
+void GpuArcVideoEncodeAccelerator::UseBitstreamBuffer(
+ mojo::ScopedHandle shmem_fd,
+ uint32_t offset,
+ uint32_t size,
+ UseBitstreamBufferCallback callback) {
+ DVLOGF(2) << "serial=" << bitstream_buffer_serial_;
+ if (!accelerator_) {
+ DLOG(ERROR) << "Accelerator is not initialized.";
+ return;
+ }
+
+ base::ScopedFD fd = UnwrapFdFromMojoHandle(std::move(shmem_fd));
+ if (!fd.is_valid())
+ return;
+
+ // TODO(rockot): Pass GUIDs through Mojo. https://crbug.com/713763.
+ // TODO(rockot): This fd comes from a mojo::ScopedHandle in
+ // GpuArcVideoService::BindSharedMemory. That should be passed through,
+ // rather than pulling out the fd. https://crbug.com/713763.
+ // TODO(rockot): Pass through a real size rather than |0|.
+ base::UnguessableToken guid = base::UnguessableToken::Create();
+ base::SharedMemoryHandle shm_handle(base::FileDescriptor(fd.release(), true),
+ 0u, guid);
+ use_bitstream_cbs_.emplace(bitstream_buffer_serial_, std::move(callback));
+ accelerator_->UseOutputBitstreamBuffer(media::BitstreamBuffer(
+ bitstream_buffer_serial_, shm_handle, size, offset));
+
+ // Mask against 30 bits to avoid (undefined) wraparound on signed integer.
+ bitstream_buffer_serial_ = (bitstream_buffer_serial_ + 1) & 0x3FFFFFFF;
+}
+
+void GpuArcVideoEncodeAccelerator::RequestEncodingParametersChange(
+ uint32_t bitrate,
+ uint32_t framerate) {
+ DVLOGF(2) << "bitrate=" << bitrate << ", framerate=" << framerate;
+ if (!accelerator_) {
+ DLOG(ERROR) << "Accelerator is not initialized.";
+ return;
+ }
+ accelerator_->RequestEncodingParametersChange(bitrate, framerate);
+}
+
+void GpuArcVideoEncodeAccelerator::Flush(FlushCallback callback) {
+ DVLOGF(2);
+ if (!accelerator_) {
+ DLOG(ERROR) << "Accelerator is not initialized.";
+ return;
+ }
+ accelerator_->Flush(std::move(callback));
+}
+
+base::ScopedFD GpuArcVideoEncodeAccelerator::UnwrapFdFromMojoHandle(
+ mojo::ScopedHandle handle) {
+ DCHECK(client_);
+ if (!handle.is_valid()) {
+ DLOG(ERROR) << "handle is invalid.";
+ client_->NotifyError(Error::kInvalidArgumentError);
+ return base::ScopedFD();
+ }
+
+ base::PlatformFile platform_file;
+ MojoResult mojo_result =
+ mojo::UnwrapPlatformFile(std::move(handle), &platform_file);
+ if (mojo_result != MOJO_RESULT_OK) {
+ DLOG(ERROR) << "UnwrapPlatformFile failed: " << mojo_result;
+ client_->NotifyError(Error::kPlatformFailureError);
+ return base::ScopedFD();
+ }
+
+ return base::ScopedFD(platform_file);
+}
+
+} // namespace arc
diff --git a/chromium/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h b/chromium/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h
new file mode 100644
index 00000000000..b799ed44f1a
--- /dev/null
+++ b/chromium/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h
@@ -0,0 +1,88 @@
+// 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 COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_ENCODE_ACCELERATOR_H_
+#define COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_ENCODE_ACCELERATOR_H_
+
+#include <memory>
+#include <unordered_map>
+#include <vector>
+
+#include "base/files/scoped_file.h"
+#include "base/macros.h"
+#include "components/arc/common/video_encode_accelerator.mojom.h"
+#include "components/arc/video_accelerator/video_frame_plane.h"
+#include "gpu/command_buffer/service/gpu_preferences.h"
+#include "media/video/video_encode_accelerator.h"
+
+namespace arc {
+
+// GpuArcVideoEncodeAccelerator manages life-cycle and IPC message translation
+// for media::VideoEncodeAccelerator.
+class GpuArcVideoEncodeAccelerator
+ : public ::arc::mojom::VideoEncodeAccelerator,
+ public media::VideoEncodeAccelerator::Client {
+ public:
+ explicit GpuArcVideoEncodeAccelerator(
+ const gpu::GpuPreferences& gpu_preferences);
+ ~GpuArcVideoEncodeAccelerator() override;
+
+ private:
+ using VideoPixelFormat = media::VideoPixelFormat;
+ using VideoCodecProfile = media::VideoCodecProfile;
+ using Error = media::VideoEncodeAccelerator::Error;
+ using VideoEncodeClientPtr = ::arc::mojom::VideoEncodeClientPtr;
+
+ // VideoEncodeAccelerator::Client implementation.
+ void RequireBitstreamBuffers(unsigned int input_count,
+ const gfx::Size& input_coded_size,
+ size_t output_buffer_size) override;
+ void BitstreamBufferReady(int32_t bitstream_buffer_id,
+ size_t payload_size,
+ bool key_frame,
+ base::TimeDelta timestamp) override;
+ void NotifyError(Error error) override;
+
+ // ::arc::mojom::VideoEncodeAccelerator implementation.
+ void GetSupportedProfiles(GetSupportedProfilesCallback callback) override;
+ void Initialize(VideoPixelFormat input_format,
+ const gfx::Size& visible_size,
+ VideoEncodeAccelerator::StorageType input_storage,
+ VideoCodecProfile output_profile,
+ uint32_t initial_bitrate,
+ VideoEncodeClientPtr client,
+ InitializeCallback callback) override;
+ void Encode(mojo::ScopedHandle fd,
+ std::vector<::arc::VideoFramePlane> planes,
+ int64_t timestamp,
+ bool force_keyframe,
+ EncodeCallback callback) override;
+ void UseBitstreamBuffer(mojo::ScopedHandle shmem_fd,
+ uint32_t offset,
+ uint32_t size,
+ UseBitstreamBufferCallback callback) override;
+ void RequestEncodingParametersChange(uint32_t bitrate,
+ uint32_t framerate) override;
+ void Flush(FlushCallback callback) override;
+
+ // Unwraps a file descriptor from the given mojo::ScopedHandle.
+ // If an error is encountered, it returns an invalid base::ScopedFD and
+ // notifies client about the error via VideoEncodeClient::NotifyError.
+ base::ScopedFD UnwrapFdFromMojoHandle(mojo::ScopedHandle handle);
+
+ gpu::GpuPreferences gpu_preferences_;
+ std::unique_ptr<media::VideoEncodeAccelerator> accelerator_;
+ ::arc::mojom::VideoEncodeClientPtr client_;
+ gfx::Size coded_size_;
+ gfx::Size visible_size_;
+ VideoPixelFormat input_pixel_format_;
+ int32_t bitstream_buffer_serial_;
+ std::unordered_map<uint32_t, UseBitstreamBufferCallback> use_bitstream_cbs_;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuArcVideoEncodeAccelerator);
+};
+
+} // namespace arc
+
+#endif // COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_ENCODE_ACCELERATOR_H_
diff --git a/chromium/components/arc/video_accelerator/protected_buffer_manager.cc b/chromium/components/arc/video_accelerator/protected_buffer_manager.cc
new file mode 100644
index 00000000000..60bb2be1821
--- /dev/null
+++ b/chromium/components/arc/video_accelerator/protected_buffer_manager.cc
@@ -0,0 +1,408 @@
+// 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 "components/arc/video_accelerator/protected_buffer_manager.h"
+
+#include "base/bits.h"
+#include "base/logging.h"
+#include "base/memory/shared_memory.h"
+#include "base/sys_info.h"
+#include "mojo/public/cpp/system/buffer.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/surface_factory_ozone.h"
+
+#define VLOGF(level) VLOG(level) << __func__ << "(): "
+
+namespace arc {
+
+namespace {
+// Size of the pixmap to be used as the dummy handle for protected buffers.
+constexpr gfx::Size kDummyBufferSize(32, 32);
+} // namespace
+
+ProtectedBufferHandle::ProtectedBufferHandle(
+ base::OnceClosure destruction_cb,
+ const base::SharedMemoryHandle& shm_handle)
+ : shm_handle_(shm_handle), destruction_cb_(std::move(destruction_cb)) {
+ DCHECK(shm_handle_.IsValid());
+ DCHECK(shm_handle.OwnershipPassesToIPC());
+}
+
+ProtectedBufferHandle::ProtectedBufferHandle(
+ base::OnceClosure destruction_cb,
+ const gfx::NativePixmapHandle& native_pixmap_handle)
+ : native_pixmap_handle_(native_pixmap_handle),
+ destruction_cb_(std::move(destruction_cb)) {
+ DCHECK(!native_pixmap_handle_.fds.empty());
+ for (const auto& fd : native_pixmap_handle_.fds)
+ DCHECK(fd.auto_close);
+}
+
+ProtectedBufferHandle::~ProtectedBufferHandle() {
+ if (shm_handle_.OwnershipPassesToIPC())
+ shm_handle_.Close();
+
+ for (const auto& fd : native_pixmap_handle_.fds) {
+ // Close the fd by wrapping it in a ScopedFD and letting
+ // it fall out of scope.
+ base::ScopedFD scoped_fd(fd.fd);
+ }
+
+ std::move(destruction_cb_).Run();
+}
+
+base::SharedMemoryHandle ProtectedBufferHandle::shm_handle() const {
+ base::SharedMemoryHandle handle = shm_handle_;
+ handle.SetOwnershipPassesToIPC(false);
+ return handle;
+}
+
+gfx::NativePixmapHandle ProtectedBufferHandle::native_pixmap_handle() const {
+ return native_pixmap_handle_;
+}
+
+class ProtectedBufferManager::ProtectedBuffer {
+ public:
+ virtual ~ProtectedBuffer() {}
+
+ // Downcasting methods to return duplicated handles to the underlying
+ // protected buffers for each buffer type, or empty/null handles if not
+ // applicable.
+ virtual base::SharedMemoryHandle DuplicateSharedMemoryHandle() const {
+ return base::SharedMemoryHandle();
+ }
+ virtual gfx::NativePixmapHandle DuplicateNativePixmapHandle() const {
+ return gfx::NativePixmapHandle();
+ }
+
+ // Downcasting method to return a scoped_refptr to the underlying
+ // NativePixmap, or null if not applicable.
+ virtual scoped_refptr<gfx::NativePixmap> GetNativePixmap() const {
+ return nullptr;
+ }
+
+ protected:
+ explicit ProtectedBuffer(scoped_refptr<gfx::NativePixmap> dummy_handle)
+ : dummy_handle_(std::move(dummy_handle)) {}
+
+ private:
+ scoped_refptr<gfx::NativePixmap> dummy_handle_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProtectedBuffer);
+};
+
+class ProtectedBufferManager::ProtectedSharedMemory
+ : public ProtectedBufferManager::ProtectedBuffer {
+ public:
+ ~ProtectedSharedMemory() override;
+
+ // Allocate a ProtectedSharedMemory buffer of |size| bytes.
+ static std::unique_ptr<ProtectedSharedMemory> Create(
+ scoped_refptr<gfx::NativePixmap> dummy_handle,
+ size_t size);
+
+ base::SharedMemoryHandle DuplicateSharedMemoryHandle() const override {
+ return base::SharedMemory::DuplicateHandle(shmem_->handle());
+ }
+
+ private:
+ explicit ProtectedSharedMemory(scoped_refptr<gfx::NativePixmap> dummy_handle);
+
+ std::unique_ptr<base::SharedMemory> shmem_;
+};
+
+ProtectedBufferManager::ProtectedSharedMemory::ProtectedSharedMemory(
+ scoped_refptr<gfx::NativePixmap> dummy_handle)
+ : ProtectedBuffer(std::move(dummy_handle)) {}
+
+ProtectedBufferManager::ProtectedSharedMemory::~ProtectedSharedMemory() {}
+
+// static
+std::unique_ptr<ProtectedBufferManager::ProtectedSharedMemory>
+ProtectedBufferManager::ProtectedSharedMemory::Create(
+ scoped_refptr<gfx::NativePixmap> dummy_handle,
+ size_t size) {
+ std::unique_ptr<ProtectedSharedMemory> protected_shmem(
+ new ProtectedSharedMemory(std::move(dummy_handle)));
+
+ size_t aligned_size =
+ base::bits::Align(size, base::SysInfo::VMAllocationGranularity());
+
+ mojo::ScopedSharedBufferHandle mojo_shared_buffer =
+ mojo::SharedBufferHandle::Create(aligned_size);
+ if (!mojo_shared_buffer->is_valid()) {
+ VLOGF(1) << "Failed to allocate shared memory";
+ return nullptr;
+ }
+
+ base::SharedMemoryHandle shm_handle;
+ MojoResult mojo_result = mojo::UnwrapSharedMemoryHandle(
+ std::move(mojo_shared_buffer), &shm_handle, nullptr, nullptr);
+ if (mojo_result != MOJO_RESULT_OK) {
+ VLOGF(1) << "Failed to unwrap a mojo shared memory handle";
+ return nullptr;
+ }
+
+ protected_shmem->shmem_ =
+ std::make_unique<base::SharedMemory>(shm_handle, false);
+ return protected_shmem;
+}
+
+class ProtectedBufferManager::ProtectedNativePixmap
+ : public ProtectedBufferManager::ProtectedBuffer {
+ public:
+ ~ProtectedNativePixmap() override;
+
+ // Allocate a ProtectedNativePixmap of |format| and |size|.
+ static std::unique_ptr<ProtectedNativePixmap> Create(
+ scoped_refptr<gfx::NativePixmap> dummy_handle,
+ gfx::BufferFormat format,
+ const gfx::Size& size);
+
+ gfx::NativePixmapHandle DuplicateNativePixmapHandle() const override {
+ return native_pixmap_->ExportHandle();
+ }
+
+ scoped_refptr<gfx::NativePixmap> GetNativePixmap() const override {
+ return native_pixmap_;
+ }
+
+ private:
+ explicit ProtectedNativePixmap(scoped_refptr<gfx::NativePixmap> dummy_handle);
+
+ scoped_refptr<gfx::NativePixmap> native_pixmap_;
+};
+
+ProtectedBufferManager::ProtectedNativePixmap::ProtectedNativePixmap(
+ scoped_refptr<gfx::NativePixmap> dummy_handle)
+ : ProtectedBuffer(std::move(dummy_handle)) {}
+
+ProtectedBufferManager::ProtectedNativePixmap::~ProtectedNativePixmap() {}
+
+// static
+std::unique_ptr<ProtectedBufferManager::ProtectedNativePixmap>
+ProtectedBufferManager::ProtectedNativePixmap::Create(
+ scoped_refptr<gfx::NativePixmap> dummy_handle,
+ gfx::BufferFormat format,
+ const gfx::Size& size) {
+ std::unique_ptr<ProtectedNativePixmap> protected_pixmap(
+ new ProtectedNativePixmap(std::move(dummy_handle)));
+
+ ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance();
+ ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone();
+ protected_pixmap->native_pixmap_ =
+ factory->CreateNativePixmap(gfx::kNullAcceleratedWidget, size, format,
+ gfx::BufferUsage::SCANOUT_VDA_WRITE);
+
+ if (!protected_pixmap->native_pixmap_) {
+ VLOGF(1) << "Failed allocating a native pixmap";
+ return nullptr;
+ }
+
+ return protected_pixmap;
+}
+
+ProtectedBufferManager::ProtectedBufferManager() : weak_factory_(this) {
+ VLOGF(2);
+ weak_this_ = weak_factory_.GetWeakPtr();
+}
+
+ProtectedBufferManager::~ProtectedBufferManager() {
+ VLOGF(2);
+}
+
+std::unique_ptr<ProtectedBufferHandle>
+ProtectedBufferManager::AllocateProtectedSharedMemory(base::ScopedFD dummy_fd,
+ size_t size) {
+ VLOGF(2) << "dummy_fd: " << dummy_fd.get() << ", size: " << size;
+
+ // Import the |dummy_fd| to produce a unique id for it.
+ uint32_t id;
+ auto pixmap = ImportDummyFd(std::move(dummy_fd), &id);
+ if (!pixmap)
+ return nullptr;
+
+ base::AutoLock lock(buffer_map_lock_);
+
+ if (buffer_map_.find(id) != buffer_map_.end()) {
+ VLOGF(1) << "A protected buffer for this handle already exists";
+ return nullptr;
+ }
+
+ // Allocate a protected buffer and associate it with the dummy pixmap.
+ // The pixmap needs to be stored to ensure the id remains the same for
+ // the entire lifetime of the dummy pixmap.
+ auto protected_shmem = ProtectedSharedMemory::Create(pixmap, size);
+ if (!protected_shmem) {
+ VLOGF(1) << "Failed allocating a protected shared memory buffer";
+ return nullptr;
+ }
+
+ auto shm_handle = protected_shmem->DuplicateSharedMemoryHandle();
+ if (!shm_handle.IsValid()) {
+ VLOGF(1) << "Failed duplicating SharedMemoryHandle";
+ return nullptr;
+ }
+
+ // Store the buffer in the buffer_map_, and return a handle to it to the
+ // client. The buffer will be permanently removed from the map when the
+ // handle is destroyed.
+ VLOGF(2) << "New protected shared memory buffer, handle id: " << id;
+ auto protected_buffer_handle = std::make_unique<ProtectedBufferHandle>(
+ base::BindOnce(&ProtectedBufferManager::RemoveEntry, weak_this_, id),
+ shm_handle);
+
+ // This will always succeed as we find() first above.
+ buffer_map_.emplace(id, std::move(protected_shmem));
+
+ return protected_buffer_handle;
+}
+
+std::unique_ptr<ProtectedBufferHandle>
+ProtectedBufferManager::AllocateProtectedNativePixmap(base::ScopedFD dummy_fd,
+ gfx::BufferFormat format,
+ const gfx::Size& size) {
+ VLOGF(2) << "dummy_fd: " << dummy_fd.get() << ", format: " << (int)format
+ << ", size: " << size.ToString();
+
+ // Import the |dummy_fd| to produce a unique id for it.
+ uint32_t id = 0;
+ auto pixmap = ImportDummyFd(std::move(dummy_fd), &id);
+ if (!pixmap)
+ return nullptr;
+
+ base::AutoLock lock(buffer_map_lock_);
+
+ if (buffer_map_.find(id) != buffer_map_.end()) {
+ VLOGF(1) << "A protected buffer for this handle already exists";
+ return nullptr;
+ }
+
+ // Allocate a protected buffer and associate it with the dummy pixmap.
+ // The pixmap needs to be stored to ensure the id remains the same for
+ // the entire lifetime of the dummy pixmap.
+ auto protected_pixmap = ProtectedNativePixmap::Create(pixmap, format, size);
+ if (!protected_pixmap) {
+ VLOGF(1) << "Failed allocating a protected native pixmap";
+ return nullptr;
+ }
+
+ auto native_pixmap_handle = protected_pixmap->DuplicateNativePixmapHandle();
+ if (native_pixmap_handle.planes.empty()) {
+ VLOGF(1) << "Failed duplicating NativePixmapHandle";
+ return nullptr;
+ }
+
+ // Store the buffer in the buffer_map_, and return a handle to it to the
+ // client. The buffer will be permanently removed from the map when the
+ // handle is destroyed.
+ VLOGF(2) << "New protected native pixmap, handle id: " << id;
+ auto protected_buffer_handle = std::make_unique<ProtectedBufferHandle>(
+ base::BindOnce(&ProtectedBufferManager::RemoveEntry, weak_this_, id),
+ native_pixmap_handle);
+
+ // This will always succeed as we find() first above.
+ buffer_map_.emplace(id, std::move(protected_pixmap));
+
+ return protected_buffer_handle;
+}
+
+base::SharedMemoryHandle
+ProtectedBufferManager::GetProtectedSharedMemoryHandleFor(
+ base::ScopedFD dummy_fd) {
+ uint32_t id = 0;
+ auto pixmap = ImportDummyFd(std::move(dummy_fd), &id);
+
+ base::AutoLock lock(buffer_map_lock_);
+ const auto& iter = buffer_map_.find(id);
+ if (iter == buffer_map_.end())
+ return base::SharedMemoryHandle();
+
+ return iter->second->DuplicateSharedMemoryHandle();
+}
+
+gfx::NativePixmapHandle
+ProtectedBufferManager::GetProtectedNativePixmapHandleFor(
+ base::ScopedFD dummy_fd) {
+ uint32_t id = 0;
+ auto pixmap = ImportDummyFd(std::move(dummy_fd), &id);
+
+ base::AutoLock lock(buffer_map_lock_);
+ const auto& iter = buffer_map_.find(id);
+ if (iter == buffer_map_.end())
+ return gfx::NativePixmapHandle();
+
+ return iter->second->DuplicateNativePixmapHandle();
+}
+
+scoped_refptr<gfx::NativePixmap>
+ProtectedBufferManager::GetProtectedNativePixmapFor(
+ const gfx::NativePixmapHandle& handle) {
+ // Only the first fd is used for lookup.
+ if (handle.fds.empty())
+ return nullptr;
+
+ base::ScopedFD dummy_fd(HANDLE_EINTR(dup(handle.fds[0].fd)));
+ uint32_t id = 0;
+ auto pixmap = ImportDummyFd(std::move(dummy_fd), &id);
+
+ base::AutoLock lock(buffer_map_lock_);
+ const auto& iter = buffer_map_.find(id);
+ if (iter == buffer_map_.end())
+ return nullptr;
+
+ auto native_pixmap = iter->second->GetNativePixmap();
+ if (native_pixmap) {
+ for (const auto& fd : handle.fds)
+ base::ScopedFD scoped_fd(fd.fd);
+ }
+
+ return native_pixmap;
+}
+
+scoped_refptr<gfx::NativePixmap> ProtectedBufferManager::ImportDummyFd(
+ base::ScopedFD dummy_fd,
+ uint32_t* id) const {
+ // 0 is an invalid handle id.
+ *id = 0;
+
+ // Import dummy_fd to acquire its unique id.
+ // CreateNativePixmapFromHandle() takes ownership and will close the handle
+ // also on failure.
+ gfx::NativePixmapHandle pixmap_handle;
+ pixmap_handle.fds.emplace_back(
+ base::FileDescriptor(dummy_fd.release(), true));
+ pixmap_handle.planes.emplace_back(gfx::NativePixmapPlane());
+ ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance();
+ ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone();
+ scoped_refptr<gfx::NativePixmap> pixmap =
+ factory->CreateNativePixmapForProtectedBufferHandle(
+ gfx::kNullAcceleratedWidget, kDummyBufferSize, gfx::BufferFormat::R_8,
+ pixmap_handle);
+ if (!pixmap) {
+ VLOGF(1) << "Failed importing dummy handle";
+ return nullptr;
+ }
+
+ *id = pixmap->GetUniqueId();
+ if (*id == 0) {
+ VLOGF(1) << "Failed acquiring unique id for handle";
+ return nullptr;
+ }
+
+ return pixmap;
+}
+
+void ProtectedBufferManager::RemoveEntry(uint32_t id) {
+ VLOGF(2) << "id: " << id;
+
+ base::AutoLock lock(buffer_map_lock_);
+ auto num_erased = buffer_map_.erase(id);
+ if (num_erased != 1)
+ VLOGF(1) << "No buffer id " << id << " to destroy";
+}
+
+} // namespace arc
diff --git a/chromium/components/arc/video_accelerator/protected_buffer_manager.h b/chromium/components/arc/video_accelerator/protected_buffer_manager.h
new file mode 100644
index 00000000000..ea6b1e23a3f
--- /dev/null
+++ b/chromium/components/arc/video_accelerator/protected_buffer_manager.h
@@ -0,0 +1,143 @@
+// 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 COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_MANAGER_H_
+#define COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_MANAGER_H_
+
+#include <map>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/shared_memory.h"
+#include "base/memory/weak_ptr.h"
+#include "base/synchronization/lock.h"
+#include "ui/gfx/gpu_memory_buffer.h"
+#include "ui/gfx/native_pixmap.h"
+
+namespace arc {
+
+// A ProtectedBufferHandle is returned to the owning client that requested
+// the underlying ProtectedBuffer to be allocated.
+//
+// A ProtectedBuffer is a buffer that can be referred to via a handle (a dummy
+// handle), which does not provide access to the actual contents of the buffer.
+//
+// The client should release this handle once the buffer is no longer needed.
+// Releasing triggers destruction of the ProtectedBuffer instance stored in
+// the ProtectedBufferManager, via the destruction callback passed to the
+// ProtectedBufferHandle's constructor.
+class ProtectedBufferHandle {
+ public:
+ // ProtectedBufferHandle takes ownership of the passed |shm_handle|.
+ ProtectedBufferHandle(base::OnceClosure destruction_cb,
+ const base::SharedMemoryHandle& shm_handle);
+
+ // ProtectedBufferHandle takes ownership of the passed |native_pixmap_handle|.
+ ProtectedBufferHandle(base::OnceClosure destruction_cb,
+ const gfx::NativePixmapHandle& native_pixmap_handle);
+
+ // Closes the underlying handle.
+ ~ProtectedBufferHandle();
+
+ // Return a non-owned SharedMemoryHandle or NativePixmapHandle for this
+ // ProtectedBufferHandle, or an invalid/null handle if not applicable for the
+ // underlying type.
+ base::SharedMemoryHandle shm_handle() const;
+ gfx::NativePixmapHandle native_pixmap_handle() const;
+
+ private:
+ // The underlying, owning handles to the protected buffer.
+ // Only one of the handles is valid for each instance of this class.
+ // Closed on destruction of this ProtectedBufferHandle.
+ base::SharedMemoryHandle shm_handle_;
+ gfx::NativePixmapHandle native_pixmap_handle_;
+
+ base::OnceClosure destruction_cb_;
+};
+
+class ProtectedBufferManager {
+ public:
+ ProtectedBufferManager();
+ ~ProtectedBufferManager();
+
+ // Allocate a ProtectedSharedMemory buffer of |size| bytes, to be referred to
+ // via |dummy_fd| as the dummy handle, returning a ProtectedBufferHandle to
+ // it.
+ // Destroying the ProtectedBufferHandle will result in permanently
+ // disassociating the |dummy_fd| with the underlying ProtectedBuffer, but may
+ // not free the underlying protected memory, which will remain valid as long
+ // as any SharedMemoryHandles to it are still in use.
+ // Return nullptr on failure.
+ std::unique_ptr<ProtectedBufferHandle> AllocateProtectedSharedMemory(
+ base::ScopedFD dummy_fd,
+ size_t size);
+
+ // Allocate a ProtectedNativePixmap of |format| and |size|, to be referred to
+ // via |dummy_fd| as the dummy handle, returning a ProtectedBufferHandle to
+ // it.
+ // Destroying the ProtectedBufferHandle will result in permanently
+ // disassociating the |dummy_fd| with the underlying ProtectedBuffer, but may
+ // not free the underlying protected memory, which will remain valid as long
+ // as any NativePixmapHandles to it are still in use.
+ // Return nullptr on failure.
+ std::unique_ptr<ProtectedBufferHandle> AllocateProtectedNativePixmap(
+ base::ScopedFD dummy_fd,
+ gfx::BufferFormat format,
+ const gfx::Size& size);
+
+ // Return a duplicated SharedMemoryHandle associated with the |dummy_fd|,
+ // if one exists, or an invalid handle otherwise.
+ // The client is responsible for closing the handle after use.
+ base::SharedMemoryHandle GetProtectedSharedMemoryHandleFor(
+ base::ScopedFD dummy_fd);
+
+ // Return a duplicated NativePixmapHandle associated with the |dummy_fd|,
+ // if one exists, or an empty handle otherwise.
+ // The client is responsible for closing the handle after use.
+ gfx::NativePixmapHandle GetProtectedNativePixmapHandleFor(
+ base::ScopedFD dummy_fd);
+
+ // Return a protected NativePixmap for a dummy |handle|, if one exists, or
+ // nullptr otherwise. On success, the |handle| is closed.
+ scoped_refptr<gfx::NativePixmap> GetProtectedNativePixmapFor(
+ const gfx::NativePixmapHandle& handle);
+
+ private:
+ // Used internally to maintain the association between the dummy handle and
+ // the underlying buffer.
+ class ProtectedBuffer;
+ class ProtectedSharedMemory;
+ class ProtectedNativePixmap;
+
+ // Imports the |dummy_fd| as a NativePixmap. This returns a unique |id|,
+ // which is guaranteed to be the same for all future imports of any fd
+ // referring to the buffer to which |dummy_fd| refers to, regardless of
+ // whether it is the same fd as the original one, or not, for the lifetime
+ // of the buffer.
+ //
+ // This allows us to have an unambiguous mapping from any fd referring to
+ // the same memory buffer to the same unique id.
+ //
+ // Returns nullptr on failure, in which case the returned id is not valid.
+ scoped_refptr<gfx::NativePixmap> ImportDummyFd(base::ScopedFD dummy_fd,
+ uint32_t* id) const;
+
+ // Removes an entry for given |id| from buffer_map_, to be called when the
+ // last reference to the buffer is dropped.
+ void RemoveEntry(uint32_t id);
+
+ // A map of unique ids to the ProtectedBuffers associated with them.
+ using ProtectedBufferMap =
+ std::map<uint32_t, std::unique_ptr<ProtectedBuffer>>;
+ ProtectedBufferMap buffer_map_;
+ base::Lock buffer_map_lock_;
+
+ base::WeakPtr<ProtectedBufferManager> weak_this_;
+ base::WeakPtrFactory<ProtectedBufferManager> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProtectedBufferManager);
+};
+
+} // namespace arc
+
+#endif // COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_MANAGER_H_
diff --git a/chromium/components/arc/video_accelerator/protected_buffer_manager_proxy.cc b/chromium/components/arc/video_accelerator/protected_buffer_manager_proxy.cc
new file mode 100644
index 00000000000..878eefa3ec3
--- /dev/null
+++ b/chromium/components/arc/video_accelerator/protected_buffer_manager_proxy.cc
@@ -0,0 +1,51 @@
+// 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 "components/arc/video_accelerator/protected_buffer_manager_proxy.h"
+
+#include "components/arc/video_accelerator/protected_buffer_manager.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+
+#define VLOGF(level) VLOG(level) << __func__ << "(): "
+
+namespace arc {
+
+GpuArcProtectedBufferManagerProxy::GpuArcProtectedBufferManagerProxy(
+ arc::ProtectedBufferManager* protected_buffer_manager)
+ : protected_buffer_manager_(protected_buffer_manager) {
+ DCHECK(protected_buffer_manager_);
+}
+
+base::ScopedFD GpuArcProtectedBufferManagerProxy::UnwrapFdFromMojoHandle(
+ mojo::ScopedHandle handle) {
+ base::PlatformFile platform_file;
+ MojoResult mojo_result =
+ mojo::UnwrapPlatformFile(std::move(handle), &platform_file);
+ if (mojo_result != MOJO_RESULT_OK) {
+ VLOGF(1) << "UnwrapPlatformFile failed: " << mojo_result;
+ return base::ScopedFD();
+ }
+
+ return base::ScopedFD(platform_file);
+}
+
+mojo::ScopedHandle GpuArcProtectedBufferManagerProxy::WrapFdInMojoHandle(
+ base::ScopedFD fd) {
+ return mojo::WrapPlatformFile(fd.release());
+}
+
+void GpuArcProtectedBufferManagerProxy::GetProtectedSharedMemoryFromHandle(
+ mojo::ScopedHandle dummy_handle,
+ GetProtectedSharedMemoryFromHandleCallback callback) {
+ base::ScopedFD unwrapped_fd = UnwrapFdFromMojoHandle(std::move(dummy_handle));
+
+ base::ScopedFD shmem_fd(
+ protected_buffer_manager_
+ ->GetProtectedSharedMemoryHandleFor(std::move(unwrapped_fd))
+ .Release());
+
+ std::move(callback).Run(WrapFdInMojoHandle(std::move(shmem_fd)));
+}
+
+} // namespace arc
diff --git a/chromium/components/arc/video_accelerator/protected_buffer_manager_proxy.h b/chromium/components/arc/video_accelerator/protected_buffer_manager_proxy.h
new file mode 100644
index 00000000000..15f77864d14
--- /dev/null
+++ b/chromium/components/arc/video_accelerator/protected_buffer_manager_proxy.h
@@ -0,0 +1,37 @@
+// 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 COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_MANAGER_PROXY_H_
+#define COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_MANAGER_PROXY_H_
+
+#include "components/arc/common/protected_buffer_manager.mojom.h"
+
+namespace arc {
+
+class ProtectedBufferManager;
+
+// Manages mojo IPC translation for arc::ProtectedBufferManager.
+class GpuArcProtectedBufferManagerProxy
+ : public ::arc::mojom::ProtectedBufferManager {
+ public:
+ explicit GpuArcProtectedBufferManagerProxy(
+ arc::ProtectedBufferManager* protected_buffer_manager);
+
+ // arc::mojom::ProtectedBufferManager implementation.
+ void GetProtectedSharedMemoryFromHandle(
+ mojo::ScopedHandle dummy_handle,
+ GetProtectedSharedMemoryFromHandleCallback callback) override;
+
+ private:
+ base::ScopedFD UnwrapFdFromMojoHandle(mojo::ScopedHandle handle);
+ mojo::ScopedHandle WrapFdInMojoHandle(base::ScopedFD fd);
+
+ arc::ProtectedBufferManager* protected_buffer_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuArcProtectedBufferManagerProxy);
+};
+
+} // namespace arc
+
+#endif // COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_MANAGER_PROXY_H_
diff --git a/chromium/components/arc/video_accelerator/video_accelerator.h b/chromium/components/arc/video_accelerator/video_frame_plane.h
index 6da58930af8..2b45a6176b2 100644
--- a/chromium/components/arc/video_accelerator/video_accelerator.h
+++ b/chromium/components/arc/video_accelerator/video_frame_plane.h
@@ -2,8 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_ARC_VIDEO_ACCELERATOR_VIDEO_ACCELERATOR_H_
-#define COMPONENTS_ARC_VIDEO_ACCELERATOR_VIDEO_ACCELERATOR_H_
+#ifndef COMPONENTS_ARC_VIDEO_ACCELERATOR_VIDEO_FRAME_PLANE_H_
+#define COMPONENTS_ARC_VIDEO_ACCELERATOR_VIDEO_FRAME_PLANE_H_
+
+#include <stdint.h>
namespace arc {
@@ -14,4 +16,4 @@ struct VideoFramePlane {
} // namespace arc
-#endif // COMPONENTS_ARC_VIDEO_ACCELERATOR_VIDEO_ACCELERATOR_H_
+#endif // COMPONENTS_ARC_VIDEO_ACCELERATOR_VIDEO_FRAME_PLANE_H_
diff --git a/chromium/components/arc/voice_interaction/OWNERS b/chromium/components/arc/voice_interaction/OWNERS
deleted file mode 100644
index ef5cf841917..00000000000
--- a/chromium/components/arc/voice_interaction/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-per-file *_struct_traits*.*=set noparent
-per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
-per-file *_struct_traits*.*=file://components/arc/common/ARC_SECURITY_OWNERS
diff --git a/chromium/components/arc/voice_interaction/voice_interaction_struct_traits.h b/chromium/components/arc/voice_interaction/voice_interaction_struct_traits.h
deleted file mode 100644
index c519f967b29..00000000000
--- a/chromium/components/arc/voice_interaction/voice_interaction_struct_traits.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// 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 COMPONENTS_ARC_VOICE_INTERACTION_VOICE_INTERACTION_STRUCT_TRAITS_H_
-#define COMPONENTS_ARC_VOICE_INTERACTION_VOICE_INTERACTION_STRUCT_TRAITS_H_
-
-#include "ash/public/cpp/voice_interaction_state.h"
-#include "components/arc/common/voice_interaction_framework.mojom.h"
-
-namespace mojo {
-
-template <>
-struct EnumTraits<arc::mojom::VoiceInteractionState,
- ash::VoiceInteractionState> {
- static arc::mojom::VoiceInteractionState ToMojom(
- ash::VoiceInteractionState state) {
- switch (state) {
- case ash::VoiceInteractionState::NOT_READY:
- return arc::mojom::VoiceInteractionState::NOT_READY;
- case ash::VoiceInteractionState::STOPPED:
- return arc::mojom::VoiceInteractionState::STOPPED;
- case ash::VoiceInteractionState::RUNNING:
- return arc::mojom::VoiceInteractionState::RUNNING;
- }
-
- NOTREACHED() << "Invalid state: " << static_cast<int>(state);
- return arc::mojom::VoiceInteractionState::NOT_READY;
- }
-
- static bool FromMojom(arc::mojom::VoiceInteractionState mojom_state,
- ash::VoiceInteractionState* state) {
- switch (mojom_state) {
- case arc::mojom::VoiceInteractionState::NOT_READY:
- *state = ash::VoiceInteractionState::NOT_READY;
- return true;
- case arc::mojom::VoiceInteractionState::STOPPED:
- *state = ash::VoiceInteractionState::STOPPED;
- return true;
- case arc::mojom::VoiceInteractionState::RUNNING:
- *state = ash::VoiceInteractionState::RUNNING;
- return true;
- }
-
- NOTREACHED() << "Invalid state: " << static_cast<int>(mojom_state);
- *state = ash::VoiceInteractionState::NOT_READY;
- return false;
- }
-};
-
-} // namespace mojo
-
-#endif // COMPONENTS_ARC_VOICE_INTERACTION_VOICE_INTERACTION_STRUCT_TRAITS_H_
diff --git a/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.cc b/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.cc
index ce6107a218e..9412567835a 100644
--- a/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.cc
+++ b/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.cc
@@ -67,7 +67,7 @@ ArcVolumeMounterBridge::~ArcVolumeMounterBridge() {
arc_bridge_service_->volume_mounter()->RemoveObserver(this);
}
-void ArcVolumeMounterBridge::OnInstanceReady() {
+void ArcVolumeMounterBridge::OnConnectionReady() {
base::PostTaskWithTraits(FROM_HERE,
{base::TaskPriority::USER_BLOCKING,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
diff --git a/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.h b/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.h
index 2e54fe6f61e..af51cf38d9e 100644
--- a/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.h
+++ b/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.h
@@ -10,7 +10,7 @@
#include "base/macros.h"
#include "chromeos/disks/disk_mount_manager.h"
#include "components/arc/common/volume_mounter.mojom.h"
-#include "components/arc/instance_holder.h"
+#include "components/arc/connection_observer.h"
#include "components/keyed_service/core/keyed_service.h"
#include "mojo/public/cpp/bindings/binding.h"
@@ -27,7 +27,7 @@ class ArcBridgeService;
class ArcVolumeMounterBridge
: public KeyedService,
public chromeos::disks::DiskMountManager::Observer,
- public InstanceHolder<mojom::VolumeMounterInstance>::Observer {
+ public ConnectionObserver<mojom::VolumeMounterInstance> {
public:
// Returns singleton instance for the given BrowserContext,
// or nullptr if the browser |context| is not allowed to use ARC.
@@ -38,8 +38,8 @@ class ArcVolumeMounterBridge
ArcBridgeService* bridge_service);
~ArcVolumeMounterBridge() override;
- // InstanceHolder<mojom::VolumeMounterInstance>::Observer overrides:
- void OnInstanceReady() override;
+ // ConnectionObserver<mojom::VolumeMounterInstance> overrides:
+ void OnConnectionReady() override;
// chromeos::disks::DiskMountManager::Observer overrides:
void OnDiskEvent(