[pip] Add ArcPipBridge.

Currently this only contains some basic things for telling Chrome when
Android PIP has started or finished, but later we may add more.

Bug: 841886
Bug: b/69370942
Test: compiles and ARC runs. ArcPipBridge comes up as well.
Change-Id: I14ac5b6d8628c4cc2f571f06690e6d3c228d943d
Reviewed-on: https://chromium-review.googlesource.com/1120085
Commit-Queue: Eliot Courtney <edcourtney@chromium.org>
Reviewed-by: Mattias Nissler <mnissler@chromium.org>
Reviewed-by: Luis Hector Chavez <lhchavez@chromium.org>
Cr-Commit-Position: refs/heads/master@{#576803}
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index a4e4f4e..3163ad7 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -448,6 +448,8 @@
     "arc/optin/arc_terms_of_service_negotiator.h",
     "arc/optin/arc_terms_of_service_oobe_negotiator.cc",
     "arc/optin/arc_terms_of_service_oobe_negotiator.h",
+    "arc/pip/arc_pip_bridge.cc",
+    "arc/pip/arc_pip_bridge.h",
     "arc/policy/arc_android_management_checker.cc",
     "arc/policy/arc_android_management_checker.h",
     "arc/policy/arc_policy_bridge.cc",
diff --git a/chrome/browser/chromeos/arc/arc_service_launcher.cc b/chrome/browser/chromeos/arc/arc_service_launcher.cc
index 82ef219..69ae214 100644
--- a/chrome/browser/chromeos/arc/arc_service_launcher.cc
+++ b/chrome/browser/chromeos/arc/arc_service_launcher.cc
@@ -27,6 +27,7 @@
 #include "chrome/browser/chromeos/arc/notification/arc_boot_error_notification.h"
 #include "chrome/browser/chromeos/arc/notification/arc_provision_notification_service.h"
 #include "chrome/browser/chromeos/arc/oemcrypto/arc_oemcrypto_bridge.h"
+#include "chrome/browser/chromeos/arc/pip/arc_pip_bridge.h"
 #include "chrome/browser/chromeos/arc/policy/arc_policy_bridge.h"
 #include "chrome/browser/chromeos/arc/policy/arc_policy_util.h"
 #include "chrome/browser/chromeos/arc/print/arc_print_service.h"
@@ -163,6 +164,7 @@
   ArcNetHostImpl::GetForBrowserContext(profile);
   ArcObbMounterBridge::GetForBrowserContext(profile);
   ArcOemCryptoBridge::GetForBrowserContext(profile);
+  ArcPipBridge::GetForBrowserContext(profile);
   ArcPolicyBridge::GetForBrowserContext(profile);
   ArcPowerBridge::GetForBrowserContext(profile);
   ArcPrintService::GetForBrowserContext(profile);
diff --git a/chrome/browser/chromeos/arc/pip/arc_pip_bridge.cc b/chrome/browser/chromeos/arc/pip/arc_pip_bridge.cc
new file mode 100644
index 0000000..568415e
--- /dev/null
+++ b/chrome/browser/chromeos/arc/pip/arc_pip_bridge.cc
@@ -0,0 +1,76 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/arc/pip/arc_pip_bridge.h"
+
+#include "base/logging.h"
+#include "base/memory/singleton.h"
+#include "components/arc/arc_bridge_service.h"
+#include "components/arc/arc_browser_context_keyed_service_factory_base.h"
+
+namespace arc {
+
+namespace {
+
+// Singleton factory for ArcPipBridge.
+class ArcPipBridgeFactory
+    : public internal::ArcBrowserContextKeyedServiceFactoryBase<
+          ArcPipBridge,
+          ArcPipBridgeFactory> {
+ public:
+  // Factory name used by ArcBrowserContextKeyedServiceFactoryBase.
+  static constexpr const char* kName = "ArcPipBridgeFactory";
+
+  static ArcPipBridgeFactory* GetInstance() {
+    return base::Singleton<ArcPipBridgeFactory>::get();
+  }
+
+ private:
+  friend base::DefaultSingletonTraits<ArcPipBridgeFactory>;
+
+  ArcPipBridgeFactory() = default;
+  ~ArcPipBridgeFactory() override = default;
+};
+
+}  // namespace
+
+// static
+ArcPipBridge* ArcPipBridge::GetForBrowserContext(
+    content::BrowserContext* context) {
+  return ArcPipBridgeFactory::GetForBrowserContext(context);
+}
+
+ArcPipBridge::ArcPipBridge(content::BrowserContext* context,
+                           ArcBridgeService* bridge_service)
+    : arc_bridge_service_(bridge_service) {
+  DVLOG(2) << "ArcPipBridge::ArcPipBridge";
+  arc_bridge_service_->pip()->SetHost(this);
+  arc_bridge_service_->pip()->AddObserver(this);
+}
+
+ArcPipBridge::~ArcPipBridge() {
+  DVLOG(2) << "ArcPipBridge::~ArcPipBridge";
+  arc_bridge_service_->pip()->RemoveObserver(this);
+  arc_bridge_service_->pip()->SetHost(nullptr);
+}
+
+void ArcPipBridge::OnConnectionReady() {
+  DVLOG(1) << "ArcPipBridge::OnConnectionReady";
+}
+
+void ArcPipBridge::OnConnectionClosed() {
+  DVLOG(1) << "ArcPipBridge::OnConnectionClosed";
+}
+
+void ArcPipBridge::OnPipEvent(arc::mojom::ArcPipEvent event) {
+  DVLOG(1) << "ArcPipBridge::OnPipEvent";
+  // TODO: Implement.
+}
+
+void ArcPipBridge::ClosePip() {
+  DVLOG(1) << "ArcPipBridge::ClosePip";
+  // TODO: Implement.
+}
+
+}  // namespace arc
diff --git a/chrome/browser/chromeos/arc/pip/arc_pip_bridge.h b/chrome/browser/chromeos/arc/pip/arc_pip_bridge.h
new file mode 100644
index 0000000..ed51047
--- /dev/null
+++ b/chrome/browser/chromeos/arc/pip/arc_pip_bridge.h
@@ -0,0 +1,50 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_ARC_PIP_ARC_PIP_BRIDGE_H_
+#define CHROME_BROWSER_CHROMEOS_ARC_PIP_ARC_PIP_BRIDGE_H_
+
+#include "components/arc/common/pip.mojom.h"
+#include "components/arc/connection_observer.h"
+#include "components/keyed_service/core/keyed_service.h"
+
+namespace content {
+class BrowserContext;
+}  // namespace content
+
+namespace arc {
+
+class ArcBridgeService;
+
+class ArcPipBridge : public KeyedService,
+                     public ConnectionObserver<mojom::PipInstance>,
+                     public mojom::PipHost {
+ public:
+  // Returns singleton instance for the given BrowserContext,
+  // or nullptr if the browser |context| is not allowed to use ARC.
+  static ArcPipBridge* GetForBrowserContext(content::BrowserContext* context);
+
+  ArcPipBridge(content::BrowserContext* context,
+               ArcBridgeService* bridge_service);
+  ~ArcPipBridge() override;
+
+  // ConnectionObserver<mojom::PipInstance> overrides.
+  void OnConnectionReady() override;
+  void OnConnectionClosed() override;
+
+  // PipHost overrides.
+  void OnPipEvent(arc::mojom::ArcPipEvent event) override;
+
+  // PipInstance methods:
+  void ClosePip();
+
+ private:
+  ArcBridgeService* const arc_bridge_service_;
+
+  DISALLOW_COPY_AND_ASSIGN(ArcPipBridge);
+};
+
+}  // namespace arc
+
+#endif  // CHROME_BROWSER_CHROMEOS_ARC_PIP_ARC_PIP_BRIDGE_H_
diff --git a/components/arc/arc_bridge_host_impl.cc b/components/arc/arc_bridge_host_impl.cc
index 93e74a8..8710786 100644
--- a/components/arc/arc_bridge_host_impl.cc
+++ b/components/arc/arc_bridge_host_impl.cc
@@ -179,6 +179,10 @@
   OnInstanceReady(arc_bridge_service_->oemcrypto(), std::move(oemcrypto_ptr));
 }
 
