Add GeolocationContext mojo interface.

This CL is one step of the Geolocation Servicification project.
Before moving geolocation core to //services, both //content and //devtools
shouldn't call the device::GeolocationContext directly, instead, they should
call via mojo.

1) Add GeolocationContext mojo interface.
2) Host the GeolocationContext by Device Service.
3) Change devtool to call the GeolocationContext mojo interface.

My test steps in Ubuntu-16.04: 
1) Build out a executable chrome, you need to obtain a Google API key
and provide it to Chromium either at build time or at runtime. See how
to do in https://www.chromium.org/developers/how-tos/api-keys

2) I setup a SimpleHTTPServer by python, add the test pages like:
<script type="text/javascript">
if (navigator.geolocation)
{  navigator.geolocation.getCurrentPosition(
     function( position ) {  
	show_msg( position );
     },
     function( err ) {
        alert('error!')
     })
}
else
   alert( 'your browser doesn't support Geolocation' );
	  
function show_msg( position )
{   var lat = position.coords.latitude;
    var lng = position.coords.longitude;
    alert( "latitude:" + lat + ",longitude" + lng );
}
</script>

3) Visit the test page, verify chrome can get the Geo-position.
4) In DevTools, choose 'Console', press "ESC" then the 'Sensors' panel
shows, change the 'Geolocation' dropbox value, verify the Geo-position is
overrided.

BUG=725063

Cq-Include-Trybots: master.tryserver.chromium.linux:linux_site_isolation
Change-Id: Ic92e3d4b10db763e6eb9dec2fa59fd0240469592
Reviewed-on: https://chromium-review.googlesource.com/735204
Commit-Queue: Ke He <ke.he@intel.com>
Reviewed-by: John Abd-El-Malek <jam@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Tim Volodine <timvolodine@chromium.org>
Reviewed-by: Colin Blundell <blundell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#515110}
diff --git a/content/browser/devtools/protocol/emulation_handler.cc b/content/browser/devtools/protocol/emulation_handler.cc
index 1822b69..5dcac90d 100644
--- a/content/browser/devtools/protocol/emulation_handler.cc
+++ b/content/browser/devtools/protocol/emulation_handler.cc
@@ -14,16 +14,14 @@
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/common/view_messages.h"
 #include "content/public/common/url_constants.h"
-#include "device/geolocation/geolocation_context.h"
 #include "device/geolocation/public/cpp/geoposition.h"
