summaryrefslogtreecommitdiffstats
path: root/rlz/lib/financial_ping.cc
diff options
context:
space:
mode:
Diffstat (limited to 'rlz/lib/financial_ping.cc')
-rw-r--r--rlz/lib/financial_ping.cc68
1 files changed, 62 insertions, 6 deletions
diff --git a/rlz/lib/financial_ping.cc b/rlz/lib/financial_ping.cc
index 5f15256..9c596a4 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