Remove call to GetBlockingPool in RLZ.

BUG=667892, 618530

Review-Url: https://codereview.chromium.org/2949263003
Cr-Commit-Position: refs/heads/master@{#491013}
diff --git a/chrome/browser/rlz/chrome_rlz_tracker_delegate.cc b/chrome/browser/rlz/chrome_rlz_tracker_delegate.cc
index 0da9621f..7312c106 100644
--- a/chrome/browser/rlz/chrome_rlz_tracker_delegate.cc
+++ b/chrome/browser/rlz/chrome_rlz_tracker_delegate.cc
@@ -36,11 +36,9 @@
 #include "chrome/installer/util/google_update_settings.h"
 #endif
 
-ChromeRLZTrackerDelegate::ChromeRLZTrackerDelegate() {
-}
+ChromeRLZTrackerDelegate::ChromeRLZTrackerDelegate() {}
 
-ChromeRLZTrackerDelegate::~ChromeRLZTrackerDelegate() {
-}
+ChromeRLZTrackerDelegate::~ChromeRLZTrackerDelegate() {}
 
 // static
 void ChromeRLZTrackerDelegate::RegisterProfilePrefs(
@@ -96,10 +94,6 @@
   return content::BrowserThread::CurrentlyOn(content::BrowserThread::UI);
 }
 
-base::SequencedWorkerPool* ChromeRLZTrackerDelegate::GetBlockingPool() {
-  return content::BrowserThread::GetBlockingPool();
-}
-
 net::URLRequestContextGetter* ChromeRLZTrackerDelegate::GetRequestContext() {
   return g_browser_process->system_request_context();
 }
diff --git a/chrome/browser/rlz/chrome_rlz_tracker_delegate.h b/chrome/browser/rlz/chrome_rlz_tracker_delegate.h
index 1fe2eaa..172d5d4 100644
--- a/chrome/browser/rlz/chrome_rlz_tracker_delegate.h
+++ b/chrome/browser/rlz/chrome_rlz_tracker_delegate.h
@@ -36,7 +36,6 @@
   // RLZTrackerDelegate implementation.
   void Cleanup() override;
   bool IsOnUIThread() override;
-  base::SequencedWorkerPool* GetBlockingPool() override;
   net::URLRequestContextGetter* GetRequestContext() override;
   bool GetBrand(std::string* brand) override;
   bool IsBrandOrganic(const std::string& brand) override;
diff --git a/chrome/browser/rlz/chrome_rlz_tracker_delegate_unittest.cc b/chrome/browser/rlz/chrome_rlz_tracker_delegate_unittest.cc
index 2d76c92a..f4e2b929 100644
--- a/chrome/browser/rlz/chrome_rlz_tracker_delegate_unittest.cc
+++ b/chrome/browser/rlz/chrome_rlz_tracker_delegate_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "base/test/scoped_task_environment.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "content/public/browser/navigation_details.h"
 #include "content/public/browser/navigation_entry.h"
@@ -29,6 +30,7 @@
   }
 
  private:
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   std::unique_ptr<ChromeRLZTrackerDelegate> delegate_;
 };
 
diff --git a/components/rlz/rlz_tracker.cc b/components/rlz/rlz_tracker.cc
index 4a1abea6..4efb733 100644
--- a/components/rlz/rlz_tracker.cc
+++ b/components/rlz/rlz_tracker.cc
@@ -13,9 +13,12 @@
 
 #include "base/bind.h"
 #include "base/message_loop/message_loop.h"
+#include "base/sequenced_task_runner.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/task_scheduler/task_traits.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
 #include "components/rlz/rlz_tracker_delegate.h"
@@ -165,7 +168,11 @@
       omnibox_used_(false),
       homepage_used_(false),
       app_list_used_(false),
-      min_init_delay_(kMinInitDelay) {
+      min_init_delay_(kMinInitDelay),
+      background_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
+          {base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
+           base::WithBaseSyncPrimitives(), base::TaskPriority::BACKGROUND})) {
+  DETACH_FROM_SEQUENCE(sequence_checker_);
 }
 
 RLZTracker::~RLZTracker() {
@@ -186,7 +193,6 @@
   DCHECK(delegate);
   DCHECK(!delegate_);
   delegate_ = std::move(delegate);
-  worker_pool_token_ = delegate_->GetBlockingPool()->GetSequenceToken();
 }
 
 // static