+#include "device/geolocation/public/interfaces/geolocation_context.mojom.h"
 #include "device/geolocation/public/interfaces/geoposition.mojom.h"
 #include "ui/events/gesture_detection/gesture_provider_config_helper.h"
 
 namespace content {
 namespace protocol {
 
-using GeolocationContext = device::GeolocationContext;
-
 namespace {
 
 blink::WebScreenOrientationType WebScreenOrientationTypeFromString(
@@ -96,8 +94,7 @@
   if (!GetWebContents())
     return Response::InternalError();
 
-  GeolocationContext* geolocation_context =
-      GetWebContents()->GetGeolocationContext();
+  auto* geolocation_context = GetWebContents()->GetGeolocationContext();
   auto geoposition = device::mojom::Geoposition::New();
   if (latitude.isJust() && longitude.isJust() && accuracy.isJust()) {
     geoposition->latitude = latitude.fromJust();
@@ -107,6 +104,7 @@
 
     if (!device::ValidateGeoposition(*geoposition))
       return Response::Error("Invalid geolocation");
+
   } else {
     geoposition->error_code =
         device::mojom::Geoposition::ErrorCode::POSITION_UNAVAILABLE;
@@ -119,8 +117,7 @@
   if (!GetWebContents())
     return Response::InternalError();
 
-  GeolocationContext* geolocation_context =
-      GetWebContents()->GetGeolocationContext();
+  auto* geolocation_context = GetWebContents()->GetGeolocationContext();
   geolocation_context->ClearOverride();
   return Response::OK();
 }
diff --git a/content/browser/frame_host/render_frame_host_delegate.cc b/content/browser/frame_host/render_frame_host_delegate.cc
index d2d2723..9d3a7d99 100644
--- a/content/browser/frame_host/render_frame_host_delegate.cc
+++ b/content/browser/frame_host/render_frame_host_delegate.cc
@@ -73,7 +73,8 @@
   return nullptr;
 }
 
-device::GeolocationContext* RenderFrameHostDelegate::GetGeolocationContext() {
+device::mojom::GeolocationContext*
+RenderFrameHostDelegate::GetGeolocationContext() {
   return nullptr;
 }
 
diff --git a/content/browser/frame_host/render_frame_host_delegate.h b/content/browser/frame_host/render_frame_host_delegate.h
index 22a2cf2..a654997 100644
--- a/content/browser/frame_host/render_frame_host_delegate.h
+++ b/content/browser/frame_host/render_frame_host_delegate.h
@@ -18,6 +18,7 @@
 #include "content/public/browser/site_instance.h"
 #include "content/public/common/javascript_dialog_type.h"
 #include "content/public/common/media_stream_request.h"
+#include "device/geolocation/public/interfaces/geolocation_context.mojom.h"
 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
 #include "net/http/http_response_headers.h"
 #include "services/device/public/interfaces/wake_lock.mojom.h"
@@ -38,10 +39,6 @@
 class Message;
 }
 
-namespace device {
-class GeolocationContext;
-}
-
 namespace gfx {
 class Rect;
 }
@@ -204,7 +201,7 @@
       int browser_plugin_instance_id);
 
   // Gets the GeolocationContext associated with this delegate.
-  virtual device::GeolocationContext* GetGeolocationContext();
+  virtual device::mojom::GeolocationContext* GetGeolocationContext();
 
   // Gets the WakeLock that serves wake lock requests from the renderer.
   virtual device::mojom::WakeLock* GetRendererWakeLock();
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 6ef5830..31fc1f88 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -2993,8 +2993,7 @@
       GetProcess()->GetBrowserContext()->GetPermissionManager();
 
   if (delegate_) {
-    device::GeolocationContext* geolocation_context =
-        delegate_->GetGeolocationContext();
+    auto* geolocation_context = delegate_->GetGeolocationContext();
     if (geolocation_context && permission_manager) {
       geolocation_service_.reset(new GeolocationServiceImpl(
           geolocation_context, permission_manager, this));
diff --git a/content/browser/geolocation/geolocation_service_impl.cc b/content/browser/geolocation/geolocation_service_impl.cc
index 0791f7e..7ea3b5a 100644
--- a/content/browser/geolocation/geolocation_service_impl.cc
+++ b/content/browser/geolocation/geolocation_service_impl.cc
@@ -8,7 +8,6 @@
 #include "content/public/browser/permission_type.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/common/content_features.h"
-#include "device/geolocation/geolocation_context.h"
 #include "third_party/WebKit/common/feature_policy/feature_policy_feature.h"
 
 namespace content {
@@ -58,7 +57,7 @@
 }
 
 GeolocationServiceImpl::GeolocationServiceImpl(
-    device::GeolocationContext* geolocation_context,
+    device::mojom::GeolocationContext* geolocation_context,
     PermissionManager* permission_manager,
     RenderFrameHost* render_frame_host)
     : geolocation_context_(geolocation_context),
@@ -102,7 +101,7 @@
   if (permission_status != blink::mojom::PermissionStatus::GRANTED)
     return;
 
-  geolocation_context_->Bind(std::move(request));
+  geolocation_context_->BindGeolocation(std::move(request));
 }
 
 }  // namespace content
diff --git a/content/browser/geolocation/geolocation_service_impl.h b/content/browser/geolocation/geolocation_service_impl.h
index 8db8b336..4d6d169 100644
--- a/content/browser/geolocation/geolocation_service_impl.h
+++ b/content/browser/geolocation/geolocation_service_impl.h
@@ -7,6 +7,7 @@
 
 #include "content/common/content_export.h"
 #include "device/geolocation/public/interfaces/geolocation.mojom.h"
+#include "device/geolocation/public/interfaces/geolocation_context.mojom.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "third_party/WebKit/public/platform/modules/geolocation/geolocation_service.mojom.h"
 
@@ -16,10 +17,6 @@
 }
 }  // namespace blink
 
