| 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 |