+void ArcBridgeHostImpl::OnPipInstanceReady(mojom::PipInstancePtr pip_ptr) {
+  OnInstanceReady(arc_bridge_service_->pip(), std::move(pip_ptr));
+}
+
 void ArcBridgeHostImpl::OnPolicyInstanceReady(
     mojom::PolicyInstancePtr policy_ptr) {
   OnInstanceReady(arc_bridge_service_->policy(), std::move(policy_ptr));
diff --git a/components/arc/arc_bridge_host_impl.h b/components/arc/arc_bridge_host_impl.h
index df466053..b1a32a3 100644
--- a/components/arc/arc_bridge_host_impl.h
+++ b/components/arc/arc_bridge_host_impl.h
@@ -79,6 +79,7 @@
       mojom::ObbMounterInstancePtr obb_mounter_ptr) override;
   void OnOemCryptoInstanceReady(
       mojom::OemCryptoInstancePtr oemcrypto_ptr) override;
+  void OnPipInstanceReady(mojom::PipInstancePtr policy_ptr) override;
   void OnPolicyInstanceReady(mojom::PolicyInstancePtr policy_ptr) override;
   void OnPowerInstanceReady(mojom::PowerInstancePtr power_ptr) override;
   void OnPrintInstanceReady(mojom::PrintInstancePtr print_ptr) override;
