Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(145)

Side by Side Diff: content/browser/geolocation/geolocation_dispatcher_host.cc

Issue 273523007: Dispatch geolocation IPCs on the UI thread. Aside from simplifying the code to avoid a lot of threa… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: review comments Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/geolocation/geolocation_dispatcher_host.h" 5 #include "content/browser/geolocation/geolocation_dispatcher_host.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
11 #include "content/browser/renderer_host/render_message_filter.h" 11 #include "content/browser/renderer_host/render_message_filter.h"
12 #include "content/browser/renderer_host/render_process_host_impl.h" 12 #include "content/browser/renderer_host/render_process_host_impl.h"
13 #include "content/browser/renderer_host/render_view_host_impl.h" 13 #include "content/browser/renderer_host/render_view_host_impl.h"
14 #include "content/browser/web_contents/web_contents_impl.h"
15 #include "content/public/browser/browser_context.h"
14 #include "content/public/browser/geolocation_permission_context.h" 16 #include "content/public/browser/geolocation_permission_context.h"
15 #include "content/public/common/geoposition.h" 17 #include "content/public/common/geoposition.h"
16 #include "content/common/geolocation_messages.h" 18 #include "content/common/geolocation_messages.h"
17 19
18 namespace content { 20 namespace content {
19 namespace { 21 namespace {
20 22
21 // Geoposition error codes for reporting in UMA. 23 // Geoposition error codes for reporting in UMA.
22 enum GeopositionErrorCode { 24 enum GeopositionErrorCode {
23 // NOTE: Do not renumber these as that would confuse interpretation of 25 // NOTE: Do not renumber these as that would confuse interpretation of
(...skipping 30 matching lines...) Expand all
54 break; 56 break;
55 case Geoposition::ERROR_CODE_TIMEOUT: 57 case Geoposition::ERROR_CODE_TIMEOUT:
56 code = GEOPOSITION_ERROR_CODE_TIMEOUT; 58 code = GEOPOSITION_ERROR_CODE_TIMEOUT;
57 break; 59 break;
58 } 60 }
59 UMA_HISTOGRAM_ENUMERATION("Geolocation.LocationUpdate.ErrorCode", 61 UMA_HISTOGRAM_ENUMERATION("Geolocation.LocationUpdate.ErrorCode",
60 code, 62 code,
61 GEOPOSITION_ERROR_CODE_COUNT); 63 GEOPOSITION_ERROR_CODE_COUNT);
62 } 64 }
63 65
64 void NotifyGeolocationProviderPermissionGranted() {
65 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
66 GeolocationProviderImpl::GetInstance()->UserDidOptIntoLocationServices();
67 }
68
69 void SendGeolocationPermissionResponse(int render_process_id, 66 void SendGeolocationPermissionResponse(int render_process_id,
70 int render_view_id, 67 int render_view_id,
71 int bridge_id, 68 int bridge_id,
72 bool allowed) { 69 bool allowed) {
73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
74 RenderViewHostImpl* render_view_host = 70 RenderViewHostImpl* render_view_host =
75 RenderViewHostImpl::FromID(render_process_id, render_view_id); 71 RenderViewHostImpl::FromID(render_process_id, render_view_id);
76 if (!render_view_host) 72 if (!render_view_host)
77 return; 73 return;
78 render_view_host->Send( 74 render_view_host->Send(
79 new GeolocationMsg_PermissionSet(render_view_id, bridge_id, allowed)); 75 new GeolocationMsg_PermissionSet(render_view_id, bridge_id, allowed));
80 76
81 if (allowed) { 77 if (allowed)
82 BrowserThread::PostTask( 78 GeolocationProviderImpl::GetInstance()->UserDidOptIntoLocationServices();
83 BrowserThread::IO, FROM_HERE,
84 base::Bind(&NotifyGeolocationProviderPermissionGranted));
85 }
86 } 79 }
87 80
88 } // namespace 81 } // namespace
89 82
90 GeolocationDispatcherHost::GeolocationDispatcherHost( 83 GeolocationDispatcherHost::GeolocationDispatcherHost(
91 int render_process_id, 84 WebContents* web_contents)
92 GeolocationPermissionContext* geolocation_permission_context) 85 : WebContentsObserver(web_contents),
93 : BrowserMessageFilter(GeolocationMsgStart), 86 watching_requested_(false),
94 render_process_id_(render_process_id), 87 paused_(false),
95 geolocation_permission_context_(geolocation_permission_context), 88 high_accuracy_(false) {
96 geolocation_provider_(NULL) { 89 // This is initialized by WebContentsImpl. Do not add any non-trivial
97 callback_ = base::Bind( 90 // initialization here, defer to OnStartUpdating which is triggered whenever
98 &GeolocationDispatcherHost::OnLocationUpdate, base::Unretained(this));
99 // This is initialized by ResourceMessageFilter. Do not add any non-trivial
100 // initialization here, defer to OnRegisterBridge which is triggered whenever
101 // a javascript geolocation object is actually initialized. 91 // a javascript geolocation object is actually initialized.
102 } 92 }
103 93
104 GeolocationDispatcherHost::~GeolocationDispatcherHost() { 94 GeolocationDispatcherHost::~GeolocationDispatcherHost() {
105 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
106 if (geolocation_provider_)
107 geolocation_provider_->RemoveLocationUpdateCallback(callback_);
108 } 95 }
109 96
110 bool GeolocationDispatcherHost::OnMessageReceived( 97 void GeolocationDispatcherHost::RenderViewHostChanged(
111 const IPC::Message& msg, bool* msg_was_ok) { 98 RenderViewHost* old_host,
112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 99 RenderViewHost* new_host) {
113 *msg_was_ok = true; 100 watching_requested_ = false;
101 paused_ = false;
102 geolocation_subscription_.reset();
benm (inactive) 2014/05/08 20:23:33 sorry if it's a silly question, but why do we clea
jam 2014/05/08 23:22:08 not a silly question, it's a bit cryptic. I was tr
103 }
104
105 bool GeolocationDispatcherHost::OnMessageReceived(const IPC::Message& msg) {
114 bool handled = true; 106 bool handled = true;
115 IPC_BEGIN_MESSAGE_MAP_EX(GeolocationDispatcherHost, msg, *msg_was_ok) 107 IPC_BEGIN_MESSAGE_MAP(GeolocationDispatcherHost, msg)
116 IPC_MESSAGE_HANDLER(GeolocationHostMsg_CancelPermissionRequest, 108 IPC_MESSAGE_HANDLER(GeolocationHostMsg_CancelPermissionRequest,
117 OnCancelPermissionRequest) 109 OnCancelPermissionRequest)
118 IPC_MESSAGE_HANDLER(GeolocationHostMsg_RequestPermission, 110 IPC_MESSAGE_HANDLER(GeolocationHostMsg_RequestPermission,
119 OnRequestPermission) 111 OnRequestPermission)
120 IPC_MESSAGE_HANDLER(GeolocationHostMsg_StartUpdating, OnStartUpdating) 112 IPC_MESSAGE_HANDLER(GeolocationHostMsg_StartUpdating, OnStartUpdating)
121 IPC_MESSAGE_HANDLER(GeolocationHostMsg_StopUpdating, OnStopUpdating) 113 IPC_MESSAGE_HANDLER(GeolocationHostMsg_StopUpdating, OnStopUpdating)
122 IPC_MESSAGE_UNHANDLED(handled = false) 114 IPC_MESSAGE_UNHANDLED(handled = false)
123 IPC_END_MESSAGE_MAP() 115 IPC_END_MESSAGE_MAP()
124 return handled; 116 return handled;
125 } 117 }
126 118
127 void GeolocationDispatcherHost::OnLocationUpdate( 119 void GeolocationDispatcherHost::OnLocationUpdate(
128 const Geoposition& geoposition) { 120 const Geoposition& geoposition) {
129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 121 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
122
130 RecordGeopositionErrorCode(geoposition.error_code); 123 RecordGeopositionErrorCode(geoposition.error_code);
131 for (std::map<int, RendererGeolocationOptions>::iterator it = 124 if (!paused_)
132 geolocation_renderers_.begin(); 125 Send(new GeolocationMsg_PositionUpdated(routing_id(), geoposition));
133 it != geolocation_renderers_.end(); ++it) {
134 if (!(it->second.is_paused))
135 Send(new GeolocationMsg_PositionUpdated(it->first, geoposition));
136 }
137 } 126 }
138 127
139 void GeolocationDispatcherHost::OnRequestPermission( 128 void GeolocationDispatcherHost::OnRequestPermission(
140 int render_view_id,
141 int bridge_id, 129 int bridge_id,
142 const GURL& requesting_frame, 130 const GURL& requesting_frame,
143 bool user_gesture) { 131 bool user_gesture) {
144 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 132 GeolocationPermissionContext* context =
145 DVLOG(1) << __FUNCTION__ << " " << render_process_id_ << ":" 133 web_contents()->GetBrowserContext()->GetGeolocationPermissionContext();
146 << render_view_id << ":" << bridge_id; 134 int render_process_id = web_contents()->GetRenderProcessHost()->GetID();
147 if (geolocation_permission_context_.get()) { 135 int render_view_id = web_contents()->GetRenderViewHost()->GetRoutingID();
148 geolocation_permission_context_->RequestGeolocationPermission( 136 if (context) {
149 render_process_id_, 137 context->RequestGeolocationPermission(
150 render_view_id, 138 web_contents(),
151 bridge_id, 139 bridge_id,
152 requesting_frame, 140 requesting_frame,
153 user_gesture, 141 user_gesture,
154 base::Bind(&SendGeolocationPermissionResponse, 142 base::Bind(&SendGeolocationPermissionResponse,
155 render_process_id_, 143 render_process_id,
156 render_view_id, 144 render_view_id,
157 bridge_id)); 145 bridge_id));
158 } else { 146 } else {
159 BrowserThread::PostTask( 147 SendGeolocationPermissionResponse(
160 BrowserThread::UI, FROM_HERE, 148 render_process_id, render_view_id, bridge_id, true);
161 base::Bind(&SendGeolocationPermissionResponse, render_process_id_,
162 render_view_id, bridge_id, true));
163 } 149 }
164 } 150 }
165 151
166 void GeolocationDispatcherHost::OnCancelPermissionRequest( 152 void GeolocationDispatcherHost::OnCancelPermissionRequest(
167 int render_view_id,
168 int bridge_id, 153 int bridge_id,
169 const GURL& requesting_frame) { 154 const GURL& requesting_frame) {
170 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 155 GeolocationPermissionContext* context =
171 DVLOG(1) << __FUNCTION__ << " " << render_process_id_ << ":" 156 web_contents()->GetBrowserContext()->GetGeolocationPermissionContext();
172 << render_view_id << ":" << bridge_id; 157 if (context) {
173 if (geolocation_permission_context_.get()) { 158 context->CancelGeolocationPermissionRequest(
174 geolocation_permission_context_->CancelGeolocationPermissionRequest( 159 web_contents(), bridge_id, requesting_frame);
175 render_process_id_, render_view_id, bridge_id, requesting_frame);
176 } 160 }
177 } 161 }
178 162
179 void GeolocationDispatcherHost::OnStartUpdating( 163 void GeolocationDispatcherHost::OnStartUpdating(
180 int render_view_id,
181 const GURL& requesting_frame, 164 const GURL& requesting_frame,
182 bool enable_high_accuracy) { 165 bool enable_high_accuracy) {
183 // StartUpdating() can be invoked as a result of high-accuracy mode 166 // StartUpdating() can be invoked as a result of high-accuracy mode
184 // being enabled / disabled. No need to record the dispatcher again. 167 // being enabled / disabled. No need to record the dispatcher again.
185 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
186 DVLOG(1) << __FUNCTION__ << " " << render_process_id_ << ":"
187 << render_view_id;
188 UMA_HISTOGRAM_BOOLEAN( 168 UMA_HISTOGRAM_BOOLEAN(
189 "Geolocation.GeolocationDispatcherHostImpl.EnableHighAccuracy", 169 "Geolocation.GeolocationDispatcherHostImpl.EnableHighAccuracy",
190 enable_high_accuracy); 170 enable_high_accuracy);
191 171
192 std::map<int, RendererGeolocationOptions>::iterator it = 172 watching_requested_ = true;
193 geolocation_renderers_.find(render_view_id); 173 high_accuracy_ = enable_high_accuracy;
194 if (it == geolocation_renderers_.end()) {
195 bool should_start_paused = false;
196 if (pending_paused_geolocation_renderers_.erase(render_view_id) == 1) {
197 should_start_paused = true;
198 }
199 RendererGeolocationOptions opts = {
200 enable_high_accuracy,
201 should_start_paused
202 };
203 geolocation_renderers_[render_view_id] = opts;
204 } else {
205 it->second.high_accuracy = enable_high_accuracy;
206 }
207 RefreshGeolocationOptions(); 174 RefreshGeolocationOptions();
208 } 175 }
209 176
210 void GeolocationDispatcherHost::OnStopUpdating(int render_view_id) { 177 void GeolocationDispatcherHost::OnStopUpdating() {
211 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 178 watching_requested_ = false;
212 DVLOG(1) << __FUNCTION__ << " " << render_process_id_ << ":"
213 << render_view_id;
214 DCHECK_EQ(1U, geolocation_renderers_.count(render_view_id));
215 geolocation_renderers_.erase(render_view_id);
216 RefreshGeolocationOptions(); 179 RefreshGeolocationOptions();
217 } 180 }
218 181
219 void GeolocationDispatcherHost::PauseOrResume(int render_view_id, 182 void GeolocationDispatcherHost::PauseOrResume(bool should_pause) {
220 bool should_pause) { 183 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 184 paused_ = should_pause;
222 std::map<int, RendererGeolocationOptions>::iterator it = 185 RefreshGeolocationOptions();
223 geolocation_renderers_.find(render_view_id); 186 }
224 if (it == geolocation_renderers_.end()) { 187
225 // This renderer is not using geolocation yet, but if it does before 188 void GeolocationDispatcherHost::RefreshGeolocationOptions() {
226 // we get a call to resume, we should start it up in the paused state. 189 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
227 if (should_pause) { 190
228 pending_paused_geolocation_renderers_.insert(render_view_id); 191 if (watching_requested_ && !paused_) {
229 } else { 192 geolocation_subscription_ = GeolocationProvider::GetInstance()->
230 pending_paused_geolocation_renderers_.erase(render_view_id); 193 AddLocationUpdateCallback(
231 } 194 base::Bind(&GeolocationDispatcherHost::OnLocationUpdate,
195 base::Unretained(this)),
196 high_accuracy_);
232 } else { 197 } else {
233 RendererGeolocationOptions* opts = &(it->second); 198 geolocation_subscription_.reset();
234 if (opts->is_paused != should_pause)
235 opts->is_paused = should_pause;
236 RefreshGeolocationOptions();
237 } 199 }
238 } 200 }
239 201
240 void GeolocationDispatcherHost::RefreshGeolocationOptions() {
241 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
242
243 bool needs_updates = false;
244 bool use_high_accuracy = false;
245 std::map<int, RendererGeolocationOptions>::const_iterator i =
246 geolocation_renderers_.begin();
247 for (; i != geolocation_renderers_.end(); ++i) {
248 needs_updates |= !(i->second.is_paused);
249 use_high_accuracy |= i->second.high_accuracy;
250 if (needs_updates && use_high_accuracy)
251 break;
252 }
253 if (needs_updates) {
254 if (!geolocation_provider_)
255 geolocation_provider_ = GeolocationProviderImpl::GetInstance();
256 // Re-add to re-establish our options, in case they changed.
257 geolocation_provider_->AddLocationUpdateCallback(
258 callback_, use_high_accuracy);
259 } else {
260 if (geolocation_provider_)
261 geolocation_provider_->RemoveLocationUpdateCallback(callback_);
262 geolocation_provider_ = NULL;
263 }
264 }
265
266 } // namespace content 202 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698