Home | History | Annotate | Download | only in src
      1 // Copyright (C) 2013 Google Inc.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 // http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include "retriever.h"
     16 
     17 #include <libaddressinput/callback.h>
     18 #include <libaddressinput/downloader.h>
     19 #include <libaddressinput/storage.h>
     20 #include <libaddressinput/util/basictypes.h>
     21 #include <libaddressinput/util/scoped_ptr.h>
     22 
     23 #include <cassert>
     24 #include <cstddef>
     25 #include <string>
     26 
     27 #include "lookup_key_util.h"
     28 #include "validating_storage.h"
     29 
     30 namespace i18n {
     31 namespace addressinput {
     32 
     33 namespace {
     34 
     35 class Helper {
     36  public:
     37   // Does not take ownership of its parameters.
     38   Helper(const std::string& key,
     39          const Retriever::Callback& retrieved,
     40          const LookupKeyUtil& lookup_key_util,
     41          const Downloader& downloader,
     42          ValidatingStorage* storage)
     43       : retrieved_(retrieved),
     44         lookup_key_util_(lookup_key_util),
     45         downloader_(downloader),
     46         storage_(storage),
     47         downloaded_(BuildCallback(this, &Helper::OnDownloaded)),
     48         validated_data_ready_(
     49             BuildCallback(this, &Helper::OnValidatedDataReady)),
     50         stale_data_() {
     51     assert(storage_ != NULL);
     52     storage_->Get(key, *validated_data_ready_);
     53   }
     54 
     55  private:
     56   ~Helper() {}
     57 
     58   void OnValidatedDataReady(bool success,
     59                             const std::string& key,
     60                             std::string* data) {
     61     if (success) {
     62       assert(data != NULL);
     63       retrieved_(success, key, *data);
     64       delete this;
     65     } else {
     66       // Validating storage returns (false, key, stale-data) for valid but stale
     67       // data. If |data| is empty, however, then it's either missing or invalid.
     68       if (data != NULL && !data->empty()) {
     69         stale_data_ = *data;
     70       }
     71       downloader_.Download(lookup_key_util_.GetUrlForKey(key), *downloaded_);
     72     }
     73     delete data;
     74   }
     75 
     76   void OnDownloaded(bool success, const std::string& url, std::string* data) {
     77     const std::string& key = lookup_key_util_.GetKeyForUrl(url);
     78     if (success) {
     79       assert(data != NULL);
     80       retrieved_(true, key, *data);
     81       storage_->Put(key, data);
     82       data = NULL;  // Deleted by Storage::Put().
     83     } else if (!stale_data_.empty()) {
     84       // Reuse the stale data if a download fails. It's better to have slightly
     85       // outdated validation rules than to suddenly lose validation ability.
     86       retrieved_(true, key, stale_data_);
     87     } else {
     88       retrieved_(false, key, std::string());
     89     }
     90     delete data;
     91     delete this;
     92   }
     93 
     94   const Retriever::Callback& retrieved_;
     95   const LookupKeyUtil& lookup_key_util_;
     96   const Downloader& downloader_;
     97   ValidatingStorage* storage_;
     98   scoped_ptr<Downloader::Callback> downloaded_;
     99   scoped_ptr<Storage::Callback> validated_data_ready_;
    100   std::string stale_data_;
    101 
    102   DISALLOW_COPY_AND_ASSIGN(Helper);
    103 };
    104 
    105 }  // namespace
    106 
    107 Retriever::Retriever(const std::string& validation_data_url,
    108                      const Downloader* downloader,
    109                      Storage* storage)
    110     : lookup_key_util_(validation_data_url),
    111       downloader_(downloader),
    112       storage_(new ValidatingStorage(storage)) {
    113   assert(storage_ != NULL);
    114   assert(downloader_ != NULL);
    115 }
    116 
    117 Retriever::~Retriever() {}
    118 
    119 void Retriever::Retrieve(const std::string& key,
    120                          const Callback& retrieved) const {
    121   new Helper(key, retrieved, lookup_key_util_, *downloader_, storage_.get());
    122 }
    123 
    124 }  // namespace addressinput
    125 }  // namespace i18n
    126