| OLD | NEW | 
|    1 // Copyright (C) 2013 Google Inc. |    1 // Copyright (C) 2013 Google Inc. | 
|    2 // |    2 // | 
|    3 // Licensed under the Apache License, Version 2.0 (the "License"); |    3 // Licensed under the Apache License, Version 2.0 (the "License"); | 
|    4 // you may not use this file except in compliance with 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 |    5 // You may obtain a copy of the License at | 
|    6 // |    6 // | 
|    7 // http://www.apache.org/licenses/LICENSE-2.0 |    7 // http://www.apache.org/licenses/LICENSE-2.0 | 
|    8 // |    8 // | 
|    9 // Unless required by applicable law or agreed to in writing, software |    9 // Unless required by applicable law or agreed to in writing, software | 
|   10 // distributed under the License is distributed on an "AS IS" BASIS, |   10 // distributed under the License is distributed on an "AS IS" BASIS, | 
|   11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |   11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|   12 // See the License for the specific language governing permissions and |   12 // See the License for the specific language governing permissions and | 
|   13 // limitations under the License. |   13 // limitations under the License. | 
|   14  |   14  | 
|   15 #include "retriever.h" |   15 #include "retriever.h" | 
|   16  |   16  | 
|   17 #include <libaddressinput/callback.h> |   17 #include <libaddressinput/callback.h> | 
|   18 #include <libaddressinput/downloader.h> |   18 #include <libaddressinput/downloader.h> | 
|   19 #include <libaddressinput/storage.h> |   19 #include <libaddressinput/storage.h> | 
|   20 #include <libaddressinput/util/basictypes.h> |   20 #include <libaddressinput/util/basictypes.h> | 
|   21 #include <libaddressinput/util/scoped_ptr.h> |   21 #include <libaddressinput/util/scoped_ptr.h> | 
|   22  |   22  | 
|   23 #include <cassert> |   23 #include <cassert> | 
|   24 #include <cstddef> |   24 #include <cstddef> | 
 |   25 #include <ctime> | 
|   25 #include <map> |   26 #include <map> | 
|   26 #include <string> |   27 #include <string> | 
|   27 #include <utility> |   28 #include <utility> | 
|   28  |   29  | 
|   29 #include "fallback_data_store.h" |   30 #include "fallback_data_store.h" | 
|   30 #include "util/stl_util.h" |   31 #include "util/stl_util.h" | 
 |   32 #include "validating_util.h" | 
