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 "chrome/browser/sync/sync_stopped_reporter.h"
7 #include "base/logging.h"
8 #include "base/strings/stringprintf.h"
9 #include "base/timer/timer.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "net/base/load_flags.h"
12 #include "net/http/http_status_code.h"
13 #include "net/url_request/url_fetcher.h"
14 #include "net/url_request/url_request_context_getter.h"
15 #include "sync/protocol/sync.pb.h"
18 const char kEventEndpoint
[] = "event";
20 // The request is tiny, so even on poor connections 10 seconds should be
21 // plenty of time. Since sync is off when this request is started, we don't
22 // want anything sync-related hanging around for very long from a human
23 // perspective either. This seems like a good compromise.
24 const base::TimeDelta kRequestTimeout
= base::TimeDelta::FromSeconds(10);
27 namespace browser_sync
{
29 SyncStoppedReporter::SyncStoppedReporter(
30 const GURL
& sync_service_url
,
31 const scoped_refptr
<net::URLRequestContextGetter
>& request_context
,
32 const ResultCallback
& callback
)
33 : sync_event_url_(GetSyncEventURL(sync_service_url
)),
34 request_context_(request_context
),
36 DCHECK(!sync_service_url
.is_empty());
37 DCHECK(request_context
);
40 SyncStoppedReporter::~SyncStoppedReporter() {}
42 void SyncStoppedReporter::ReportSyncStopped(const std::string
& access_token
,
43 const std::string
& cache_guid
,
44 const std::string
& birthday
) {
45 DCHECK(!access_token
.empty());
46 DCHECK(!cache_guid
.empty());
47 DCHECK(!birthday
.empty());
49 // Make the request proto with the GUID identifying this client.
50 sync_pb::EventRequest event_request
;
51 sync_pb::SyncDisabledEvent
* sync_disabled_event
=
52 event_request
.mutable_sync_disabled();
53 sync_disabled_event
->set_cache_guid(cache_guid
);
54 sync_disabled_event
->set_store_birthday(birthday
);
57 event_request
.SerializeToString(&msg
);
59 fetcher_
.reset(net::URLFetcher::Create(
60 sync_event_url_
, net::URLFetcher::POST
, this));
61 fetcher_
->AddExtraRequestHeader(base::StringPrintf(
62 "%s: Bearer %s", net::HttpRequestHeaders::kAuthorization
,
63 access_token
.c_str()));
64 fetcher_
->SetRequestContext(request_context_
.get());
65 fetcher_
->SetUploadData("application/octet-stream", msg
);
66 fetcher_
->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES
);
68 timer_
.Start(FROM_HERE
, kRequestTimeout
, this,
69 &SyncStoppedReporter::OnTimeout
);
72 void SyncStoppedReporter::OnURLFetchComplete(const net::URLFetcher
* source
) {
73 Result result
= source
->GetResponseCode() == net::HTTP_OK
74 ? RESULT_SUCCESS
: RESULT_ERROR
;
77 if (!callback_
.is_null()) {
78 base::MessageLoop::current()->PostTask(FROM_HERE
,
79 base::Bind(callback_
, result
));
83 void SyncStoppedReporter::OnTimeout() {
85 if (!callback_
.is_null()) {
86 base::MessageLoop::current()->PostTask(FROM_HERE
,
87 base::Bind(callback_
, RESULT_TIMEOUT
));
92 GURL
SyncStoppedReporter::GetSyncEventURL(const GURL
& sync_service_url
) {
93 std::string path
= sync_service_url
.path();
94 if (path
.empty() || *path
.rbegin() != '/') {
97 path
+= kEventEndpoint
;
98 GURL::Replacements replacements
;
99 replacements
.SetPathStr(path
);
100 return sync_service_url
.ReplaceComponents(replacements
);
103 void SyncStoppedReporter::SetTimerTaskRunnerForTest(
104 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
) {
105 timer_
.SetTaskRunner(task_runner
);
108 } // namespace browser_sync