0ca65c4ef432c08e6c53d3b61950b49e4ebee3fd
[platform/framework/web/crosswalk.git] / src / xwalk / runtime / browser / geolocation / tizen / location_provider_tizen.cc
1 // Copyright (c) 2013 Intel Corporation. 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.
4
5 #include "xwalk/runtime/browser/geolocation/tizen/location_provider_tizen.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/time/time.h"
11 #include "content/public/common/geoposition.h"
12
13 namespace xwalk {
14
15 LocationProviderTizen::LocationProviderTizen()
16   : manager_(NULL),
17     geolocation_message_loop_(base::MessageLoop::current()),
18     is_permission_granted_(false) {}
19
20 LocationProviderTizen::~LocationProviderTizen() {
21   StopProvider();
22 }
23
24 bool LocationProviderTizen::StartProvider(bool high_accuracy) {
25   // Tizen location framework doesn't have API that could be used to set
26   // preferred accuracy. Accuracy would be provided by the framework when
27   // position is updated.
28   if (InitLocationManager() && is_permission_granted_)
29     return location_manager_start(manager_) == LOCATIONS_ERROR_NONE;
30
31   return false;
32 }
33
34 void LocationProviderTizen::StopProvider() {
35   if (manager_) {
36     location_manager_unset_position_updated_cb(manager_);
37     location_manager_stop(manager_);
38     location_manager_destroy(manager_);
39     manager_ = NULL;
40   } else {
41     LOG(WARNING) << "Location manager not initialized.";
42   }
43 }
44
45 void LocationProviderTizen::GetPosition(content::Geoposition* position) {
46   *position = last_position_;
47 }
48
49 void LocationProviderTizen::RequestRefresh() {
50   // Tizen location framework sends updates automatically. No need to refresh.
51 }
52
53 void LocationProviderTizen::OnPermissionGranted() {
54   is_permission_granted_ = true;
55   if (manager_)
56     StartProvider(true);
57 }
58
59 bool LocationProviderTizen::InitLocationManager() {
60   if (manager_)
61     return true;
62
63   // FIXME(shalamov): Tizen location manager throws critical error when
64   // hybrid location method is used. Using GPS until it is fixed.
65   int ret = location_manager_create(LOCATIONS_METHOD_GPS, &manager_);
66   if (ret != LOCATIONS_ERROR_NONE) {
67     LOG(ERROR) << "Cannot create location manager.";
68     manager_ = NULL;
69     return false;
70   }
71
72   ret = location_manager_set_service_state_changed_cb(manager_,
73          &LocationProviderTizen::OnStateChanged,
74          this);
75
76   if (ret != LOCATIONS_ERROR_NONE) {
77     location_manager_unset_position_updated_cb(manager_);
78     location_manager_destroy(manager_);
79     manager_ = NULL;
80     return false;
81   }
82
83   return true;
84 }
85
86 void LocationProviderTizen::NotifyLocationProvider() {
87   DCHECK(manager_);
88   int ret;
89   content::Geoposition pos;
90   time_t timestamp;
91   ret = location_manager_get_position(manager_,
92                                       &pos.altitude,
93                                       &pos.latitude,
94                                       &pos.longitude,
95                                       &timestamp);
96   pos.timestamp = base::Time::FromTimeT(timestamp);
97
98   if (ret != LOCATIONS_ERROR_NONE) {
99     LOG(ERROR) << "Cannot retrieve position from location manager.";
100     return;
101   }
102
103   location_accuracy_level_e level;
104   double horizontal;
105   double vertical;
106   ret = location_manager_get_accuracy(manager_,
107                                       &level,
108                                       &horizontal,
109                                       &vertical);
110
111   if (ret != LOCATIONS_ERROR_NONE)
112     LOG(ERROR) << "Cannot retrieve position accuracy from location manager.";
113   else
114     pos.accuracy = (horizontal / 2) + (vertical / 2);
115
116   last_position_ = pos;
117   if (geolocation_message_loop_) {
118     base::Closure task = base::Bind(&LocationProviderTizen::NotifyCallback,
119                                     base::Unretained(this),
120                                     last_position_);
121     geolocation_message_loop_->PostTask(FROM_HERE, task);
122   }
123 }
124
125 void LocationProviderTizen::OnStateChanged(location_service_state_e state,
126                                            void* data) {
127   DCHECK(data);
128   LocationProviderTizen* impl = static_cast<LocationProviderTizen*>(data);
129   if (state == LOCATIONS_SERVICE_ENABLED)
130     impl->NotifyLocationProvider();
131 }
132
133 }  // namespace xwalk
134
135 namespace content {
136 __attribute__((visibility("default"))) content::LocationProvider*
137     NewSystemLocationProvider() {
138   return new xwalk::LocationProviderTizen;
139 }
140
141 }  // namespace content