Index: chrome/browser/supervised_user/experimental/supervised_user_report_url_apiary.cc |
diff --git a/chrome/browser/supervised_user/experimental/supervised_user_report_url_apiary.cc b/chrome/browser/supervised_user/experimental/supervised_user_report_url_apiary.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..053c99d63bc969b68f24f2e0e9834156350f345a |
--- /dev/null |
+++ b/chrome/browser/supervised_user/experimental/supervised_user_report_url_apiary.cc |
@@ -0,0 +1,193 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/supervised_user/experimental/supervised_user_report_url_apiary.h" |
+ |
+#include "base/callback.h" |
+#include "base/json/json_writer.h" |
+#include "base/strings/stringprintf.h" |
+#include "chrome/browser/profiles/profile.h" |
+#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" |
+#include "chrome/browser/signin/signin_manager_factory.h" |
+#include "components/signin/core/browser/profile_oauth2_token_service.h" |
+#include "components/signin/core/browser/signin_manager.h" |
+#include "components/signin/core/browser/signin_manager_base.h" |
+#include "google_apis/gaia/google_service_auth_error.h" |
+#include "net/base/load_flags.h" |
+#include "net/base/net_errors.h" |
+#include "net/http/http_status_code.h" |
+#include "net/url_request/url_fetcher.h" |
+#include "net/url_request/url_request_status.h" |
+#include "url/gurl.h" |
+ |
+using net::URLFetcher; |
+ |
+const char kApiUrl[] = |
+ "https://safesearch.googleapis.com/v1:report"; |
+const char kApiScope[] = "https://www.googleapis.com/auth/safesearch.reporting"; |
+ |
+const int kNumRetries = 1; |
+ |
+const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s"; |
+ |
+// Request keys |
+const char kUrlKey[] = "url"; |
+ |
+ |
+struct SupervisedUserReportURLApiary::Request { |
+ Request(const GURL& url, |
+ const SuccessCallback& callback, |
+ int url_fetcher_id); |
+ ~Request(); |
+ |
+ GURL url; |
+ SuccessCallback callback; |
+ scoped_ptr<OAuth2TokenService::Request> access_token_request; |
+ std::string access_token; |
+ bool access_token_expired; |
+ int url_fetcher_id; |
+ scoped_ptr<URLFetcher> url_fetcher; |
+}; |
+ |
+SupervisedUserReportURLApiary::Request::Request( |
+ const GURL& url, |
+ const SuccessCallback& callback, |
+ int url_fetcher_id) |
+ : url(url), |
+ callback(callback), |
+ access_token_expired(false), |
+ url_fetcher_id(url_fetcher_id) {} |
+ |
+SupervisedUserReportURLApiary::Request::~Request() {} |
+ |
+SupervisedUserReportURLApiary::SupervisedUserReportURLApiary( |
+ OAuth2TokenService* oauth2_token_service, |
+ const std::string& account_id, |
+ net::URLRequestContextGetter* context) |
+ : OAuth2TokenService::Consumer("report_url"), |
+ oauth2_token_service_(oauth2_token_service), |
+ account_id_(account_id), |
+ context_(context), |
+ url_fetcher_id_(0) {} |
+ |
+SupervisedUserReportURLApiary::~SupervisedUserReportURLApiary() {} |
+ |
+// static |
+scoped_ptr<ReportUrlRequestCreator> |
+SupervisedUserReportURLApiary::CreateWithProfile(Profile* profile) { |
+ ProfileOAuth2TokenService* token_service = |
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile); |
+ SigninManagerBase* signin = SigninManagerFactory::GetForProfile(profile); |
+ return make_scoped_ptr(new SupervisedUserReportURLApiary( |
+ token_service, |
+ signin->GetAuthenticatedAccountId(), |
+ profile->GetRequestContext())); |
+} |
+ |
+void SupervisedUserReportURLApiary::CreateReportUrlRequest( |
+ const GURL& url, |
+ const SuccessCallback& callback) { |
+ requests_.push_back(make_scoped_ptr( |
+ new Request(url, callback, url_fetcher_id_))); |
+ StartFetching(requests_.back().get()); |
+} |
+ |
+void SupervisedUserReportURLApiary::StartFetching( |
+ Request* request) { |
+ OAuth2TokenService::ScopeSet scopes; |
+ scopes.insert(kApiScope); |
+ request->access_token_request = oauth2_token_service_->StartRequest( |
+ account_id_, scopes, this); |
+} |
+ |
+void SupervisedUserReportURLApiary::OnGetTokenSuccess( |
+ const OAuth2TokenService::Request* request, |
+ const std::string& access_token, |
+ const base::Time& expiration_time) { |
+ RequestIterator it = requests_.begin(); |
+ while (it != requests_.end()) { |
+ if (request == (*it)->access_token_request.get()) |
+ break; |
+ it++; |
+ } |
+ DCHECK(it != requests_.end()); |
+ |
+ (*it)->access_token = access_token; |
+ |
+ (*it)->url_fetcher = URLFetcher::Create((*it)->url_fetcher_id, GURL(kApiUrl), |
+ URLFetcher::POST, this); |
+ |
+ (*it)->url_fetcher->SetRequestContext(context_); |
+ (*it)->url_fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | |
+ net::LOAD_DO_NOT_SAVE_COOKIES); |
+ (*it)->url_fetcher->SetAutomaticallyRetryOnNetworkChanges(kNumRetries); |
+ (*it)->url_fetcher->AddExtraRequestHeader( |
+ base::StringPrintf(kAuthorizationHeaderFormat, access_token.c_str())); |
+ |
+ base::DictionaryValue dict; |
+ dict.SetStringWithoutPathExpansion(kUrlKey, (*it)->url.spec().c_str()); |
+ |
+ std::string body; |
+ base::JSONWriter::Write(dict, &body); |
+ (*it)->url_fetcher->SetUploadData("application/json", body); |
+ |
+ (*it)->url_fetcher->Start(); |
+} |
+ |
+void SupervisedUserReportURLApiary::OnGetTokenFailure( |
+ const OAuth2TokenService::Request* request, |
+ const GoogleServiceAuthError& error) { |
+ RequestIterator it = requests_.begin(); |
+ while (it != requests_.end()) { |
+ if (request == (*it)->access_token_request.get()) |
+ break; |
+ it++; |
+ } |
+ DCHECK(it != requests_.end()); |
+ LOG(WARNING) << "Token error: " << error.ToString(); |
+ DispatchResult(it, false); |
+} |
+ |
+void SupervisedUserReportURLApiary::OnURLFetchComplete( |
+ const URLFetcher* source) { |
+ RequestIterator it = requests_.begin(); |
+ while (it != requests_.end()) { |
+ if (source == (*it)->url_fetcher.get()) |
+ break; |
+ ++it; |
+ } |
+ DCHECK(it != requests_.end()); |
+ |
+ const net::URLRequestStatus& status = source->GetStatus(); |
+ if (!status.is_success()) { |
+ LOG(WARNING) << "Network error " << status.error(); |
+ DispatchResult(it, false); |
+ return; |
+ } |
+ |
+ int response_code = source->GetResponseCode(); |
+ if (response_code == net::HTTP_UNAUTHORIZED && !(*it)->access_token_expired) { |
+ (*it)->access_token_expired = true; |
+ OAuth2TokenService::ScopeSet scopes; |
+ scopes.insert(kApiScope); |
+ oauth2_token_service_->InvalidateAccessToken(account_id_, scopes, |
+ (*it)->access_token); |
+ StartFetching((*it).get()); |
+ return; |
+ } |
+ |
+ if (response_code != net::HTTP_OK) { |
+ LOG(WARNING) << "HTTP error " << response_code; |
+ DispatchResult(it, false); |
+ return; |
+ } |
+ |
+ DispatchResult(it, true); |
+} |
+ |
+void SupervisedUserReportURLApiary::DispatchResult(RequestIterator it, |
+ bool success) { |
+ (*it)->callback.Run(success); |
+ requests_.erase(it); |
+} |