0

Remove call to GetBlockingPool in RLZ.

BUG=667892, 618530

Review-Url: https://codereview.chromium.org/2949263003
Cr-Commit-Position: refs/heads/master@{#491013}
This commit is contained in:
rogerta
2017-08-01 09:40:30 -07:00
committed by Commit Bot
parent dbced2bcec
commit c4a9c77f6e
10 changed files with 201 additions and 152 deletions

@ -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 @@ bool ChromeRLZTrackerDelegate::IsOnUIThread() {
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();
}

@ -36,7 +36,6 @@ class ChromeRLZTrackerDelegate : public rlz::RLZTrackerDelegate,
// 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;

@ -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 @@ class ChromeRLZTrackerDelegateTest : public testing::Test {
}
private:
base::test::ScopedTaskEnvironment scoped_task_environment_;
std::unique_ptr<ChromeRLZTrackerDelegate> delegate_;
};

@ -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 @@ RLZTracker::RLZTracker()
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 @@ void RLZTracker::SetDelegate(std::unique_ptr<RLZTrackerDelegate> delegate) {
DCHECK(delegate);
DCHECK(!delegate_);
delegate_ = std::move(delegate);
worker_pool_token_ = delegate_->GetBlockingPool()->GetSequenceToken();
}
// static
@ -264,12 +270,13 @@ void RLZTracker::ScheduleDelayedInit(base::TimeDelta delay) {
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::DelayedInit() {
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 @@ bool RLZTracker::RecordProductEventImpl(rlz_lib::Product product,
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 @@ bool RLZTracker::ScheduleRecordProductEvent(rlz_lib::Product product,
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 @@ void RLZTracker::RecordFirstSearch(rlz_lib::AccessPoint point) {
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 @@ bool RLZTracker::GetAccessPointRlzImpl(rlz_lib::AccessPoint point,
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 @@ bool RLZTracker::ScheduleGetAccessPointRlz(rlz_lib::AccessPoint point) {
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 @@ void RLZTracker::ClearRlzStateImpl() {
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 @@ bool RLZTracker::ScheduleClearRlzState() {
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

@ -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 @@ class RLZTracker {
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 @@ class RLZTracker {
// 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);
};

@ -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 @@ class RLZTrackerDelegate {
// 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;

@ -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 @@ namespace {
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 @@ class TestRLZTrackerDelegate : public RLZTrackerDelegate {
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 @@ class TestRLZTrackerDelegate : public RLZTrackerDelegate {
}
private:
base::SequencedWorkerPoolOwner worker_pool_owner_;
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
std::string brand_override_;
@ -257,7 +251,7 @@ class RlzLibTest : public testing::Test {
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_;

@ -58,10 +58,6 @@ bool RLZTrackerDelegateImpl::IsOnUIThread() {
return web::WebThread::CurrentlyOn(web::WebThread::UI);
}
base::SequencedWorkerPool* RLZTrackerDelegateImpl::GetBlockingPool() {
return web::WebThread::GetBlockingPool();
}
net::URLRequestContextGetter* RLZTrackerDelegateImpl::GetRequestContext() {
return GetApplicationContext()->GetSystemURLRequestContext();
}

@ -33,7 +33,6 @@ class RLZTrackerDelegateImpl : public rlz::RLZTrackerDelegate {
// 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;

@ -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 @@ bool FinancialPing::SetURLRequestContext(
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();
}
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;
}
void OnURLFetchComplete(const net::URLFetcher* source) override;
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 @@ 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::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
}