Home | History | Annotate | Download | only in web_resource
      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/web_resource/web_resource_service.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "base/prefs/pref_service.h"
     10 #include "base/strings/string_number_conversions.h"
     11 #include "base/strings/string_util.h"
     12 #include "base/strings/utf_string_conversions.h"
     13 #include "base/time/time.h"
     14 #include "base/values.h"
     15 #include "chrome/browser/browser_process.h"
     16 #include "components/google/core/browser/google_util.h"
     17 #include "net/base/load_flags.h"
     18 #include "net/url_request/url_fetcher.h"
     19 #include "net/url_request/url_request_status.h"
     20 #include "url/gurl.h"
     21 
     22 WebResourceService::WebResourceService(
     23     PrefService* prefs,
     24     const GURL& web_resource_server,
     25     bool apply_locale_to_url,
     26     const char* last_update_time_pref_name,
     27     int start_fetch_delay_ms,
     28     int cache_update_delay_ms)
     29     : prefs_(prefs),
     30       json_unpacker_(NULL),
     31       in_fetch_(false),
     32       web_resource_server_(web_resource_server),
     33       apply_locale_to_url_(apply_locale_to_url),
     34       last_update_time_pref_name_(last_update_time_pref_name),
     35       start_fetch_delay_ms_(start_fetch_delay_ms),
     36       cache_update_delay_ms_(cache_update_delay_ms),
     37       weak_ptr_factory_(this) {
     38   resource_request_allowed_notifier_.Init(this);
     39   DCHECK(prefs);
     40 }
     41 
     42 WebResourceService::~WebResourceService() {
     43   if (in_fetch_)
     44     EndFetch();
     45 }
     46 
     47 void WebResourceService::OnUnpackFinished(
     48     const base::DictionaryValue& parsed_json) {
     49   Unpack(parsed_json);
     50   EndFetch();
     51 }
     52 
     53 void WebResourceService::OnUnpackError(const std::string& error_message) {
     54   LOG(ERROR) << error_message;
     55   EndFetch();
     56 }
     57 
     58 void WebResourceService::EndFetch() {
     59   if (json_unpacker_) {
     60     json_unpacker_->ClearDelegate();
     61     json_unpacker_ = NULL;
     62   }
     63   in_fetch_ = false;
     64 }
     65 
     66 void WebResourceService::StartAfterDelay() {
     67   // If resource requests are not allowed, we'll get a callback when they are.
     68   if (resource_request_allowed_notifier_.ResourceRequestsAllowed())
     69     OnResourceRequestsAllowed();
     70 }
     71 
     72 void WebResourceService::OnResourceRequestsAllowed() {
     73   int64 delay = start_fetch_delay_ms_;
     74   // Check whether we have ever put a value in the web resource cache;
     75   // if so, pull it out and see if it's time to update again.
     76   if (prefs_->HasPrefPath(last_update_time_pref_name_)) {
     77     std::string last_update_pref =
     78         prefs_->GetString(last_update_time_pref_name_);
     79     if (!last_update_pref.empty()) {
     80       double last_update_value;
     81       base::StringToDouble(last_update_pref, &last_update_value);
     82       int64 ms_until_update = cache_update_delay_ms_ -
     83           static_cast<int64>((base::Time::Now() - base::Time::FromDoubleT(
     84           last_update_value)).InMilliseconds());
     85       // Wait at least |start_fetch_delay_ms_|.
     86       if (ms_until_update > start_fetch_delay_ms_)
     87         delay = ms_until_update;
     88     }
     89   }
     90   // Start fetch and wait for UpdateResourceCache.
     91   ScheduleFetch(delay);
     92 }
     93 
     94 // Delay initial load of resource data into cache so as not to interfere
     95 // with startup time.
     96 void WebResourceService::ScheduleFetch(int64 delay_ms) {
     97   base::MessageLoop::current()->PostDelayedTask(
     98       FROM_HERE,
     99       base::Bind(&WebResourceService::StartFetch,
    100                  weak_ptr_factory_.GetWeakPtr()),
    101       base::TimeDelta::FromMilliseconds(delay_ms));
    102 }
    103 
    104 // Initializes the fetching of data from the resource server.  Data
    105 // load calls OnURLFetchComplete.
    106 void WebResourceService::StartFetch() {
    107   // First, put our next cache load on the MessageLoop.
    108   ScheduleFetch(cache_update_delay_ms_);
    109 
    110   // Set cache update time in preferences.
    111   prefs_->SetString(last_update_time_pref_name_,
    112       base::DoubleToString(base::Time::Now().ToDoubleT()));
    113 
    114   // If we are still fetching data, exit.
    115   if (in_fetch_)
    116     return;
    117   in_fetch_ = true;
    118 
    119   // Balanced in OnURLFetchComplete.
    120   AddRef();
    121 
    122   GURL web_resource_server =
    123       apply_locale_to_url_
    124           ? google_util::AppendGoogleLocaleParam(
    125                 web_resource_server_, g_browser_process->GetApplicationLocale())
    126           : web_resource_server_;
    127 
    128   DVLOG(1) << "WebResourceService StartFetch " << web_resource_server;
    129   url_fetcher_.reset(net::URLFetcher::Create(
    130       web_resource_server, net::URLFetcher::GET, this));
    131   // Do not let url fetcher affect existing state in system context
    132   // (by setting cookies, for example).
    133   url_fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE |
    134                              net::LOAD_DO_NOT_SEND_COOKIES |
    135                              net::LOAD_DO_NOT_SAVE_COOKIES);
    136   net::URLRequestContextGetter* url_request_context_getter =
    137       g_browser_process->system_request_context();
    138   url_fetcher_->SetRequestContext(url_request_context_getter);
    139   url_fetcher_->Start();
    140 }
    141 
    142 void WebResourceService::OnURLFetchComplete(const net::URLFetcher* source) {
    143   // Delete the URLFetcher when this function exits.
    144   scoped_ptr<net::URLFetcher> clean_up_fetcher(url_fetcher_.release());
    145 
    146   if (source->GetStatus().is_success() && source->GetResponseCode() == 200) {
    147     std::string data;
    148     source->GetResponseAsString(&data);
    149 
    150     // UnpackerClient calls EndFetch and releases itself on completion.
    151     json_unpacker_ = JSONAsynchronousUnpacker::Create(this);
    152     json_unpacker_->Start(data);
    153   } else {
    154     // Don't parse data if attempt to download was unsuccessful.
    155     // Stop loading new web resource data, and silently exit.
    156     // We do not call UnpackerClient, so we need to call EndFetch ourselves.
    157     EndFetch();
    158   }
    159 
    160   Release();
    161 }
    162