[content shell] implement testRunner.overridePreference
[chromium-blink-merge.git] / content / browser / geolocation / win7_location_api_win.cc
blob72ac44aeb6e7bda9c4f8e80a93a12776be34f8d1
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/geolocation/win7_location_api_win.h"
7 #include "base/base_paths_win.h"
8 #include "base/command_line.h"
9 #include "base/file_path.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/path_service.h"
13 #include "content/public/common/content_switches.h"
14 #include "content/public/common/geoposition.h"
16 namespace content {
17 namespace {
18 const double kKnotsToMetresPerSecondConversionFactor = 0.5144;
20 void ConvertKnotsToMetresPerSecond(double* knots) {
21 *knots *= kKnotsToMetresPerSecondConversionFactor;
24 HINSTANCE LoadWin7Library(const string16& lib_name) {
25 FilePath sys_dir;
26 PathService::Get(base::DIR_SYSTEM, &sys_dir);
27 return LoadLibrary(sys_dir.Append(lib_name).value().c_str());
31 Win7LocationApi::Win7LocationApi()
32 : prop_lib_(0),
33 PropVariantToDouble_function_(0),
34 locator_(0) {
37 void Win7LocationApi::Init(HINSTANCE prop_library,
38 PropVariantToDoubleFunction PropVariantToDouble_function,
39 ILocation* locator) {
40 prop_lib_ = prop_library;
41 PropVariantToDouble_function_ = PropVariantToDouble_function;
42 locator_ = locator;
45 Win7LocationApi::~Win7LocationApi() {
46 if (prop_lib_ != NULL)
47 FreeLibrary(prop_lib_);
50 Win7LocationApi* Win7LocationApi::Create() {
51 if (!CommandLine::ForCurrentProcess()
52 ->HasSwitch(switches::kExperimentalLocationFeatures))
53 return NULL;
55 scoped_ptr<Win7LocationApi> result(new Win7LocationApi);
56 // Load probsys.dll
57 string16 lib_needed = L"propsys.dll";
58 HINSTANCE prop_lib = LoadWin7Library(lib_needed);
59 if (!prop_lib)
60 return NULL;
61 // Get pointer to function.
62 PropVariantToDoubleFunction PropVariantToDouble_function;
63 PropVariantToDouble_function =
64 reinterpret_cast<PropVariantToDoubleFunction>(
65 GetProcAddress(prop_lib, "PropVariantToDouble"));
66 if (!PropVariantToDouble_function) {
67 FreeLibrary(prop_lib);
68 return NULL;
70 // Create the ILocation object that receives location reports.
71 HRESULT result_type;
72 CComPtr<ILocation> locator;
73 result_type = CoCreateInstance(
74 CLSID_Location, NULL, CLSCTX_INPROC, IID_PPV_ARGS(&locator));
75 if (!SUCCEEDED(result_type)) {
76 FreeLibrary(prop_lib);
77 return NULL;
79 IID reports_needed[] = { IID_ILatLongReport };
80 result_type = locator->RequestPermissions(NULL, reports_needed, 1, TRUE);
81 result->Init(prop_lib, PropVariantToDouble_function, locator);
82 return result.release();
85 Win7LocationApi* Win7LocationApi::CreateForTesting(
86 PropVariantToDoubleFunction PropVariantToDouble_function,
87 ILocation* locator) {
88 Win7LocationApi* result = new Win7LocationApi;
89 result->Init(NULL, PropVariantToDouble_function, locator);
90 return result;
93 void Win7LocationApi::GetPosition(Geoposition* position) {
94 DCHECK(position);
95 position->error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
96 if (!locator_)
97 return;
98 // Try to get a position fix
99 if (!GetPositionIfFixed(position))
100 return;
101 position->error_code = Geoposition::ERROR_CODE_NONE;
102 if (!position->Validate()) {
103 // GetPositionIfFixed returned true, yet we've not got a valid fix.
104 // This shouldn't happen; something went wrong in the conversion.
105 NOTREACHED() << "Invalid position from GetPositionIfFixed: lat,long "
106 << position->latitude << "," << position->longitude
107 << " accuracy " << position->accuracy << " time "
108 << position->timestamp.ToDoubleT();
109 position->error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
110 position->error_message = "Bad fix from Win7 provider";
114 bool Win7LocationApi::GetPositionIfFixed(Geoposition* position) {
115 HRESULT result_type;
116 CComPtr<ILocationReport> location_report;
117 CComPtr<ILatLongReport> lat_long_report;
118 result_type = locator_->GetReport(IID_ILatLongReport, &location_report);
119 // Checks to see if location access is allowed.
120 if (result_type == E_ACCESSDENIED)
121 position->error_code = Geoposition::ERROR_CODE_PERMISSION_DENIED;
122 // Checks for any other errors while requesting a location report.
123 if (!SUCCEEDED(result_type))
124 return false;
125 result_type = location_report->QueryInterface(&lat_long_report);
126 if (!SUCCEEDED(result_type))
127 return false;
128 result_type = lat_long_report->GetLatitude(&position->latitude);
129 if (!SUCCEEDED(result_type))
130 return false;
131 result_type = lat_long_report->GetLongitude(&position->longitude);
132 if (!SUCCEEDED(result_type))
133 return false;
134 result_type = lat_long_report->GetErrorRadius(&position->accuracy);
135 if (!SUCCEEDED(result_type) || position->accuracy <= 0)
136 return false;
137 double temp_dbl;
138 result_type = lat_long_report->GetAltitude(&temp_dbl);
139 if (SUCCEEDED(result_type))
140 position->altitude = temp_dbl;
141 result_type = lat_long_report->GetAltitudeError(&temp_dbl);
142 if (SUCCEEDED(result_type))
143 position->altitude_accuracy = temp_dbl;
144 PROPVARIANT heading;
145 PropVariantInit(&heading);
146 result_type = lat_long_report->GetValue(
147 SENSOR_DATA_TYPE_TRUE_HEADING_DEGREES, &heading);
148 if (SUCCEEDED(result_type))
149 PropVariantToDouble_function_(heading, &position->heading);
150 PROPVARIANT speed;
151 PropVariantInit(&speed);
152 result_type = lat_long_report->GetValue(
153 SENSOR_DATA_TYPE_SPEED_KNOTS, &speed);
154 if (SUCCEEDED(result_type)) {
155 PropVariantToDouble_function_(speed, &position->speed);
156 ConvertKnotsToMetresPerSecond(&position->speed);
158 position->timestamp = base::Time::Now();
159 return true;
162 bool Win7LocationApi::SetHighAccuracy(bool acc) {
163 HRESULT result_type;
164 result_type = locator_->SetDesiredAccuracy(IID_ILatLongReport,
165 acc ? LOCATION_DESIRED_ACCURACY_HIGH :
166 LOCATION_DESIRED_ACCURACY_DEFAULT);
167 return SUCCEEDED(result_type);
170 } // namespace content