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 &g_context, reinterpret_cast<AtomicWord>(context)); |
186 return true; | 193 return true; |
187 } | 194 } |
188 | 195 |
189 namespace { | 196 namespace { |
190 | 197 |
191 class FinancialPingUrlFetcherDelegate : public net::URLFetcherDelegate { | 198 class FinancialPingUrlFetcherDelegate : public net::URLFetcherDelegate { |
192 public: | 199 public: |
193 FinancialPingUrlFetcherDelegate(const base::Closure& callback) | 200 FinancialPingUrlFetcherDelegate(const base::Closure& callback) |
194 : callback_(callback) { | 201 : callback_(callback) { |
195 } | 202 } |
196 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; | 203 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; |
197 | 204 |
198 private: | 205 private: |
199 base::Closure callback_; | 206 base::Closure callback_; |
200 }; | 207 }; |
201 | 208 |
202 void FinancialPingUrlFetcherDelegate::OnURLFetchComplete( | 209 void FinancialPingUrlFetcherDelegate::OnURLFetchComplete( |
203 const net::URLFetcher* source) { | 210 const net::URLFetcher* source) { |
204 callback_.Run(); | 211 callback_.Run(); |
205 } | 212 } |
206 | 213 |
| 214 #if defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET) |
| 215 bool send_financial_ping_interrupted_for_test = false; |
| 216 #endif |
| 217 |
207 } // namespace | 218 } // namespace |
208 | 219 |
209 #endif | 220 #endif |
210 | 221 |
| 222 #if defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET) |
| 223 void ShutdownCheck(base::WeakPtr<base::RunLoop> weak) { |
| 224 if (!weak.get()) |
| 225 return; |
| 226 if (!base::subtle::NoBarrier_Load(&g_context)) { |
| 227 send_financial_ping_interrupted_for_test = true; |
| 228 weak->QuitClosure().Run(); |
| 229 return; |
| 230 } |
| 231 // How frequently the financial ping thread should check |
| 232 // the shutdown condition? |
| 233 const base::TimeDelta kInterval = base::TimeDelta::FromMilliseconds(500); |
| 234 base::MessageLoop::current()->PostDelayedTask( |
| 235 FROM_HERE, |
| 236 base::Bind(&ShutdownCheck, weak), |
| 237 kInterval); |
| 238 } |
| 239 #endif |
| 240 |
211 bool FinancialPing::PingServer(const char* request, std::string* response) { | 241 bool FinancialPing::PingServer(const char* request, std::string* response) { |
212 if (!response) | 242 if (!response) |
213 return false; | 243 return false; |
214 | 244 |
215 response->clear(); | 245 response->clear(); |
216 | 246 |
217 #if defined(RLZ_NETWORK_IMPLEMENTATION_WIN_INET) | 247 #if defined(RLZ_NETWORK_IMPLEMENTATION_WIN_INET) |
218 // Initialize WinInet. | 248 // Initialize WinInet. |
219 InternetHandle inet_handle = InternetOpenA(kFinancialPingUserAgent, | 249 InternetHandle inet_handle = InternetOpenA(kFinancialPingUserAgent, |
220 INTERNET_OPEN_TYPE_PRECONFIG, | 250 INTERNET_OPEN_TYPE_PRECONFIG, |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 | 288 |
259 DWORD bytes_read = 0; | 289 DWORD bytes_read = 0; |
260 while (InternetReadFile(http_handle, buffer.get(), kMaxPingResponseLength, | 290 while (InternetReadFile(http_handle, buffer.get(), kMaxPingResponseLength, |
261 &bytes_read) && bytes_read > 0) { | 291 &bytes_read) && bytes_read > 0) { |
262 response->append(buffer.get(), bytes_read); | 292 response->append(buffer.get(), bytes_read); |
263 bytes_read = 0; | 293 bytes_read = 0; |
264 }; | 294 }; |
265 | 295 |
266 return true; | 296 return true; |
267 #else | 297 #else |
| 298 // Copy the pointer to stack because g_context may be set to NULL |
| 299 // in different thread. The instance is guaranteed to exist while |
| 300 // the method is running. |
| 301 net::URLRequestContextGetter* context = |
| 302 reinterpret_cast<net::URLRequestContextGetter*>( |
| 303 base::subtle::NoBarrier_Load(&g_context)); |
| 304 |
268 // Browser shutdown will cause the context to be reset to NULL. | 305 // Browser shutdown will cause the context to be reset to NULL. |
269 if (!g_context) | 306 if (!context) |
270 return false; | 307 return false; |
271 | 308 |
272 // Run a blocking event loop to match the win inet implementation. | 309 // Run a blocking event loop to match the win inet implementation. |
273 scoped_ptr<base::MessageLoop> message_loop; | 310 scoped_ptr<base::MessageLoop> message_loop; |
274 // Ensure that we have a MessageLoop. | 311 // Ensure that we have a MessageLoop. |
275 if (!base::MessageLoop::current()) | 312 if (!base::MessageLoop::current()) |
276 message_loop.reset(new base::MessageLoop); | 313 message_loop.reset(new base::MessageLoop); |
277 base::RunLoop loop; | 314 base::RunLoop loop; |
278 FinancialPingUrlFetcherDelegate delegate(loop.QuitClosure()); | 315 FinancialPingUrlFetcherDelegate delegate(loop.QuitClosure()); |
279 | 316 |
280 std::string url = base::StringPrintf("http://%s:%d%s", | 317 std::string url = base::StringPrintf("http://%s:%d%s", |
281 kFinancialServer, kFinancialPort, | 318 kFinancialServer, kFinancialPort, |
282 request); | 319 request); |
283 | 320 |
284 scoped_ptr<net::URLFetcher> fetcher(net::URLFetcher::Create( | 321 scoped_ptr<net::URLFetcher> fetcher(net::URLFetcher::Create( |
285 GURL(url), net::URLFetcher::GET, &delegate)); | 322 GURL(url), net::URLFetcher::GET, &delegate)); |
286 | 323 |
287 fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE | | 324 fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE | |
288 net::LOAD_DO_NOT_SEND_AUTH_DATA | | 325 net::LOAD_DO_NOT_SEND_AUTH_DATA | |
289 net::LOAD_DO_NOT_PROMPT_FOR_LOGIN | | 326 net::LOAD_DO_NOT_PROMPT_FOR_LOGIN | |
290 net::LOAD_DO_NOT_SEND_COOKIES | | 327 net::LOAD_DO_NOT_SEND_COOKIES | |
291 net::LOAD_DO_NOT_SAVE_COOKIES); | 328 net::LOAD_DO_NOT_SAVE_COOKIES); |
292 | 329 |
293 // Ensure rlz_lib::SetURLRequestContext() has been called before sending | 330 // Ensure rlz_lib::SetURLRequestContext() has been called before sending |
294 // pings. | 331 // pings. |
295 fetcher->SetRequestContext(g_context); | 332 fetcher->SetRequestContext(context); |
| 333 |
| 334 base::WeakPtrFactory<base::RunLoop> weak(&loop); |
296 | 335 |
297 const base::TimeDelta kTimeout = base::TimeDelta::FromMinutes(5); | 336 const base::TimeDelta kTimeout = base::TimeDelta::FromMinutes(5); |
298 base::MessageLoop::ScopedNestableTaskAllower allow_nested( | 337 base::MessageLoop::ScopedNestableTaskAllower allow_nested( |
299 base::MessageLoop::current()); | 338 base::MessageLoop::current()); |
300 base::MessageLoop::current()->PostTask( | 339 base::MessageLoop::current()->PostTask( |
301 FROM_HERE, | 340 FROM_HERE, |
| 341 base::Bind(&ShutdownCheck, weak.GetWeakPtr())); |
| 342 base::MessageLoop::current()->PostTask( |
| 343 FROM_HERE, |
302 base::Bind(&net::URLFetcher::Start, base::Unretained(fetcher.get()))); | 344 base::Bind(&net::URLFetcher::Start, base::Unretained(fetcher.get()))); |
303 base::MessageLoop::current()->PostDelayedTask( | 345 base::MessageLoop::current()->PostDelayedTask( |
304 FROM_HERE, loop.QuitClosure(), kTimeout); | 346 FROM_HERE, loop.QuitClosure(), kTimeout); |
305 | 347 |
306 loop.Run(); | 348 loop.Run(); |
307 | 349 |
308 if (fetcher->GetResponseCode() != 200) | 350 if (fetcher->GetResponseCode() != 200) |
309 return false; | 351 return false; |
310 | 352 |
311 return fetcher->GetResponseAsString(response); | 353 return fetcher->GetResponseAsString(response); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
352 | 394 |
353 | 395 |
354 bool FinancialPing::ClearLastPingTime(Product product) { | 396 bool FinancialPing::ClearLastPingTime(Product product) { |
355 ScopedRlzValueStoreLock lock; | 397 ScopedRlzValueStoreLock lock; |
356 RlzValueStore* store = lock.GetStore(); | 398 RlzValueStore* store = lock.GetStore(); |
357 if (!store || !store->HasAccess(RlzValueStore::kWriteAccess)) | 399 if (!store || !store->HasAccess(RlzValueStore::kWriteAccess)) |
358 return false; | 400 return false; |
359 return store->ClearPingTime(product); | 401 return store->ClearPingTime(product); |
360 } | 402 } |
361 | 403 |
362 } // namespace | 404 #if defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET) |
| 405 namespace test { |
| 406 |
| 407 void ResetSendFinancialPingInterrupted() { |
| 408 send_financial_ping_interrupted_for_test = false; |
| 409 } |
| 410 |
| 411 bool WasSendFinancialPingInterrupted() { |
| 412 return send_financial_ping_interrupted_for_test; |
| 413 } |
| 414 |
| 415 } // namespace test |
| 416 #endif |
| 417 |
| 418 } // namespace rlz_lib |
OLD | NEW |