Index: rlz/lib/financial_ping.cc |
diff --git a/rlz/lib/financial_ping.cc b/rlz/lib/financial_ping.cc |
index 5f152569dd6cc5bddb6537a28cb84e1c1b33b2e7..9c596a4d5ce7f9470e7a5f05b9043628717fd2f9 100644 |
--- a/rlz/lib/financial_ping.cc |
+++ b/rlz/lib/financial_ping.cc |
@@ -6,8 +6,10 @@ |
#include "rlz/lib/financial_ping.h" |
+#include "base/atomicops.h" |
#include "base/basictypes.h" |
#include "base/memory/scoped_ptr.h" |
+#include "base/memory/weak_ptr.h" |
#include "base/strings/string_util.h" |
#include "base/strings/stringprintf.h" |
#include "base/strings/utf_string_conversions.h" |
@@ -84,6 +86,8 @@ int64 GetSystemTimeAsInt64() { |
namespace rlz_lib { |
+using base::subtle::AtomicWord; |
+ |
bool FinancialPing::FormRequest(Product product, |
const AccessPoint* access_points, const char* product_signature, |
const char* product_brand, const char* product_id, |
@@ -177,12 +181,15 @@ bool FinancialPing::FormRequest(Product product, |
} |
#if defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET) |
-// The URLRequestContextGetter used by FinancialPing::PingServer(). |
-net::URLRequestContextGetter* g_context; |
+// The pointer to URLRequestContextGetter used by FinancialPing::PingServer(). |
+// It is atomic pointer because it can be accessed and modified by multiple |
+// threads. |
+AtomicWord g_context; |
bool FinancialPing::SetURLRequestContext( |
net::URLRequestContextGetter* context) { |
- g_context = context; |
+ base::subtle::NoBarrier_Store( |
+ &g_context, reinterpret_cast<AtomicWord>(context)); |
return true; |
} |
@@ -204,10 +211,33 @@ void FinancialPingUrlFetcherDelegate::OnURLFetchComplete( |
callback_.Run(); |
} |
+#if defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET) |
+bool send_financial_ping_interrupted_for_test = false; |
+#endif |
+ |
} // namespace |
#endif |
+#if defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET) |
+void ShutdownCheck(base::WeakPtr<base::RunLoop> weak) { |
+ if (!weak.get()) |
+ return; |
+ if (!base::subtle::NoBarrier_Load(&g_context)) { |
+ send_financial_ping_interrupted_for_test = true; |
+ weak->QuitClosure().Run(); |
+ return; |
+ } |
+ // How frequently the financial ping thread should check |
+ // the shutdown condition? |
+ const base::TimeDelta kInterval = base::TimeDelta::FromMilliseconds(500); |
+ base::MessageLoop::current()->PostDelayedTask( |
+ FROM_HERE, |
+ base::Bind(&ShutdownCheck, weak), |
+ kInterval); |
+} |
+#endif |
+ |
bool FinancialPing::PingServer(const char* request, std::string* response) { |
if (!response) |
return false; |
@@ -265,8 +295,15 @@ bool FinancialPing::PingServer(const char* request, std::string* response) { |
return true; |
#else |
+ // Copy the pointer to stack because g_context may be set to NULL |
+ // in different thread. The instance is guaranteed to exist while |
+ // the method is running. |
+ net::URLRequestContextGetter* context = |
+ reinterpret_cast<net::URLRequestContextGetter*>( |
+ base::subtle::NoBarrier_Load(&g_context)); |
+ |
// Browser shutdown will cause the context to be reset to NULL. |
- if (!g_context) |
+ if (!context) |
return false; |
// Run a blocking event loop to match the win inet implementation. |
@@ -292,13 +329,18 @@ bool FinancialPing::PingServer(const char* request, std::string* response) { |
// Ensure rlz_lib::SetURLRequestContext() has been called before sending |
// pings. |
- fetcher->SetRequestContext(g_context); |
+ fetcher->SetRequestContext(context); |
+ |
+ base::WeakPtrFactory<base::RunLoop> weak(&loop); |
const base::TimeDelta kTimeout = base::TimeDelta::FromMinutes(5); |
base::MessageLoop::ScopedNestableTaskAllower allow_nested( |
base::MessageLoop::current()); |
base::MessageLoop::current()->PostTask( |
FROM_HERE, |
+ base::Bind(&ShutdownCheck, weak.GetWeakPtr())); |
+ base::MessageLoop::current()->PostTask( |
+ FROM_HERE, |
base::Bind(&net::URLFetcher::Start, base::Unretained(fetcher.get()))); |
base::MessageLoop::current()->PostDelayedTask( |
FROM_HERE, loop.QuitClosure(), kTimeout); |
@@ -359,4 +401,18 @@ bool FinancialPing::ClearLastPingTime(Product product) { |
return store->ClearPingTime(product); |
} |
-} // namespace |
+#if defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET) |
+namespace test { |
+ |
+void ResetSendFinancialPingInterrupted() { |
+ send_financial_ping_interrupted_for_test = false; |
+} |
+ |
+bool WasSendFinancialPingInterrupted() { |
+ return send_financial_ping_interrupted_for_test; |
+} |
+ |
+} // namespace test |
+#endif |
+ |
+} // namespace rlz_lib |