diff --git a/components/arc/arc_bridge_service.h b/components/arc/arc_bridge_service.h
index 75dc046..d0602a6 100644
--- a/components/arc/arc_bridge_service.h
+++ b/components/arc/arc_bridge_service.h
@@ -61,6 +61,8 @@
 class ObbMounterInstance;
 class OemCryptoHost;
 class OemCryptoInstance;
+class PipHost;
+class PipInstance;
 class PolicyHost;
 class PolicyInstance;
 class PowerHost;
@@ -187,6 +189,7 @@
   oemcrypto() {
     return &oemcrypto_;
   }
+  ConnectionHolder<mojom::PipInstance, mojom::PipHost>* pip() { return &pip_; }
   ConnectionHolder<mojom::PolicyInstance, mojom::PolicyHost>* policy() {
     return &policy_;
   }
@@ -277,6 +280,7 @@
   ConnectionHolder<mojom::ObbMounterInstance, mojom::ObbMounterHost>
       obb_mounter_;
   ConnectionHolder<mojom::OemCryptoInstance, mojom::OemCryptoHost> oemcrypto_;
+  ConnectionHolder<mojom::PipInstance, mojom::PipHost> pip_;
   ConnectionHolder<mojom::PolicyInstance, mojom::PolicyHost> policy_;
   ConnectionHolder<mojom::PowerInstance, mojom::PowerHost> power_;
   ConnectionHolder<mojom::PrintInstance, mojom::PrintHost> print_;
diff --git a/components/arc/common/BUILD.gn b/components/arc/common/BUILD.gn
index fba35b7..c93e2bb 100644
--- a/components/arc/common/BUILD.gn
+++ b/components/arc/common/BUILD.gn
@@ -38,6 +38,7 @@
       "obb_mounter.mojom",
       "oemcrypto.mojom",
       "oemcrypto_daemon.mojom",
+      "pip.mojom",
       "policy.mojom",
       "power.mojom",
       "print.mojom",
diff --git a/components/arc/common/arc_bridge.mojom b/components/arc/common/arc_bridge.mojom
index 0ddd823..e0e35fe 100644
--- a/components/arc/common/arc_bridge.mojom
+++ b/components/arc/common/arc_bridge.mojom
@@ -30,6 +30,7 @@
 import "components/arc/common/notifications.mojom";
 import "components/arc/common/obb_mounter.mojom";
 import "components/arc/common/oemcrypto.mojom";
+import "components/arc/common/pip.mojom";
 import "components/arc/common/policy.mojom";
 import "components/arc/common/power.mojom";
 import "components/arc/common/print.mojom";