|   31  |   33  | 
|   32 namespace i18n { |   34 namespace i18n { | 
|   33 namespace addressinput { |   35 namespace addressinput { | 
|   34  |   36  | 
|   35 Retriever::Retriever(const std::string& validation_data_url, |   37 Retriever::Retriever(const std::string& validation_data_url, | 
|   36                      scoped_ptr<Downloader> downloader, |   38                      scoped_ptr<Downloader> downloader, | 
|   37                      scoped_ptr<Storage> storage) |   39                      scoped_ptr<Storage> storage) | 
|   38     : validation_data_url_(validation_data_url), |   40     : validation_data_url_(validation_data_url), | 
|   39       downloader_(downloader.Pass()), |   41       downloader_(downloader.Pass()), | 
|   40       storage_(storage.Pass()) { |   42       storage_(storage.Pass()), | 
 |   43       stale_data_() { | 
|   41   assert(validation_data_url_.length() > 0); |   44   assert(validation_data_url_.length() > 0); | 
|   42   assert(validation_data_url_[validation_data_url_.length() - 1] == '/'); |   45   assert(validation_data_url_[validation_data_url_.length() - 1] == '/'); | 
|   43   assert(storage_ != NULL); |   46   assert(storage_ != NULL); | 
|   44   assert(downloader_ != NULL); |   47   assert(downloader_ != NULL); | 
|   45 } |   48 } | 
|   46  |   49  | 
|   47 Retriever::~Retriever() { |   50 Retriever::~Retriever() { | 
|   48   STLDeleteValues(&requests_); |   51   STLDeleteValues(&requests_); | 
|   49 } |   52 } | 
|   50  |   53  | 
|   51 void Retriever::Retrieve(const std::string& key, |   54 void Retriever::Retrieve(const std::string& key, | 
|   52                          scoped_ptr<Callback> retrieved) { |   55                          scoped_ptr<Callback> retrieved) { | 
|   53   std::map<std::string, Callback*>::iterator request_it = |   56   std::map<std::string, Callback*>::iterator request_it = | 
|   54       requests_.find(key); |   57       requests_.find(key); | 
|   55   if (request_it != requests_.end()) { |   58   if (request_it != requests_.end()) { | 
|   56     // Abandon a previous request. |   59     // Abandon a previous request. | 
|   57     delete request_it->second; |   60     delete request_it->second; | 
|   58     requests_.erase(request_it); |   61     requests_.erase(request_it); | 
|   59   } |   62   } | 
|   60  |   63  | 
|   61   requests_[key] = retrieved.release(); |   64   requests_[key] = retrieved.release(); | 
|   62   storage_->Get(key, |   65   storage_->Get(key, | 
|   63                 BuildCallback(this, &Retriever::OnDataRetrievedFromStorage)); |   66                 BuildCallback(this, &Retriever::OnDataRetrievedFromStorage)); | 
|   64 } |   67 } | 
|   65  |   68  | 
|   66 void Retriever::OnDataRetrievedFromStorage(bool success, |   69 void Retriever::OnDataRetrievedFromStorage(bool success, | 
|   67                                            const std::string& key, |   70                                            const std::string& key, | 
|   68                                            const std::string& stored_data) { |   71                                            const std::string& stored_data) { | 
|   69   // TODO(rouslan): Add validation for data integrity and freshness. If a |   72   std::string unwrapped = stored_data; | 
|   70   // download fails, then it's OK to use stale data. |   73   ValidatingUtil::TimestampStatus timestamp_status = | 
|   71   if (success) { |   74       ValidatingUtil::UnwrapTimestamp(&unwrapped, time(NULL)); | 
 |   75   bool checksum_valid = ValidatingUtil::UnwrapChecksum(&unwrapped); | 
 |   76  | 
 |   77   if (success && | 
 |   78       timestamp_status == ValidatingUtil::TIMESTAMP_VALID && | 
 |   79       checksum_valid) { | 
|   72     scoped_ptr<Callback> retrieved = GetCallbackForKey(key); |   80     scoped_ptr<Callback> retrieved = GetCallbackForKey(key); | 
|   73     if (retrieved != NULL) { |   81     if (retrieved != NULL) { | 
|   74       (*retrieved)(success, key, stored_data); |   82       (*retrieved)(success, key, unwrapped); | 
|   75     } |   83     } | 
|   76   } else { |   84   } else { | 
 |   85     if (success && | 
 |   86         timestamp_status == ValidatingUtil::TIMESTAMP_STALE && | 
 |   87         checksum_valid) { | 
 |   88       stale_data_[key] = unwrapped; | 
 |   89     } | 
|   77     downloader_->Download(GetUrlForKey(key), |   90     downloader_->Download(GetUrlForKey(key), | 
|   78                           BuildCallback(this, &Retriever::OnDownloaded)); |   91                           BuildCallback(this, &Retriever::OnDownloaded)); | 
|   79   } |   92   } | 
|   80 } |   93 } | 
|   81  |   94  | 
|   82 void Retriever::OnDownloaded(bool success, |   95 void Retriever::OnDownloaded(bool success, | 
|   83                              const std::string& url, |   96                              const std::string& url, | 
|   84                              const std::string& downloaded_data) { |   97                              const std::string& downloaded_data) { | 
|   85   const std::string& key = GetKeyForUrl(url); |   98   const std::string& key = GetKeyForUrl(url); | 
|   86   std::string response; |   99   std::string response; | 
 |  100   std::map<std::string, std::string>::iterator stale_data_it = | 
 |  101       stale_data_.find(key); | 
 |  102  | 
|   87   if (success) { |  103   if (success) { | 
|   88     storage_->Put(key, downloaded_data); |  104     storage_->Put(key, ValidatingUtil::Wrap(downloaded_data, time(NULL))); | 
|   89     response = downloaded_data; |  105     response = downloaded_data; | 
 |  106   } else if (stale_data_it != stale_data_.end()) { | 
 |  107     success = true; | 
 |  108     response = stale_data_it->second; | 
|   90   } else { |  109   } else { | 
|   91     success = FallbackDataStore::Get(key, &response); |  110       success = FallbackDataStore::Get(key, &response); | 
 |  111   } | 
 |  112  | 
 |  113   if (stale_data_it != stale_data_.end()) { | 
 |  114     stale_data_.erase(stale_data_it); | 
|   92   } |  115   } | 
|   93  |  116  | 
|   94   scoped_ptr<Callback> retrieved = GetCallbackForKey(key); |  117   scoped_ptr<Callback> retrieved = GetCallbackForKey(key); | 
|   95   if (retrieved != NULL) { |  118   if (retrieved != NULL) { | 
|   96     (*retrieved)(success, key, response); |  119     (*retrieved)(success, key, response); | 
|   97   } |  120   } | 
|   98 } |  121 } | 
|   99  |  122  | 
|  100 std::string Retriever::GetUrlForKey(const std::string& key) const { |  123 std::string Retriever::GetUrlForKey(const std::string& key) const { | 
|  101   return validation_data_url_ + key; |  124   return validation_data_url_ + key; | 
| (...skipping 19 matching lines...) Expand all  Loading... | 
|  121     // An abandonened request. |  144     // An abandonened request. | 
|  122     return scoped_ptr<Callback>(); |  145     return scoped_ptr<Callback>(); | 
|  123   } |  146   } | 
|  124   scoped_ptr<Callback> callback(iter->second); |  147   scoped_ptr<Callback> callback(iter->second); | 
|  125   requests_.erase(iter); |  148   requests_.erase(iter); | 
|  126   return callback.Pass(); |  149   return callback.Pass(); | 
|  127 } |  150 } | 
|  128  |  151  | 
|  129 }  // namespace addressinput |  152 }  // namespace addressinput | 
|  130 }  // namespace i18n |  153 }  // namespace i18n | 
| OLD | NEW |