OLD | NEW |
---|---|
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 // Library functions related to the Financial Server ping. | 5 // Library functions related to the Financial Server ping. |
6 | 6 |
7 #include "rlz/lib/financial_ping.h" | 7 #include "rlz/lib/financial_ping.h" |
8 | 8 |
9 #include "base/atomicops.h" | |
9 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
10 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
12 #include "base/memory/weak_ptr.h" | |
11 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
12 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
13 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
14 #include "rlz/lib/assert.h" | 16 #include "rlz/lib/assert.h" |
15 #include "rlz/lib/lib_values.h" | 17 #include "rlz/lib/lib_values.h" |
16 #include "rlz/lib/machine_id.h" | 18 #include "rlz/lib/machine_id.h" |
17 #include "rlz/lib/rlz_lib.h" | 19 #include "rlz/lib/rlz_lib.h" |
18 #include "rlz/lib/rlz_value_store.h" | 20 #include "rlz/lib/rlz_value_store.h" |
19 #include "rlz/lib/string_utils.h" | 21 #include "rlz/lib/string_utils.h" |
20 | 22 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
77 double now_seconds = base::Time::Now().ToDoubleT(); | 79 double now_seconds = base::Time::Now().ToDoubleT(); |
78 return static_cast<int64>(now_seconds * 1000 * 1000 * 10); | 80 return static_cast<int64>(now_seconds * 1000 * 1000 * 10); |
79 #endif | 81 #endif |
80 } | 82 } |
81 | 83 |
82 } // namespace | 84 } // namespace |
83 | 85 |
84 | 86 |
85 namespace rlz_lib { | 87 namespace rlz_lib { |
86 | 88 |
89 using base::subtle::AtomicWord; | |
90 | |
87 bool FinancialPing::FormRequest(Product product, | 91 bool FinancialPing::FormRequest(Product product, |
88 const AccessPoint* access_points, const char* product_signature, | 92 const AccessPoint* access_points, const char* product_signature, |
89 const char* product_brand, const char* product_id, | 93 const char* product_brand, const char* product_id, |
90 const char* product_lang, bool exclude_machine_id, | 94 const char* product_lang, bool exclude_machine_id, |
91 std::string* request) { | 95 std::string* request) { |
92 if (!request) { | 96 if (!request) { |
93 ASSERT_STRING("FinancialPing::FormRequest: request is NULL"); | 97 ASSERT_STRING("FinancialPing::FormRequest: request is NULL"); |
94 return false; | 98 return false; |
95 } | 99 } |
96 | 100 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
170 if (GetMachineId(&machine_id)) { | 174 if (GetMachineId(&machine_id)) { |
171 base::StringAppendF(request, "&%s=%s", kMachineIdCgiVariable, | 175 base::StringAppendF(request, "&%s=%s", kMachineIdCgiVariable, |
172 machine_id.c_str()); | 176 machine_id.c_str()); |
173 } | 177 } |
174 } | 178 } |
175 | 179 |
176 return true; | 180 return true; |
177 } | 181 } |
178 | 182 |
179 #if defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET) | 183 #if defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET) |
180 // The URLRequestContextGetter used by FinancialPing::PingServer(). | 184 // The pointer to URLRequestContextGetter used by FinancialPing::PingServer(). |
181 net::URLRequestContextGetter* g_context; | 185 // It is atomic pointer because it can be accessed and modified by multiple |
186 // threads. | |
187 AtomicWord g_context; | |
182 | 188 |
183 bool FinancialPing::SetURLRequestContext( | 189 bool FinancialPing::SetURLRequestContext( |
184 net::URLRequestContextGetter* context) { | 190 net::URLRequestContextGetter* context) { |
185 g_context = context; | 191 base::subtle::NoBarrier_Store( |
192 reinterpret_cast<AtomicWord*>(&g_context), | |
193 reinterpret_cast<AtomicWord>(context)); | |
Roger Tawa OOO till Jul 10th
2013/10/17 01:03:22
Do you need the first reinterpret_cast<>?
oshima
2013/10/17 01:09:06
Done.
| |
186 return true; | 194 return true; |
187 } | 195 } |
188 | 196 |
189 namespace { | 197 namespace { |
190 | 198 |
191 class FinancialPingUrlFetcherDelegate : public net::URLFetcherDelegate { | 199 class FinancialPingUrlFetcherDelegate : public net::URLFetcherDelegate { |
192 public: | 200 public: |
193 FinancialPingUrlFetcherDelegate(const base::Closure& callback) | 201 FinancialPingUrlFetcherDelegate(const base::Closure& callback) |
194 : callback_(callback) { | 202 : callback_(callback) { |
195 } | 203 } |
196 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; | 204 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; |
197 | 205 |
198 private: | 206 private: |
199 base::Closure callback_; | 207 base::Closure callback_; |
200 }; | 208 }; |
201 | 209 |
202 void FinancialPingUrlFetcherDelegate::OnURLFetchComplete( | 210 void FinancialPingUrlFetcherDelegate::OnURLFetchComplete( |
203 const net::URLFetcher* source) { | 211 const net::URLFetcher* source) { |
204 callback_.Run(); | 212 callback_.Run(); |
205 } | 213 } |
206 | 214 |
215 #if defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET) | |
216 bool send_financial_ping_interrupted_for_test = false; | |
217 #endif | |
218 | |
207 } // namespace | 219 } // namespace |
208 | 220 |
209 #endif | 221 #endif |
210 | 222 |
223 #if defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET) | |
224 void ShutdownCheck(base::WeakPtr<base::RunLoop> weak) { | |
225 if (!weak.get()) | |
226 return; | |
227 | |
228 if (!g_context) { | |
Roger Tawa OOO till Jul 10th
2013/10/17 01:03:22
Should use nobarrier_load here too.
oshima
2013/10/17 01:09:06
Done.
| |
229 send_financial_ping_interrupted_for_test = true; | |
230 weak->QuitClosure().Run(); | |
231 return; | |
232 } | |
233 // How frequently the financial ping thread should check | |
234 // the shutdown condition? | |
235 const base::TimeDelta kInterval = base::TimeDelta::FromMilliseconds(500); | |
236 base::MessageLoop::current()->PostDelayedTask( | |
237 FROM_HERE, | |
238 base::Bind(&ShutdownCheck, weak), | |
239 kInterval); | |
240 } | |
241 #endif | |
242 | |
211 bool FinancialPing::PingServer(const char* request, std::string* response) { | 243 bool FinancialPing::PingServer(const char* request, std::string* response) { |
212 if (!response) | 244 if (!response) |
213 return false; | 245 return false; |
214 | 246 |
215 response->clear(); | 247 response->clear(); |
216 | 248 |
217 #if defined(RLZ_NETWORK_IMPLEMENTATION_WIN_INET) | 249 #if defined(RLZ_NETWORK_IMPLEMENTATION_WIN_INET) |
218 // Initialize WinInet. | 250 // Initialize WinInet. |
219 InternetHandle inet_handle = InternetOpenA(kFinancialPingUserAgent, | 251 InternetHandle inet_handle = InternetOpenA(kFinancialPingUserAgent, |
220 INTERNET_OPEN_TYPE_PRECONFIG, | 252 INTERNET_OPEN_TYPE_PRECONFIG, |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
258 | 290 |
259 DWORD bytes_read = 0; | 291 DWORD bytes_read = 0; |
260 while (InternetReadFile(http_handle, buffer.get(), kMaxPingResponseLength, | 292 while (InternetReadFile(http_handle, buffer.get(), kMaxPingResponseLength, |
261 &bytes_read) && bytes_read > 0) { | 293 &bytes_read) && bytes_read > 0) { |
262 response->append(buffer.get(), bytes_read); | 294 response->append(buffer.get(), bytes_read); |
263 bytes_read = 0; | 295 bytes_read = 0; |
264 }; | 296 }; |
265 | 297 |
266 return true; | 298 return true; |
267 #else | 299 #else |
300 // Copy the pointer to stack because g_context may be set to NULL | |
301 // in different thread. The instance is guaranteed to exist while | |
302 // the method is running. | |
303 net::URLRequestContextGetter* context = | |
304 reinterpret_cast<net::URLRequestContextGetter*>( | |
305 base::subtle::NoBarrier_Load(&g_context)); | |
306 | |
268 // Browser shutdown will cause the context to be reset to NULL. | 307 // Browser shutdown will cause the context to be reset to NULL. |
269 if (!g_context) | 308 if (!context) |
270 return false; | 309 return false; |
271 | 310 |
272 // Run a blocking event loop to match the win inet implementation. | 311 // Run a blocking event loop to match the win inet implementation. |
273 scoped_ptr<base::MessageLoop> message_loop; | 312 scoped_ptr<base::MessageLoop> message_loop; |
274 // Ensure that we have a MessageLoop. | 313 // Ensure that we have a MessageLoop. |
275 if (!base::MessageLoop::current()) | 314 if (!base::MessageLoop::current()) |
276 message_loop.reset(new base::MessageLoop); | 315 message_loop.reset(new base::MessageLoop); |
277 base::RunLoop loop; | 316 base::RunLoop loop; |
278 FinancialPingUrlFetcherDelegate delegate(loop.QuitClosure()); | 317 FinancialPingUrlFetcherDelegate delegate(loop.QuitClosure()); |
279 | 318 |
280 std::string url = base::StringPrintf("http://%s:%d%s", | 319 std::string url = base::StringPrintf("http://%s:%d%s", |
281 kFinancialServer, kFinancialPort, | 320 kFinancialServer, kFinancialPort, |
282 request); | 321 request); |
283 | 322 |
284 scoped_ptr<net::URLFetcher> fetcher(net::URLFetcher::Create( | 323 scoped_ptr<net::URLFetcher> fetcher(net::URLFetcher::Create( |
285 GURL(url), net::URLFetcher::GET, &delegate)); | 324 GURL(url), net::URLFetcher::GET, &delegate)); |
286 | 325 |
287 fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE | | 326 fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE | |
288 net::LOAD_DO_NOT_SEND_AUTH_DATA | | 327 net::LOAD_DO_NOT_SEND_AUTH_DATA | |
289 net::LOAD_DO_NOT_PROMPT_FOR_LOGIN | | 328 net::LOAD_DO_NOT_PROMPT_FOR_LOGIN | |
290 net::LOAD_DO_NOT_SEND_COOKIES | | 329 net::LOAD_DO_NOT_SEND_COOKIES | |
291 net::LOAD_DO_NOT_SAVE_COOKIES); | 330 net::LOAD_DO_NOT_SAVE_COOKIES); |
292 | 331 |
293 // Ensure rlz_lib::SetURLRequestContext() has been called before sending | 332 // Ensure rlz_lib::SetURLRequestContext() has been called before sending |
294 // pings. | 333 // pings. |
295 fetcher->SetRequestContext(g_context); | 334 fetcher->SetRequestContext(context); |
335 | |
336 base::WeakPtrFactory<base::RunLoop> weak(&loop); | |
296 | 337 |
297 const base::TimeDelta kTimeout = base::TimeDelta::FromMinutes(5); | 338 const base::TimeDelta kTimeout = base::TimeDelta::FromMinutes(5); |
298 base::MessageLoop::ScopedNestableTaskAllower allow_nested( | 339 base::MessageLoop::ScopedNestableTaskAllower allow_nested( |
299 base::MessageLoop::current()); | 340 base::MessageLoop::current()); |
300 base::MessageLoop::current()->PostTask( | 341 base::MessageLoop::current()->PostTask( |
301 FROM_HERE, | 342 FROM_HERE, |
343 base::Bind(&ShutdownCheck, weak.GetWeakPtr())); | |
344 base::MessageLoop::current()->PostTask( | |
345 FROM_HERE, | |
302 base::Bind(&net::URLFetcher::Start, base::Unretained(fetcher.get()))); | 346 base::Bind(&net::URLFetcher::Start, base::Unretained(fetcher.get()))); |
303 base::MessageLoop::current()->PostDelayedTask( | 347 base::MessageLoop::current()->PostDelayedTask( |
304 FROM_HERE, loop.QuitClosure(), kTimeout); | 348 FROM_HERE, loop.QuitClosure(), kTimeout); |
305 | 349 |
306 loop.Run(); | 350 loop.Run(); |
307 | 351 |
308 if (fetcher->GetResponseCode() != 200) | 352 if (fetcher->GetResponseCode() != 200) |
309 return false; | 353 return false; |
310 | 354 |
311 return fetcher->GetResponseAsString(response); | 355 return fetcher->GetResponseAsString(response); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
352 | 396 |
353 | 397 |
354 bool FinancialPing::ClearLastPingTime(Product product) { | 398 bool FinancialPing::ClearLastPingTime(Product product) { |
355 ScopedRlzValueStoreLock lock; | 399 ScopedRlzValueStoreLock lock; |
356 RlzValueStore* store = lock.GetStore(); | 400 RlzValueStore* store = lock.GetStore(); |
357 if (!store || !store->HasAccess(RlzValueStore::kWriteAccess)) | 401 if (!store || !store->HasAccess(RlzValueStore::kWriteAccess)) |
358 return false; | 402 return false; |
359 return store->ClearPingTime(product); | 403 return store->ClearPingTime(product); |
360 } | 404 } |
361 | 405 |
362 } // namespace | 406 #if defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET) |
407 namespace test { | |
408 | |
409 void ResetSendFinancialPingInterrupted() { | |
410 send_financial_ping_interrupted_for_test = false; | |
411 } | |
412 | |
413 bool WasSendFinancialPingInterrupted() { | |
414 return send_financial_ping_interrupted_for_test; | |
415 } | |
416 | |
417 } // namespace test | |
418 #endif | |
419 | |
420 } // namespace rlz_lib | |
OLD | NEW |