summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorbulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-18 16:44:22 +0000
committerbulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-18 16:44:22 +0000
commit434afdcf94e2319ff03872db312d489a44637508 (patch)
tree3414ee5da70cb7ada1074c36cfc001e4ebfd5438 /chrome
parentf01e0a37fa8f328b8694c9abc69ecc62fbc9690a (diff)
downloadchromium_src-434afdcf94e2319ff03872db312d489a44637508.zip
chromium_src-434afdcf94e2319ff03872db312d489a44637508.tar.gz
chromium_src-434afdcf94e2319ff03872db312d489a44637508.tar.bz2
Initial Geolocation implementation
Adds IPC plumbing. Adds Infobar buttons for requesting permission TEST=geolocation_browsertest.cc Review URL: http://codereview.chromium.org/548188 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@39366 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/app/generated_resources.grd16
-rw-r--r--chrome/app/theme/theme_resources.grd4
-rw-r--r--chrome/browser/geolocation/geolocation_browsertest.cc248
-rw-r--r--chrome/browser/geolocation/geolocation_dispatcher_host.cc154
-rw-r--r--chrome/browser/geolocation/geolocation_dispatcher_host.h77
-rw-r--r--chrome/browser/geolocation/geolocation_permission_context.cc291
-rw-r--r--chrome/browser/geolocation/geolocation_permission_context.h88
-rw-r--r--chrome/browser/geolocation/location_arbitrator.cc4
-rw-r--r--chrome/browser/geolocation/location_arbitrator.h4
-rw-r--r--chrome/browser/geolocation/location_arbitrator_unittest.cc14
-rw-r--r--chrome/browser/geolocation/location_provider.h3
-rw-r--r--chrome/browser/geolocation/network_location_provider.cc14
-rw-r--r--chrome/browser/geolocation/network_location_provider.h8
-rw-r--r--chrome/browser/geolocation/network_location_provider_unittest.cc2
-rw-r--r--chrome/browser/geolocation/network_location_request.cc16
-rw-r--r--chrome/browser/geolocation/network_location_request.h3
-rw-r--r--chrome/browser/renderer_host/render_view_host.h2
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc10
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.h4
-rwxr-xr-xchrome/chrome_browser.gypi8
-rw-r--r--chrome/chrome_common.gypi2
-rwxr-xr-xchrome/chrome_renderer.gypi2
-rwxr-xr-xchrome/chrome_tests.gypi1
-rw-r--r--chrome/common/common_param_traits.cc63
-rw-r--r--chrome/common/common_param_traits.h17
-rw-r--r--chrome/common/common_param_traits_unittest.cc39
-rw-r--r--chrome/common/geoposition.cc (renamed from chrome/browser/geolocation/geoposition.cc)40
-rw-r--r--chrome/common/geoposition.h (renamed from chrome/browser/geolocation/geoposition.h)16
-rw-r--r--chrome/common/render_messages_internal.h77
-rw-r--r--chrome/renderer/geolocation_dispatcher.cc104
-rw-r--r--chrome/renderer/geolocation_dispatcher.h57
-rw-r--r--chrome/renderer/render_view.cc13
-rw-r--r--chrome/renderer/render_view.h9
-rw-r--r--chrome/test/data/geolocation/simple.html35
34 files changed, 1385 insertions, 60 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 502d4f8..22f82c4 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -6510,7 +6510,21 @@ Keep your key file in a safe place. You will need it to create new versions of y
The following Privacy Blacklists prevented this content from showing:
</message>
- <!-- ProcessSingleton -->
+ <!-- Geolocation messages -->
+ <message name="IDS_GEOLOCATION_INFOBAR_QUESTION" desc="Question asked on the info bar whenever URL wants to access the user physical location">
+ <ph name="URL">
+ $1<ex>google.com</ex>
+ </ph> wants to track your physical location
+ </message>
+ <message name="IDS_GEOLOCATION_ALLOW_BUTTON" desc="A button in geolocation infobar for allowing access to geolocation for a given domain.">
+ Allow
+ </message>
+ <message name="IDS_GEOLOCATION_DENY_BUTTON" desc="A button in geolocation infobar for denying access to geolocation for a given domain.">
+ Deny
+ </message>
+
+
+ <!-- ProcessSingleton -->
<message name="IDS_PROFILE_IN_USE_LINUX" desc="Message shown when the browser cannot start because the profile is in use on a different host.">
The profile appears to be in use by process <ph name="PROCESS_ID">$1<ex>12345</ex></ph> on host <ph name="HOST_NAME">$2<ex>example.com</ex></ph>. If you are sure no other processes are using this profile, delete the file <ph name="LOCK_FILE">$3<ex>/home/user/.config/google-chrome/SingletonLock</ex></ph> and restart <ph name="PRODUCT_NAME">$4<ex>Google Chrome</ex></ph>.
</message>
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index acf7d2f..64f075e 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -318,6 +318,10 @@
<include name="IDR_BALLOON_OPTIONS_ARROW" file="balloon_options_arrow.png" type="BINDATA" />
<include name="IDR_BALLOON_OPTIONS_ARROW_HOVER" file="balloon_options_arrow_hover.png" type="BINDATA" />
+ <!-- Geolocation -->
+ <include name="IDR_GEOLOCATION_INFOBAR_ICON" file="geolocation_infobar_icon.png" type="BINDATA" />
+
+
<if expr="pp_ifdef('_google_chrome')">
<include name="IDR_ABOUT_BACKGROUND" file="google_chrome/about_background.png" type="BINDATA" />
<include name="IDR_ABOUT_BACKGROUND_RTL" file="google_chrome/about_background_rtl.png" type="BINDATA" />
diff --git a/chrome/browser/geolocation/geolocation_browsertest.cc b/chrome/browser/geolocation/geolocation_browsertest.cc
new file mode 100644
index 0000000..40c7bd9
--- /dev/null
+++ b/chrome/browser/geolocation/geolocation_browsertest.cc
@@ -0,0 +1,248 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/string_util.h"
+#include "chrome/browser/app_modal_dialog.h"
+#include "chrome/browser/browser.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/geoposition.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
+#include "chrome/common/render_messages.h"
+#include "chrome/test/in_process_browser_test.h"
+#include "chrome/test/ui_test_utils.h"
+#include "net/base/net_util.h"
+
+// This is a browser test for Geolocation.
+// It exercises various integration points from javascript <-> browser:
+// 1. Infobar is displayed when a geolocation is requested from an unauthorized
+// origin.
+// 2. Denying the infobar triggers the correct error callback.
+// 3. Allowing the infobar does not trigger an error, and allow a geoposition to
+// be passed to javascript.
+// 4. Permissions persisted in disk are respected.
+// 5. Off the record profiles don't use saved permissions.
+class GeolocationBrowserTest
+ : public InProcessBrowserTest, public NotificationObserver {
+ public:
+ GeolocationBrowserTest() : infobar_(NULL), current_browser_(NULL) {
+ EnableDOMAutomation();
+ }
+
+ enum InitializationOptions {
+ INITIALIZATION_NONE,
+ INITIALIZATION_OFFTHERECORD,
+ INITIALIZATION_NEWTAB,
+ };
+
+ void Initialize(InitializationOptions options) {
+ if (!server_.get()) {
+ server_ = StartHTTPServer();
+ }
+ GURL url = server_->TestServerPage("files/geolocation/simple.html");
+ if (options == INITIALIZATION_OFFTHERECORD) {
+ ui_test_utils::OpenURLOffTheRecord(browser()->profile(), url);
+ current_browser_ = BrowserList::FindBrowserWithType(
+ browser()->profile()->GetOffTheRecordProfile(), Browser::TYPE_NORMAL);
+ } else if (options == INITIALIZATION_NEWTAB) {
+ current_browser_ = browser();
+ current_browser_->NewTab();
+ ui_test_utils::NavigateToURL(current_browser_, url);
+ } else {
+ current_browser_ = browser();
+ ui_test_utils::NavigateToURL(current_browser_, url);
+ }
+ EXPECT_TRUE(current_browser_);
+
+ int watch_id = 0;
+ EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractInt(
+ current_browser_->GetSelectedTabContents()->render_view_host(), L"",
+ UTF8ToWide("window.domAutomationController.send(geoStart());"),
+ &watch_id));
+ EXPECT_GT(watch_id, 0);
+ }
+
+ void SendGeoposition(bool wait_for_infobar, const Geoposition& geoposition) {
+ if (wait_for_infobar) {
+ // Observe infobar notification.
+ registrar_.Add(
+ this, NotificationType::TAB_CONTENTS_INFOBAR_ADDED,
+ NotificationService::AllSources());
+ }
+
+ // Sending the Geoposition makes webkit trigger the permission request flow.
+ // If the origin is already allowed, no infobar will be displayed.
+ RenderViewHost* render_view_host =
+ current_browser_->GetSelectedTabContents()->render_view_host();
+ render_view_host->Send(
+ new ViewMsg_Geolocation_PositionUpdated(
+ render_view_host->routing_id(), geoposition));
+
+ if (wait_for_infobar) {
+ ui_test_utils::RunMessageLoop();
+ EXPECT_TRUE(infobar_);
+ registrar_.Remove(this, NotificationType::TAB_CONTENTS_INFOBAR_ADDED,
+ NotificationService::AllSources());
+ }
+ }
+
+ void WaitForJSPrompt() {
+ AppModalDialog* alert = ui_test_utils::WaitForAppModalDialog();
+ ASSERT_TRUE(alert);
+ alert->CloseModalDialog();
+ }
+
+ void SetInfobarResponse(bool allowed) {
+ registrar_.Add(
+ this, NotificationType::TAB_CONTENTS_INFOBAR_REMOVED,
+ NotificationService::AllSources());
+ ASSERT_TRUE(infobar_);
+ if (allowed)
+ infobar_->AsConfirmInfoBarDelegate()->Accept();
+ else
+ infobar_->AsConfirmInfoBarDelegate()->Cancel();
+ current_browser_->GetSelectedTabContents()->RemoveInfoBar(infobar_);
+ EXPECT_FALSE(infobar_);
+ registrar_.Remove(this, NotificationType::TAB_CONTENTS_INFOBAR_REMOVED,
+ NotificationService::AllSources());
+ }
+
+ void CheckValueFromJavascript(
+ const std::string& expected, const std::string& function) {
+ std::string js_call = StringPrintf(
+ "window.domAutomationController.send(%s);", function.c_str());
+ std::string value;
+ EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString(
+ current_browser_->GetSelectedTabContents()->render_view_host(), L"",
+ UTF8ToWide(js_call),
+ &value));
+ EXPECT_EQ(expected, value);
+ }
+
+ // InProcessBrowserTest
+ virtual void SetUpCommandLine(CommandLine* command_line) {
+ InProcessBrowserTest::SetUpCommandLine(command_line);
+ command_line->AppendSwitch(switches::kEnableGeolocation);
+ }
+
+ // NotificationObserver
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ if (type.value == NotificationType::TAB_CONTENTS_INFOBAR_ADDED) {
+ infobar_ = Details<InfoBarDelegate>(details).ptr();
+ ASSERT_TRUE(infobar_->GetIcon());
+ ASSERT_TRUE(infobar_->AsConfirmInfoBarDelegate());
+ MessageLoopForUI::current()->Quit();
+ } else if (type.value == NotificationType::TAB_CONTENTS_INFOBAR_REMOVED) {
+ infobar_ = NULL;
+ }
+ }
+
+ NotificationRegistrar registrar_;
+ InfoBarDelegate* infobar_;
+ Browser* current_browser_;
+ scoped_refptr<HTTPTestServer> server_;
+};
+
+IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, DisplaysPermissionBar) {
+ Initialize(INITIALIZATION_NONE);
+ SendGeoposition(true, Geoposition());
+}
+
+IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, ErrorOnPermissionDenied) {
+ Initialize(INITIALIZATION_NONE);
+ SendGeoposition(true, Geoposition());
+ // Infobar was displayed, deny access and check for error code.
+ SetInfobarResponse(false);
+ WaitForJSPrompt();
+ CheckValueFromJavascript("1", "geoGetLastError()");
+}
+
+IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, NoInfobarForSecondTab) {
+#if 0
+ Initialize(INITIALIZATION_NONE);
+ SendGeoposition(true, Geoposition());
+ SetInfobarResponse(true);
+ WaitForJSPrompt();
+ // Checks infobar will not be created a second tab.
+ Initialize(INITIALIZATION_NEWTAB);
+ SendGeoposition(false, Geoposition());
+ WaitForJSPrompt();
+ CheckValueFromJavascript("0", "geoGetLastError()");
+#endif
+}
+
+IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, NoInfobarForDeniedOrigin) {
+#if 0
+ WritePermissionFile("{\"allowed\":false}");
+ // Checks no infobar will be created.
+ Initialize(INITIALIZATION_NONE);
+ SendGeoposition(false, Geoposition());
+ WaitForJSPrompt();
+ CheckValueFromJavascript("1", "geoGetLastError()");
+ // Checks infobar will not be created a second tab.
+ Initialize(INITIALIZATION_NEWTAB);
+ SendGeoposition(false, Geoposition());
+ WaitForJSPrompt();
+ CheckValueFromJavascript("1", "geoGetLastError()");
+#endif
+}
+
+IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, NoInfobarForAllowedOrigin) {
+#if 0
+ WritePermissionFile("{\"allowed\":true}");
+ // Checks no infobar will be created and there's no error callback.
+ Initialize(INITIALIZATION_NONE);
+ SendGeoposition(false, Geoposition());
+ WaitForJSPrompt();
+ CheckValueFromJavascript("0", "geoGetLastError()");
+#endif
+}
+
+IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, InfobarForOffTheRecord) {
+#if 0
+ // Checks infobar will be created for regular profile.
+ Initialize(INITIALIZATION_NONE);
+ SendGeoposition(true, Geoposition());
+ SetInfobarResponse(true);
+ WaitForJSPrompt();
+ CheckValueFromJavascript("0", "geoGetLastError()");
+ // Go off the record, and checks infobar will be created and an error callback
+ // is triggered.
+ Initialize(INITIALIZATION_OFFTHERECORD);
+ SendGeoposition(true, Geoposition());
+ SetInfobarResponse(false);
+ WaitForJSPrompt();
+ CheckValueFromJavascript("1", "geoGetLastError()");
+#endif
+}
+
+IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, Geoposition) {
+ // Checks infobar will be created.
+ Initialize(INITIALIZATION_NONE);
+ SendGeoposition(true, Geoposition());
+ // Infobar was displayed, allow access and check there's no error code.
+ SetInfobarResponse(true);
+ WaitForJSPrompt();
+ CheckValueFromJavascript("0", "geoGetLastError()");
+ // Sends a Geoposition over IPC, and check it arrives in the javascript side.
+ Geoposition geoposition;
+ geoposition.latitude = 3.17;
+ geoposition.longitude = 4.23;
+ SendGeoposition(false, geoposition);
+ WaitForJSPrompt();
+ // Checks we have no error.
+ CheckValueFromJavascript("0", "geoGetLastError()");
+ CheckValueFromJavascript(
+ DoubleToString(geoposition.latitude), "geoGetLastPositionLatitude()");
+ CheckValueFromJavascript(
+ DoubleToString(geoposition.longitude), "geoGetLastPositionLongitude()");
+}
diff --git a/chrome/browser/geolocation/geolocation_dispatcher_host.cc b/chrome/browser/geolocation/geolocation_dispatcher_host.cc
new file mode 100644
index 0000000..1217224
--- /dev/null
+++ b/chrome/browser/geolocation/geolocation_dispatcher_host.cc
@@ -0,0 +1,154 @@
+// Copyright (c) 2010 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/geolocation/geolocation_dispatcher_host.h"
+
+#include "chrome/common/geoposition.h"
+#include "chrome/browser/geolocation/geolocation_permission_context.h"
+#include "chrome/browser/renderer_host/render_process_host.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/render_view_host_notification_task.h"
+#include "chrome/browser/renderer_host/resource_message_filter.h"
+#include "chrome/common/render_messages.h"
+
+GeolocationDispatcherHost::GeolocationDispatcherHost(
+ int resource_message_filter_process_id,
+ GeolocationPermissionContext* geolocation_permission_context)
+ : resource_message_filter_process_id_(resource_message_filter_process_id),
+ geolocation_permission_context_(geolocation_permission_context) {
+ // This is initialized by ResourceMessageFilter. Do not add any non-trivial
+ // initialization here, defer to OnRegisterBridge which is triggered whenever
+ // a javascript geolocation object is actually initialized.
+}
+
+GeolocationDispatcherHost::~GeolocationDispatcherHost() {
+}
+
+bool GeolocationDispatcherHost::OnMessageReceived(
+ const IPC::Message& msg, bool* msg_was_ok) {
+ *msg_was_ok = true;
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(GeolocationDispatcherHost, msg, *msg_was_ok)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_Geolocation_RegisterDispatcher,
+ OnRegisterDispatcher)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_Geolocation_UnregisterDispatcher,
+ OnUnregisterDispatcher)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_Geolocation_RequestPermission,
+ OnRequestPermission)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_Geolocation_StartUpdating,
+ OnStartUpdating)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_Geolocation_StopUpdating,
+ OnStopUpdating)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_Geolocation_Suspend,
+ OnSuspend)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_Geolocation_Resume,
+ OnResume)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void GeolocationDispatcherHost::NotifyPositionUpdated(
+ const Geoposition& geoposition) {
+ if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(
+ this, &GeolocationDispatcherHost::NotifyPositionUpdated,
+ geoposition));
+ return;
+ }
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+
+ for (std::set<GeolocationServiceRenderId>::iterator geo =
+ geolocation_renderers_.begin();
+ geo != geolocation_renderers_.end();
+ ++geo) {
+ IPC::Message* message;
+ if (geoposition.error_code != Geoposition::ERROR_CODE_NONE) {
+ message = new ViewMsg_Geolocation_PositionUpdated(
+ geo->route_id, geoposition);
+ } else {
+ message = new ViewMsg_Geolocation_Error(
+ geo->route_id, geoposition.error_code,
+ WideToUTF8(geoposition.error_message));
+ }
+ CallRenderViewHost(
+ geo->process_id, geo->route_id, &RenderViewHost::Send, message);
+ }
+}
+
+void GeolocationDispatcherHost::OnRegisterDispatcher(int route_id) {
+ // TODO(bulach): is this the right way to get the RendererViewHost process id
+ // to be used by RenderViewHost::FromID?
+ RegisterDispatcher(resource_message_filter_process_id_, route_id);
+}
+
+void GeolocationDispatcherHost::OnUnregisterDispatcher(int route_id) {
+ UnregisterDispatcher(resource_message_filter_process_id_, route_id);
+}
+
+void GeolocationDispatcherHost::OnRequestPermission(
+ int route_id, int bridge_id, const GURL& origin) {
+ LOG(INFO) << "permission request";
+ geolocation_permission_context_->RequestGeolocationPermission(
+ resource_message_filter_process_id_, route_id, bridge_id, origin);
+}
+
+void GeolocationDispatcherHost::OnStartUpdating(
+ int route_id, int bridge_id, bool high_accuracy) {
+ LOG(INFO) << "start updating" << route_id;
+ // TODO(bulach): connect this with GeolocationServiceProvider.
+}
+
+void GeolocationDispatcherHost::OnStopUpdating(int route_id, int bridge_id) {
+ LOG(INFO) << "stop updating" << route_id;
+ // TODO(bulach): connect this with GeolocationServiceProvider.
+}
+
+void GeolocationDispatcherHost::OnSuspend(int route_id, int bridge_id) {
+ LOG(INFO) << "suspend" << route_id;
+ // TODO(bulach): connect this with GeolocationServiceProvider.
+}
+
+void GeolocationDispatcherHost::OnResume(int route_id, int bridge_id) {
+ LOG(INFO) << "resume" << route_id;
+ // TODO(bulach): connect this with GeolocationServiceProvider.
+}
+
+void GeolocationDispatcherHost::RegisterDispatcher(
+ int process_id, int route_id) {
+ if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) {
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ this, &GeolocationDispatcherHost::RegisterDispatcher, process_id,
+ route_id));
+ return;
+ }
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+
+ GeolocationServiceRenderId geolocation_render_id(process_id, route_id);
+ std::set<GeolocationServiceRenderId>::const_iterator existing =
+ geolocation_renderers_.find(geolocation_render_id);
+ DCHECK(existing == geolocation_renderers_.end());
+ geolocation_renderers_.insert(geolocation_render_id);
+}
+
+void GeolocationDispatcherHost::UnregisterDispatcher(
+ int process_id, int route_id) {
+ if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) {
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ this, &GeolocationDispatcherHost::UnregisterDispatcher, process_id,
+ route_id));
+ return;
+ }
+ GeolocationServiceRenderId geolocation_render_id(process_id, route_id);
+ std::set<GeolocationServiceRenderId>::iterator existing =
+ geolocation_renderers_.find(geolocation_render_id);
+ DCHECK(existing != geolocation_renderers_.end());
+ geolocation_renderers_.erase(existing);
+}
diff --git a/chrome/browser/geolocation/geolocation_dispatcher_host.h b/chrome/browser/geolocation/geolocation_dispatcher_host.h
new file mode 100644
index 0000000..8bd7eaf
--- /dev/null
+++ b/chrome/browser/geolocation/geolocation_dispatcher_host.h
@@ -0,0 +1,77 @@
+// Copyright (c) 2010 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_GEOLOCATION_GEOLOCATION_DISPATCHER_HOST_H_
+#define CHROME_BROWSER_GEOLOCATION_GEOLOCATION_DISPATCHER_HOST_H_
+
+#include <set>
+
+#include "base/basictypes.h"
+#include "base/ref_counted.h"
+#include "ipc/ipc_message.h"
+
+class GeolocationPermissionContext;
+struct Geoposition;
+class GURL;
+class ResourceMessageFilter;
+
+// GeolocationDispatcherHost is a delegate for Geolocation messages used by
+// ResourceMessageFilter.
+// It's the complement of GeolocationDispatcher (owned by RenderView).
+class GeolocationDispatcherHost
+ : public base::RefCountedThreadSafe<GeolocationDispatcherHost> {
+ public:
+ GeolocationDispatcherHost(
+ int resource_message_filter_process_id,
+ GeolocationPermissionContext* geolocation_permission_context);
+
+ // Called to possibly handle the incoming IPC message. Returns true if
+ // handled. Called in the browser process.
+ bool OnMessageReceived(const IPC::Message& msg, bool* msg_was_ok);
+
+ // Tells the render view that a new geolocation position is available.
+ void NotifyPositionUpdated(const Geoposition& geoposition);
+
+ private:
+ friend class base::RefCountedThreadSafe<GeolocationDispatcherHost>;
+ ~GeolocationDispatcherHost();
+
+ void OnRegisterDispatcher(int route_id);
+ void OnUnregisterDispatcher(int route_id);
+ void OnRequestPermission(int route_id, int bridge_id, const GURL& origin);
+ void OnStartUpdating(int route_id, int bridge_id, bool high_accuracy);
+ void OnStopUpdating(int route_id, int bridge_id);
+ void OnSuspend(int route_id, int bridge_id);
+ void OnResume(int route_id, int bridge_id);
+
+ // Registers the bridge created in the renderer side. They'll delegate to the
+ // UI thread if not already in there.
+ void RegisterDispatcher(int process_id, int route_id);
+ void UnregisterDispatcher(int process_id, int route_id);
+
+ int resource_message_filter_process_id_;
+ scoped_refptr<GeolocationPermissionContext> geolocation_permission_context_;
+
+ struct GeolocationServiceRenderId {
+ int process_id;
+ int route_id;
+ GeolocationServiceRenderId(int process_id, int route_id)
+ : process_id(process_id), route_id(route_id) {
+ }
+ bool operator==(const GeolocationServiceRenderId& rhs) const {
+ return process_id == rhs.route_id &&
+ route_id == rhs.route_id;
+ }
+ bool operator<(const GeolocationServiceRenderId& rhs) const {
+ return process_id < rhs.route_id &&
+ route_id < rhs.route_id;
+ }
+ };
+ // Only used on the UI thread.
+ std::set<GeolocationServiceRenderId> geolocation_renderers_;
+
+ DISALLOW_COPY_AND_ASSIGN(GeolocationDispatcherHost);
+};
+
+#endif // CHROME_BROWSER_GEOLOCATION_GEOLOCATION_DISPATCHER_HOST_H_
diff --git a/chrome/browser/geolocation/geolocation_permission_context.cc b/chrome/browser/geolocation/geolocation_permission_context.cc
new file mode 100644
index 0000000..853e0a7
--- /dev/null
+++ b/chrome/browser/geolocation/geolocation_permission_context.cc
@@ -0,0 +1,291 @@
+// Copyright (c) 2010 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/geolocation/geolocation_permission_context.h"
+
+#include "app/l10n_util.h"
+#include "app/resource_bundle.h"
+#include "base/file_util.h"
+#include "googleurl/src/gurl.h"
+#include "chrome/browser/browser.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/geolocation/geolocation_dispatcher_host.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/renderer_host/render_process_host.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/render_view_host_notification_task.h"
+#include "chrome/browser/tab_contents/infobar_delegate.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/json_value_serializer.h"
+#include "chrome/common/render_messages.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+
+namespace {
+
+const FilePath::CharType kGeolocationPermissionPath[] =
+ FILE_PATH_LITERAL("Geolocation");
+
+const wchar_t kAllowedDictionaryKey[] = L"allowed";
+
+// This is the delegate used to display the confirmation info bar.
+class GeolocationConfirmInfoBarDelegate : public ConfirmInfoBarDelegate {
+ public:
+ GeolocationConfirmInfoBarDelegate(
+ TabContents* tab_contents, GeolocationPermissionContext* context,
+ int render_process_id, int render_view_id, int bridge_id,
+ const GURL& origin)
+ : ConfirmInfoBarDelegate(tab_contents), context_(context),
+ render_process_id_(render_process_id), render_view_id_(render_view_id),
+ bridge_id_(bridge_id), origin_(origin) {
+ }
+
+ // ConfirmInfoBarDelegate
+ virtual Type GetInfoBarType() { return INFO_TYPE; }
+ virtual bool Accept() { return SetPermission(true); }
+ virtual bool Cancel() { return SetPermission(false); }
+ virtual int GetButtons() const { return BUTTON_OK | BUTTON_CANCEL; }
+
+ virtual std::wstring GetButtonLabel(InfoBarButton button) const {
+ switch (button) {
+ case BUTTON_OK:
+ return l10n_util::GetString(IDS_GEOLOCATION_ALLOW_BUTTON);
+ case BUTTON_CANCEL:
+ return l10n_util::GetString(IDS_GEOLOCATION_DENY_BUTTON);
+ default:
+ // All buttons are labeled above.
+ NOTREACHED() << "Bad button id " << button;
+ return L"";
+ }
+ }
+
+ virtual std::wstring GetMessageText() const {
+ return l10n_util::GetStringF(
+ IDS_GEOLOCATION_INFOBAR_QUESTION, UTF8ToWide(origin_.host()));
+ }
+
+ virtual SkBitmap* GetIcon() const {
+ return ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ IDR_GEOLOCATION_INFOBAR_ICON);
+ }
+
+ private:
+ bool SetPermission(bool confirm) {
+ context_->SetPermission(
+ render_process_id_, render_view_id_, bridge_id_, origin_, confirm);
+ return true;
+ }
+
+ scoped_refptr<GeolocationPermissionContext> context_;
+ int render_process_id_;
+ int render_view_id_;
+ int bridge_id_;
+ GURL origin_;
+};
+
+// TODO(bulach): use HostContentSettingsMap instead!
+FilePath::StringType StdStringToFilePathString(const std::string& std_string) {
+#if defined(OS_WIN)
+ return UTF8ToWide(std_string);
+#else
+ return std_string;
+#endif
+}
+
+std::string GURLToCacheKey(const GURL& gurl) {
+ return gurl.host();
+}
+
+// Returns true if permission was successfully read from file, and *allowed
+// be set accordingly.
+// Returns false otherwise.
+bool ReadPermissionFromFile(
+ const GURL& origin, const FilePath& permissions_path, bool* allowed) {
+ DCHECK(allowed);
+ *allowed = false;
+ // TODO(bulach): this is probably wrong! is there any utility to convert a URL
+ // to FilePath?
+ FilePath permission_file(
+ permissions_path.Append(StdStringToFilePathString(
+ GURLToCacheKey(origin))));
+ if (!file_util::PathExists(permission_file))
+ return false;
+ JSONFileValueSerializer serializer(permission_file);
+ scoped_ptr<Value> root_value(serializer.Deserialize(NULL));
+ bool ret = root_value.get() &&
+ root_value->GetType() == Value::TYPE_DICTIONARY;
+ DictionaryValue* dictionary = static_cast<DictionaryValue*>(root_value.get());
+ return ret &&
+ dictionary->GetBoolean(kAllowedDictionaryKey, allowed);
+}
+
+void SavePermissionToFile(
+ const GURL& origin, const FilePath& permissions_path, bool allowed) {
+#if 0
+ if (!file_util::DirectoryExists(permissions_path))
+ file_util::CreateDirectory(permissions_path);
+ // TODO(bulach): this is probably wrong! is there any utility to convert a URL
+ // to FilePath?
+ FilePath permission_file(
+ permissions_path.Append(StdStringToFilePathString(
+ GURLToCacheKey(origin))));
+ DictionaryValue dictionary;
+ dictionary.SetBoolean(kAllowedDictionaryKey, allowed);
+ std::string permission_data;
+ JSONStringValueSerializer serializer(&permission_data);
+ serializer.Serialize(dictionary);
+ file_util::WriteFile(
+ permission_file, permission_data.c_str(), permission_data.length());
+#endif // if 0
+}
+
+} // namespace
+
+GeolocationPermissionContext::GeolocationPermissionContext(
+ Profile* profile)
+ : profile_(profile),
+ is_off_the_record_(profile->IsOffTheRecord()),
+ permissions_path_(profile->GetPath().Append(FilePath(
+ kGeolocationPermissionPath))) {
+}
+
+GeolocationPermissionContext::~GeolocationPermissionContext() {
+}
+
+void GeolocationPermissionContext::RequestGeolocationPermission(
+ int render_process_id, int render_view_id, int bridge_id,
+ const GURL& origin) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ std::map<std::string, bool>::const_iterator permission =
+ permissions_.find(GURLToCacheKey(origin));
+ if (permission != permissions_.end()) {
+ NotifyPermissionSet(
+ render_process_id, render_view_id, bridge_id, permission->second);
+ } else {
+ HandlePermissionMemoryCacheMiss(
+ render_process_id, render_view_id, bridge_id, origin);
+ }
+}
+
+void GeolocationPermissionContext::SetPermission(
+ int render_process_id, int render_view_id, int bridge_id,
+ const GURL& origin, bool allowed) {
+ SetPermissionMemoryCacheOnIOThread(origin, allowed);
+ SetPermissionOnFileThread(origin, allowed);
+ NotifyPermissionSet(render_process_id, render_view_id, bridge_id, allowed);
+}
+
+void GeolocationPermissionContext::HandlePermissionMemoryCacheMiss(
+ int render_process_id, int render_view_id, int bridge_id,
+ const GURL& origin) {
+ if (!ChromeThread::CurrentlyOn(ChromeThread::FILE)) {
+ ChromeThread::PostTask(
+ ChromeThread::FILE, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &GeolocationPermissionContext::HandlePermissionMemoryCacheMiss,
+ render_process_id, render_view_id, bridge_id, origin));
+ return;
+ }
+
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ // TODO(bulach): should we save a file per origin or have some smarter
+ // storage? Use HostContentSettingsMap instead.
+ bool allowed;
+ if (is_off_the_record_ ||
+ !ReadPermissionFromFile(origin, permissions_path_, &allowed)) {
+ RequestPermissionFromUI(
+ render_process_id, render_view_id, bridge_id, origin);
+ } else {
+ SetPermissionMemoryCacheOnIOThread(origin, allowed);
+ NotifyPermissionSet(render_process_id, render_view_id, bridge_id, allowed);
+ }
+}
+
+void GeolocationPermissionContext::RequestPermissionFromUI(
+ int render_process_id, int render_view_id, int bridge_id,
+ const GURL& origin) {
+ if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(
+ this, &GeolocationPermissionContext::RequestPermissionFromUI,
+ render_process_id, render_view_id, bridge_id, origin));
+ return;
+ }
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+
+ Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
+ for (int i = 0; i < browser->tab_count(); ++i) {
+ TabContents* tab_contents = browser->GetTabContentsAt(i);
+ RenderViewHost* render_view_host = tab_contents->render_view_host();
+ if (render_view_host->process()->id() == render_process_id &&
+ render_view_host->routing_id() == render_view_id &&
+ tab_contents->GetURL().GetOrigin() == origin) {
+ tab_contents->AddInfoBar(
+ new GeolocationConfirmInfoBarDelegate(
+ tab_contents, this, render_process_id, render_view_id,
+ bridge_id, origin));
+ break;
+ }
+ }
+}
+
+void GeolocationPermissionContext::NotifyPermissionSet(
+ int render_process_id, int render_view_id, int bridge_id, bool allowed) {
+ if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(
+ this, &GeolocationPermissionContext::NotifyPermissionSet,
+ render_process_id, render_view_id, bridge_id, allowed));
+ return;
+ }
+
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ CallRenderViewHost(
+ render_process_id, render_view_id,
+ &RenderViewHost::Send,
+ new ViewMsg_Geolocation_PermissionSet(
+ render_view_id, bridge_id, allowed));
+}
+
+void GeolocationPermissionContext::SetPermissionMemoryCacheOnIOThread(
+ const GURL& origin, bool allowed) {
+ if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) {
+ ChromeThread::PostTask(
+ ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &GeolocationPermissionContext::SetPermissionMemoryCacheOnIOThread,
+ origin, allowed));
+ return;
+ }
+
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ permissions_[GURLToCacheKey(origin)] = allowed;
+}
+
+void GeolocationPermissionContext::SetPermissionOnFileThread(
+ const GURL& origin, bool allowed) {
+ if (is_off_the_record_)
+ return;
+ if (!ChromeThread::CurrentlyOn(ChromeThread::FILE)) {
+ ChromeThread::PostTask(
+ ChromeThread::FILE, FROM_HERE,
+ NewRunnableMethod(
+ this, &GeolocationPermissionContext::SetPermissionOnFileThread,
+ origin, allowed));
+ return;
+ }
+
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
+
+ // TODO(bulach): should we save a file per origin or have some smarter
+ // storage? Use HostContentSettingsMap instead.
+#if 0
+ SavePermissionToFile(origin, permissions_path_, allowed);
+#endif
+}
diff --git a/chrome/browser/geolocation/geolocation_permission_context.h b/chrome/browser/geolocation/geolocation_permission_context.h
new file mode 100644
index 0000000..c859648
--- /dev/null
+++ b/chrome/browser/geolocation/geolocation_permission_context.h
@@ -0,0 +1,88 @@
+// Copyright (c) 2010 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_GEOLOCATION_GEOLOCATION_PERMISSION_CONTEXT_H_
+#define CHROME_BROWSER_GEOLOCATION_GEOLOCATION_PERMISSION_CONTEXT_H_
+
+#include <map>
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "base/ref_counted.h"
+
+class GeolocationDispatcherHost;
+class GURL;
+class Profile;
+class RenderViewHost;
+
+// GeolocationPermissionContext manages Geolocation permissions per origin.
+// It keeps an in-memory cache of permissions, and if not available, loads
+// from disk. If there's no data, it'll trigger the UI elements to ask the
+// user for permission.
+// Regardless of where the permission data came from, it always notifies the
+// requesting render_view asynchronously via ViewMsg_Geolocation_PermissionSet.
+class GeolocationPermissionContext
+ : public base::RefCountedThreadSafe<GeolocationPermissionContext> {
+ public:
+ explicit GeolocationPermissionContext(Profile* profile);
+
+ // The render is requesting permission to use Geolocation.
+ // Response will be sent asynchronously as ViewMsg_Geolocation_PermissionSet.
+ // Must be called from the IO thread.
+ void RequestGeolocationPermission(
+ int render_process_id, int render_view_id, int bridge_id,
+ const GURL& origin);
+
+ // Called once the user sets the geolocation permission.
+ // It'll update the internal state on different threads via
+ // SetPermissionMemoryCacheOnIOThread and SetPermissionOnFileThread.
+ void SetPermission(
+ int render_process_id, int render_view_id, int bridge_id,
+ const GURL& origin, bool allowed);
+
+ private:
+ friend class base::RefCountedThreadSafe<GeolocationPermissionContext>;
+ ~GeolocationPermissionContext();
+
+ // This is initially called on the IO thread by the public API
+ // RequestGeolocationPermission when there's no data available in the
+ // in-memory cache.
+ // It forwards a call to the FILE thread which tries to load permission data
+ // from disk:
+ // - If available, it will call SetPermissionMemoryCacheOnIOThread() to write
+ // the in-memory cache in the IO thread, and NotifyPermissionSet to send the
+ // message to the corresponding render.
+ // - If not available, it'll delegate to RequestPermissionDataFromUI.
+ void HandlePermissionMemoryCacheMiss(
+ int render_process_id, int render_view_id, int bridge_id,
+ const GURL& origin);
+
+ // Triggers the associated UI element to request permission.
+ void RequestPermissionFromUI(
+ int render_process_id, int render_view_id, int bridge_id,
+ const GURL& origin);
+
+ // Notifies whether or not the corresponding render is allowed to use
+ // geolocation.
+ void NotifyPermissionSet(
+ int render_process_id, int render_view_id, int bridge_id,
+ bool allowed);
+
+ // Sets permissions_ cache (if not on IO thread, will forward to it).
+ void SetPermissionMemoryCacheOnIOThread(const GURL& origin, bool allowed);
+ // Sets permissions file data (if not on FILE thread, will forward to it).
+ void SetPermissionOnFileThread(const GURL& origin, bool allowed);
+
+ // This should only be accessed from the UI thread.
+ Profile* const profile_;
+ // Indicates whether profile_ is off the record.
+ bool const is_off_the_record_;
+ // The path where geolocation permission data is stored.
+ FilePath const permissions_path_;
+ // This should only be accessed from the UI thread.
+ std::map<std::string, bool> permissions_;
+
+ DISALLOW_COPY_AND_ASSIGN(GeolocationPermissionContext);
+};
+
+#endif // CHROME_BROWSER_GEOLOCATION_GEOLOCATION_PERMISSION_CONTEXT_H_
diff --git a/chrome/browser/geolocation/location_arbitrator.cc b/chrome/browser/geolocation/location_arbitrator.cc
index 0b5fc0af..c82fb1d 100644
--- a/chrome/browser/geolocation/location_arbitrator.cc
+++ b/chrome/browser/geolocation/location_arbitrator.cc
@@ -13,8 +13,8 @@
#include "base/string_util.h"
#include "chrome/browser/net/url_request_context_getter.h"
#include "chrome/browser/geolocation/access_token_store.h"
-#include "chrome/browser/geolocation/geoposition.h"
#include "chrome/browser/geolocation/location_provider.h"
+#include "chrome/common/geoposition.h"
#include "googleurl/src/gurl.h"
namespace {
@@ -109,7 +109,7 @@ void GeolocationArbitratorImpl::LocationUpdateAvailable(
LocationProviderBase* provider) {
DCHECK(CalledOnValidThread());
DCHECK(provider);
- Position position;
+ Geoposition position;
provider->GetPosition(&position);
// TODO(joth): Arbitrate.
for (DelegateMap::const_iterator it = observers_.begin();
diff --git a/chrome/browser/geolocation/location_arbitrator.h b/chrome/browser/geolocation/location_arbitrator.h
index aaf61a0..b0c10bc9 100644
--- a/chrome/browser/geolocation/location_arbitrator.h
+++ b/chrome/browser/geolocation/location_arbitrator.h
@@ -7,7 +7,7 @@
class AccessTokenStoreFactory;
class URLRequestContextGetter;
-struct Position;
+struct Geoposition;
// This is the main API to the geolocaiton subsystem. Typically the application
// will hold a single instance of this class, and can register multiple
@@ -29,7 +29,7 @@ class GeolocationArbitrator {
// This will be called whenever the 'best available' location is updated,
// or when an error is encountered meaning no location data will be
// available in the forseeable future.
- virtual void OnLocationUpdate(const Position& position) = 0;
+ virtual void OnLocationUpdate(const Geoposition& position) = 0;
protected:
virtual ~Delegate() {}
diff --git a/chrome/browser/geolocation/location_arbitrator_unittest.cc b/chrome/browser/geolocation/location_arbitrator_unittest.cc
index 6e0c1d8..8d162f3 100644
--- a/chrome/browser/geolocation/location_arbitrator_unittest.cc
+++ b/chrome/browser/geolocation/location_arbitrator_unittest.cc
@@ -6,8 +6,8 @@
#include "base/scoped_ptr.h"
#include "chrome/browser/geolocation/fake_access_token_store.h"
-#include "chrome/browser/geolocation/geoposition.h"
#include "chrome/browser/geolocation/location_provider.h"
+#include "chrome/common/geoposition.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
@@ -31,11 +31,11 @@ class MockLocationProvider : public LocationProviderBase {
++started_count_;
return true;
}
- virtual void GetPosition(Position *position) {
+ virtual void GetPosition(Geoposition *position) {
*position = position_;
}
- Position position_;
+ Geoposition position_;
int started_count_;
static MockLocationProvider* instance_;
@@ -49,18 +49,18 @@ class MockLocationObserver : public GeolocationArbitrator::Delegate {
public:
void InvalidateLastPosition() {
last_position_.accuracy = -1;
- last_position_.error_code = Position::ERROR_CODE_NONE;
+ last_position_.error_code = Geoposition::ERROR_CODE_NONE;
ASSERT_FALSE(last_position_.IsInitialized());
}
// Delegate
- virtual void OnLocationUpdate(const Position& position) {
+ virtual void OnLocationUpdate(const Geoposition& position) {
last_position_ = position;
}
- Position last_position_;
+ Geoposition last_position_;
};
-void SetReferencePosition(Position* position) {
+void SetReferencePosition(Geoposition* position) {
position->latitude = 51.0;
position->longitude = -0.1;
position->accuracy = 400;
diff --git a/chrome/browser/geolocation/location_provider.h b/chrome/browser/geolocation/location_provider.h
index 8ff4acd..fbb49ad 100644
--- a/chrome/browser/geolocation/location_provider.h
+++ b/chrome/browser/geolocation/location_provider.h
@@ -20,6 +20,7 @@
class AccessTokenStore;
class GURL;
class URLRequestContextGetter;
+struct Geoposition;
struct Position;
// The base class used by all location providers.
@@ -64,7 +65,7 @@ class LocationProviderBase : public NonThreadSafe {
// Returns false if the provider failed to start.
virtual bool StartProvider() = 0;
// Gets the current best position estimate.
- virtual void GetPosition(Position* position) = 0;
+ virtual void GetPosition(Geoposition* position) = 0;
// Provides a hint to the provider that new location data is needed as soon
// as possible. Default implementation does nothing.
virtual void UpdatePosition() {}
diff --git a/chrome/browser/geolocation/network_location_provider.cc b/chrome/browser/geolocation/network_location_provider.cc
index 8d0c69e..1b05018 100644
--- a/chrome/browser/geolocation/network_location_provider.cc
+++ b/chrome/browser/geolocation/network_location_provider.cc
@@ -32,7 +32,7 @@ class NetworkLocationProvider::PositionCache {
// WiFi data. Returns true on success, false otherwise.
bool CachePosition(const RadioData& radio_data,
const WifiData& wifi_data,
- const Position& position) {
+ const Geoposition& position) {
// Check that we can generate a valid key for the device data.
string16 key;
if (!MakeKey(radio_data, wifi_data, &key)) {
@@ -57,8 +57,8 @@ class NetworkLocationProvider::PositionCache {
// Searches for a cached position response for the current set of cell ID and
// WiFi data. Returns the cached position if available, NULL otherwise.
- const Position *FindPosition(const RadioData &radio_data,
- const WifiData &wifi_data) {
+ const Geoposition *FindPosition(const RadioData &radio_data,
+ const WifiData &wifi_data) {
string16 key;
if (!MakeKey(radio_data, wifi_data, &key)) {
return NULL;
@@ -96,7 +96,7 @@ class NetworkLocationProvider::PositionCache {
// The cache of positions. This is stored using two maps. One map is keyed on
// a string that represents a set of device data, the other is keyed on the
// timestamp of the position.
- typedef std::map<string16, Position> CacheMap;
+ typedef std::map<string16, Geoposition> CacheMap;
CacheMap cache_;
typedef std::map<int64, CacheMap::iterator> CacheTimesMap;
CacheTimesMap cache_times_;
@@ -141,7 +141,7 @@ NetworkLocationProvider::~NetworkLocationProvider() {
}
// LocationProviderBase implementation
-void NetworkLocationProvider::GetPosition(Position *position) {
+void NetworkLocationProvider::GetPosition(Geoposition *position) {
DCHECK(position);
AutoLock lock(position_mutex_);
*position = position_;
@@ -176,7 +176,7 @@ void NetworkLocationProvider::DeviceDataUpdateAvailable(
// NetworkLocationRequest::ListenerInterface implementation.
void NetworkLocationProvider::LocationResponseAvailable(
- const Position& position,
+ const Geoposition& position,
bool server_error,
const string16& access_token) {
DCHECK(CalledOnValidThread());
@@ -238,7 +238,7 @@ void NetworkLocationProvider::RequestPosition() {
DCHECK(CalledOnValidThread());
delayed_start_task_.RevokeAll();
- const Position* cached_position;
+ const Geoposition* cached_position;
{
AutoLock lock(data_mutex_);
cached_position = position_cache_->FindPosition(radio_data_, wifi_data_);
diff --git a/chrome/browser/geolocation/network_location_provider.h b/chrome/browser/geolocation/network_location_provider.h
index 9dfe59ac..2988841 100644
--- a/chrome/browser/geolocation/network_location_provider.h
+++ b/chrome/browser/geolocation/network_location_provider.h
@@ -12,9 +12,9 @@
#include "base/string16.h"
#include "base/thread.h"
#include "chrome/browser/geolocation/device_data_provider.h"
-#include "chrome/browser/geolocation/geoposition.h"
#include "chrome/browser/geolocation/location_provider.h"
#include "chrome/browser/geolocation/network_location_request.h"
+#include "chrome/common/geoposition.h"
class URLFetcherProtectEntry;
@@ -32,7 +32,7 @@ class NetworkLocationProvider
// LocationProviderBase implementation
virtual bool StartProvider();
- virtual void GetPosition(Position *position);
+ virtual void GetPosition(Geoposition *position);
virtual void UpdatePosition();
private:
@@ -50,7 +50,7 @@ class NetworkLocationProvider
virtual void DeviceDataUpdateAvailable(WifiDataProvider* provider);
// NetworkLocationRequest::ListenerInterface implementation.
- virtual void LocationResponseAvailable(const Position& position,
+ virtual void LocationResponseAvailable(const Geoposition& position,
bool server_error,
const string16& access_token);
@@ -74,7 +74,7 @@ class NetworkLocationProvider
string16 access_token_;
// The current best position estimate and its guarding mutex
- Position position_;
+ Geoposition position_;
Lock position_mutex_;
bool is_new_data_available_;
diff --git a/chrome/browser/geolocation/network_location_provider_unittest.cc b/chrome/browser/geolocation/network_location_provider_unittest.cc
index f8af128..34e6b2d 100644
--- a/chrome/browser/geolocation/network_location_provider_unittest.cc
+++ b/chrome/browser/geolocation/network_location_provider_unittest.cc
@@ -298,7 +298,7 @@ TEST_F(GeolocationNetworkProviderTest, MultipleWifiScansComplete) {
EXPECT_TRUE(access_token_store_->GetAccessToken(&token));
EXPECT_EQ(REFERENCE_ACCESS_TOKEN, UTF16ToUTF8(token));
- Position position;
+ Geoposition position;
provider->GetPosition(&position);
EXPECT_FALSE(position.IsValidFix());
diff --git a/chrome/browser/geolocation/network_location_request.cc b/chrome/browser/geolocation/network_location_request.cc
index 65e3f37..ecf41d9 100644
--- a/chrome/browser/geolocation/network_location_request.cc
+++ b/chrome/browser/geolocation/network_location_request.cc
@@ -8,8 +8,8 @@
#include "base/json/json_writer.h"
#include "base/string_util.h"
#include "base/values.h"
-#include "chrome/browser/geolocation/geoposition.h"
#include "chrome/browser/net/url_request_context_getter.h"
+#include "chrome/common/geoposition.h"
#include "net/url_request/url_request_status.h"
namespace {
@@ -39,7 +39,7 @@ void GetLocationFromResponse(bool http_post_result,
const std::string& response_body,
int64 timestamp,
const GURL& server_url,
- Position* position,
+ Geoposition* position,
string16* access_token);
const char* RadioTypeToString(RadioType type);
@@ -54,7 +54,7 @@ void AddInteger(const std::wstring& property_name,
// Parses the server response body. Returns true if parsing was successful.
bool ParseServerResponse(const std::string& response_body,
int64 timestamp,
- Position* position,
+ Geoposition* position,
string16* access_token);
void AddRadioData(const RadioData& radio_data, DictionaryValue* body_object);
void AddWifiData(const WifiData& wifi_data, DictionaryValue* body_object);
@@ -105,7 +105,7 @@ void NetworkLocationRequest::OnURLFetchComplete(const URLFetcher* source,
DCHECK_EQ(url_fetcher_.get(), source);
DCHECK(url_.possibly_invalid_spec() == url.possibly_invalid_spec());
- Position position;
+ Geoposition position;
string16 access_token;
GetLocationFromResponse(status.is_success(), response_code, data,
timestamp_, url, &position, &access_token);
@@ -162,8 +162,8 @@ bool FormRequestBody(const string16& host_name,
void FormatPositionError(const GURL& server_url,
const std::wstring& message,
- Position* position) {
- position->error_code = Position::ERROR_CODE_POSITION_UNAVAILABLE;
+ Geoposition* position) {
+ position->error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
position->error_message = L"Network location provider at '";
position->error_message += ASCIIToWide(server_url.possibly_invalid_spec());
position->error_message += L"' : ";
@@ -178,7 +178,7 @@ void GetLocationFromResponse(bool http_post_result,
const std::string& response_body,
int64 timestamp,
const GURL& server_url,
- Position* position,
+ Geoposition* position,
string16* access_token) {
DCHECK(position);
DCHECK(access_token);
@@ -268,7 +268,7 @@ bool GetAsDouble(const DictionaryValue& object,
bool ParseServerResponse(const std::string& response_body,
int64 timestamp,
- Position* position,
+ Geoposition* position,
string16* access_token) {
DCHECK(position);
DCHECK(access_token);
diff --git a/chrome/browser/geolocation/network_location_request.h b/chrome/browser/geolocation/network_location_request.h
index da89cb1..97cf16c 100644
--- a/chrome/browser/geolocation/network_location_request.h
+++ b/chrome/browser/geolocation/network_location_request.h
@@ -14,6 +14,7 @@
class URLRequestContextGetter;
class URLFetcher;
+struct Geoposition;
struct Position;
// Takes a set of device data and sends it to a server to get a position fix.
@@ -26,7 +27,7 @@ class NetworkLocationRequest : private URLFetcher::Delegate {
// Updates the listener with a new position. server_error indicates whether
// was a server or network error - either no response or a 500 error code.
virtual void LocationResponseAvailable(
- const Position& position,
+ const Geoposition& position,
bool server_error,
const string16& access_token) = 0;
diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h
index 52453a2..7747066 100644
--- a/chrome/browser/renderer_host/render_view_host.h
+++ b/chrome/browser/renderer_host/render_view_host.h
@@ -611,7 +611,9 @@ class RenderViewHost : public RenderWidgetHost {
void OnPageTranslated(int32 page_id,
const std::string& original_lang,
const std::string& translated_lang);
+
void OnContentBlocked(ContentSettingsType type);
+
private:
friend class TestRenderViewHost;
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index 92efd4b..a1f00d6 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -18,6 +18,8 @@
#include "chrome/browser/download/download_file.h"
#include "chrome/browser/extensions/extension_file_util.h"
#include "chrome/browser/extensions/extension_message_service.h"
+#include "chrome/browser/geolocation/geolocation_permission_context.h"
+#include "chrome/browser/geolocation/geolocation_dispatcher_host.h"
#include "chrome/browser/host_zoom_map.h"
#include "chrome/browser/in_process_webkit/dom_storage_dispatcher_host.h"
#include "chrome/browser/nacl_host/nacl_process_host.h"
@@ -297,7 +299,10 @@ ResourceMessageFilter::ResourceMessageFilter(
off_the_record_(profile->IsOffTheRecord()),
next_route_id_callback_(NewCallbackWithReturnValue(
render_widget_helper, &RenderWidgetHelper::GetNextRoutingID)),
- ALLOW_THIS_IN_INITIALIZER_LIST(translation_service_(this)) {
+ ALLOW_THIS_IN_INITIALIZER_LIST(translation_service_(this)),
+ ALLOW_THIS_IN_INITIALIZER_LIST(geolocation_dispatcher_host_(
+ new GeolocationDispatcherHost(
+ this->id(), new GeolocationPermissionContext(profile)))) {
DCHECK(request_context_);
DCHECK(media_request_context_);
DCHECK(audio_renderer_host_.get());
@@ -387,7 +392,8 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) {
audio_renderer_host_->OnMessageReceived(msg, &msg_is_ok) ||
db_dispatcher_host_->OnMessageReceived(msg, &msg_is_ok) ||
mp_dispatcher->OnMessageReceived(
- msg, this, next_route_id_callback(), &msg_is_ok);
+ msg, this, next_route_id_callback(), &msg_is_ok) ||
+ geolocation_dispatcher_host_->OnMessageReceived(msg, &msg_is_ok);
if (!handled) {
DCHECK(msg_is_ok); // It should have been marked handled if it wasn't OK.
diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h
index 82070fb..076989b 100644
--- a/chrome/browser/renderer_host/resource_message_filter.h
+++ b/chrome/browser/renderer_host/resource_message_filter.h
@@ -38,6 +38,7 @@ class ChromeURLRequestContext;
class DatabaseDispatcherHost;
class DOMStorageDispatcherHost;
class ExtensionMessageService;
+class GeolocationDispatcherHost;
class HostZoomMap;
class NotificationsPrefsCache;
class Profile;
@@ -402,6 +403,9 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
// Used to translate page contents from one language to another.
TranslationService translation_service_;
+ // Used to handle geolocation-related messages.
+ scoped_refptr<GeolocationDispatcherHost> geolocation_dispatcher_host_;
+
DISALLOW_COPY_AND_ASSIGN(ResourceMessageFilter);
};
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 5fb5032..2fca9c4 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -932,10 +932,12 @@
'browser/geolocation/device_data_provider.h',
'browser/geolocation/empty_device_data_provider.cc',
'browser/geolocation/empty_device_data_provider.h',
+ 'browser/geolocation/geolocation_dispatcher_host.cc',
+ 'browser/geolocation/geolocation_dispatcher_host.h',
+ 'browser/geolocation/geolocation_permission_context.cc',
+ 'browser/geolocation/geolocation_permission_context.h',
'browser/geolocation/geolocation_prefs.cc',
- 'browser/geolocation/geolocation_prefs.h',
- 'browser/geolocation/geoposition.cc',
- 'browser/geolocation/geoposition.h',
+ 'browser/geolocation/geolocation_prefs.h',
'browser/geolocation/location_arbitrator.cc',
'browser/geolocation/location_arbitrator.h',
'browser/geolocation/location_provider.cc',
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index 59097a4..131c543 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -44,6 +44,8 @@
'common/debug_flags.h',
'common/devtools_messages.h',
'common/devtools_messages_internal.h',
+ 'common/geoposition.cc',
+ 'common/geoposition.h',
'common/gpu_messages.h',
'common/gpu_messages_internal.h',
'common/io_surface_support_mac.cc',
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index 77252ba..125c0fa 100755
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -83,6 +83,8 @@
'renderer/external_extension.h',
'renderer/form_manager.cc',
'renderer/form_manager.h',
+ 'renderer/geolocation_dispatcher.cc',
+ 'renderer/geolocation_dispatcher.h',
'renderer/localized_error.cc',
'renderer/localized_error.h',
'renderer/navigation_state.h',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index f6c3b4f..7c0d1d2 100755
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1158,6 +1158,7 @@
'browser/extensions/permissions_apitest.cc',
'browser/extensions/stubs_apitest.cc',
'browser/geolocation/access_token_store_browsertest.cc',
+ 'browser/geolocation/geolocation_browsertest.cc',
'browser/gtk/bookmark_manager_browsertest.cc',
'browser/net/cookie_policy_browsertest.cc',
'browser/net/ftp_browsertest.cc',
diff --git a/chrome/common/common_param_traits.cc b/chrome/common/common_param_traits.cc
index e213f6d..62e57ff 100644
--- a/chrome/common/common_param_traits.cc
+++ b/chrome/common/common_param_traits.cc
@@ -245,5 +245,66 @@ void ParamTraits<webkit_glue::WebApplicationInfo>::Log(
l->append(L"<WebApplicationInfo>");
}
-} // namespace IPC
+void ParamTraits<Geoposition::ErrorCode>::Write(
+ Message* m, const Geoposition::ErrorCode& p) {
+ int error_code = p;
+ WriteParam(m, error_code);
+}
+
+bool ParamTraits<Geoposition::ErrorCode>::Read(
+ const Message* m, void** iter, Geoposition::ErrorCode* p) {
+ int error_code_param = 0;
+ bool ret = ReadParam(m, iter, &error_code_param);
+ *p = static_cast<Geoposition::ErrorCode>(error_code_param);
+ return ret;
+}
+void ParamTraits<Geoposition::ErrorCode>::Log(
+ const Geoposition::ErrorCode& p, std::wstring* l) {
+ int error_code = p;
+ l->append(StringPrintf(L"<Geoposition::ErrorCode>%d", error_code));
+}
+
+void ParamTraits<Geoposition>::Write(Message* m, const Geoposition& p) {
+ WriteParam(m, p.latitude);
+ WriteParam(m, p.longitude);
+ WriteParam(m, p.accuracy);
+ WriteParam(m, p.altitude);
+ WriteParam(m, p.altitude_accuracy);
+ WriteParam(m, p.speed);
+ WriteParam(m, p.heading);
+ WriteParam(m, p.timestamp);
+ WriteParam(m, p.error_code);
+ WriteParam(m, p.error_message);
+}
+
+bool ParamTraits<Geoposition>::Read(
+ const Message* m, void** iter, Geoposition* p) {
+ bool ret = ReadParam(m, iter, &p->latitude);
+ ret = ret && ReadParam(m, iter, &p->longitude);
+ ret = ret && ReadParam(m, iter, &p->accuracy);
+ ret = ret && ReadParam(m, iter, &p->altitude);
+ ret = ret && ReadParam(m, iter, &p->altitude_accuracy);
+ ret = ret && ReadParam(m, iter, &p->speed);
+ ret = ret && ReadParam(m, iter, &p->heading);
+ ret = ret && ReadParam(m, iter, &p->timestamp);
+ ret = ret && ReadParam(m, iter, &p->error_code);
+ ret = ret && ReadParam(m, iter, &p->error_message);
+ return ret;
+}
+
+void ParamTraits<Geoposition>::Log(const Geoposition& p, std::wstring* l) {
+ l->append(
+ StringPrintf(
+ L"<Geoposition>"
+ L"%.6f %.6f %.6f %.6f "
+ L"%.6f %.6f %.6f "
+ L"%lld ",
+ p.latitude, p.longitude, p.accuracy, p.altitude,
+ p.altitude_accuracy, p.speed, p.heading,
+ p.timestamp));
+ l->append(p.error_message);
+ LogParam<Geoposition::ErrorCode>(p.error_code, l);
+}
+
+} // namespace IPC
diff --git a/chrome/common/common_param_traits.h b/chrome/common/common_param_traits.h
index 83148a6..99b1896 100644
--- a/chrome/common/common_param_traits.h
+++ b/chrome/common/common_param_traits.h
@@ -15,6 +15,7 @@
#include "app/gfx/native_widget_types.h"
#include "chrome/common/content_settings.h"
+#include "chrome/common/geoposition.h"
#include "chrome/common/page_zoom.h"
#include "chrome/common/thumbnail_score.h"
#include "chrome/common/transport_dib.h"
@@ -392,6 +393,22 @@ struct ParamTraits<ThumbnailScore> {
}
};
+template <>
+struct ParamTraits<Geoposition> {
+ typedef Geoposition param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* p);
+ static void Log(const param_type& p, std::wstring* l);
+};
+
+template <>
+struct ParamTraits<Geoposition::ErrorCode> {
+ typedef Geoposition::ErrorCode param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, void** iter, param_type* p);
+ static void Log(const param_type& p, std::wstring* l);
+};
+
} // namespace IPC
#endif // CHROME_COMMON_COMMON_PARAM_TRAITS_H_
diff --git a/chrome/common/common_param_traits_unittest.cc b/chrome/common/common_param_traits_unittest.cc
index f5db121..d888084 100644
--- a/chrome/common/common_param_traits_unittest.cc
+++ b/chrome/common/common_param_traits_unittest.cc
@@ -166,3 +166,42 @@ TEST(IPCMessageTest, DictionaryValue) {
iter = NULL;
EXPECT_FALSE(IPC::ReadParam(&bad_msg, &iter, &output));
}
+
+TEST(IPCMessageTest, Geoposition) {
+ Geoposition input;
+ input.latitude = 0.1;
+ input.longitude = 51.3;
+ input.accuracy = 13.7;
+ input.altitude = 42.24;
+ input.altitude_accuracy = 9.3;
+ input.speed = 55;
+ input.heading = 120;
+ input.timestamp = 1977;
+ input.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
+ input.error_message = L"unittest error message for geoposition";
+
+ IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
+ IPC::WriteParam(&msg, input);
+
+ Geoposition output;
+ void* iter = NULL;
+ EXPECT_TRUE(IPC::ReadParam(&msg, &iter, &output));
+ EXPECT_EQ(input.altitude, output.altitude);
+ EXPECT_EQ(input.altitude_accuracy, output.altitude_accuracy);
+ EXPECT_EQ(input.latitude, output.latitude);
+ EXPECT_EQ(input.longitude, output.longitude);
+ EXPECT_EQ(input.accuracy, output.accuracy);
+ EXPECT_EQ(input.heading, output.heading);
+ EXPECT_EQ(input.speed, output.speed);
+ EXPECT_EQ(input.error_code, output.error_code);
+ EXPECT_EQ(input.error_message, output.error_message);
+
+ std::wstring log_message;
+ IPC::LogParam(output, &log_message);
+ EXPECT_STREQ(L"<Geoposition>"
+ L"0.100000 51.300000 13.700000 42.240000 "
+ L"9.300000 55.000000 120.000000 "
+ L"1977 unittest error message for geoposition"
+ L"<Geoposition::ErrorCode>2",
+ log_message.c_str());
+}
diff --git a/chrome/browser/geolocation/geoposition.cc b/chrome/common/geoposition.cc
index 8618431..d4989ed 100644
--- a/chrome/browser/geolocation/geoposition.cc
+++ b/chrome/common/geoposition.cc
@@ -2,54 +2,66 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/browser/geolocation/geoposition.h"
+#include "chrome/common/geoposition.h"
namespace {
// Sentinel values to mark invalid data. (WebKit carries companion is_valid
// bools for this purpose; we may eventually follow that approach, but
// sentinels worked OK in the gears code this is based on.)
-const double kBadLatLng = 200;
-// Lowest point on land is at approximately -400 metres.
-const int kBadAltitude = -1000;
+const double kBadLatitudeLongitude = 200;
+// Lowest point on land is at approximately -400 meters.
+const int kBadAltitude = -10000;
const int kBadAccuracy = -1; // Accuracy must be non-negative.
const int64 kBadTimestamp = kint64min;
+const int kBadHeading = -1; // Heading must be non-negative.
+const int kBadSpeed = -1;
}
-Position::Position()
- : latitude(kBadLatLng),
- longitude(kBadLatLng),
+Geoposition::Geoposition()
+ : latitude(kBadLatitudeLongitude),
+ longitude(kBadLatitudeLongitude),
altitude(kBadAltitude),
accuracy(kBadAccuracy),
altitude_accuracy(kBadAccuracy),
+ heading(kBadHeading),
+ speed(kBadSpeed),
timestamp(kBadTimestamp),
error_code(ERROR_CODE_NONE) {
}
-bool Position::is_valid_latlong() const {
+bool Geoposition::is_valid_latlong() const {
return latitude >= -90.0 && latitude <= 90.0 &&
longitude >= -180.0 && longitude <= 180.0;
}
-bool Position::is_valid_altitude() const {
+bool Geoposition::is_valid_altitude() const {
return altitude > kBadAltitude;
}
-bool Position::is_valid_accuracy() const {
+bool Geoposition::is_valid_accuracy() const {
return accuracy >= 0.0;
}
-bool Position::is_valid_altitude_accuracy() const {
+bool Geoposition::is_valid_altitude_accuracy() const {
return altitude_accuracy >= 0.0;
}
-bool Position::is_valid_timestamp() const {
+bool Geoposition::is_valid_heading() const {
+ return heading >= 0 && heading <= 360;
+}
+
+bool Geoposition::is_valid_speed() const {
+ return speed >= 0;
+}
+
+bool Geoposition::is_valid_timestamp() const {
return timestamp != kBadTimestamp;
}
-bool Position::IsValidFix() const {
+bool Geoposition::IsValidFix() const {
return is_valid_latlong() && is_valid_accuracy() && is_valid_timestamp();
}
-bool Position::IsInitialized() const {
+bool Geoposition::IsInitialized() const {
return error_code != ERROR_CODE_NONE || IsValidFix();
}
diff --git a/chrome/browser/geolocation/geoposition.h b/chrome/common/geoposition.h
index 7143638..94c1dc9 100644
--- a/chrome/browser/geolocation/geoposition.h
+++ b/chrome/common/geoposition.h
@@ -6,14 +6,14 @@
// position fix. Originally derived from
// http://gears.googlecode.com/svn/trunk/gears/geolocation/geolocation.h
-#ifndef CHROME_BROWSER_GEOLOCATION_GEOPOSITION_H_
-#define CHROME_BROWSER_GEOLOCATION_GEOPOSITION_H_
+#ifndef CHROME_COMMON_GEOPOSITION_H_
+#define CHROME_COMMON_GEOPOSITION_H_
#include "base/string16.h"
-// The internal representation of a position. Some properties use different
+// The internal representation of a geo position. Some properties use different
// types when passed to JavaScript.
-struct Position {
+struct Geoposition {
public:
// Error codes for returning to JavaScript. These values are defined by the
// W3C spec. Note that Gears does not use all of these codes, but we need
@@ -26,12 +26,14 @@ struct Position {
ERROR_CODE_TIMEOUT = 3,
};
- Position();
+ Geoposition();
bool is_valid_latlong() const;
bool is_valid_altitude() const;
bool is_valid_accuracy() const;
bool is_valid_altitude_accuracy() const;
+ bool is_valid_heading() const;
+ bool is_valid_speed() const;
bool is_valid_timestamp() const;
// A valid fix has a valid latitude, longitude, accuracy and timestamp.
@@ -47,6 +49,8 @@ struct Position {
double altitude; // In metres
double accuracy; // In metres
double altitude_accuracy; // In metres
+ double heading; // In degrees clockwise relative to the true north
+ double speed; // In meters per second
int64 timestamp; // Milliseconds since 1st Jan 1970
// These properties are returned to JavaScript as a PositionError object.
@@ -54,4 +58,4 @@ struct Position {
std::wstring error_message; // Human-readable error message
};
-#endif // CHROME_BROWSER_GEOLOCATION_GEOPOSITION_H_
+#endif // CHROME_COMMON_GEOPOSITION_H_
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 208a280..a07dd2e 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -19,6 +19,7 @@
#include "base/values.h"
#include "chrome/common/content_settings.h"
#include "chrome/common/extensions/update_manifest.h"
+#include "chrome/common/geoposition.h"
#include "chrome/common/nacl_types.h"
#include "chrome/common/notification_type.h"
#include "chrome/common/page_zoom.h"
@@ -899,6 +900,22 @@ IPC_BEGIN_MESSAGES(View)
int /* error id of translation work */,
std::vector<string16> /* the translated text chunks */)
+ // Reply in response to ViewHostMsg_Geolocation_RequestPermission.
+ IPC_MESSAGE_ROUTED2(ViewMsg_Geolocation_PermissionSet,
+ int /* bridge_id */,
+ bool /* is_allowed */)
+
+ // Sent after ViewHostMsg_Geolocation_StartUpdating iff the user has granted
+ // permission and we have a position available.
+ IPC_MESSAGE_ROUTED1(ViewMsg_Geolocation_PositionUpdated,
+ Geoposition /* geoposition */)
+
+ // Sent after ViewHostMsg_Geolocation_StartUpdating in case of error (such as
+ // permission denied, position unavailable, etc.).
+ IPC_MESSAGE_ROUTED2(ViewMsg_Geolocation_Error,
+ int /* code */,
+ std::string /* message */)
+
IPC_END_MESSAGES(View)
@@ -2130,4 +2147,64 @@ IPC_BEGIN_MESSAGES(ViewHost)
IPC_MESSAGE_CONTROL1(ViewHostMsg_TranslateText,
ViewHostMsg_TranslateTextParam)
+ //---------------------------------------------------------------------------
+ // Geolocation services messages
+
+ // A GeolocationServiceBridgeImpl in the renderer process has been created.
+ // This is used to lazily initialize the host dispatchers and related
+ // Geolocation infrastructure in the browser process.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_Geolocation_RegisterDispatcher,
+ int /* route_id */)
+
+ // A GeolocationServiceBridgeImpl has been destroyed.
+ // This is used to let the Geolocation infrastructure do its cleanup.
+ IPC_MESSAGE_CONTROL1(ViewHostMsg_Geolocation_UnregisterDispatcher,
+ int /* route_id */)
+
+ // The |route_id| and |bridge_id| representing |URL| is requesting permission
+ // to access geolocation position.
+ // This will be replied by ViewMsg_Geolocation_PermissionSet.
+ IPC_MESSAGE_CONTROL3(ViewHostMsg_Geolocation_RequestPermission,
+ int /* route_id */,
+ int /* bridge_id */,
+ GURL /* URL of the page*/)
+
+ // The |route_id| and |bridge_id| requests Geolocation service to start
+ // updating.
+ // This is an asynchronous call, and the browser process may eventually reply
+ // with the updated geoposition, or an error (access denied, location
+ // unavailable, etc.)
+ IPC_MESSAGE_CONTROL3(ViewHostMsg_Geolocation_StartUpdating,
+ int /* route_id */,
+ int /* bridge_id */,
+ bool /* high_accuracy */)
+
+ // The |route_id| and |bridge_id| requests Geolocation service to stop
+ // updating.
+ // Note that the geolocation service may continue to fetch geolocation data
+ // for other origins.
+ IPC_MESSAGE_CONTROL2(ViewHostMsg_Geolocation_StopUpdating,
+ int /* route_id */,
+ int /* bridge_id */)
+
+ // The |route_id| and |bridge_id| requests Geolocation service to suspend.
+ // Note that the geolocation service may continue to fetch geolocation data
+ // for other origins.
+ IPC_MESSAGE_CONTROL2(ViewHostMsg_Geolocation_Suspend,
+ int /* route_id */,
+ int /* bridge_id */)
+
+ // The |route_id| and |bridge_id| requests Geolocation service to resume.
+ IPC_MESSAGE_CONTROL2(ViewHostMsg_Geolocation_Resume,
+ int /* route_id */,
+ int /* bridge_id */)
+
+ // Sent to indicate whether this particular GeolocationServiceBridgeImpl
+ // (identified by |route_id| and |bridge_id|) is allowed to use geolocation
+ // services.
+ IPC_MESSAGE_CONTROL3(ViewHostMsg_Geolocation_PermissionSet,
+ int /* route_id */,
+ int /* bridge_id */,
+ bool /* is_allowed */)
+
IPC_END_MESSAGES(ViewHost)
diff --git a/chrome/renderer/geolocation_dispatcher.cc b/chrome/renderer/geolocation_dispatcher.cc
new file mode 100644
index 0000000..fedad06
--- /dev/null
+++ b/chrome/renderer/geolocation_dispatcher.cc
@@ -0,0 +1,104 @@
+// Copyright (c) 2010 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/renderer/geolocation_dispatcher.h"
+
+#include "base/command_line.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/renderer/render_view.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebCString.h"
+
+using WebKit::WebFrame;
+
+GeolocationDispatcher::GeolocationDispatcher(RenderView* render_view)
+ : render_view_(render_view) {
+ render_view_->Send(new ViewHostMsg_Geolocation_RegisterDispatcher(
+ render_view_->routing_id()));
+}
+
+GeolocationDispatcher::~GeolocationDispatcher() {
+ render_view_->Send(new ViewHostMsg_Geolocation_UnregisterDispatcher(
+ render_view_->routing_id()));
+}
+
+bool GeolocationDispatcher::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(GeolocationDispatcher, message)
+ IPC_MESSAGE_HANDLER(ViewMsg_Geolocation_PermissionSet,
+ OnGeolocationPermissionSet)
+ IPC_MESSAGE_HANDLER(ViewMsg_Geolocation_PositionUpdated,
+ OnGeolocationPositionUpdated)
+ IPC_MESSAGE_HANDLER(ViewMsg_Geolocation_Error, OnGeolocationError)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void GeolocationDispatcher::requestPermissionForFrame(
+ int bridge_id, const WebKit::WebURL& url) {
+ render_view_->Send(new ViewHostMsg_Geolocation_RequestPermission(
+ bridge_id, render_view_->routing_id(), GURL(url).GetOrigin()));
+}
+
+void GeolocationDispatcher::startUpdating(int bridge_id, bool hasHighAccuracy) {
+ render_view_->Send(new ViewHostMsg_Geolocation_StartUpdating(
+ bridge_id, render_view_->routing_id(), hasHighAccuracy));
+}
+
+void GeolocationDispatcher::stopUpdating(int bridge_id) {
+ render_view_->Send(new ViewHostMsg_Geolocation_StopUpdating(
+ bridge_id, render_view_->routing_id()));
+}
+
+void GeolocationDispatcher::suspend(int bridge_id) {
+ render_view_->Send(new ViewHostMsg_Geolocation_Suspend(
+ bridge_id, render_view_->routing_id()));
+}
+
+void GeolocationDispatcher::resume(int bridge_id) {
+ render_view_->Send(new ViewHostMsg_Geolocation_Resume(
+ bridge_id, render_view_->routing_id()));
+}
+
+int GeolocationDispatcher::attachBridge(
+ WebKit::WebGeolocationServiceBridge* bridge) {
+ return bridges_map_.Add(bridge);
+}
+
+void GeolocationDispatcher::dettachBridge(int bridge_id) {
+ bridges_map_.Remove(bridge_id);
+}
+
+void GeolocationDispatcher::OnGeolocationPermissionSet(int bridge_id,
+ bool allowed) {
+ WebKit::WebGeolocationServiceBridge* bridge = bridges_map_.Lookup(bridge_id);
+ if (bridge) {
+ bridge->setIsAllowed(allowed);
+ }
+}
+
+void GeolocationDispatcher::OnGeolocationPositionUpdated(
+ const Geoposition& geoposition) {
+ for (IDMap<WebKit::WebGeolocationServiceBridge>::iterator it(&bridges_map_);
+ !it.IsAtEnd(); it.Advance()) {
+ it.GetCurrentValue()->setLastPosition(
+ geoposition.latitude, geoposition.longitude,
+ geoposition.is_valid_altitude(), geoposition.altitude,
+ geoposition.accuracy,
+ geoposition.is_valid_altitude_accuracy(), geoposition.altitude_accuracy,
+ geoposition.is_valid_heading(), geoposition.heading,
+ geoposition.is_valid_speed(), geoposition.speed,
+ geoposition.timestamp);
+ }
+}
+
+void GeolocationDispatcher::OnGeolocationError(int code,
+ const std::string& message) {
+ for (IDMap<WebKit::WebGeolocationServiceBridge>::iterator it(&bridges_map_);
+ !it.IsAtEnd(); it.Advance()) {
+ it.GetCurrentValue()->setLastError(
+ code, WebKit::WebString::fromUTF8(message));
+ }
+}
diff --git a/chrome/renderer/geolocation_dispatcher.h b/chrome/renderer/geolocation_dispatcher.h
new file mode 100644
index 0000000..31fdab4c
--- /dev/null
+++ b/chrome/renderer/geolocation_dispatcher.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2010 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_RENDERER_GEOLOCATION_DISPATCHER_H_
+#define CHROME_RENDERER_GEOLOCATION_DISPATCHER_H_
+
+#include "base/basictypes.h"
+#include "base/id_map.h"
+#include "chrome/common/geoposition.h"
+#include "ipc/ipc_message.h"
+#include "googleurl/src/gurl.h"
+#include "third_party/WebKit/WebKit/chromium/public/GeolocationServiceBridgeChromium.h"
+
+class GURL;
+class RenderView;
+
+// GeolocationDispatcher is a delegate for Geolocation messages used by
+// WebKit.
+// It's the complement of GeolocationDispatcherHost (owned by RenderViewHost).
+class GeolocationDispatcher : public WebKit::WebGeolocationServiceInterface {
+ public:
+ explicit GeolocationDispatcher(RenderView* render_view);
+ virtual ~GeolocationDispatcher();
+
+ // Called to possibly handle the incoming IPC message. Returns true if
+ // handled. Called in render thread.
+ bool OnMessageReceived(const IPC::Message& msg);
+
+ // WebKit::GeolocationServiceInterfaceChromium.
+ void requestPermissionForFrame(int bridge_id, const WebKit::WebURL& url);
+ void startUpdating(int bridge_id, bool hasHighAccuracy);
+ void stopUpdating(int bridge_id);
+ void suspend(int bridge_id);
+ void resume(int bridge_id);
+ int attachBridge(WebKit::WebGeolocationServiceBridge* geolocation_service);
+ void dettachBridge(int bridge_id);
+
+ private:
+ // Permission for using geolocation has been set.
+ void OnGeolocationPermissionSet(int bridge_id, bool is_allowed);
+
+ // We have an updated geolocation position.
+ void OnGeolocationPositionUpdated(const Geoposition& geoposition);
+
+ // An error has happened when fetching a geolocation position.
+ void OnGeolocationError(int code, const std::string& message);
+
+ RenderView* render_view_;
+
+ // The geolocation services attached to this dispatcher.
+ IDMap<WebKit::WebGeolocationServiceBridge> bridges_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(GeolocationDispatcher);
+};
+
+#endif // CHROME_RENDERER_GEOLOCATION_DISPATCHER_H_
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 6c287d0..f8fb11a 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -44,6 +44,7 @@
#include "chrome/renderer/extensions/event_bindings.h"
#include "chrome/renderer/extensions/extension_process_bindings.h"
#include "chrome/renderer/extensions/renderer_extension_bindings.h"
+#include "chrome/renderer/geolocation_dispatcher.h"
#include "chrome/renderer/localized_error.h"
#include "chrome/renderer/media/audio_renderer_impl.h"
#include "chrome/renderer/navigation_state.h"
@@ -67,6 +68,7 @@
#include "skia/ext/bitmap_platform_device.h"
#include "skia/ext/image_operations.h"
#include "third_party/cld/encodings/compact_lang_det/win/cld_unicodetext.h"
+#include "third_party/WebKit/WebKit/chromium/public/GeolocationServiceBridgeChromium.h"
#include "third_party/WebKit/WebKit/chromium/public/WebAccessibilityCache.h"
#include "third_party/WebKit/WebKit/chromium/public/WebAccessibilityObject.h"
#include "third_party/WebKit/WebKit/chromium/public/WebCString.h"
@@ -481,6 +483,10 @@ void RenderView::OnMessageReceived(const IPC::Message& message) {
return;
if (notification_provider_->OnMessageReceived(message))
return;
+ if (geolocation_dispatcher_.get() &&
+ geolocation_dispatcher_->OnMessageReceived(message)) {
+ return;
+ }
IPC_BEGIN_MESSAGE_MAP(RenderView, message)
IPC_MESSAGE_HANDLER(ViewMsg_CaptureThumbnail, SendThumbnail)
@@ -4506,3 +4512,10 @@ void RenderView::GPUPluginBuffersSwapped(gfx::PluginWindowHandle window) {
Send(new ViewHostMsg_GPUPluginBuffersSwapped(routing_id(), window));
}
#endif
+
+WebKit::WebGeolocationServiceInterface* RenderView::getGeolocationService() {
+ if (!geolocation_dispatcher_.get())
+ geolocation_dispatcher_.reset(new GeolocationDispatcher(this));
+ return geolocation_dispatcher_.get();
+}
+
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index 60deea6..b08bd21 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -69,6 +69,7 @@ class DictionaryValue;
class DevToolsAgent;
class DevToolsClient;
class FilePath;
+class GeolocationDispatcher;
class GURL;
class ListValue;
class NavigationState;
@@ -89,6 +90,10 @@ struct FileUploadData;
}
namespace WebKit {
+class WebGeolocationServiceInterfaceChromium;
+}
+
+namespace WebKit {
class WebAccessibilityCache;
class WebDataSource;
class WebDragData;
@@ -259,6 +264,7 @@ class RenderView : public RenderWidget,
virtual WebKit::WebNotificationPresenter* GetNotificationPresenter() {
return notification_provider_.get();
}
+ virtual WebKit::WebGeolocationServiceInterface* getGeolocationService();
// Sets the content settings that back allowScripts(), allowImages(), and
// allowPlugins().
@@ -1111,6 +1117,9 @@ class RenderView : public RenderWidget,
std::set<WebPluginDelegateProxy*> plugin_delegates_;
#endif
+ // The geolocation dispatcher attached to this view, lazily initialized.
+ scoped_ptr<GeolocationDispatcher> geolocation_dispatcher_;
+
DISALLOW_COPY_AND_ASSIGN(RenderView);
};
diff --git a/chrome/test/data/geolocation/simple.html b/chrome/test/data/geolocation/simple.html
new file mode 100644
index 0000000..fef9724
--- /dev/null
+++ b/chrome/test/data/geolocation/simple.html
@@ -0,0 +1,35 @@
+<html>
+ <head>
+ <script>
+ var last_position = 0;
+ var last_error = 0;
+ var watch_id = 0;
+ function geoSuccessCallback(position) {
+ last_position = position;
+ alert('geoSuccessCallback');
+ }
+ function geoErrorCallback(error) {
+ last_error = error;
+ alert('geoErrorCallback');
+ }
+ function geoStart() {
+ watch_id = navigator.geolocation.watchPosition(
+ geoSuccessCallback, geoErrorCallback,
+ {maximumAge:600000, timeout:100000, enableHighAccuracy:true});
+ return watch_id;
+ }
+ function geoGetLastPositionLatitude() {
+ return "" + last_position.coords.latitude;
+ }
+ function geoGetLastPositionLongitude() {
+ return "" + last_position.coords.longitude;
+ }
+ function geoGetLastError() {
+ return "" + (last_error ? last_error.code : 0);
+ }
+ </script>
+ </head>
+ <body>
+ <input type="button" value="manual" onclick="geoStart()"/>
+ </body>
+</html>