1// Copyright 2014 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.
4
5#include "components/enhanced_bookmarks/bookmark_server_service.h"
6
7#include "base/auto_reset.h"
8#include "components/enhanced_bookmarks/enhanced_bookmark_model.h"
9#include "components/signin/core/browser/profile_oauth2_token_service.h"
10#include "components/signin/core/browser/signin_manager_base.h"
11#include "google_apis/gaia/gaia_constants.h"
12#include "net/base/load_flags.h"
13#include "net/url_request/url_request_context_getter.h"
14#include "ui/base/models/tree_node_iterator.h"
15
16namespace enhanced_bookmarks {
17
18BookmarkServerService::BookmarkServerService(
19    scoped_refptr<net::URLRequestContextGetter> request_context_getter,
20    ProfileOAuth2TokenService* token_service,
21    SigninManagerBase* signin_manager,
22    EnhancedBookmarkModel* enhanced_bookmark_model)
23    : OAuth2TokenService::Consumer("bookmark_server_service"),
24      model_(enhanced_bookmark_model),
25      token_service_(token_service),
26      signin_manager_(signin_manager),
27      request_context_getter_(request_context_getter) {
28  DCHECK(request_context_getter.get());
29  DCHECK(token_service);
30  DCHECK(signin_manager);
31  DCHECK(enhanced_bookmark_model);
32  model_->AddObserver(this);
33}
34
35BookmarkServerService::~BookmarkServerService() {
36  model_->RemoveObserver(this);
37}
38
39void BookmarkServerService::AddObserver(
40    BookmarkServerServiceObserver* observer) {
41  observers_.AddObserver(observer);
42}
43
44void BookmarkServerService::RemoveObserver(
45    BookmarkServerServiceObserver* observer) {
46  observers_.RemoveObserver(observer);
47}
48
49const BookmarkNode* BookmarkServerService::BookmarkForRemoteId(
50    const std::string& remote_id) const {
51  std::map<std::string, const BookmarkNode*>::const_iterator it =
52      starsid_to_bookmark_.find(remote_id);
53  if (it == starsid_to_bookmark_.end())
54    return NULL;
55  return it->second;
56}
57
58const std::string BookmarkServerService::RemoteIDForBookmark(
59    const BookmarkNode* bookmark) const {
60  return model_->GetRemoteId(bookmark);
61}
62
63void BookmarkServerService::Notify() {
64  FOR_EACH_OBSERVER(BookmarkServerServiceObserver, observers_, OnChange(this));
65}
66
67void BookmarkServerService::TriggerTokenRequest(bool cancel_previous) {
68  if (cancel_previous)
69    url_fetcher_.reset();
70
71  if (token_request_ || url_fetcher_)
72    return;  // Fetcher is already running.
73
74  const std::string username(signin_manager_->GetAuthenticatedUsername());
75  if (!username.length()) {
76    // User is not signed in.
77    CleanAfterFailure();
78    Notify();
79    return;
80  }
81  // Find a token.
82  OAuth2TokenService::ScopeSet scopes;
83  scopes.insert(GaiaConstants::kChromeSyncOAuth2Scope);
84  token_request_ = token_service_->StartRequest(username, scopes, this);
85}
86
87//
88// OAuth2AccessTokenConsumer methods.
89//
90void BookmarkServerService::OnGetTokenSuccess(
91    const OAuth2TokenService::Request* request,
92    const std::string& access_token,
93    const base::Time& expiration_time) {
94  url_fetcher_.reset(CreateFetcher());
95  // Free the token request.
96  token_request_.reset();
97
98  if (!url_fetcher_) {
99    CleanAfterFailure();
100    Notify();
101    return;
102  }
103  url_fetcher_->SetRequestContext(request_context_getter_.get());
104
105  // Add the token.
106  std::string headers;
107  headers = "Authorization: Bearer ";
108  headers += access_token;
109  headers += "\r\n";
110  url_fetcher_->SetExtraRequestHeaders(headers);
111
112  // Do not pollute the cookie store with cruft, or mix the users cookie in this
113  // request.
114  url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
115                             net::LOAD_DO_NOT_SAVE_COOKIES);
116
117  url_fetcher_->Start();
118}
119
120void BookmarkServerService::OnGetTokenFailure(
121    const OAuth2TokenService::Request* request,
122    const GoogleServiceAuthError& error) {
123  // Free the request.
124  token_request_.reset();
125  CleanAfterFailure();
126  Notify();
127}
128
129//
130// net::URLFetcherDelegate methods.
131//
132void BookmarkServerService::OnURLFetchComplete(const net::URLFetcher* source) {
133  scoped_ptr<net::URLFetcher> url_fetcher(url_fetcher_.Pass());
134  std::string response;
135  bool should_notify = true;
136
137  if (url_fetcher->GetResponseCode() != 200 ||
138      !url_fetcher->GetResponseAsString(&response) ||
139      !ProcessResponse(response, &should_notify)) {
140    CleanAfterFailure();
141  }
142  if (should_notify)
143    Notify();
144}
145
146void BookmarkServerService::EnhancedBookmarkModelShuttingDown() {
147  NOTREACHED();
148}
149
150SigninManagerBase* BookmarkServerService::GetSigninManager() {
151  DCHECK(signin_manager_);
152  return signin_manager_;
153}
154
155}  // namespace enhanced_bookmarks
156