1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/sync_driver/sync_stopped_reporter.h"
7 #include "base/location.h"
8 #include "base/logging.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "base/timer/timer.h"
13 #include "net/base/load_flags.h"
14 #include "net/http/http_status_code.h"
15 #include "net/url_request/url_fetcher.h"
16 #include "net/url_request/url_request_context_getter.h"
17 #include "sync/protocol/sync.pb.h"
21 const char kEventEndpoint
[] = "event";
23 // The request is tiny, so even on poor connections 10 seconds should be
24 // plenty of time. Since sync is off when this request is started, we don't
25 // want anything sync-related hanging around for very long from a human
26 // perspective either. This seems like a good compromise.
27 const int kRequestTimeoutSeconds
= 10;
31 namespace browser_sync
{
33 SyncStoppedReporter::SyncStoppedReporter(
34 const GURL
& sync_service_url
,
35 const std::string
& user_agent
,
36 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
37 const ResultCallback
& callback
)
38 : sync_event_url_(GetSyncEventURL(sync_service_url
)),
39 user_agent_(user_agent
),
40 request_context_(request_context
),
42 DCHECK(!sync_service_url
.is_empty());
43 DCHECK(!user_agent_
.empty());
44 DCHECK(request_context
);
47 SyncStoppedReporter::~SyncStoppedReporter() {}
49 void SyncStoppedReporter::ReportSyncStopped(const std::string
& access_token
,
50 const std::string
& cache_guid
,
51 const std::string
& birthday
) {
52 DCHECK(!access_token
.empty());
53 DCHECK(!cache_guid
.empty());
54 DCHECK(!birthday
.empty());
56 // Make the request proto with the GUID identifying this client.
57 sync_pb::EventRequest event_request
;
58 sync_pb::SyncDisabledEvent
* sync_disabled_event
=
59 event_request
.mutable_sync_disabled();
60 sync_disabled_event
->set_cache_guid(cache_guid
);
61 sync_disabled_event
->set_store_birthday(birthday
);
64 event_request
.SerializeToString(&msg
);
67 net::URLFetcher::Create(sync_event_url_
, net::URLFetcher::POST
, this);
68 fetcher_
->AddExtraRequestHeader(base::StringPrintf(
69 "%s: Bearer %s", net::HttpRequestHeaders::kAuthorization
,
70 access_token
.c_str()));
71 fetcher_
->AddExtraRequestHeader(base::StringPrintf(
72 "%s: %s", net::HttpRequestHeaders::kUserAgent
, user_agent_
.c_str()));
73 fetcher_
->SetRequestContext(request_context_
.get());
74 fetcher_
->SetUploadData("application/octet-stream", msg
);
75 fetcher_
->SetLoadFlags(net::LOAD_BYPASS_CACHE
|
76 net::LOAD_DISABLE_CACHE
|
77 net::LOAD_DO_NOT_SAVE_COOKIES
|
78 net::LOAD_DO_NOT_SEND_COOKIES
);
80 timer_
.Start(FROM_HERE
, base::TimeDelta::FromSeconds(kRequestTimeoutSeconds
),
81 this, &SyncStoppedReporter::OnTimeout
);
84 void SyncStoppedReporter::OnURLFetchComplete(const net::URLFetcher
* source
) {
85 Result result
= source
->GetResponseCode() == net::HTTP_OK
86 ? RESULT_SUCCESS
: RESULT_ERROR
;
89 if (!callback_
.is_null()) {
90 base::ThreadTaskRunnerHandle::Get()->PostTask(
91 FROM_HERE
, base::Bind(callback_
, result
));
95 void SyncStoppedReporter::OnTimeout() {
97 if (!callback_
.is_null()) {
98 base::ThreadTaskRunnerHandle::Get()->PostTask(
99 FROM_HERE
, base::Bind(callback_
, RESULT_TIMEOUT
));
104 GURL
SyncStoppedReporter::GetSyncEventURL(const GURL
& sync_service_url
) {
105 std::string path
= sync_service_url
.path();
106 if (path
.empty() || *path
.rbegin() != '/') {
109 path
+= kEventEndpoint
;
110 GURL::Replacements replacements
;
111 replacements
.SetPathStr(path
);
112 return sync_service_url
.ReplaceComponents(replacements
);
115 void SyncStoppedReporter::SetTimerTaskRunnerForTest(
116 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
) {
117 timer_
.SetTaskRunner(task_runner
);
120 } // namespace browser_sync