@@ -48,9 +49,9 @@
 import "components/arc/common/wake_lock.mojom";
 import "components/arc/common/wallpaper.mojom";
 
-// Next MinVersion: 41
+// Next MinVersion: 42
 // Deprecated method IDs: 101, 105
-// Next method ID: 146
+// Next method ID: 147
 interface ArcBridgeHost {
   // Keep the entries alphabetical. In order to do so without breaking
   // compatibility with the ARC instance, explicitly assign each interface a
@@ -143,6 +144,9 @@
   // Notifies Chrome that the OemCryptoInstance interface is ready.
   [MinVersion=28] OnOemCryptoInstanceReady@133(OemCryptoInstance instance_ptr);
 
+  // Notifies Chrome that the PipInstance interface is ready.
+  [MinVersion=41] OnPipInstanceReady@146(PipInstance instance_ptr);
+
   // Notifies Chrome that the PolicyInstance interface is ready.
   [MinVersion=7] OnPolicyInstanceReady@114(PolicyInstance instance_ptr);
 
diff --git a/components/arc/common/pip.mojom b/components/arc/common/pip.mojom
new file mode 100644
index 0000000..a466947
--- /dev/null
+++ b/components/arc/common/pip.mojom
@@ -0,0 +1,37 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Next MinVersion: 1
+
+module arc.mojom;
+
+// Contains the types of PIP events that happened in Android that we may want
+// to react to on the Chrome side. Currently, this only contains the ENTER
+// event, but if we want to signal other events later, we can add
+// a new event type here (e.g. media started/stopped playing).
+[Extensible]
+enum ArcPipEvent {
+  ENTER = 0,
+};
+
+// Interface for Android communicating to Chrome.
+// Next Method ID: 1
+interface PipHost {
+  // Tells Chrome about the status of the Android PIP window. If Android
+  // opens a PIP window, we may want to close any existing Chrome-side PIP
+  // windows.
+  OnPipEvent@0(ArcPipEvent event);
+};
+
+// Interface for communicating to Android.
+// Next Method ID: 2
+interface PipInstance {
+  // Establishes full-duplex communication with the host.
+  Init@0(PipHost host_ptr) => ();
+
+  // Instruct Android to close the current Android PIP window, if it exists.
+  // This is used if the user initiates a Chrome side PIP window, since we
+  // want to avoid showing two PIP windows at the same time.
+  ClosePip@1();
+};
diff --git a/components/arc/test/fake_arc_bridge_host.cc b/components/arc/test/fake_arc_bridge_host.cc
index de7adea..1d4f3f9 100644
--- a/components/arc/test/fake_arc_bridge_host.cc
+++ b/components/arc/test/fake_arc_bridge_host.cc
@@ -84,6 +84,8 @@
 void FakeArcBridgeHost::OnOemCryptoInstanceReady(
     mojom::OemCryptoInstancePtr oemcrypto_ptr) {}
 
+void FakeArcBridgeHost::OnPipInstanceReady(mojom::PipInstancePtr pip_ptr) {}
+
 void FakeArcBridgeHost::OnPolicyInstanceReady(
     mojom::PolicyInstancePtr policy_ptr) {}
 
diff --git a/components/arc/test/fake_arc_bridge_host.h b/components/arc/test/fake_arc_bridge_host.h
index 452e28460..00e922d 100644
--- a/components/arc/test/fake_arc_bridge_host.h
+++ b/components/arc/test/fake_arc_bridge_host.h
@@ -59,6 +59,7 @@
       mojom::ObbMounterInstancePtr obb_mounter_ptr) override;
   void OnOemCryptoInstanceReady(
       mojom::OemCryptoInstancePtr oemcrypto_ptr) override;
+  void OnPipInstanceReady(mojom::PipInstancePtr pip_ptr) override;
   void OnPolicyInstanceReady(mojom::PolicyInstancePtr policy_ptr) override;
   void OnPowerInstanceReady(mojom::PowerInstancePtr power_ptr) override;
   void OnPrintInstanceReady(mojom::PrintInstancePtr print_ptr) override;