| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 // Copyright 2013 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 "chrome/browser/ui/webui/identity_internals_ui.h" |  | 
| 6 |  | 
| 7 #include <set> |  | 
| 8 #include <string> |  | 
| 9 |  | 
| 10 #include "base/bind.h" |  | 
| 11 #include "base/i18n/time_formatting.h" |  | 
| 12 #include "base/strings/utf_string_conversions.h" |  | 
| 13 #include "base/values.h" |  | 
| 14 #include "chrome/browser/extensions/api/identity/identity_api.h" |  | 
| 15 #include "chrome/browser/extensions/extension_service.h" |  | 
| 16 #include "chrome/browser/profiles/profile.h" |  | 
| 17 #include "chrome/common/url_constants.h" |  | 
| 18 #include "content/public/browser/web_ui.h" |  | 
| 19 #include "content/public/browser/web_ui_controller.h" |  | 
| 20 #include "content/public/browser/web_ui_data_source.h" |  | 
| 21 #include "content/public/browser/web_ui_message_handler.h" |  | 
| 22 #include "extensions/browser/extension_system.h" |  | 
| 23 #include "google_apis/gaia/gaia_auth_fetcher.h" |  | 
| 24 #include "google_apis/gaia/gaia_constants.h" |  | 
| 25 #include "grit/browser_resources.h" |  | 
| 26 #include "grit/generated_resources.h" |  | 
| 27 #include "ui/base/l10n/l10n_util.h" |  | 
| 28 |  | 
| 29 namespace { |  | 
| 30 |  | 
| 31 // Properties of the Javascript object representing a token. |  | 
| 32 const char kExtensionId[] = "extensionId"; |  | 
| 33 const char kExtensionName[] = "extensionName"; |  | 
| 34 const char kScopes[] = "scopes"; |  | 
| 35 const char kStatus[] = "status"; |  | 
| 36 const char kTokenExpirationTime[] = "expirationTime"; |  | 
| 37 const char kAccessToken[] = "accessToken"; |  | 
| 38 |  | 
| 39 // RevokeToken message parameter offsets. |  | 
| 40 const int kRevokeTokenExtensionOffset = 0; |  | 
| 41 const int kRevokeTokenTokenOffset = 1; |  | 
| 42 |  | 
| 43 class IdentityInternalsTokenRevoker; |  | 
| 44 |  | 
| 45 // Class acting as a controller of the chrome://identity-internals WebUI. |  | 
| 46 class IdentityInternalsUIMessageHandler : public content::WebUIMessageHandler { |  | 
| 47  public: |  | 
| 48   IdentityInternalsUIMessageHandler(); |  | 
| 49   virtual ~IdentityInternalsUIMessageHandler(); |  | 
| 50 |  | 
| 51   // Ensures that a proper clean up happens after a token is revoked. That |  | 
| 52   // includes deleting the |token_revoker|, removing the token from Identity API |  | 
| 53   // cache and updating the UI that the token is gone. |  | 
| 54   void OnTokenRevokerDone(IdentityInternalsTokenRevoker* token_revoker); |  | 
| 55 |  | 
| 56   // WebUIMessageHandler implementation. |  | 
| 57   virtual void RegisterMessages() OVERRIDE; |  | 
| 58 |  | 
| 59  private: |  | 
| 60   // Gets the name of an extension referred to by |token_cache_key| as a string. |  | 
| 61   const std::string GetExtensionName( |  | 
| 62       const extensions::ExtensionTokenKey& token_cache_key); |  | 
| 63 |  | 
| 64   // Gets a list of scopes specified in |token_cache_key| and returns a pointer |  | 
| 65   // to a ListValue containing the scopes. The caller gets ownership of the |  | 
| 66   // returned object. |  | 
| 67   base::ListValue* GetScopes( |  | 
| 68       const extensions::ExtensionTokenKey& token_cache_key); |  | 
| 69 |  | 
| 70   // Gets a localized status of the access token in |token_cache_value|. |  | 
| 71   const base::string16 GetStatus( |  | 
| 72       const extensions::IdentityTokenCacheValue& token_cache_value); |  | 
| 73 |  | 
| 74   // Gets a string representation of an expiration time of the access token in |  | 
| 75   // |token_cache_value|. |  | 
| 76   const std::string GetExpirationTime( |  | 
| 77       const extensions::IdentityTokenCacheValue& token_cache_value); |  | 
| 78 |  | 
| 79   // Converts a pair of |token_cache_key| and |token_cache_value| to a |  | 
| 80   // DictionaryValue object with corresponding information in a localized and |  | 
| 81   // readable form and returns a pointer to created object. Caller gets the |  | 
| 82   // ownership of the returned object. |  | 
| 83   base::DictionaryValue* GetInfoForToken( |  | 
| 84       const extensions::ExtensionTokenKey& token_cache_key, |  | 
| 85       const extensions::IdentityTokenCacheValue& token_cache_value); |  | 
| 86 |  | 
| 87   // Gets all of the tokens stored in IdentityAPI token cache and returns them |  | 
| 88   // to the caller using Javascript callback function |  | 
| 89   // |identity_internals.returnTokens()|. |  | 
| 90   void GetInfoForAllTokens(const base::ListValue* args); |  | 
| 91 |  | 
| 92   // Initiates revoking of the token, based on the extension ID and token |  | 
| 93   // passed as entries in the |args| list. Updates the caller of completion |  | 
| 94   // using Javascript callback function |identity_internals.tokenRevokeDone()|. |  | 
| 95   void RevokeToken(const base::ListValue* args); |  | 
| 96 |  | 
| 97   // A vector of token revokers that are currently revoking tokens. |  | 
| 98   ScopedVector<IdentityInternalsTokenRevoker> token_revokers_; |  | 
| 99 }; |  | 
| 100 |  | 
| 101 // Handles the revoking of an access token and helps performing the clean up |  | 
| 102 // after it is revoked by holding information about the access token and related |  | 
| 103 // extension ID. |  | 
| 104 class IdentityInternalsTokenRevoker : public GaiaAuthConsumer { |  | 
| 105  public: |  | 
| 106   // Revokes |access_token| from extension with |extension_id|. |  | 
| 107   // |profile| is required for its request context. |consumer| will be |  | 
| 108   // notified when revocation succeeds via |OnTokenRevokerDone()|. |  | 
| 109   IdentityInternalsTokenRevoker(const std::string& extension_id, |  | 
| 110                                 const std::string& access_token, |  | 
| 111                                 Profile* profile, |  | 
| 112                                 IdentityInternalsUIMessageHandler* consumer); |  | 
| 113   virtual ~IdentityInternalsTokenRevoker(); |  | 
| 114 |  | 
| 115   // Returns the access token being revoked. |  | 
| 116   const std::string& access_token() const { return access_token_; } |  | 
| 117 |  | 
| 118   // Returns the ID of the extension the access token is related to. |  | 
| 119   const std::string& extension_id() const { return extension_id_; } |  | 
| 120 |  | 
| 121   // GaiaAuthConsumer implementation. |  | 
| 122   virtual void OnOAuth2RevokeTokenCompleted() OVERRIDE; |  | 
| 123 |  | 
| 124  private: |  | 
| 125   // An object used to start a token revoke request. |  | 
| 126   GaiaAuthFetcher fetcher_; |  | 
| 127   // An ID of an extension the access token is related to. |  | 
| 128   const std::string extension_id_; |  | 
| 129   // The access token to revoke. |  | 
| 130   const std::string access_token_; |  | 
| 131   // An object that needs to be notified once the access token is revoked. |  | 
| 132   IdentityInternalsUIMessageHandler* consumer_;  // weak. |  | 
| 133 |  | 
| 134   DISALLOW_COPY_AND_ASSIGN(IdentityInternalsTokenRevoker); |  | 
| 135 }; |  | 
| 136 |  | 
| 137 IdentityInternalsUIMessageHandler::IdentityInternalsUIMessageHandler() {} |  | 
| 138 |  | 
| 139 IdentityInternalsUIMessageHandler::~IdentityInternalsUIMessageHandler() {} |  | 
| 140 |  | 
| 141 void IdentityInternalsUIMessageHandler::OnTokenRevokerDone( |  | 
| 142     IdentityInternalsTokenRevoker* token_revoker) { |  | 
| 143   // Remove token from the cache. |  | 
| 144   extensions::IdentityAPI::GetFactoryInstance() |  | 
| 145       ->Get(Profile::FromWebUI(web_ui())) |  | 
| 146       ->EraseCachedToken(token_revoker->extension_id(), |  | 
| 147                          token_revoker->access_token()); |  | 
| 148 |  | 
| 149   // Update view about the token being removed. |  | 
| 150   base::ListValue result; |  | 
| 151   result.AppendString(token_revoker->access_token()); |  | 
| 152   web_ui()->CallJavascriptFunction("identity_internals.tokenRevokeDone", |  | 
| 153                                    result); |  | 
| 154 |  | 
| 155   // Erase the revoker. |  | 
| 156   ScopedVector<IdentityInternalsTokenRevoker>::iterator iter = |  | 
| 157       std::find(token_revokers_.begin(), token_revokers_.end(), token_revoker); |  | 
| 158   DCHECK(iter != token_revokers_.end()); |  | 
| 159   token_revokers_.erase(iter); |  | 
| 160 } |  | 
| 161 |  | 
| 162 const std::string IdentityInternalsUIMessageHandler::GetExtensionName( |  | 
| 163     const extensions::ExtensionTokenKey& token_cache_key) { |  | 
| 164   ExtensionService* extension_service = extensions::ExtensionSystem::Get( |  | 
| 165       Profile::FromWebUI(web_ui()))->extension_service(); |  | 
| 166   const extensions::Extension* extension = |  | 
| 167       extension_service->extensions()->GetByID(token_cache_key.extension_id); |  | 
| 168   if (!extension) |  | 
| 169     return std::string(); |  | 
| 170   return extension->name(); |  | 
| 171 } |  | 
| 172 |  | 
| 173 base::ListValue* IdentityInternalsUIMessageHandler::GetScopes( |  | 
| 174     const extensions::ExtensionTokenKey& token_cache_key) { |  | 
| 175   base::ListValue* scopes_value = new base::ListValue(); |  | 
| 176   for (std::set<std::string>::const_iterator |  | 
| 177            iter = token_cache_key.scopes.begin(); |  | 
| 178        iter != token_cache_key.scopes.end(); ++iter) { |  | 
| 179     scopes_value->AppendString(*iter); |  | 
| 180   } |  | 
| 181   return scopes_value; |  | 
| 182 } |  | 
| 183 |  | 
| 184 const base::string16 IdentityInternalsUIMessageHandler::GetStatus( |  | 
| 185     const extensions::IdentityTokenCacheValue& token_cache_value) { |  | 
| 186   switch (token_cache_value.status()) { |  | 
| 187     case extensions::IdentityTokenCacheValue::CACHE_STATUS_ADVICE: |  | 
| 188       // Fallthrough to NOT FOUND case, as ADVICE is short lived. |  | 
| 189     case extensions::IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND: |  | 
| 190       return l10n_util::GetStringUTF16( |  | 
| 191           IDS_IDENTITY_INTERNALS_TOKEN_NOT_FOUND); |  | 
| 192     case extensions::IdentityTokenCacheValue::CACHE_STATUS_TOKEN: |  | 
| 193       return l10n_util::GetStringUTF16( |  | 
| 194           IDS_IDENTITY_INTERNALS_TOKEN_PRESENT); |  | 
| 195   } |  | 
| 196   NOTREACHED(); |  | 
| 197   return base::string16(); |  | 
| 198 } |  | 
| 199 |  | 
| 200 const std::string IdentityInternalsUIMessageHandler::GetExpirationTime( |  | 
| 201     const extensions::IdentityTokenCacheValue& token_cache_value) { |  | 
| 202   return base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime( |  | 
| 203       token_cache_value.expiration_time())); |  | 
| 204 } |  | 
| 205 |  | 
| 206 base::DictionaryValue* IdentityInternalsUIMessageHandler::GetInfoForToken( |  | 
| 207     const extensions::ExtensionTokenKey& token_cache_key, |  | 
| 208     const extensions::IdentityTokenCacheValue& token_cache_value) { |  | 
| 209   base::DictionaryValue* token_data = new base::DictionaryValue(); |  | 
| 210   token_data->SetString(kExtensionId, token_cache_key.extension_id); |  | 
| 211   token_data->SetString(kExtensionName, GetExtensionName(token_cache_key)); |  | 
| 212   token_data->Set(kScopes, GetScopes(token_cache_key)); |  | 
| 213   token_data->SetString(kStatus, GetStatus(token_cache_value)); |  | 
| 214   token_data->SetString(kAccessToken, token_cache_value.token()); |  | 
| 215   token_data->SetString(kTokenExpirationTime, |  | 
| 216                         GetExpirationTime(token_cache_value)); |  | 
| 217   return token_data; |  | 
| 218 } |  | 
| 219 |  | 
| 220 void IdentityInternalsUIMessageHandler::GetInfoForAllTokens( |  | 
| 221     const base::ListValue* args) { |  | 
| 222   base::ListValue results; |  | 
| 223   extensions::IdentityAPI::CachedTokens tokens = |  | 
| 224       extensions::IdentityAPI::GetFactoryInstance() |  | 
| 225           ->Get(Profile::FromWebUI(web_ui())) |  | 
| 226           ->GetAllCachedTokens(); |  | 
| 227   for (extensions::IdentityAPI::CachedTokens::const_iterator |  | 
| 228            iter = tokens.begin(); iter != tokens.end(); ++iter) { |  | 
| 229     results.Append(GetInfoForToken(iter->first, iter->second)); |  | 
| 230   } |  | 
| 231 |  | 
| 232   web_ui()->CallJavascriptFunction("identity_internals.returnTokens", results); |  | 
| 233 } |  | 
| 234 |  | 
| 235 void IdentityInternalsUIMessageHandler::RegisterMessages() { |  | 
| 236   web_ui()->RegisterMessageCallback("identityInternalsGetTokens", |  | 
| 237       base::Bind(&IdentityInternalsUIMessageHandler::GetInfoForAllTokens, |  | 
| 238                  base::Unretained(this))); |  | 
| 239   web_ui()->RegisterMessageCallback("identityInternalsRevokeToken", |  | 
| 240       base::Bind(&IdentityInternalsUIMessageHandler::RevokeToken, |  | 
| 241                  base::Unretained(this))); |  | 
| 242 } |  | 
| 243 |  | 
| 244 void IdentityInternalsUIMessageHandler::RevokeToken( |  | 
| 245     const base::ListValue* args) { |  | 
| 246   std::string extension_id; |  | 
| 247   std::string access_token; |  | 
| 248   args->GetString(kRevokeTokenExtensionOffset, &extension_id); |  | 
| 249   args->GetString(kRevokeTokenTokenOffset, &access_token); |  | 
| 250   token_revokers_.push_back(new IdentityInternalsTokenRevoker( |  | 
| 251       extension_id, access_token, Profile::FromWebUI(web_ui()), this)); |  | 
| 252 } |  | 
| 253 |  | 
| 254 IdentityInternalsTokenRevoker::IdentityInternalsTokenRevoker( |  | 
| 255     const std::string& extension_id, |  | 
| 256     const std::string& access_token, |  | 
| 257     Profile* profile, |  | 
| 258     IdentityInternalsUIMessageHandler* consumer) |  | 
| 259     : fetcher_(this, GaiaConstants::kChromeSource, |  | 
| 260                profile->GetRequestContext()), |  | 
| 261       extension_id_(extension_id), |  | 
| 262       access_token_(access_token), |  | 
| 263       consumer_(consumer) { |  | 
| 264   DCHECK(consumer_); |  | 
| 265   fetcher_.StartRevokeOAuth2Token(access_token); |  | 
| 266 } |  | 
| 267 |  | 
| 268 IdentityInternalsTokenRevoker::~IdentityInternalsTokenRevoker() {} |  | 
| 269 |  | 
| 270 void IdentityInternalsTokenRevoker::OnOAuth2RevokeTokenCompleted() { |  | 
| 271   consumer_->OnTokenRevokerDone(this); |  | 
| 272 } |  | 
| 273 |  | 
| 274 }  // namespace |  | 
| 275 |  | 
| 276 IdentityInternalsUI::IdentityInternalsUI(content::WebUI* web_ui) |  | 
| 277   : content::WebUIController(web_ui) { |  | 
| 278   // chrome://identity-internals source. |  | 
| 279   content::WebUIDataSource* html_source = |  | 
| 280     content::WebUIDataSource::Create(chrome::kChromeUIIdentityInternalsHost); |  | 
| 281   html_source->SetUseJsonJSFormatV2(); |  | 
| 282 |  | 
| 283   // Localized strings |  | 
| 284   html_source->AddLocalizedString("tokenCacheHeader", |  | 
| 285       IDS_IDENTITY_INTERNALS_TOKEN_CACHE_TEXT); |  | 
| 286   html_source->AddLocalizedString("accessToken", |  | 
| 287       IDS_IDENTITY_INTERNALS_ACCESS_TOKEN); |  | 
| 288   html_source->AddLocalizedString("extensionName", |  | 
| 289       IDS_IDENTITY_INTERNALS_EXTENSION_NAME); |  | 
| 290   html_source->AddLocalizedString("extensionId", |  | 
| 291       IDS_IDENTITY_INTERNALS_EXTENSION_ID); |  | 
| 292   html_source->AddLocalizedString("tokenStatus", |  | 
| 293       IDS_IDENTITY_INTERNALS_TOKEN_STATUS); |  | 
| 294   html_source->AddLocalizedString("expirationTime", |  | 
| 295       IDS_IDENTITY_INTERNALS_EXPIRATION_TIME); |  | 
| 296   html_source->AddLocalizedString("scopes", |  | 
| 297       IDS_IDENTITY_INTERNALS_SCOPES); |  | 
| 298   html_source->AddLocalizedString("revoke", |  | 
| 299       IDS_IDENTITY_INTERNALS_REVOKE); |  | 
| 300   html_source->SetJsonPath("strings.js"); |  | 
| 301 |  | 
| 302   // Required resources |  | 
| 303   html_source->AddResourcePath("identity_internals.css", |  | 
| 304       IDR_IDENTITY_INTERNALS_CSS); |  | 
| 305   html_source->AddResourcePath("identity_internals.js", |  | 
| 306       IDR_IDENTITY_INTERNALS_JS); |  | 
| 307   html_source->SetDefaultResource(IDR_IDENTITY_INTERNALS_HTML); |  | 
| 308 |  | 
| 309   content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), html_source); |  | 
| 310 |  | 
| 311   web_ui->AddMessageHandler(new IdentityInternalsUIMessageHandler()); |  | 
| 312 } |  | 
| 313 |  | 
| 314 IdentityInternalsUI::~IdentityInternalsUI() {} |  | 
| OLD | NEW | 
|---|