| OLD | NEW | 
|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "chrome/browser/extensions/install_signer.h" | 5 #include "chrome/browser/extensions/install_signer.h" | 
| 6 | 6 | 
| 7 #include "base/base64.h" | 7 #include "base/base64.h" | 
| 8 #include "base/bind.h" | 8 #include "base/bind.h" | 
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" | 
| 10 #include "base/json/json_reader.h" | 10 #include "base/json/json_reader.h" | 
| 11 #include "base/json/json_writer.h" | 11 #include "base/json/json_writer.h" | 
|  | 12 #include "base/lazy_instance.h" | 
| 12 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" | 
| 13 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" | 
|  | 15 #include "base/process/process_info.h" | 
| 14 #include "base/stl_util.h" | 16 #include "base/stl_util.h" | 
| 15 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" | 
| 16 #include "base/strings/string_split.h" | 18 #include "base/strings/string_split.h" | 
| 17 #include "base/strings/string_util.h" | 19 #include "base/strings/string_util.h" | 
| 18 #include "base/strings/stringprintf.h" | 20 #include "base/strings/stringprintf.h" | 
|  | 21 #include "base/time/time.h" | 
| 19 #include "base/values.h" | 22 #include "base/values.h" | 
| 20 #include "chrome/common/chrome_switches.h" | 23 #include "chrome/common/chrome_switches.h" | 
| 21 #include "chrome/common/extensions/extension_constants.h" | 24 #include "chrome/common/extensions/extension_constants.h" | 
| 22 #include "crypto/random.h" | 25 #include "crypto/random.h" | 
| 23 #include "crypto/secure_hash.h" | 26 #include "crypto/secure_hash.h" | 
| 24 #include "crypto/sha2.h" | 27 #include "crypto/sha2.h" | 
| 25 #include "crypto/signature_verifier.h" | 28 #include "crypto/signature_verifier.h" | 
| 26 #include "net/url_request/url_fetcher.h" | 29 #include "net/url_request/url_fetcher.h" | 
| 27 #include "net/url_request/url_fetcher_delegate.h" | 30 #include "net/url_request/url_fetcher_delegate.h" | 
| 28 #include "net/url_request/url_request_context_getter.h" | 31 #include "net/url_request/url_request_context_getter.h" | 
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 236   std::string value = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 239   std::string value = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 
| 237       switches::kExtensionsNotWebstore); | 240       switches::kExtensionsNotWebstore); | 
| 238   if (value.empty()) | 241   if (value.empty()) | 
| 239     return ExtensionIdSet(); | 242     return ExtensionIdSet(); | 
| 240 | 243 | 
| 241   std::vector<std::string> ids; | 244   std::vector<std::string> ids; | 
| 242   base::SplitString(value, ',', &ids); | 245   base::SplitString(value, ',', &ids); | 
| 243   return ExtensionIdSet(ids.begin(), ids.end()); | 246   return ExtensionIdSet(ids.begin(), ids.end()); | 
| 244 } | 247 } | 
| 245 | 248 | 
|  | 249 namespace { | 
|  | 250 | 
|  | 251 static int g_request_count = 0; | 
|  | 252 | 
|  | 253 base::LazyInstance<base::TimeTicks> g_last_request_time = | 
|  | 254     LAZY_INSTANCE_INITIALIZER; | 
|  | 255 | 
|  | 256 base::LazyInstance<base::ThreadChecker> g_single_thread_checker = | 
|  | 257     LAZY_INSTANCE_INITIALIZER; | 
|  | 258 | 
|  | 259 void LogRequestStartHistograms() { | 
|  | 260   // Make sure we only ever call this from one thread, so that we don't have to | 
|  | 261   // worry about race conditions setting g_last_request_time. | 
|  | 262   DCHECK(g_single_thread_checker.Get().CalledOnValidThread()); | 
|  | 263 | 
|  | 264   const base::Time process_creation_time = | 
|  | 265       base::CurrentProcessInfo::CreationTime(); | 
|  | 266   UMA_HISTOGRAM_COUNTS("ExtensionInstallSigner.UptimeAtTimeOfRequest", | 
|  | 267                        (base::Time::Now() - process_creation_time).InSeconds()); | 
|  | 268 | 
|  | 269   base::TimeDelta delta; | 
|  | 270   base::TimeTicks now = base::TimeTicks::Now(); | 
|  | 271   if (!g_last_request_time.Get().is_null()) | 
|  | 272     delta = now - g_last_request_time.Get(); | 
|  | 273   g_last_request_time.Get() = now; | 
|  | 274   UMA_HISTOGRAM_COUNTS("ExtensionInstallSigner.SecondsSinceLastRequest", | 
|  | 275                        delta.InSeconds()); | 
|  | 276 | 
|  | 277   g_request_count += 1; | 
|  | 278   UMA_HISTOGRAM_COUNTS_100("ExtensionInstallSigner.RequestCount", | 
|  | 279                            g_request_count); | 
|  | 280 } | 
|  | 281 | 
|  | 282 }  // namespace | 
|  | 283 | 
| 246 void InstallSigner::GetSignature(const SignatureCallback& callback) { | 284 void InstallSigner::GetSignature(const SignatureCallback& callback) { | 
| 247   CHECK(!url_fetcher_.get()); | 285   CHECK(!url_fetcher_.get()); | 
| 248   CHECK(callback_.is_null()); | 286   CHECK(callback_.is_null()); | 
| 249   CHECK(salt_.empty()); | 287   CHECK(salt_.empty()); | 
| 250   callback_ = callback; | 288   callback_ = callback; | 
| 251 | 289 | 
| 252   // If the set of ids is empty, just return an empty signature and skip the | 290   // If the set of ids is empty, just return an empty signature and skip the | 
| 253   // call to the server. | 291   // call to the server. | 
| 254   if (ids_.empty()) { | 292   if (ids_.empty()) { | 
| 255     if (!callback_.is_null()) | 293     if (!callback_.is_null()) | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 294     id_list->AppendString(*i); | 332     id_list->AppendString(*i); | 
| 295   } | 333   } | 
| 296   dictionary.Set(kIdsKey, id_list.release()); | 334   dictionary.Set(kIdsKey, id_list.release()); | 
| 297   std::string json; | 335   std::string json; | 
| 298   base::JSONWriter::Write(&dictionary, &json); | 336   base::JSONWriter::Write(&dictionary, &json); | 
| 299   if (json.empty()) { | 337   if (json.empty()) { | 
| 300     ReportErrorViaCallback(); | 338     ReportErrorViaCallback(); | 
| 301     return; | 339     return; | 
| 302   } | 340   } | 
| 303   url_fetcher_->SetUploadData("application/json", json); | 341   url_fetcher_->SetUploadData("application/json", json); | 
|  | 342   LogRequestStartHistograms(); | 
| 304   url_fetcher_->Start(); | 343   url_fetcher_->Start(); | 
| 305 } | 344 } | 
| 306 | 345 | 
| 307 void InstallSigner::ReportErrorViaCallback() { | 346 void InstallSigner::ReportErrorViaCallback() { | 
| 308   InstallSignature* null_signature = NULL; | 347   InstallSignature* null_signature = NULL; | 
| 309   if (!callback_.is_null()) | 348   if (!callback_.is_null()) | 
| 310     callback_.Run(scoped_ptr<InstallSignature>(null_signature)); | 349     callback_.Run(scoped_ptr<InstallSignature>(null_signature)); | 
| 311 } | 350 } | 
| 312 | 351 | 
| 313 void InstallSigner::ParseFetchResponse() { | 352 void InstallSigner::ParseFetchResponse() { | 
|  | 353   bool fetch_success = url_fetcher_->GetStatus().is_success(); | 
|  | 354   UMA_HISTOGRAM_BOOLEAN("ExtensionInstallSigner.FetchSuccess", fetch_success); | 
|  | 355 | 
| 314   std::string response; | 356   std::string response; | 
| 315   if (!url_fetcher_->GetStatus().is_success() || | 357   if (fetch_success) { | 
| 316       !url_fetcher_->GetResponseAsString(&response) || | 358     if (!url_fetcher_->GetResponseAsString(&response)) | 
| 317       response.empty()) { | 359       response.clear(); | 
|  | 360   } | 
|  | 361   UMA_HISTOGRAM_BOOLEAN("ExtensionInstallSigner.GetResponseSuccess", | 
|  | 362                         !response.empty()); | 
|  | 363   if (!fetch_success || response.empty()) { | 
| 318     ReportErrorViaCallback(); | 364     ReportErrorViaCallback(); | 
| 319     return; | 365     return; | 
| 320   } | 366   } | 
| 321 | 367 | 
| 322   // The response is JSON of the form: | 368   // The response is JSON of the form: | 
| 323   // { | 369   // { | 
| 324   //   "protocol_version": "1", | 370   //   "protocol_version": "1", | 
| 325   //   "signature": "<base64-encoded signature>", | 371   //   "signature": "<base64-encoded signature>", | 
| 326   //   "expiry": "<date in YYYY-MM-DD form>", | 372   //   "expiry": "<date in YYYY-MM-DD form>", | 
| 327   //   "invalid_ids": [ "<id3>", "<id4>" ] | 373   //   "invalid_ids": [ "<id3>", "<id4>" ] | 
| 328   // } | 374   // } | 
| 329   // where |invalid_ids| is a list of ids from the original request that | 375   // where |invalid_ids| is a list of ids from the original request that | 
| 330   // could not be verified to be in the webstore. | 376   // could not be verified to be in the webstore. | 
| 331 | 377 | 
| 332   base::DictionaryValue* dictionary = NULL; | 378   base::DictionaryValue* dictionary = NULL; | 
| 333   scoped_ptr<base::Value> parsed(base::JSONReader::Read(response)); | 379   scoped_ptr<base::Value> parsed(base::JSONReader::Read(response)); | 
| 334   if (!parsed.get() || !parsed->GetAsDictionary(&dictionary)) { | 380   bool json_success = parsed.get() && parsed->GetAsDictionary(&dictionary); | 
|  | 381   UMA_HISTOGRAM_BOOLEAN("ExtensionInstallSigner.ParseJsonSuccess", | 
|  | 382                         json_success); | 
|  | 383   if (!json_success) { | 
| 335     ReportErrorViaCallback(); | 384     ReportErrorViaCallback(); | 
| 336     return; | 385     return; | 
| 337   } | 386   } | 
| 338 | 387 | 
| 339   int protocol_version = 0; | 388   int protocol_version = 0; | 
| 340   std::string signature_base64; | 389   std::string signature_base64; | 
| 341   std::string signature; | 390   std::string signature; | 
| 342   std::string expire_date; | 391   std::string expire_date; | 
| 343 | 392 | 
| 344   dictionary->GetInteger(kProtocolVersionKey, &protocol_version); | 393   dictionary->GetInteger(kProtocolVersionKey, &protocol_version); | 
| 345   dictionary->GetString(kSignatureKey, &signature_base64); | 394   dictionary->GetString(kSignatureKey, &signature_base64); | 
| 346   dictionary->GetString(kExpiryKey, &expire_date); | 395   dictionary->GetString(kExpiryKey, &expire_date); | 
| 347 | 396 | 
| 348   if (protocol_version != 1 || signature_base64.empty() || | 397   bool fields_success = | 
| 349       !ValidateExpireDateFormat(expire_date) || | 398       protocol_version == 1 && !signature_base64.empty() && | 
| 350       !base::Base64Decode(signature_base64, &signature)) { | 399       ValidateExpireDateFormat(expire_date) && | 
|  | 400       base::Base64Decode(signature_base64, &signature); | 
|  | 401   UMA_HISTOGRAM_BOOLEAN("ExtensionInstallSigner.ParseFieldsSuccess", | 
|  | 402                         fields_success); | 
|  | 403   if (!fields_success) { | 
| 351     ReportErrorViaCallback(); | 404     ReportErrorViaCallback(); | 
| 352     return; | 405     return; | 
| 353   } | 406   } | 
| 354 | 407 | 
| 355   ExtensionIdSet invalid_ids; | 408   ExtensionIdSet invalid_ids; | 
| 356   const base::ListValue* invalid_ids_list = NULL; | 409   const base::ListValue* invalid_ids_list = NULL; | 
| 357   if (dictionary->GetList(kInvalidIdsKey, &invalid_ids_list)) { | 410   if (dictionary->GetList(kInvalidIdsKey, &invalid_ids_list)) { | 
| 358     for (size_t i = 0; i < invalid_ids_list->GetSize(); i++) { | 411     for (size_t i = 0; i < invalid_ids_list->GetSize(); i++) { | 
| 359       std::string id; | 412       std::string id; | 
| 360       if (!invalid_ids_list->GetString(i, &id)) { | 413       if (!invalid_ids_list->GetString(i, &id)) { | 
| (...skipping 27 matching lines...) Expand all  Loading... | 
| 388     if (!verified) | 441     if (!verified) | 
| 389       result.reset(); | 442       result.reset(); | 
| 390   } | 443   } | 
| 391 | 444 | 
| 392   if (!callback_.is_null()) | 445   if (!callback_.is_null()) | 
| 393     callback_.Run(result.Pass()); | 446     callback_.Run(result.Pass()); | 
| 394 } | 447 } | 
| 395 | 448 | 
| 396 | 449 | 
| 397 }  // namespace extensions | 450 }  // namespace extensions | 
| OLD | NEW | 
|---|