@@ -264,12 +270,13 @@
   DCHECK(delegate_) << "RLZTracker used before initialization";
   // The RLZTracker is a singleton object that outlives any runnable tasks
   // that will be queued up.
-  delegate_->GetBlockingPool()->PostDelayedSequencedWorkerTask(
-      worker_pool_token_, FROM_HERE,
-      base::Bind(&RLZTracker::DelayedInit, base::Unretained(this)), delay);
+  background_task_runner_->PostDelayedTask(
+      FROM_HERE, base::Bind(&RLZTracker::DelayedInit, base::Unretained(this)),
+      delay);
 }
 
 void RLZTracker::DelayedInit() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(delegate_) << "RLZTracker used before initialization";
   bool schedule_ping = false;
 
@@ -302,13 +309,12 @@
 
 void RLZTracker::ScheduleFinancialPing() {
   DCHECK(delegate_) << "RLZTracker used before initialization";
-  delegate_->GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
-      worker_pool_token_, FROM_HERE,
-      base::Bind(&RLZTracker::PingNowImpl, base::Unretained(this)),
-      base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
+  background_task_runner_->PostTask(
+      FROM_HERE, base::Bind(&RLZTracker::PingNowImpl, base::Unretained(this)));
 }
 
 void RLZTracker::PingNowImpl() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(delegate_) << "RLZTracker used before initialization";
   TRACE_EVENT0("RLZ", "RLZTracker::PingNowImpl");
   base::string16 lang;
@@ -368,6 +374,8 @@
   if (ScheduleRecordProductEvent(product, point, event_id))
     return true;
 
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
   bool ret = rlz_lib::RecordProductEvent(product, point, event_id);
 
   // If chrome has been reactivated, record the event for this brand as well.
@@ -386,12 +394,9 @@
   if (!delegate_->IsOnUIThread())
     return false;
 
-  delegate_->GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
-      worker_pool_token_, FROM_HERE,
-      base::Bind(base::IgnoreResult(&RLZTracker::RecordProductEvent), product,
-                 point, event_id),
-      base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
-
+  background_task_runner_->PostTask(
+      FROM_HERE, base::Bind(base::IgnoreResult(&RLZTracker::RecordProductEvent),
+                            product, point, event_id));
   return true;
 }
 
@@ -402,24 +407,26 @@
   if (ScheduleRecordFirstSearch(point))
     return;
 
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
   bool* record_used = GetAccessPointRecord(point);
 
   // Try to record event now, else set the flag to try later when we
   // attempt the ping.
-  if (!RecordProductEvent(rlz_lib::CHROME, point, rlz_lib::FIRST_SEARCH))
+  if (!RecordProductEvent(rlz_lib::CHROME, point, rlz_lib::FIRST_SEARCH)) {
     *record_used = true;
-  else if (send_ping_immediately_ && point == ChromeOmnibox())
+  } else if (send_ping_immediately_ && point == ChromeOmnibox()) {
     ScheduleDelayedInit(base::TimeDelta());
+  }
 }
 
 bool RLZTracker::ScheduleRecordFirstSearch(rlz_lib::AccessPoint point) {
   DCHECK(delegate_) << "RLZTracker used before initialization";
   if (!delegate_->IsOnUIThread())
     return false;
-  delegate_->GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
-      worker_pool_token_, FROM_HERE,
-      base::Bind(&RLZTracker::RecordFirstSearch, base::Unretained(this), point),
-      base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
+  background_task_runner_->PostTask(FROM_HERE,
+                                    base::Bind(&RLZTracker::RecordFirstSearch,
+                                               base::Unretained(this), point));
   return true;
 }
 
@@ -489,6 +496,8 @@
   if (!rlz_lib::GetAccessPointRlz(point, str_rlz, rlz_lib::kMaxRlzLength))
     return false;
 
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
   base::string16 rlz_local(base::ASCIIToUTF16(str_rlz));
   if (rlz)
     *rlz = rlz_local;
@@ -504,11 +513,9 @@
     return false;
 
   base::string16* not_used = nullptr;
-  delegate_->GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
-      worker_pool_token_, FROM_HERE,
-      base::Bind(base::IgnoreResult(&RLZTracker::GetAccessPointRlz), point,
-                 not_used),
-      base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
+  background_task_runner_->PostTask(
+      FROM_HERE, base::Bind(base::IgnoreResult(&RLZTracker::GetAccessPointRlz),
+                            point, not_used));
   return true;
 }
 
