Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/chromeos/certificate_provider/certificate_provider_serv ice.h" | 5 #include "chrome/browser/chromeos/certificate_provider/certificate_provider_serv ice.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "ash/shell.h" | |
| 11 #include "base/bind.h" | 12 #include "base/bind.h" |
| 12 #include "base/bind_helpers.h" | 13 #include "base/bind_helpers.h" |
| 13 #include "base/callback.h" | 14 #include "base/callback.h" |
| 14 #include "base/location.h" | 15 #include "base/location.h" |
| 15 #include "base/logging.h" | 16 #include "base/logging.h" |
| 16 #include "base/macros.h" | 17 #include "base/macros.h" |
| 17 #include "base/memory/ptr_util.h" | 18 #include "base/memory/ptr_util.h" |
| 18 #include "base/stl_util.h" | 19 #include "base/stl_util.h" |
| 19 #include "base/strings/string_piece.h" | 20 #include "base/strings/string_piece.h" |
| 21 #include "base/strings/utf_string_conversions.h" | |
| 20 #include "base/task_runner.h" | 22 #include "base/task_runner.h" |
| 21 #include "base/threading/thread_task_runner_handle.h" | 23 #include "base/threading/thread_task_runner_handle.h" |
| 22 #include "chrome/browser/chromeos/certificate_provider/certificate_provider.h" | 24 #include "chrome/browser/chromeos/certificate_provider/certificate_provider.h" |
| 25 #include "chrome/browser/chromeos/login/ui/login_display_host.h" | |
| 26 #include "chrome/browser/profiles/profile_manager.h" | |
| 27 #include "chrome/browser/ui/browser_finder.h" | |
| 28 #include "chrome/browser/ui/browser_window.h" | |
| 23 #include "net/base/net_errors.h" | 29 #include "net/base/net_errors.h" |
| 24 #include "net/ssl/client_key_store.h" | 30 #include "net/ssl/client_key_store.h" |
| 31 #include "ui/views/widget/widget.h" | |
| 32 #include "ui/views/window/dialog_client_view.h" | |
| 25 | 33 |
| 26 namespace chromeos { | 34 namespace chromeos { |
| 27 | 35 |
| 28 namespace { | 36 namespace { |
| 29 | 37 |
| 30 void PostSignResultToTaskRunner( | 38 void PostSignResultToTaskRunner( |
| 31 const scoped_refptr<base::TaskRunner>& target_task_runner, | 39 const scoped_refptr<base::TaskRunner>& target_task_runner, |
| 32 const net::SSLPrivateKey::SignCallback& callback, | 40 const net::SSLPrivateKey::SignCallback& callback, |
| 33 net::Error error, | 41 net::Error error, |
| 34 const std::vector<uint8_t>& signature) { | 42 const std::vector<uint8_t>& signature) { |
| 35 target_task_runner->PostTask(FROM_HERE, | 43 target_task_runner->PostTask(FROM_HERE, |
| 36 base::Bind(callback, error, signature)); | 44 base::Bind(callback, error, signature)); |
| 37 } | 45 } |
| 38 | 46 |
| 39 void PostCertificatesToTaskRunner( | 47 void PostCertificatesToTaskRunner( |
| 40 const scoped_refptr<base::TaskRunner>& target_task_runner, | 48 const scoped_refptr<base::TaskRunner>& target_task_runner, |
| 41 const base::Callback<void(const net::CertificateList&)>& callback, | 49 const base::Callback<void(const net::CertificateList&)>& callback, |
| 42 const net::CertificateList& certs) { | 50 const net::CertificateList& certs) { |
| 43 target_task_runner->PostTask(FROM_HERE, base::Bind(callback, certs)); | 51 target_task_runner->PostTask(FROM_HERE, base::Bind(callback, certs)); |
| 44 } | 52 } |
| 45 | 53 |
| 46 } // namespace | 54 } // namespace |
| 47 | 55 |
| 56 // Define timeout for issued sign_request_id. | |
| 57 const uint64_t SIGN_REQUEST_ID_TIMEOUT = 10 * 60; // 10 minutes | |
| 58 | |
| 59 // The limit of the sign_request_id map size, after which the sanitizing process | |
| 60 // will be applied to remove expired entries. | |
| 61 const int MAX_SIGN_REQUESTS_MAP_SIZE = 10; | |
| 62 | |
| 48 class CertificateProviderService::CertKeyProviderImpl | 63 class CertificateProviderService::CertKeyProviderImpl |
| 49 : public net::ClientKeyStore::CertKeyProvider { | 64 : public net::ClientKeyStore::CertKeyProvider { |
| 50 public: | 65 public: |
| 51 // |certificate_map| must outlive this provider. |service| must be | 66 // |certificate_map| must outlive this provider. |service| must be |
| 52 // dereferenceable on |service_task_runner|. | 67 // dereferenceable on |service_task_runner|. |
| 53 // This provider may be accessed from any thread. Methods and destructor must | 68 // This provider may be accessed from any thread. Methods and destructor must |
| 54 // never be called concurrently. | 69 // never be called concurrently. |
| 55 CertKeyProviderImpl( | 70 CertKeyProviderImpl( |
| 56 const scoped_refptr<base::SequencedTaskRunner>& service_task_runner, | 71 const scoped_refptr<base::SequencedTaskRunner>& service_task_runner, |
| 57 const base::WeakPtr<CertificateProviderService>& service, | 72 const base::WeakPtr<CertificateProviderService>& service, |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 289 } | 304 } |
| 290 | 305 |
| 291 void CertificateProviderService::SSLPrivateKey::DidSignDigest( | 306 void CertificateProviderService::SSLPrivateKey::DidSignDigest( |
| 292 const SignCallback& callback, | 307 const SignCallback& callback, |
| 293 net::Error error, | 308 net::Error error, |
| 294 const std::vector<uint8_t>& signature) { | 309 const std::vector<uint8_t>& signature) { |
| 295 DCHECK(thread_checker_.CalledOnValidThread()); | 310 DCHECK(thread_checker_.CalledOnValidThread()); |
| 296 callback.Run(error, signature); | 311 callback.Run(error, signature); |
| 297 } | 312 } |
| 298 | 313 |
| 299 CertificateProviderService::CertificateProviderService() | 314 CertificateProviderService::CertificateProviderService() : weak_factory_(this) { |
| 300 : weak_factory_(this) {} | 315 AddSignRequestId(123); |
|
stevenjb
2016/08/09 21:04:38
What is 123? This should be a constant.
igorcov1
2016/08/10 18:05:03
Sorry, I forgot to remove it. It was added to be a
| |
| 316 } | |
| 301 | 317 |
| 302 CertificateProviderService::~CertificateProviderService() { | 318 CertificateProviderService::~CertificateProviderService() { |
| 303 DCHECK(thread_checker_.CalledOnValidThread()); | 319 DCHECK(thread_checker_.CalledOnValidThread()); |
| 304 | 320 |
| 305 // ClientKeyStore serializes access to |cert_key_provider_|. | 321 // ClientKeyStore serializes access to |cert_key_provider_|. |
| 306 // Once RemoveProvider() returns, it is guaranteed that there are no more | 322 // Once RemoveProvider() returns, it is guaranteed that there are no more |
| 307 // accesses to |cert_key_provider_| in flight and no references to | 323 // accesses to |cert_key_provider_| in flight and no references to |
| 308 // |cert_key_provider_| are remaining. This service will hold the last | 324 // |cert_key_provider_| are remaining. This service will hold the last |
| 309 // reference to |cert_key_provider_|. | 325 // reference to |cert_key_provider_|. |
| 310 net::ClientKeyStore::GetInstance()->RemoveProvider(cert_key_provider_.get()); | 326 net::ClientKeyStore::GetInstance()->RemoveProvider(cert_key_provider_.get()); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 393 base::Callback<void(const net::CertificateList&)> callback; | 409 base::Callback<void(const net::CertificateList&)> callback; |
| 394 certificate_requests_.RemoveRequest(cert_request_id, &certificates, | 410 certificate_requests_.RemoveRequest(cert_request_id, &certificates, |
| 395 &callback); | 411 &callback); |
| 396 UpdateCertificatesAndRun(certificates, callback); | 412 UpdateCertificatesAndRun(certificates, callback); |
| 397 } | 413 } |
| 398 | 414 |
| 399 certificate_map_.RemoveExtension(extension_id); | 415 certificate_map_.RemoveExtension(extension_id); |
| 400 | 416 |
| 401 for (auto callback : sign_requests_.RemoveAllRequests(extension_id)) | 417 for (auto callback : sign_requests_.RemoveAllRequests(extension_id)) |
| 402 callback.Run(net::ERR_FAILED, std::vector<uint8_t>()); | 418 callback.Run(net::ERR_FAILED, std::vector<uint8_t>()); |
| 419 | |
| 420 last_rejected_[extension_id] = false; | |
| 421 } | |
| 422 | |
| 423 void CertificateProviderService::OnPinDialogInput( | |
| 424 const std::string& extension_id, | |
| 425 const bool closed) { | |
| 426 last_rejected_[extension_id] = closed; | |
| 427 if (closed) { | |
| 428 active_pin_dialog_ = nullptr; | |
|
stevenjb
2016/08/09 21:04:39
return and elim else
igorcov1
2016/08/10 18:05:03
Done.
| |
| 429 } else { | |
| 430 // Set the temporary callback to be called if user closes the dialog while | |
| 431 // request is processing by the extension. | |
| 432 active_pin_dialog_->SetCallback( | |
| 433 base::Bind(&CertificateProviderService::OnFlowInterrupted, | |
| 434 base::Unretained(this))); | |
| 435 } | |
| 436 } | |
| 437 | |
| 438 void CertificateProviderService::OnFlowInterrupted( | |
| 439 const base::string16& value) { | |
| 440 DCHECK(value.empty()); | |
| 441 OnPinDialogInput(active_dialog_extension_id_, true); | |
| 442 } | |
| 443 | |
| 444 bool CertificateProviderService::LastPinDialogClosed( | |
| 445 const std::string& extension_id) { | |
| 446 return last_rejected_[extension_id]; | |
| 447 } | |
| 448 | |
| 449 bool CertificateProviderService::UpdatePinDialog( | |
| 450 const std::string& extension_id, | |
| 451 const base::string16& error_message, | |
| 452 const bool accept_input, | |
| 453 const RequestPinView::RequestPinCallback& callback) { | |
| 454 if (active_pin_dialog_ == nullptr) { | |
| 455 return false; | |
| 456 } | |
| 457 | |
| 458 if (extension_id != active_dialog_extension_id_ || | |
| 459 !active_pin_dialog_->IsLocked()) { | |
| 460 return false; | |
| 461 } | |
| 462 | |
| 463 active_pin_dialog_->SetCallback(callback); | |
| 464 active_pin_dialog_->SetDialogParameters(error_message, accept_input); | |
| 465 active_pin_dialog_->GetDialogClientView()->UpdateDialogButtons(); | |
| 466 return true; | |
| 467 } | |
| 468 | |
| 469 RequestPinResponse CertificateProviderService::ShowPinDialog( | |
| 470 const std::string& extension_id, | |
| 471 const std::string& extension_name, | |
| 472 const long long sign_request_id, | |
| 473 const std::string& dialog_type, | |
| 474 const base::string16& error_message, | |
| 475 const bool accept_input, | |
| 476 const RequestPinView::RequestPinCallback& callback) { | |
| 477 // Don't allow the extension to create anything if an active dialog already | |
| 478 // exists. Still if the dialog is there, initiated by the extension then skip | |
| 479 // the signRequestId check as it's possibly expired. | |
| 480 if (active_pin_dialog_ != nullptr) { | |
| 481 if (!active_dialog_extension_id_.empty() && | |
| 482 extension_id == active_dialog_extension_id_ && | |
| 483 active_pin_dialog_->IsLocked()) { | |
| 484 // Set the new callback to be used by the view. | |
| 485 active_pin_dialog_->SetCallback(callback); | |
| 486 active_pin_dialog_->SetDialogParameters(dialog_type, error_message, | |
| 487 accept_input); | |
| 488 active_pin_dialog_->GetDialogClientView()->UpdateDialogButtons(); | |
| 489 return RequestPinResponse::SUCCESS; | |
| 490 } | |
| 491 | |
| 492 return RequestPinResponse::OTHER_FLOW_IN_PROGRESS; | |
| 493 } | |
| 494 | |
| 495 // Check the validity of sign_request_id | |
| 496 if (sign_request_ids_.find(sign_request_id) == sign_request_ids_.end()) { | |
| 497 return RequestPinResponse::INVALID_ID; | |
| 498 } | |
| 499 | |
| 500 struct timeval tv; | |
| 501 int result = gettimeofday(&tv, NULL); | |
| 502 DCHECK_EQ(0, result); | |
| 503 if (tv.tv_sec - sign_request_ids_[sign_request_id] > SIGN_REQUEST_ID_TIMEOUT) | |
| 504 return RequestPinResponse::INVALID_ID; | |
| 505 | |
| 506 active_dialog_extension_id_ = extension_id; | |
| 507 active_pin_dialog_ = new chromeos::RequestPinView( | |
| 508 extension_name, dialog_type, error_message, accept_input, callback); | |
| 509 gfx::NativeWindow context = ash::Shell::GetPrimaryRootWindow(); | |
| 510 if (chromeos::LoginDisplayHost::default_host()) { | |
| 511 active_window_ = views::DialogDelegate::CreateDialogWidget( | |
| 512 active_pin_dialog_, context, | |
| 513 chromeos::LoginDisplayHost::default_host()->GetNativeWindow()); | |
| 514 active_window_->Show(); | |
| 515 } else { | |
| 516 Browser* browser = chrome::FindTabbedBrowser( | |
| 517 ProfileManager::GetPrimaryUserProfile(), true); | |
| 518 if (browser) { | |
| 519 gfx::NativeWindow native_window = browser->window()->GetNativeWindow(); | |
| 520 active_window_ = views::DialogDelegate::CreateDialogWidget( | |
| 521 active_pin_dialog_, context, native_window); | |
| 522 active_window_->Show(); | |
| 523 } | |
|
stevenjb
2016/08/09 21:04:38
Is this still successful if there is no browser?
igorcov1
2016/08/10 18:05:03
Didn't test it yet, but should be. It's the code t
| |
| 524 } | |
| 525 | |
| 526 return RequestPinResponse::SUCCESS; | |
| 527 } | |
| 528 | |
| 529 bool CertificateProviderService::CloseDialog(const std::string& extension_id) { | |
| 530 if (extension_id != active_dialog_extension_id_ || | |
| 531 active_pin_dialog_ == nullptr) { | |
| 532 LOG(ERROR) << "StopPinRequest called by wrong extension"; | |
| 533 return false; | |
| 534 } | |
| 535 | |
| 536 // Notifying the old callback if present. | |
| 537 active_pin_dialog_->Cancel(); | |
| 538 | |
| 539 // Close the window. |active_pin_dialog_| gets deleted inside Close(). | |
| 540 active_window_->Close(); | |
| 541 active_pin_dialog_ = nullptr; | |
| 542 | |
| 543 return true; | |
| 544 } | |
| 545 | |
| 546 bool CertificateProviderService::AddSignRequestId( | |
| 547 const uint64_t sign_request_id) { | |
| 548 if (sign_request_ids_[sign_request_id]) { | |
| 549 return false; | |
| 550 } | |
| 551 // Cache the ID with current timestamp. | |
| 552 struct timeval tv; | |
| 553 int result = gettimeofday(&tv, NULL); | |
| 554 DCHECK_EQ(0, result); | |
| 555 sign_request_ids_[sign_request_id] = tv.tv_sec; | |
| 556 if (sign_request_ids_.size() > MAX_SIGN_REQUESTS_MAP_SIZE) { | |
| 557 RemoveExpiredSignRequests(&tv); | |
| 558 } | |
| 559 | |
| 560 return true; | |
| 403 } | 561 } |
| 404 | 562 |
| 405 void CertificateProviderService::GetCertificatesFromExtensions( | 563 void CertificateProviderService::GetCertificatesFromExtensions( |
| 406 const base::Callback<void(const net::CertificateList&)>& callback) { | 564 const base::Callback<void(const net::CertificateList&)>& callback) { |
| 407 DCHECK(thread_checker_.CalledOnValidThread()); | 565 DCHECK(thread_checker_.CalledOnValidThread()); |
| 408 | 566 |
| 409 const std::vector<std::string> provider_extensions( | 567 const std::vector<std::string> provider_extensions( |
| 410 delegate_->CertificateProviderExtensions()); | 568 delegate_->CertificateProviderExtensions()); |
| 411 | 569 |
| 412 if (provider_extensions.empty()) { | 570 if (provider_extensions.empty()) { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 469 | 627 |
| 470 const int sign_request_id = sign_requests_.AddRequest(extension_id, callback); | 628 const int sign_request_id = sign_requests_.AddRequest(extension_id, callback); |
| 471 if (!delegate_->DispatchSignRequestToExtension(extension_id, sign_request_id, | 629 if (!delegate_->DispatchSignRequestToExtension(extension_id, sign_request_id, |
| 472 hash, certificate, digest)) { | 630 hash, certificate, digest)) { |
| 473 sign_requests_.RemoveRequest(extension_id, sign_request_id, | 631 sign_requests_.RemoveRequest(extension_id, sign_request_id, |
| 474 nullptr /* callback */); | 632 nullptr /* callback */); |
| 475 callback.Run(net::ERR_FAILED, std::vector<uint8_t>()); | 633 callback.Run(net::ERR_FAILED, std::vector<uint8_t>()); |
| 476 } | 634 } |
| 477 } | 635 } |
| 478 | 636 |
| 637 void CertificateProviderService::RemoveExpiredSignRequests(timeval* tv) { | |
| 638 for (auto it = sign_request_ids_.cbegin(); it != sign_request_ids_.cend();) { | |
| 639 if (tv->tv_sec - it->second > SIGN_REQUEST_ID_TIMEOUT) { | |
| 640 sign_request_ids_.erase(it++); | |
| 641 } else { | |
| 642 ++it; | |
| 643 } | |
| 644 } | |
| 645 } | |
| 646 | |
| 479 } // namespace chromeos | 647 } // namespace chromeos |
| OLD | NEW |