-namespace device {
-class GeolocationContext;
-}
-
 namespace content {
 class RenderFrameHost;
 class PermissionManager;
@@ -47,7 +44,7 @@
 class CONTENT_EXPORT GeolocationServiceImpl
     : public blink::mojom::GeolocationService {
  public:
-  GeolocationServiceImpl(device::GeolocationContext* geolocation_context,
+  GeolocationServiceImpl(device::mojom::GeolocationContext* geolocation_context,
                          PermissionManager* permission_manager,
                          RenderFrameHost* render_frame_host);
   ~GeolocationServiceImpl() override;
@@ -67,7 +64,7 @@
       device::mojom::GeolocationRequest request,
       blink::mojom::PermissionStatus permission_status);
 
-  device::GeolocationContext* geolocation_context_;
+  device::mojom::GeolocationContext* geolocation_context_;
   PermissionManager* permission_manager_;
   RenderFrameHost* render_frame_host_;
 
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 5c02096f..e51a993 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -120,9 +120,9 @@
 #include "content/public/common/page_state.h"
 #include "content/public/common/page_zoom.h"
 #include "content/public/common/result_codes.h"
+#include "content/public/common/service_manager_connection.h"
 #include "content/public/common/url_utils.h"
 #include "content/public/common/web_preferences.h"
-#include "device/geolocation/geolocation_context.h"
 #include "net/base/url_util.h"
 #include "net/http/http_cache.h"
 #include "net/http/http_transaction_factory.h"
@@ -130,7 +130,9 @@
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "ppapi/features/features.h"
+#include "services/device/public/interfaces/constants.mojom.h"
 #include "services/metrics/public/cpp/ukm_recorder.h"
+#include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "third_party/WebKit/common/mime_util/mime_util.h"
 #include "third_party/WebKit/common/sandbox_flags.h"
@@ -539,7 +541,6 @@
       is_subframe_(false),
       force_disable_overscroll_content_(false),
       last_dialog_suppressed_(false),
-      geolocation_context_(new device::GeolocationContext()),
       accessibility_mode_(
           BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode()),
       audio_stream_monitor_(this),
@@ -2722,7 +2723,17 @@
   return guest->GetMainFrame();
 }
 
-device::GeolocationContext* WebContentsImpl::GetGeolocationContext() {
+device::mojom::GeolocationContext* WebContentsImpl::GetGeolocationContext() {
+  if (geolocation_context_)
+    return geolocation_context_.get();
+
+  auto request = mojo::MakeRequest(&geolocation_context_);
+  if (!ServiceManagerConnection::GetForProcess())
+    return geolocation_context_.get();
+
+  service_manager::Connector* connector =
+      ServiceManagerConnection::GetForProcess()->GetConnector();
+  connector->BindInterface(device::mojom::kServiceName, std::move(request));
   return geolocation_context_.get();
 }
 
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 0ee69ade..edf88164 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -46,6 +46,7 @@
 #include "content/public/common/renderer_preferences.h"
 #include "content/public/common/resource_type.h"
 #include "content/public/common/three_d_api_types.h"
+#include "device/geolocation/public/interfaces/geolocation_context.mojom.h"
 #include "net/base/load_states.h"
 #include "net/http/http_response_headers.h"
 #include "ppapi/features/features.h"
@@ -524,7 +525,7 @@
   RenderFrameHost* GetGuestByInstanceID(
       RenderFrameHost* render_frame_host,
       int browser_plugin_instance_id) override;
-  device::GeolocationContext* GetGeolocationContext() override;
+  device::mojom::GeolocationContext* GetGeolocationContext() override;
   device::mojom::WakeLockContext* GetWakeLockContext() override;
   device::mojom::WakeLock* GetRendererWakeLock() override;
 #if defined(OS_ANDROID)
@@ -1598,7 +1599,7 @@
   // Whether the last JavaScript dialog shown was suppressed. Used for testing.
   bool last_dialog_suppressed_;
 
-  std::unique_ptr<device::GeolocationContext> geolocation_context_;
+  device::mojom::GeolocationContextPtr geolocation_context_;
 
   std::unique_ptr<WakeLockContextHost> wake_lock_context_host_;
 
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json
index a1847b8..60aa626 100644
--- a/content/public/app/mojo/content_browser_manifest.json
+++ b/content/public/app/mojo/content_browser_manifest.json
@@ -73,6 +73,7 @@
         "device": [
           "device:battery_monitor",
           "device:generic_sensor",
+          "device:geolocation",
           "device:hid",
           "device:input_service",
           "device:nfc",
diff --git a/device/geolocation/geolocation_context.cc b/device/geolocation/geolocation_context.cc
index 75d7740..d66bddcf 100644
--- a/device/geolocation/geolocation_context.cc
+++ b/device/geolocation/geolocation_context.cc
@@ -8,6 +8,7 @@
 
 #include "base/memory/ptr_util.h"
 #include "device/geolocation/geolocation_impl.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
 
 namespace device {
 
@@ -15,7 +16,13 @@
 
 GeolocationContext::~GeolocationContext() {}
 
-void GeolocationContext::Bind(mojom::GeolocationRequest request) {
+// static
+void GeolocationContext::Create(mojom::GeolocationContextRequest request) {
+  mojo::MakeStrongBinding(base::MakeUnique<GeolocationContext>(),
+                          std::move(request));
+}
+
+void GeolocationContext::BindGeolocation(mojom::GeolocationRequest request) {
   GeolocationImpl* impl = new GeolocationImpl(std::move(request), this);
   impls_.push_back(base::WrapUnique<GeolocationImpl>(impl));
   if (geoposition_override_)
diff --git a/device/geolocation/geolocation_context.h b/device/geolocation/geolocation_context.h
index b642cbbd..1cdcb88 100644
--- a/device/geolocation/geolocation_context.h
+++ b/device/geolocation/geolocation_context.h
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "device/geolocation/geolocation_export.h"
 #include "device/geolocation/public/interfaces/geolocation.mojom.h"
+#include "device/geolocation/public/interfaces/geolocation_context.mojom.h"
 #include "device/geolocation/public/interfaces/geoposition.mojom.h"
 
 namespace device {
@@ -20,25 +21,24 @@
 // Provides information to a set of GeolocationImpl instances that are
 // associated with a given context. Notably, allows pausing and resuming
 // geolocation on these instances.
-class DEVICE_GEOLOCATION_EXPORT GeolocationContext {
+class DEVICE_GEOLOCATION_EXPORT GeolocationContext
+    : public mojom::GeolocationContext {
  public:
   GeolocationContext();
-  virtual ~GeolocationContext();
+  ~GeolocationContext() override;
 
-  // Creates a GeolocationImpl that is weakly bound to |request|.
-  void Bind(mojom::GeolocationRequest request);
+  // Creates GeolocationContext that is strongly bound to |request|.
+  static void Create(mojom::GeolocationContextRequest request);
+
+  // mojom::GeolocationContext implementation:
+  void BindGeolocation(mojom::GeolocationRequest request) override;
+  void SetOverride(mojom::GeopositionPtr geoposition) override;
+  void ClearOverride() override;
 
   // Called when a GeolocationImpl has a connection error. After this call, it
   // is no longer safe to access |impl|.
   void OnConnectionError(GeolocationImpl* impl);
 
-  // Enables geolocation override. This method can be used to trigger possible
-  // location-specific behavior in a particular context.
-  void SetOverride(mojom::GeopositionPtr geoposition);
-
-  // Disables geolocation override.
-  void ClearOverride();
-
  private:
   std::vector<std::unique_ptr<GeolocationImpl>> impls_;
 
diff --git a/device/geolocation/public/interfaces/BUILD.gn b/device/geolocation/public/interfaces/BUILD.gn
index 84ece2b..cb53b6d 100644
--- a/device/geolocation/public/interfaces/BUILD.gn
+++ b/device/geolocation/public/interfaces/BUILD.gn
@@ -8,6 +8,7 @@
   sources = [
     "geolocation.mojom",
     "geolocation_config.mojom",
+    "geolocation_context.mojom",
     "geoposition.mojom",
   ]
   public_deps = [
diff --git a/device/geolocation/public/interfaces/geolocation_context.mojom b/device/geolocation/public/interfaces/geolocation_context.mojom
new file mode 100644
index 0000000..e223cfe
--- /dev/null
+++ b/device/geolocation/public/interfaces/geolocation_context.mojom
@@ -0,0 +1,24 @@
+// 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.
+
+module device.mojom;
+
+import "device/geolocation/public/interfaces/geolocation.mojom";
+import "device/geolocation/public/interfaces/geoposition.mojom";
+
+// GeolocationContext provides methods to bind Geolocation instance and to
+// set/clear overrides of geoposition that will apply to all Geolocation
+// instances created by this context.
+interface GeolocationContext {
+  // Creates a Geolocation instance that is bound to the |request|.
+  BindGeolocation(Geolocation& request);
+
+  // Enables geolocation override. This method can be used to trigger possible
+  // location-specific behavior in GeolocationImpl created by this
+  // GeolocationContext.
+  SetOverride(Geoposition geoposition);
+
+  // Disables geolocation override.
+  ClearOverride();
+};
diff --git a/services/device/BUILD.gn b/services/device/BUILD.gn
index 96cffc5..fa55c45 100644
--- a/services/device/BUILD.gn
+++ b/services/device/BUILD.gn
@@ -27,6 +27,8 @@
 
   deps = [
     "//base",
+    "//device/geolocation",
+    "//device/geolocation/public/interfaces",
     "//device/sensors",
     "//device/sensors/public/interfaces",
     "//services/device/fingerprint",
diff --git a/services/device/device_service.cc b/services/device/device_service.cc
index 83d997fb..ed8da6c 100644
--- a/services/device/device_service.cc
+++ b/services/device/device_service.cc
@@ -12,6 +12,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "device/geolocation/geolocation_context.h"
 #include "mojo/public/cpp/system/message_pipe.h"
 #include "services/device/fingerprint/fingerprint.h"
 #include "services/device/generic_sensor/sensor_provider_impl.h"
@@ -88,6 +89,8 @@
 void DeviceService::OnStart() {
   registry_.AddInterface<mojom::Fingerprint>(base::Bind(
       &DeviceService::BindFingerprintRequest, base::Unretained(this)));
+  registry_.AddInterface<mojom::GeolocationContext>(base::Bind(
+      &DeviceService::BindGeolocationContextRequest, base::Unretained(this)));
   registry_.AddInterface<mojom::PowerMonitor>(base::Bind(
       &DeviceService::BindPowerMonitorRequest, base::Unretained(this)));
   registry_.AddInterface<mojom::ScreenOrientationListener>(
@@ -173,6 +176,11 @@
   Fingerprint::Create(std::move(request));
 }
 
+void DeviceService::BindGeolocationContextRequest(
+    mojom::GeolocationContextRequest request) {
+  GeolocationContext::Create(std::move(request));
+}
+
 void DeviceService::BindPowerMonitorRequest(
     mojom::PowerMonitorRequest request) {
   if (!power_monitor_message_broadcaster_) {
diff --git a/services/device/device_service.h b/services/device/device_service.h
index e8dc7ff4..4f4139a 100644
--- a/services/device/device_service.h
+++ b/services/device/device_service.h
@@ -7,6 +7,7 @@
 
 #include "base/memory/ref_counted.h"
 #include "build/build_config.h"
+#include "device/geolocation/public/interfaces/geolocation_context.mojom.h"
 #include "device/screen_orientation/public/interfaces/screen_orientation.mojom.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/device/public/interfaces/battery_monitor.mojom.h"
@@ -82,6 +83,7 @@
                        mojo::ScopedMessagePipeHandle interface_pipe) override;
 
   void BindFingerprintRequest(mojom::FingerprintRequest request);
+  void BindGeolocationContextRequest(mojom::GeolocationContextRequest request);
 
 #if defined(OS_LINUX) && defined(USE_UDEV)
   void BindInputDeviceManagerRequest(mojom::InputDeviceManagerRequest request);
diff --git a/services/device/manifest.json b/services/device/manifest.json
index e35496c..35f09ba 100644
--- a/services/device/manifest.json
+++ b/services/device/manifest.json
@@ -9,6 +9,7 @@
         "device:input_service": [ "device::mojom::InputDeviceManager" ],
         "device:fingerprint": [ "device::mojom::Fingerprint" ],
         "device:generic_sensor": [ "device::mojom::SensorProvider" ],
+        "device:geolocation": [ "device::mojom::GeolocationContext" ],
         "device:nfc": [ "device::mojom::NFCProvider" ],
         "device:power_monitor": [ "device::mojom::PowerMonitor" ],
         "device:screen_orientation": [ "device::mojom::ScreenOrientationListener" ],