1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file.
4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/supervised_user/permission_request_creator_apiary.h"
6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/callback.h"
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/command_line.h"
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/json/json_reader.h"
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/json/json_writer.h"
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/logging.h"
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/strings/stringprintf.h"
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/values.h"
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/signin/signin_manager_factory.h"
17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/sync/supervised_user_signin_manager_wrapper.h"
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/signin/core/browser/profile_oauth2_token_service.h"
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/signin/core/browser/signin_manager.h"
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/signin/core/browser/signin_manager_base.h"
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "google_apis/gaia/google_service_auth_error.h"
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/base/load_flags.h"
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/base/net_errors.h"
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/http/http_status_code.h"
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/url_request/url_fetcher.h"
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/url_request/url_request_status.h"
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)using net::URLFetcher;
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const int kNumRetries = 1;
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char kIdKey[] = "id";
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char kNamespace[] = "CHROME";
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const char kState[] = "PENDING";
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)static const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s";
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistruct PermissionRequestCreatorApiary::Request {
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Request(const GURL& url_requested, const base::Closure& callback);
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ~Request();
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  GURL url_requested;
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::Closure callback;
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<OAuth2TokenService::Request> access_token_request;
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string access_token;
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool access_token_expired;
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<net::URLFetcher> url_fetcher;
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciPermissionRequestCreatorApiary::Request::Request(const GURL& url_requested,
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                 const base::Closure& callback)
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    : url_requested(url_requested),
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      callback(callback),
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      access_token_expired(false) {
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciPermissionRequestCreatorApiary::Request::~Request() {}
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PermissionRequestCreatorApiary::PermissionRequestCreatorApiary(
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    OAuth2TokenService* oauth2_token_service,
61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    scoped_ptr<SupervisedUserSigninManagerWrapper> signin_wrapper,
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    net::URLRequestContextGetter* context)
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : OAuth2TokenService::Consumer("permissions_creator"),
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      oauth2_token_service_(oauth2_token_service),
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      signin_wrapper_(signin_wrapper.Pass()),
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      context_(context) {}
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PermissionRequestCreatorApiary::~PermissionRequestCreatorApiary() {}
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)scoped_ptr<PermissionRequestCreator>
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PermissionRequestCreatorApiary::CreateWithProfile(Profile* profile) {
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ProfileOAuth2TokenService* token_service =
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SigninManagerBase* signin = SigninManagerFactory::GetForProfile(profile);
76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SupervisedUserSigninManagerWrapper> signin_wrapper(
77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      new SupervisedUserSigninManagerWrapper(profile, signin));
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<PermissionRequestCreator> creator(
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new PermissionRequestCreatorApiary(
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          token_service, signin_wrapper.Pass(), profile->GetRequestContext()));
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return creator.Pass();
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PermissionRequestCreatorApiary::CreatePermissionRequest(
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const GURL& url_requested,
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const base::Closure& callback) {
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  requests_.push_back(new Request(url_requested, callback));
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  StartFetching(requests_.back());
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistd::string PermissionRequestCreatorApiary::GetApiScopeToUse() const {
926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (CommandLine::ForCurrentProcess()->HasSwitch(
936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          switches::kPermissionRequestApiScope)) {
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        switches::kPermissionRequestApiScope);
966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  } else {
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return signin_wrapper_->GetSyncScopeToUse();
986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PermissionRequestCreatorApiary::StartFetching(Request* request) {
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  OAuth2TokenService::ScopeSet scopes;
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scopes.insert(GetApiScopeToUse());
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  request->access_token_request = oauth2_token_service_->StartRequest(
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      signin_wrapper_->GetAccountIdToUse(), scopes, this);
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PermissionRequestCreatorApiary::OnGetTokenSuccess(
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const OAuth2TokenService::Request* request,
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::string& access_token,
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const base::Time& expiration_time) {
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  RequestIterator it = requests_.begin();
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  while (it != requests_.end()) {
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (request == (*it)->access_token_request.get())
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      break;
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ++it;
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(it != requests_.end());
1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  (*it)->access_token = access_token;
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GURL url(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      switches::kPermissionRequestApiUrl));
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const int id = 0;
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  (*it)->url_fetcher.reset(URLFetcher::Create(id, url, URLFetcher::POST, this));
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  (*it)->url_fetcher->SetRequestContext(context_);
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  (*it)->url_fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                   net::LOAD_DO_NOT_SAVE_COOKIES);
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  (*it)->url_fetcher->SetAutomaticallyRetryOnNetworkChanges(kNumRetries);
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  (*it)->url_fetcher->AddExtraRequestHeader(
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::StringPrintf(kAuthorizationHeaderFormat, access_token.c_str()));
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::DictionaryValue dict;
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  dict.SetStringWithoutPathExpansion("namespace", kNamespace);
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  dict.SetStringWithoutPathExpansion("objectRef", (*it)->url_requested.spec());
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  dict.SetStringWithoutPathExpansion("state", kState);
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::string body;
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::JSONWriter::Write(&dict, &body);
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  (*it)->url_fetcher->SetUploadData("application/json", body);
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  (*it)->url_fetcher->Start();
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PermissionRequestCreatorApiary::OnGetTokenFailure(
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const OAuth2TokenService::Request* request,
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const GoogleServiceAuthError& error) {
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  RequestIterator it = requests_.begin();
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  while (it != requests_.end()) {
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (request == (*it)->access_token_request.get())
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      break;
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ++it;
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(it != requests_.end());
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  (*it)->callback.Run();
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  requests_.erase(it);
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PermissionRequestCreatorApiary::OnURLFetchComplete(
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const URLFetcher* source) {
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  RequestIterator it = requests_.begin();
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  while (it != requests_.end()) {
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (source == (*it)->url_fetcher.get())
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      break;
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ++it;
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(it != requests_.end());
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const net::URLRequestStatus& status = source->GetStatus();
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!status.is_success()) {
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DispatchNetworkError(it, status.error());
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int response_code = source->GetResponseCode();
1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (response_code == net::HTTP_UNAUTHORIZED && !(*it)->access_token_expired) {
1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    (*it)->access_token_expired = true;
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    OAuth2TokenService::ScopeSet scopes;
1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scopes.insert(GetApiScopeToUse());
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    oauth2_token_service_->InvalidateToken(
1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        signin_wrapper_->GetAccountIdToUse(), scopes, (*it)->access_token);
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    StartFetching(*it);
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (response_code != net::HTTP_OK) {
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DLOG(WARNING) << "HTTP error " << response_code;
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DispatchGoogleServiceAuthError(
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        it, GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED));
189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::string response_body;
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  source->GetResponseAsString(&response_body);
194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<base::Value> value(base::JSONReader::Read(response_body));
195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::DictionaryValue* dict = NULL;
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!value || !value->GetAsDictionary(&dict)) {
1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DispatchNetworkError(it, net::ERR_INVALID_RESPONSE);
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::string id;
201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!dict->GetString(kIdKey, &id)) {
2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DispatchNetworkError(it, net::ERR_INVALID_RESPONSE);
203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  (*it)->callback.Run();
2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  requests_.erase(it);
207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PermissionRequestCreatorApiary::DispatchNetworkError(RequestIterator it,
2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                          int error_code) {
211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DispatchGoogleServiceAuthError(
2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      it, GoogleServiceAuthError::FromConnectionError(error_code));
213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PermissionRequestCreatorApiary::DispatchGoogleServiceAuthError(
2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    RequestIterator it,
217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const GoogleServiceAuthError& error) {
2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  (*it)->callback.Run();
2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  requests_.erase(it);
220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
221