Home | History | Annotate | Download | only in geolocation
      1 // Copyright (c) 2012 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/geolocation/chrome_access_token_store.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/prefs/pref_registry_simple.h"
      9 #include "base/prefs/pref_service.h"
     10 #include "base/strings/string_piece.h"
     11 #include "base/strings/utf_string_conversions.h"
     12 #include "base/values.h"
     13 #include "chrome/browser/browser_process.h"
     14 #include "chrome/browser/prefs/scoped_user_pref_update.h"
     15 #include "chrome/common/pref_names.h"
     16 #include "content/public/browser/browser_thread.h"
     17 #include "url/gurl.h"
     18 
     19 using content::AccessTokenStore;
     20 using content::BrowserThread;
     21 
     22 namespace {
     23 
     24 bool IsUnsupportedNetworkProviderUrl(const GURL& url) {
     25   const std::string& spec = url.spec();
     26 
     27   // Unsupported after Chrome v14.
     28   if (spec == "https://www.google.com/loc/json")
     29     return true;
     30 
     31   // Unsupported after Chrome v22.
     32   if (spec == "https://maps.googleapis.com/maps/api/browserlocation/json")
     33     return true;
     34 
     35   return false;
     36 }
     37 
     38 // Loads access tokens and other necessary data on the UI thread, and
     39 // calls back to the originator on the originating threaad.
     40 class TokenLoadingJob : public base::RefCountedThreadSafe<TokenLoadingJob> {
     41  public:
     42   TokenLoadingJob(
     43       const AccessTokenStore::LoadAccessTokensCallbackType& callback)
     44       : callback_(callback),
     45         system_request_context_(NULL) {
     46   }
     47 
     48   void Run() {
     49     BrowserThread::PostTaskAndReply(
     50         BrowserThread::UI,
     51         FROM_HERE,
     52         base::Bind(&TokenLoadingJob::PerformWorkOnUIThread, this),
     53         base::Bind(&TokenLoadingJob::RespondOnOriginatingThread, this));
     54   }
     55 
     56  private:
     57   friend class base::RefCountedThreadSafe<TokenLoadingJob>;
     58 
     59   ~TokenLoadingJob() {}
     60 
     61   void PerformWorkOnUIThread() {
     62     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     63     DictionaryPrefUpdate update(g_browser_process->local_state(),
     64                                 prefs::kGeolocationAccessToken);
     65     DictionaryValue* token_dictionary = update.Get();
     66 
     67     std::vector<std::string> providers_to_remove;
     68     // The dictionary value could be NULL if the pref has never been set.
     69     if (token_dictionary != NULL) {
     70       for (DictionaryValue::Iterator it(*token_dictionary); !it.IsAtEnd();
     71            it.Advance()) {
     72         GURL url(it.key());
     73         if (!url.is_valid())
     74           continue;
     75         if (IsUnsupportedNetworkProviderUrl(url)) {
     76           providers_to_remove.push_back(it.key());
     77           continue;
     78         }
     79         it.value().GetAsString(&access_token_set_[url]);
     80       }
     81       for (size_t i = 0; i < providers_to_remove.size(); ++i) {
     82         token_dictionary->RemoveWithoutPathExpansion(
     83             providers_to_remove[i], NULL);
     84       }
     85     }
     86 
     87     system_request_context_ = g_browser_process->system_request_context();
     88   }
     89 
     90   void RespondOnOriginatingThread() {
     91     callback_.Run(access_token_set_, system_request_context_);
     92   }
     93 
     94   AccessTokenStore::LoadAccessTokensCallbackType callback_;
     95   AccessTokenStore::AccessTokenSet access_token_set_;
     96   net::URLRequestContextGetter* system_request_context_;
     97 };
     98 
     99 }  // namespace
    100 
    101 void ChromeAccessTokenStore::RegisterPrefs(PrefRegistrySimple* registry) {
    102   registry->RegisterDictionaryPref(prefs::kGeolocationAccessToken);
    103 }
    104 
    105 ChromeAccessTokenStore::ChromeAccessTokenStore() {}
    106 
    107 void ChromeAccessTokenStore::LoadAccessTokens(
    108     const LoadAccessTokensCallbackType& callback) {
    109   scoped_refptr<TokenLoadingJob> job(new TokenLoadingJob(callback));
    110   job->Run();
    111 }
    112 
    113 ChromeAccessTokenStore::~ChromeAccessTokenStore() {}
    114 
    115 static void SetAccessTokenOnUIThread(const GURL& server_url,
    116                                      const string16& token) {
    117   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    118   DictionaryPrefUpdate update(g_browser_process->local_state(),
    119                               prefs::kGeolocationAccessToken);
    120   DictionaryValue* access_token_dictionary = update.Get();
    121   access_token_dictionary->SetWithoutPathExpansion(
    122       server_url.spec(), Value::CreateStringValue(token));
    123 }
    124 
    125 void ChromeAccessTokenStore::SaveAccessToken(const GURL& server_url,
    126                                              const string16& access_token) {
    127   BrowserThread::PostTask(
    128       BrowserThread::UI, FROM_HERE,
    129       base::Bind(&SetAccessTokenOnUIThread, server_url, access_token));
    130 }
    131