@@ -524,6 +531,8 @@
   DCHECK(delegate_) << "RLZTracker used before initialization";
   if (ScheduleClearRlzState())
     return;
+
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   rlz_lib::ClearAllProductEvents(rlz_lib::CHROME);
 }
 
@@ -532,10 +541,9 @@
   if (!delegate_->IsOnUIThread())
     return false;
 
-  delegate_->GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
-      worker_pool_token_, FROM_HERE,
-      base::Bind(&RLZTracker::ClearRlzStateImpl, base::Unretained(this)),
-      base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
+  background_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&RLZTracker::ClearRlzStateImpl, base::Unretained(this)));
   return true;
 }
 #endif
diff --git a/components/rlz/rlz_tracker.h b/components/rlz/rlz_tracker.h
index bbf8db5..6e6009a 100644
--- a/components/rlz/rlz_tracker.h
+++ b/components/rlz/rlz_tracker.h
@@ -10,13 +10,18 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/singleton.h"
+#include "base/sequence_checker.h"
 #include "base/strings/string16.h"
-#include "base/threading/sequenced_worker_pool.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "rlz/lib/rlz_lib.h"
 
+namespace base {
+class SequencedTaskRunner;
+}
+
 namespace rlz {
 
 class RLZTrackerDelegate;
@@ -205,10 +210,6 @@
   bool is_google_homepage_;
   bool is_google_in_startpages_;
 
-  // Unique sequence token so that tasks posted by RLZTracker are executed
-  // sequentially in the blocking pool.
-  base::SequencedWorkerPool::SequenceToken worker_pool_token_;
-
   // Keeps track if the RLZ tracker has already performed its delayed
   // initialization.
   bool already_ran_;
@@ -231,6 +232,11 @@
   // Minimum delay before sending financial ping after initialization.
   base::TimeDelta min_init_delay_;
 
+  // Runner for RLZ background tasks.  The checked is used to verify operations
+  // occur in the correct sequence, especially in tests.
+  scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(RLZTracker);
 };
 
diff --git a/components/rlz/rlz_tracker_delegate.h b/components/rlz/rlz_tracker_delegate.h
index d1270e4..bbf43df 100644
--- a/components/rlz/rlz_tracker_delegate.h
+++ b/components/rlz/rlz_tracker_delegate.h
@@ -10,11 +10,6 @@
 #include "base/callback_forward.h"
 #include "base/macros.h"
 #include "base/strings/string16.h"
