| 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   // CurrentProcessInfo::CreationTime is only defined on some platforms. | 
|  | 265 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX) | 
|  | 266   const base::Time process_creation_time = | 
|  | 267       base::CurrentProcessInfo::CreationTime(); | 
|  | 268   UMA_HISTOGRAM_COUNTS("ExtensionInstallSigner.UptimeAtTimeOfRequest", | 
|  | 269                        (base::Time::Now() - process_creation_time).InSeconds()); | 
|  | 270 #endif  // defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX) | 
|  | 271 | 
|  | 272   base::TimeDelta delta; | 
|  | 273   base::TimeTicks now = base::TimeTicks::Now(); | 
|  | 274   if (!g_last_request_time.Get().is_null()) | 
|  | 275     delta = now - g_last_request_time.Get(); | 
|  | 276   g_last_request_time.Get() = now; | 
|  | 277   UMA_HISTOGRAM_COUNTS("ExtensionInstallSigner.SecondsSinceLastRequest", | 
|  | 278                        delta.InSeconds()); | 
|  | 279 | 
|  | 280   g_request_count += 1; | 
|  | 281   UMA_HISTOGRAM_COUNTS_100("ExtensionInstallSigner.RequestCount", | 
|  | 282                            g_request_count); | 
|  | 283 } | 
|  | 284 | 
|  | 285 }  // namespace | 
|  | 286 | 
| 246 void InstallSigner::GetSignature(const SignatureCallback& callback) { | 287 void InstallSigner::GetSignature(const SignatureCallback& callback) { | 
| 247   CHECK(!url_fetcher_.get()); | 288   CHECK(!url_fetcher_.get()); | 
| 248   CHECK(callback_.is_null()); | 289   CHECK(callback_.is_null()); | 
| 249   CHECK(salt_.empty()); | 290   CHECK(salt_.empty()); | 
| 250   callback_ = callback; | 291   callback_ = callback; | 
| 251 | 292 | 
| 252   // If the set of ids is empty, just return an empty signature and skip the | 293   // If the set of ids is empty, just return an empty signature and skip the | 
| 253   // call to the server. | 294   // call to the server. | 
| 254   if (ids_.empty()) { | 295   if (ids_.empty()) { | 
| 255     if (!callback_.is_null()) | 296     if (!callback_.is_null()) | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 294     id_list->AppendString(*i); | 335     id_list->AppendString(*i); | 
| 295   } | 336   } | 
| 296   dictionary.Set(kIdsKey, id_list.release()); | 337   dictionary.Set(kIdsKey, id_list.release()); | 
| 297   std::string json; | 338   std::string json; | 
| 298   base::JSONWriter::Write(&dictionary, &json); | 339   base::JSONWriter::Write(&dictionary, &json); | 
| 299   if (json.empty()) { | 340   if (json.empty()) { | 
| 300     ReportErrorViaCallback(); | 341     ReportErrorViaCallback(); | 
| 301     return; | 342     return; | 
| 302   } | 343   } | 
| 303   url_fetcher_->SetUploadData("application/json", json); | 344   url_fetcher_->SetUploadData("application/json", json); | 
|  | 345   LogRequestStartHistograms(); | 
| 304   url_fetcher_->Start(); | 346   url_fetcher_->Start(); | 
| 305 } | 347 } | 
| 306 | 348 | 
| 307 void InstallSigner::ReportErrorViaCallback() { | 349 void InstallSigner::ReportErrorViaCallback() { | 
| 308   InstallSignature* null_signature = NULL; | 350   InstallSignature* null_signature = NULL; | 
| 309   if (!callback_.is_null()) | 351   if (!callback_.is_null()) | 
| 310     callback_.Run(scoped_ptr<InstallSignature>(null_signature)); | 352     callback_.Run(scoped_ptr<InstallSignature>(null_signature)); | 
| 311 } | 353 } | 
| 312 | 354 | 
| 313 void InstallSigner::ParseFetchResponse() { | 355 void InstallSigner::ParseFetchResponse() { | 
|  | 356   bool fetch_success = url_fetcher_->GetStatus().is_success(); | 
|  | 357   UMA_HISTOGRAM_BOOLEAN("ExtensionInstallSigner.FetchSuccess", fetch_success); | 
|  | 358 | 
| 314   std::string response; | 359   std::string response; | 
| 315   if (!url_fetcher_->GetStatus().is_success() || | 360   if (fetch_success) { | 
| 316       !url_fetcher_->GetResponseAsString(&response) || | 361     if (!url_fetcher_->GetResponseAsString(&response)) | 
| 317       response.empty()) { | 362       response.clear(); | 
|  | 363   } | 
|  | 364   UMA_HISTOGRAM_BOOLEAN("ExtensionInstallSigner.GetResponseSuccess", | 
|  | 365                         !response.empty()); | 
|  | 366   if (!fetch_success || response.empty()) { | 
| 318     ReportErrorViaCallback(); | 367     ReportErrorViaCallback(); | 
| 319     return; | 368     return; | 
| 320   } | 369   } | 
| 321 | 370 | 
| 322   // The response is JSON of the form: | 371   // The response is JSON of the form: | 
| 323   // { | 372   // { | 
| 324   //   "protocol_version": "1", | 373   //   "protocol_version": "1", | 
| 325   //   "signature": "<base64-encoded signature>", | 374   //   "signature": "<base64-encoded signature>", | 
| 326   //   "expiry": "<date in YYYY-MM-DD form>", | 375   //   "expiry": "<date in YYYY-MM-DD form>", | 
| 327   //   "invalid_ids": [ "<id3>", "<id4>" ] | 376   //   "invalid_ids": [ "<id3>", "<id4>" ] | 
| 328   // } | 377   // } | 
| 329   // where |invalid_ids| is a list of ids from the original request that | 378   // where |invalid_ids| is a list of ids from the original request that | 
| 330   // could not be verified to be in the webstore. | 379   // could not be verified to be in the webstore. | 
| 331 | 380 | 
| 332   base::DictionaryValue* dictionary = NULL; | 381   base::DictionaryValue* dictionary = NULL; | 
| 333   scoped_ptr<base::Value> parsed(base::JSONReader::Read(response)); | 382   scoped_ptr<base::Value> parsed(base::JSONReader::Read(response)); | 
| 334   if (!parsed.get() || !parsed->GetAsDictionary(&dictionary)) { | 383   bool json_success = parsed.get() && parsed->GetAsDictionary(&dictionary); | 
|  | 384   UMA_HISTOGRAM_BOOLEAN("ExtensionInstallSigner.ParseJsonSuccess", | 
|  | 385                         json_success); | 
|  | 386   if (!json_success) { | 
| 335     ReportErrorViaCallback(); | 387     ReportErrorViaCallback(); | 
| 336     return; | 388     return; | 
| 337   } | 389   } | 
| 338 | 390 | 
| 339   int protocol_version = 0; | 391   int protocol_version = 0; | 
| 340   std::string signature_base64; | 392   std::string signature_base64; | 
| 341   std::string signature; | 393   std::string signature; | 
| 342   std::string expire_date; | 394   std::string expire_date; | 
| 343 | 395 | 
| 344   dictionary->GetInteger(kProtocolVersionKey, &protocol_version); | 396   dictionary->GetInteger(kProtocolVersionKey, &protocol_version); | 
| 345   dictionary->GetString(kSignatureKey, &signature_base64); | 397   dictionary->GetString(kSignatureKey, &signature_base64); | 
| 346   dictionary->GetString(kExpiryKey, &expire_date); | 398   dictionary->GetString(kExpiryKey, &expire_date); | 
| 347 | 399 | 
| 348   if (protocol_version != 1 || signature_base64.empty() || | 400   bool fields_success = | 
| 349       !ValidateExpireDateFormat(expire_date) || | 401       protocol_version == 1 && !signature_base64.empty() && | 
| 350       !base::Base64Decode(signature_base64, &signature)) { | 402       ValidateExpireDateFormat(expire_date) && | 
|  | 403       base::Base64Decode(signature_base64, &signature); | 
|  | 404   UMA_HISTOGRAM_BOOLEAN("ExtensionInstallSigner.ParseFieldsSuccess", | 
|  | 405                         fields_success); | 
|  | 406   if (!fields_success) { | 
| 351     ReportErrorViaCallback(); | 407     ReportErrorViaCallback(); | 
| 352     return; | 408     return; | 
| 353   } | 409   } | 
| 354 | 410 | 
| 355   ExtensionIdSet invalid_ids; | 411   ExtensionIdSet invalid_ids; | 
| 356   const base::ListValue* invalid_ids_list = NULL; | 412   const base::ListValue* invalid_ids_list = NULL; | 
| 357   if (dictionary->GetList(kInvalidIdsKey, &invalid_ids_list)) { | 413   if (dictionary->GetList(kInvalidIdsKey, &invalid_ids_list)) { | 
| 358     for (size_t i = 0; i < invalid_ids_list->GetSize(); i++) { | 414     for (size_t i = 0; i < invalid_ids_list->GetSize(); i++) { | 
| 359       std::string id; | 415       std::string id; | 
| 360       if (!invalid_ids_list->GetString(i, &id)) { | 416       if (!invalid_ids_list->GetString(i, &id)) { | 
| (...skipping 27 matching lines...) Expand all  Loading... | 
| 388     if (!verified) | 444     if (!verified) | 
| 389       result.reset(); | 445       result.reset(); | 
| 390   } | 446   } | 
| 391 | 447 | 
| 392   if (!callback_.is_null()) | 448   if (!callback_.is_null()) | 
| 393     callback_.Run(result.Pass()); | 449     callback_.Run(result.Pass()); | 
| 394 } | 450 } | 
| 395 | 451 | 
| 396 | 452 | 
| 397 }  // namespace extensions | 453 }  // namespace extensions | 
| OLD | NEW | 
|---|