-#include "base/threading/sequenced_worker_pool.h"
-
-namespace base {
-class SequencedWorkerPool;
-}
 
 namespace net {
 class URLRequestContextGetter;
@@ -35,10 +30,6 @@
   // Returns whether the current thread is the UI thread.
   virtual bool IsOnUIThread() = 0;
 
-  // Returns the SequencedWorkerPool where the RLZTracker will post its tasks
-  // that should be executed in the background.
-  virtual base::SequencedWorkerPool* GetBlockingPool() = 0;
-
   // Returns the URLRequestContextGetter to use for network connections.
   virtual net::URLRequestContextGetter* GetRequestContext() = 0;
 
diff --git a/components/rlz/rlz_tracker_unittest.cc b/components/rlz/rlz_tracker_unittest.cc
index 937bb4f..20c54fe 100644
--- a/components/rlz/rlz_tracker_unittest.cc
+++ b/components/rlz/rlz_tracker_unittest.cc
@@ -11,7 +11,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/test/sequenced_worker_pool_owner.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
@@ -34,8 +34,7 @@
 class TestRLZTrackerDelegate : public RLZTrackerDelegate {
  public:
   TestRLZTrackerDelegate()
-      : worker_pool_owner_(2, "TestRLZTracker"),
-        request_context_getter_(new net::TestURLRequestContextGetter(
+      : request_context_getter_(new net::TestURLRequestContextGetter(
             base::ThreadTaskRunnerHandle::Get())) {}
 
   void set_brand(const char* brand) { brand_override_ = brand; }
@@ -69,10 +68,6 @@
 
   bool IsOnUIThread() override { return true; }
 
-  base::SequencedWorkerPool* GetBlockingPool() override {
-    return worker_pool_owner_.pool().get();
-  }
-
   net::URLRequestContextGetter* GetRequestContext() override {
     return request_context_getter_.get();
   }
@@ -110,7 +105,6 @@
   }
 
  private:
-  base::SequencedWorkerPoolOwner worker_pool_owner_;
   scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
 
   std::string brand_override_;
@@ -257,7 +251,7 @@
   void ExpectRlzPingSent(bool expected);
   void ExpectReactivationRlzPingSent(bool expected);
 
-  base::MessageLoop message_loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   TestRLZTrackerDelegate* delegate_;
   std::unique_ptr<TestRLZTracker> tracker_;
   RlzLibTestNoMachineStateHelper m_rlz_test_helper_;
diff --git a/ios/chrome/browser/rlz/rlz_tracker_delegate_impl.cc b/ios/chrome/browser/rlz/rlz_tracker_delegate_impl.cc
index ce6606c..a8a80ac 100644
--- a/ios/chrome/browser/rlz/rlz_tracker_delegate_impl.cc
+++ b/ios/chrome/browser/rlz/rlz_tracker_delegate_impl.cc
@@ -58,10 +58,6 @@
   return web::WebThread::CurrentlyOn(web::WebThread::UI);
 }
 
-base::SequencedWorkerPool* RLZTrackerDelegateImpl::GetBlockingPool() {
-  return web::WebThread::GetBlockingPool();
-}
-
 net::URLRequestContextGetter* RLZTrackerDelegateImpl::GetRequestContext() {
   return GetApplicationContext()->GetSystemURLRequestContext();
 }
diff --git a/ios/chrome/browser/rlz/rlz_tracker_delegate_impl.h b/ios/chrome/browser/rlz/rlz_tracker_delegate_impl.h
index 5c2be98..2bf2ed5 100644
--- a/ios/chrome/browser/rlz/rlz_tracker_delegate_impl.h
+++ b/ios/chrome/browser/rlz/rlz_tracker_delegate_impl.h
@@ -33,7 +33,6 @@
   // RLZTrackerDelegate implementation.
   void Cleanup() override;
   bool IsOnUIThread() override;
-  base::SequencedWorkerPool* GetBlockingPool() override;
   net::URLRequestContextGetter* GetRequestContext() override;
   bool GetBrand(std::string* brand) override;
   bool IsBrandOrganic(const std::string& brand) override;
diff --git a/rlz/lib/financial_ping.cc b/rlz/lib/financial_ping.cc
index 04bd45a..775c1ad 100644
--- a/rlz/lib/financial_ping.cc
+++ b/rlz/lib/financial_ping.cc
@@ -13,11 +13,13 @@
 #include "base/atomicops.h"
 #include "base/location.h"
 #include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/single_thread_task_runner.h"
+#include "base/memory/ref_counted.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/synchronization/lock.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "rlz/lib/assert.h"
@@ -203,39 +205,147 @@
 
 namespace {
 
-class FinancialPingUrlFetcherDelegate : public net::URLFetcherDelegate {
+// A waitable event used to detect when either:
+//
+//   1/ the RLZ ping request completes
+//   2/ the RLZ ping request times out
+//   3/ browser shutdown begins
+class RefCountedWaitableEvent
+    : public base::RefCountedThreadSafe<RefCountedWaitableEvent> {
  public:
-  FinancialPingUrlFetcherDelegate(const base::Closure& callback)
-      : callback_(callback) {
+  RefCountedWaitableEvent()
+      : event_(base::WaitableEvent::ResetPolicy::MANUAL,
+               base::WaitableEvent::InitialState::NOT_SIGNALED) {}
+
+  void SignalShutdown() { event_.Signal(); }
+
+  void SignalFetchComplete(int response_code, std::string response) {
+    base::AutoLock autolock(lock_);
+    response_code_ = response_code;
+    response_ = std::move(response);
+    event_.Signal();
   }
-  void OnURLFetchComplete(const net::URLFetcher* source) override;
+
+  bool TimedWait(base::TimeDelta timeout) { return event_.TimedWait(timeout); }
+
+  int GetResponseCode() {
+    base::AutoLock autolock(lock_);
+    return response_code_;
+  }
+
+  std::string TakeResponse() {
+    base::AutoLock autolock(lock_);
+    std::string temp = std::move(response_);
+    response_.clear();
+    return temp;
+  }
 
  private:
-  base::Closure callback_;
+  ~RefCountedWaitableEvent() {}
+  friend class base::RefCountedThreadSafe<RefCountedWaitableEvent>;
+
+  base::WaitableEvent event_;
+  base::Lock lock_;
+  std::string response_;
+  int response_code_ = net::URLFetcher::RESPONSE_CODE_INVALID;
 };
 
-void FinancialPingUrlFetcherDelegate::OnURLFetchComplete(
-    const net::URLFetcher* source) {
-  callback_.Run();
-}
+// A fetcher delegate that signals an instance of RefCountedWaitableEvent when
+// the fetch completes.
+class FinancialPingUrlFetcherDelegate : public net::URLFetcherDelegate {
+ public:
+  FinancialPingUrlFetcherDelegate(scoped_refptr<RefCountedWaitableEvent> event)
+      : event_(std::move(event)) {}
+
+  void SetFetcher(std::unique_ptr<net::URLFetcher> fetcher) {
+    fetcher_ = std::move(fetcher);
+  }
+
+ private:
+  void OnURLFetchComplete(const net::URLFetcher* source) override {
+    std::string response;
+    source->GetResponseAsString(&response);
+    event_->SignalFetchComplete(source->GetResponseCode(), std::move(response));
+    base::SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
+  }
+
+  scoped_refptr<RefCountedWaitableEvent> event_;
+  std::unique_ptr<net::URLFetcher> fetcher_;
+};
 
 bool send_financial_ping_interrupted_for_test = false;
 
 }  // namespace
 
-void ShutdownCheck(base::WeakPtr<base::RunLoop> weak) {
-  if (!weak.get())
-    return;
+void ShutdownCheck(scoped_refptr<RefCountedWaitableEvent> event) {
   if (!base::subtle::Acquire_Load(&g_context)) {
     send_financial_ping_interrupted_for_test = true;
-    weak->QuitClosure().Run();
+    event->SignalShutdown();
     return;
   }
   // How frequently the financial ping thread should check
   // the shutdown condition?
   const base::TimeDelta kInterval = base::TimeDelta::FromMilliseconds(500);
-  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-      FROM_HERE, base::Bind(&ShutdownCheck, weak), kInterval);
+  base::PostDelayedTaskWithTraits(FROM_HERE, {base::TaskPriority::BACKGROUND},
+                                  base::Bind(&ShutdownCheck, event), kInterval);
+}
+
+void PingRlzServer(std::string url,
+                   scoped_refptr<RefCountedWaitableEvent> event) {
+  // 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::Acquire_Load(&g_context));
+
+  // Browser shutdown will cause the context to be reset to NULL.
+  // ShutdownCheck will catch this.
+  if (!context)
+    return;
+
+  // Delegate will delete itself when the fetch completes.
+  FinancialPingUrlFetcherDelegate* delegate =
+      new FinancialPingUrlFetcherDelegate(event);
+
+  net::NetworkTrafficAnnotationTag traffic_annotation =
+      net::DefineNetworkTrafficAnnotation("rlz_ping", R"(
+        semantics {
+          sender: "RLZ Ping"
+          description:
+            "Used for measuring the effectiveness of a promotion. See the "
+            "Chrome Privacy Whitepaper for complete details."
+          trigger:
+            "1- At Chromium first run.\n"
+            "2- When Chromium is re-activated by a new promotion.\n"
+            "3- Once a week thereafter as long as Chromium is used.\n"
+          data:
+            "1- Non-unique cohort tag of when Chromium was installed.\n"
+            "2- Unique machine id on desktop platforms.\n"
+            "3- Whether Google is the default omnibox search.\n"
+            "4- Whether google.com is the default home page."
+          destination: GOOGLE_OWNED_SERVICE
+        }
+        policy {
+          cookies_allowed: NO
+          setting: "This feature cannot be disabled in settings."
+          policy_exception_justification: "Not implemented."
+        })");
+  std::unique_ptr<net::URLFetcher> fetcher = net::URLFetcher::Create(
+      GURL(url), net::URLFetcher::GET, delegate, traffic_annotation);
+
+  fetcher->SetLoadFlags(
+      net::LOAD_DISABLE_CACHE | net::LOAD_DO_NOT_SEND_AUTH_DATA |
+      net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES);
+
+  // Ensure rlz_lib::SetURLRequestContext() has been called before sending
+  // pings.
+  fetcher->SetRequestContext(context);
+  fetcher->Start();
+
+  // Pass ownership of the fetcher to the delegate.  Otherwise the fetch will
+  // be canceled when the URLFetcher object is destroyed.
+  delegate->SetFetcher(std::move(fetcher));
 }
 #endif
 
@@ -296,83 +406,33 @@
 
   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::Acquire_Load(&g_context));
-
-  // Browser shutdown will cause the context to be reset to NULL.
-  if (!context)
-    return false;
-
-  // Run a blocking event loop to match the win inet implementation.
-  std::unique_ptr<base::MessageLoop> message_loop;
-  // Ensure that we have a MessageLoop.
-  if (!base::MessageLoop::current())
-    message_loop.reset(new base::MessageLoop);
-  base::RunLoop loop;
-  FinancialPingUrlFetcherDelegate delegate(loop.QuitClosure());
-
   std::string url = base::StringPrintf("http://%s:%d%s",
                                        kFinancialServer, kFinancialPort,
                                        request);
 
-  net::NetworkTrafficAnnotationTag traffic_annotation =
-      net::DefineNetworkTrafficAnnotation("rlz_ping", R"(
-        semantics {
-          sender: "RLZ Ping"
-          description:
-            "Used for measuring the effectiveness of a promotion. See the "
-            "Chrome Privacy Whitepaper for complete details."
-          trigger:
-            "1- At Chromium first run.\n"
-            "2- When Chromium is re-activated by a new promotion.\n"
-            "3- Once a week thereafter as long as Chromium is used.\n"
-          data:
-            "1- Non-unique cohort tag of when Chromium was installed.\n"
-            "2- Unique machine id on desktop platforms.\n"
-            "3- Whether Google is the default omnibox search.\n"
-            "4- Whether google.com is the default home page."
-          destination: GOOGLE_OWNED_SERVICE
-        }
-        policy {
-          cookies_allowed: NO
-          setting: "This feature cannot be disabled in settings."
-          policy_exception_justification: "Not implemented."
-        })");
-  std::unique_ptr<net::URLFetcher> fetcher = net::URLFetcher::Create(
-      GURL(url), net::URLFetcher::GET, &delegate, traffic_annotation);
+  // Use a waitable event to cause this function to block, to match the
+  // wininet implementation.
+  auto event = base::MakeRefCounted<RefCountedWaitableEvent>();
 
-  fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE |
-                        net::LOAD_DO_NOT_SEND_AUTH_DATA |
-                        net::LOAD_DO_NOT_SEND_COOKIES |
-                        net::LOAD_DO_NOT_SAVE_COOKIES);
+  base::PostTaskWithTraits(FROM_HERE, {base::TaskPriority::BACKGROUND},
+                           base::Bind(&ShutdownCheck, event));
 
-  // Ensure rlz_lib::SetURLRequestContext() has been called before sending
-  // pings.
-  fetcher->SetRequestContext(context);
+  // PingRlzServer must be run in a separate sequence so that the TimedWait()
+  // call below does not block the URL fetch response from being handled by
+  // the URL delegate.
+  scoped_refptr<base::SequencedTaskRunner> background_runner(
+      base::CreateSequencedTaskRunnerWithTraits(
+          {base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
+           base::TaskPriority::BACKGROUND}));
+  background_runner->PostTask(FROM_HERE,
+                              base::Bind(&PingRlzServer, url, event));
 
-  base::WeakPtrFactory<base::RunLoop> weak(&loop);
-
-  const base::TimeDelta kTimeout = base::TimeDelta::FromMinutes(5);
-  base::MessageLoop::ScopedNestableTaskAllower allow_nested(
-      base::MessageLoop::current());
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::Bind(&ShutdownCheck, weak.GetWeakPtr()));
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::Bind(&net::URLFetcher::Start, base::Unretained(fetcher.get())));
-  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-      FROM_HERE, loop.QuitClosure(), kTimeout);
-
-  loop.Run();
-
-  if (fetcher->GetResponseCode() != 200)
+  bool is_signaled = event->TimedWait(base::TimeDelta::FromMinutes(5));
+  if (!is_signaled || event->GetResponseCode() != 200)
     return false;
 
-  return fetcher->GetResponseAsString(response);
+  *response = event->TakeResponse();
+  return true;
 #endif
 }