| 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/safe_browsing/chrome_cleaner/reporter_runner_win.h" | 5 #include "chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_win.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <memory> | 10 #include <memory> |
| 11 #include <utility> | 11 #include <utility> |
| 12 #include <vector> | 12 #include <vector> |
| 13 | 13 |
| 14 #include "base/bind.h" | 14 #include "base/bind.h" |
| 15 #include "base/bind_helpers.h" | 15 #include "base/bind_helpers.h" |
| 16 #include "base/callback_helpers.h" | 16 #include "base/callback_helpers.h" |
| 17 #include "base/command_line.h" | 17 #include "base/command_line.h" |
| 18 #include "base/debug/leak_annotations.h" | 18 #include "base/debug/leak_annotations.h" |
| 19 #include "base/files/file_path.h" | 19 #include "base/files/file_path.h" |
| 20 #include "base/macros.h" | 20 #include "base/macros.h" |
| 21 #include "base/memory/ptr_util.h" | 21 #include "base/memory/ptr_util.h" |
| 22 #include "base/metrics/field_trial.h" | 22 #include "base/metrics/field_trial.h" |
| 23 #include "base/metrics/histogram_macros.h" | 23 #include "base/metrics/histogram_macros.h" |
| 24 #include "base/metrics/sparse_histogram.h" | 24 #include "base/metrics/sparse_histogram.h" |
| 25 #include "base/process/launch.h" |
| 26 #include "base/process/process.h" |
| 25 #include "base/strings/string_number_conversions.h" | 27 #include "base/strings/string_number_conversions.h" |
| 26 #include "base/strings/stringprintf.h" | 28 #include "base/strings/stringprintf.h" |
| 27 #include "base/strings/utf_string_conversions.h" | 29 #include "base/strings/utf_string_conversions.h" |
| 28 #include "base/task_runner_util.h" | 30 #include "base/task_runner_util.h" |
| 29 #include "base/task_scheduler/post_task.h" | 31 #include "base/task_scheduler/post_task.h" |
| 30 #include "base/task_scheduler/task_traits.h" | 32 #include "base/task_scheduler/task_traits.h" |
| 31 #include "base/time/time.h" | |
| 32 #include "base/version.h" | 33 #include "base/version.h" |
| 33 #include "base/win/registry.h" | 34 #include "base/win/registry.h" |
| 34 #include "chrome/browser/browser_process.h" | 35 #include "chrome/browser/browser_process.h" |
| 35 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" | 36 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" |
| 36 #include "chrome/browser/profiles/profile.h" | 37 #include "chrome/browser/profiles/profile.h" |
| 37 #include "chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_fetcher_win
.h" | 38 #include "chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_fetcher_win
.h" |
| 38 #include "chrome/browser/safe_browsing/chrome_cleaner/srt_chrome_prompt_impl.h" | |
| 39 #include "chrome/browser/safe_browsing/chrome_cleaner/srt_client_info_win.h" | 39 #include "chrome/browser/safe_browsing/chrome_cleaner/srt_client_info_win.h" |
| 40 #include "chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.h" |
| 40 #include "chrome/browser/safe_browsing/chrome_cleaner/srt_global_error_win.h" | 41 #include "chrome/browser/safe_browsing/chrome_cleaner/srt_global_error_win.h" |
| 41 #include "chrome/browser/ui/browser_finder.h" | 42 #include "chrome/browser/ui/browser_finder.h" |
| 42 #include "chrome/browser/ui/browser_list.h" | 43 #include "chrome/browser/ui/browser_list.h" |
| 43 #include "chrome/browser/ui/browser_list_observer.h" | 44 #include "chrome/browser/ui/browser_list_observer.h" |
| 44 #include "chrome/browser/ui/global_error/global_error_service.h" | 45 #include "chrome/browser/ui/global_error/global_error_service.h" |
| 45 #include "chrome/browser/ui/global_error/global_error_service_factory.h" | 46 #include "chrome/browser/ui/global_error/global_error_service_factory.h" |
| 46 #include "chrome/common/pref_names.h" | 47 #include "chrome/common/pref_names.h" |
| 47 #include "components/chrome_cleaner/public/constants/constants.h" | 48 #include "components/chrome_cleaner/public/constants/constants.h" |
| 48 #include "components/component_updater/pref_names.h" | 49 #include "components/component_updater/pref_names.h" |
| 49 #include "components/prefs/pref_service.h" | 50 #include "components/prefs/pref_service.h" |
| 50 #include "components/version_info/version_info.h" | 51 #include "components/version_info/version_info.h" |
| 51 #include "content/public/browser/browser_thread.h" | 52 #include "content/public/browser/browser_thread.h" |
| 52 #include "mojo/edk/embedder/connection_params.h" | |
| 53 #include "mojo/edk/embedder/outgoing_broker_client_invitation.h" | |
| 54 #include "mojo/edk/embedder/platform_channel_pair.h" | |
| 55 #include "mojo/public/cpp/system/message_pipe.h" | |
| 56 #include "net/http/http_status_code.h" | 53 #include "net/http/http_status_code.h" |
| 57 | 54 |
| 58 using content::BrowserThread; | 55 using content::BrowserThread; |
| 59 | 56 |
| 60 namespace safe_browsing { | 57 namespace safe_browsing { |
| 61 | 58 |
| 62 const base::Feature kInBrowserCleanerUIFeature{ | |
| 63 "InBrowserCleanerUI", base::FEATURE_DISABLED_BY_DEFAULT}; | |
| 64 | |
| 65 namespace { | 59 namespace { |
| 66 | 60 |
| 67 // Used to send UMA information about missing start and end time registry | 61 // Used to send UMA information about missing start and end time registry |
| 68 // values for the reporter. Replicated in the histograms.xml file, so the order | 62 // values for the reporter. Replicated in the histograms.xml file, so the order |
| 69 // MUST NOT CHANGE. | 63 // MUST NOT CHANGE. |
| 70 enum SwReporterRunningTimeRegistryError { | 64 enum SwReporterRunningTimeRegistryError { |
| 71 REPORTER_RUNNING_TIME_ERROR_NO_ERROR = 0, | 65 REPORTER_RUNNING_TIME_ERROR_NO_ERROR = 0, |
| 72 REPORTER_RUNNING_TIME_ERROR_REGISTRY_KEY_INVALID = 1, | 66 REPORTER_RUNNING_TIME_ERROR_REGISTRY_KEY_INVALID = 1, |
| 73 REPORTER_RUNNING_TIME_ERROR_MISSING_START_TIME = 2, | 67 REPORTER_RUNNING_TIME_ERROR_MISSING_START_TIME = 2, |
| 74 REPORTER_RUNNING_TIME_ERROR_MISSING_END_TIME = 3, | 68 REPORTER_RUNNING_TIME_ERROR_MISSING_END_TIME = 3, |
| (...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 543 if (error->GetBubbleView()) { | 537 if (error->GetBubbleView()) { |
| 544 show_bubble = false; | 538 show_bubble = false; |
| 545 break; | 539 break; |
| 546 } | 540 } |
| 547 } | 541 } |
| 548 } | 542 } |
| 549 if (show_bubble) | 543 if (show_bubble) |
| 550 global_error->ShowBubbleView(browser); | 544 global_error->ShowBubbleView(browser); |
| 551 } | 545 } |
| 552 | 546 |
| 553 // Handles the case when the remote end has been closed, by performing the | 547 // This function is called from a worker thread to launch the SwReporter and |
| 554 // necessary cleanups if the prompt dialog is being shown to the user. | 548 // wait for termination to collect its exit code. This task could be |
| 555 void OnConnectionClosed() { | 549 // interrupted by a shutdown at any time, so it shouldn't depend on anything |
| 556 // Placeholder. This should handle cases when the reporter process is | 550 // external that could be shut down beforehand. |
| 557 // disconnected (e.g. due to a crash) and the prompt dialog is being shown | 551 int LaunchAndWaitForExitOnBackgroundThread( |
| 558 // to the user. | 552 const SwReporterInvocation& invocation) { |
| 559 } | 553 if (g_testing_delegate_) |
| 560 | 554 return g_testing_delegate_->LaunchReporter(invocation); |
| 561 // Handles the case when a mojo::ReportBadMessage has been explicitly reported. | |
| 562 void OnConnectionError(const std::string& message) { | |
| 563 // Placeholder. This should handle cases when the reporter process sends | |
| 564 // a bad message and the prompt dialog is being shown to the user. | |
| 565 } | |
| 566 | |
| 567 // Class responsible for launching the reporter process and waiting for its | |
| 568 // completion. If feature InBrowserCleanerUI is enabled, this object will also | |
| 569 // be responsible for starting the ChromePromptImpl object on the IO thread and | |
| 570 // controlling its lifetime. | |
| 571 // | |
| 572 // Expected lifecycle of a SwReporterProcess: | |
| 573 // - created on the UI thread before the reporter process launch is posted | |
| 574 // (method ScheduleNextInvocation); | |
| 575 // - deleted on the UI thread once ReporterDone() finishes (the method is | |
| 576 // called after the reporter process exits). | |
| 577 // | |
| 578 // If feature InBrowserCleanerUI feature is enabled, the following tasks will | |
| 579 // be posted in sequence to the IO Thread and will retain the SwReporterProcess | |
| 580 // object: | |
| 581 // - creation of a ChromePromptImpl object right after the reporter process is | |
| 582 // launched (that object will be responsible for handling IPC requests from | |
| 583 // the reporter process); | |
| 584 // - deletion of the ChromePromptImpl object on ReporterDone(). | |
| 585 // As a consequence, the SwReporterProcess object can outlive ReporterDone() | |
| 586 // and will only be deleted after the ChromePromptImpl object is released on | |
| 587 // the IO thread. | |
| 588 class SwReporterProcess : public base::RefCountedThreadSafe<SwReporterProcess> { | |
| 589 public: | |
| 590 explicit SwReporterProcess(const SwReporterInvocation& invocation) | |
| 591 : invocation_(invocation) {} | |
| 592 | |
| 593 // This function is called from a worker thread to launch the SwReporter and | |
| 594 // wait for termination to collect its exit code. This task could be | |
| 595 // interrupted by a shutdown at any time, so it shouldn't depend on anything | |
| 596 // external that could be shut down beforehand. | |
| 597 int LaunchAndWaitForExitOnBackgroundThread(); | |
| 598 | |
| 599 // Schedules to release the instance of ChromePromptImpl on the IO thread. | |
| 600 void OnReporterDone(); | |
| 601 | |
| 602 const SwReporterInvocation& invocation() const { return invocation_; } | |
| 603 | |
| 604 private: | |
| 605 friend class base::RefCountedThreadSafe<SwReporterProcess>; | |
| 606 ~SwReporterProcess() = default; | |
| 607 | |
| 608 // Starts a new IPC service implementing the ChromePrompt interface and | |
| 609 // launches a new reporter process that can connect to the IPC. | |
| 610 base::Process LaunchConnectedReporterProcess(); | |
| 611 | |
| 612 // Starts a new instance of ChromePromptImpl to receive requests from the | |
| 613 // reporter and establishes the mojo connection to it. | |
| 614 // Must be run on the IO thread. | |
| 615 void CreateChromePromptImpl( | |
| 616 chrome_cleaner::mojom::ChromePromptRequest chrome_prompt_request); | |
| 617 | |
| 618 // Releases the instance of ChromePromptImpl. Must be run on the IO thread. | |
| 619 void ReleaseChromePromptImpl(); | |
| 620 | |
| 621 // Launches a new process with the command line in the invocation and | |
| 622 // provided launch options. Uses g_testing_delegate_ if not null. | |
| 623 base::Process LaunchReporterProcess( | |
| 624 const SwReporterInvocation& invocation, | |
| 625 const base::LaunchOptions& launch_options); | |
| 626 | |
| 627 // The invocation for the current reporter process. | |
| 628 SwReporterInvocation invocation_; | |
| 629 | |
| 630 // Implementation of the ChromePrompt service to be used by the current | |
| 631 // reporter process. Can only be accessed on the IO thread. | |
| 632 std::unique_ptr<ChromePromptImpl> chrome_prompt_impl_; | |
| 633 }; | |
| 634 | |
| 635 int SwReporterProcess::LaunchAndWaitForExitOnBackgroundThread() { | |
| 636 base::Process reporter_process = | 555 base::Process reporter_process = |
| 637 base::FeatureList::IsEnabled(kInBrowserCleanerUIFeature) | 556 base::LaunchProcess(invocation.command_line, base::LaunchOptions()); |
| 638 ? LaunchConnectedReporterProcess() | |
| 639 : LaunchReporterProcess(invocation_, base::LaunchOptions()); | |
| 640 | |
| 641 // This exit code is used to identify that a reporter run didn't happen, so | 557 // This exit code is used to identify that a reporter run didn't happen, so |
| 642 // the result should be ignored and a rerun scheduled for the usual delay. | 558 // the result should be ignored and a rerun scheduled for the usual delay. |
| 643 int exit_code = kReporterNotLaunchedExitCode; | 559 int exit_code = kReporterNotLaunchedExitCode; |
| 644 UMAHistogramReporter uma(invocation_.suffix); | 560 UMAHistogramReporter uma(invocation.suffix); |
| 645 if (reporter_process.IsValid()) { | 561 if (reporter_process.IsValid()) { |
| 646 uma.RecordReporterStep(SW_REPORTER_START_EXECUTION); | 562 uma.RecordReporterStep(SW_REPORTER_START_EXECUTION); |
| 647 bool success = reporter_process.WaitForExit(&exit_code); | 563 bool success = reporter_process.WaitForExit(&exit_code); |
| 648 DCHECK(success); | 564 DCHECK(success); |
| 649 } else { | 565 } else { |
| 650 uma.RecordReporterStep(SW_REPORTER_FAILED_TO_START); | 566 uma.RecordReporterStep(SW_REPORTER_FAILED_TO_START); |
| 651 } | 567 } |
| 652 return exit_code; | 568 return exit_code; |
| 653 } | 569 } |
| 654 | 570 |
| 655 void SwReporterProcess::OnReporterDone() { | |
| 656 if (base::FeatureList::IsEnabled(kInBrowserCleanerUIFeature)) { | |
| 657 BrowserThread::GetTaskRunnerForThread(BrowserThread::IO) | |
| 658 ->PostTask(FROM_HERE, | |
| 659 base::Bind(&SwReporterProcess::ReleaseChromePromptImpl, | |
| 660 base::RetainedRef(this))); | |
| 661 } | |
| 662 } | |
| 663 | |
| 664 base::Process SwReporterProcess::LaunchConnectedReporterProcess() { | |
| 665 DCHECK(base::FeatureList::IsEnabled(kInBrowserCleanerUIFeature)); | |
| 666 | |
| 667 mojo::edk::OutgoingBrokerClientInvitation invitation; | |
| 668 std::string mojo_pipe_token = mojo::edk::GenerateRandomToken(); | |
| 669 mojo::ScopedMessagePipeHandle mojo_pipe = | |
| 670 invitation.AttachMessagePipe(mojo_pipe_token); | |
| 671 invocation_.command_line.AppendSwitchASCII( | |
| 672 chrome_cleaner::kChromeMojoPipeTokenSwitch, mojo_pipe_token); | |
| 673 invocation_.command_line.AppendSwitchASCII( | |
| 674 chrome_cleaner::kExecutionModeSwitch, | |
| 675 base::IntToString( | |
| 676 static_cast<int>(chrome_cleaner::ExecutionMode::kScanning))); | |
| 677 | |
| 678 mojo::edk::PlatformChannelPair channel; | |
| 679 base::HandlesToInheritVector handles_to_inherit; | |
| 680 channel.PrepareToPassClientHandleToChildProcess(&invocation_.command_line, | |
| 681 &handles_to_inherit); | |
| 682 | |
| 683 base::LaunchOptions launch_options; | |
| 684 launch_options.handles_to_inherit = &handles_to_inherit; | |
| 685 base::Process reporter_process = | |
| 686 LaunchReporterProcess(invocation_, launch_options); | |
| 687 | |
| 688 if (!reporter_process.IsValid()) | |
| 689 return reporter_process; | |
| 690 | |
| 691 // ChromePromptImpl tasks will need to run on the IO thread. There is no | |
| 692 // need to synchronize its creation, since the client end will wait for this | |
| 693 // initialization to be done before sending requests. | |
| 694 BrowserThread::GetTaskRunnerForThread(BrowserThread::IO) | |
| 695 ->PostTask(FROM_HERE, | |
| 696 base::BindOnce(&SwReporterProcess::CreateChromePromptImpl, | |
| 697 base::RetainedRef(this), | |
| 698 chrome_cleaner::mojom::ChromePromptRequest( | |
| 699 std::move(mojo_pipe)))); | |
| 700 | |
| 701 mojo::edk::ProcessErrorCallback on_connection_error = | |
| 702 g_testing_delegate_ | |
| 703 ? base::Bind(&SwReporterTestingDelegate::OnConnectionError, | |
| 704 base::Unretained(g_testing_delegate_)) | |
| 705 : base::Bind(&OnConnectionError); | |
| 706 invitation.Send( | |
| 707 reporter_process.Handle(), | |
| 708 mojo::edk::ConnectionParams(mojo::edk::TransportProtocol::kLegacy, | |
| 709 channel.PassServerHandle()), | |
| 710 on_connection_error); | |
| 711 | |
| 712 return reporter_process; | |
| 713 } | |
| 714 | |
| 715 base::Process SwReporterProcess::LaunchReporterProcess( | |
| 716 const SwReporterInvocation& invocation, | |
| 717 const base::LaunchOptions& launch_options) { | |
| 718 return g_testing_delegate_ | |
| 719 ? g_testing_delegate_->LaunchReporter(invocation, launch_options) | |
| 720 : base::LaunchProcess(invocation.command_line, launch_options); | |
| 721 } | |
| 722 | |
| 723 void SwReporterProcess::CreateChromePromptImpl( | |
| 724 chrome_cleaner::mojom::ChromePromptRequest chrome_prompt_request) { | |
| 725 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 726 DCHECK(base::FeatureList::IsEnabled(kInBrowserCleanerUIFeature)); | |
| 727 | |
| 728 chrome_prompt_impl_ = | |
| 729 g_testing_delegate_ | |
| 730 ? g_testing_delegate_->CreateChromePromptImpl( | |
| 731 std::move(chrome_prompt_request)) | |
| 732 : base::MakeUnique<ChromePromptImpl>(std::move(chrome_prompt_request), | |
| 733 base::Bind(&OnConnectionClosed)); | |
| 734 } | |
| 735 | |
| 736 void SwReporterProcess::ReleaseChromePromptImpl() { | |
| 737 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 738 DCHECK(base::FeatureList::IsEnabled(kInBrowserCleanerUIFeature)); | |
| 739 | |
| 740 chrome_prompt_impl_.release(); | |
| 741 } | |
| 742 | |
| 743 } // namespace | 571 } // namespace |
| 744 | 572 |
| 745 void DisplaySRTPromptForTesting(const base::FilePath& download_path) { | 573 void DisplaySRTPromptForTesting(const base::FilePath& download_path) { |
| 746 DisplaySRTPrompt(download_path, net::HTTP_OK); | 574 DisplaySRTPrompt(download_path, net::HTTP_OK); |
| 747 } | 575 } |
| 748 | 576 |
| 749 namespace { | 577 namespace { |
| 750 | 578 |
| 751 // Try to fetch the SRT, and on success, show the prompt to run it. | 579 // Try to fetch the SRT, and on success, show the prompt to run it. |
| 752 void MaybeFetchSRT(Browser* browser, const base::Version& reporter_version) { | 580 void MaybeFetchSRT(Browser* browser, const base::Version& reporter_version) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 778 prefs->SetString(prefs::kSwReporterPromptSeed, incoming_seed); | 606 prefs->SetString(prefs::kSwReporterPromptSeed, incoming_seed); |
| 779 // Forget about pending prompts if prompt seed has changed. | 607 // Forget about pending prompts if prompt seed has changed. |
| 780 if (local_state) | 608 if (local_state) |
| 781 local_state->SetBoolean(prefs::kSwReporterPendingPrompt, false); | 609 local_state->SetBoolean(prefs::kSwReporterPendingPrompt, false); |
| 782 } | 610 } |
| 783 prefs->SetString(prefs::kSwReporterPromptVersion, | 611 prefs->SetString(prefs::kSwReporterPromptVersion, |
| 784 reporter_version.GetString()); | 612 reporter_version.GetString()); |
| 785 | 613 |
| 786 // Download the SRT. | 614 // Download the SRT. |
| 787 RecordReporterStepHistogram(SW_REPORTER_DOWNLOAD_START); | 615 RecordReporterStepHistogram(SW_REPORTER_DOWNLOAD_START); |
| 788 | |
| 789 // All the work happens in the self-deleting class below. | |
| 790 FetchChromeCleaner(base::Bind(DisplaySRTPrompt)); | 616 FetchChromeCleaner(base::Bind(DisplaySRTPrompt)); |
| 791 } | 617 } |
| 792 | 618 |
| 793 base::Time Now() { | 619 base::Time Now() { |
| 794 return g_testing_delegate_ ? g_testing_delegate_->Now() : base::Time::Now(); | 620 return g_testing_delegate_ ? g_testing_delegate_->Now() : base::Time::Now(); |
| 795 } | 621 } |
| 796 | 622 |
| 797 } // namespace | 623 } // namespace |
| 798 | 624 |
| 799 // This class tries to run a queue of reporters and react to their exit codes. | 625 // This class tries to run a queue of reporters and react to their exit codes. |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 844 void ScheduleNextInvocation() { | 670 void ScheduleNextInvocation() { |
| 845 DCHECK(!current_invocations_.empty()); | 671 DCHECK(!current_invocations_.empty()); |
| 846 auto next_invocation = current_invocations_.front(); | 672 auto next_invocation = current_invocations_.front(); |
| 847 current_invocations_.pop(); | 673 current_invocations_.pop(); |
| 848 | 674 |
| 849 AppendInvocationSpecificSwitches(&next_invocation); | 675 AppendInvocationSpecificSwitches(&next_invocation); |
| 850 | 676 |
| 851 base::TaskRunner* task_runner = | 677 base::TaskRunner* task_runner = |
| 852 g_testing_delegate_ ? g_testing_delegate_->BlockingTaskRunner() | 678 g_testing_delegate_ ? g_testing_delegate_->BlockingTaskRunner() |
| 853 : blocking_task_runner_.get(); | 679 : blocking_task_runner_.get(); |
| 854 auto sw_reporter_process = | |
| 855 make_scoped_refptr(new SwReporterProcess(next_invocation)); | |
| 856 auto launch_and_wait = | 680 auto launch_and_wait = |
| 857 base::Bind(&SwReporterProcess::LaunchAndWaitForExitOnBackgroundThread, | 681 base::Bind(&LaunchAndWaitForExitOnBackgroundThread, next_invocation); |
| 858 sw_reporter_process); | |
| 859 auto reporter_done = | 682 auto reporter_done = |
| 860 base::Bind(&ReporterRunner::ReporterDone, base::Unretained(this), Now(), | 683 base::Bind(&ReporterRunner::ReporterDone, base::Unretained(this), Now(), |
| 861 version_, std::move(sw_reporter_process)); | 684 version_, next_invocation); |
| 862 base::PostTaskAndReplyWithResult(task_runner, FROM_HERE, | 685 base::PostTaskAndReplyWithResult(task_runner, FROM_HERE, |
| 863 std::move(launch_and_wait), | 686 std::move(launch_and_wait), |
| 864 std::move(reporter_done)); | 687 std::move(reporter_done)); |
| 865 } | 688 } |
| 866 | 689 |
| 867 // This method is called on the UI thread when an invocation of the reporter | 690 // This method is called on the UI thread when an invocation of the reporter |
| 868 // has completed. This is run as a task posted from an interruptible worker | 691 // has completed. This is run as a task posted from an interruptible worker |
| 869 // thread so should be resilient to unexpected shutdown. | 692 // thread so should be resilient to unexpected shutdown. |
| 870 void ReporterDone(const base::Time& reporter_start_time, | 693 void ReporterDone(const base::Time& reporter_start_time, |
| 871 const base::Version& version, | 694 const base::Version& version, |
| 872 scoped_refptr<SwReporterProcess> sw_reporter_process, | 695 const SwReporterInvocation& finished_invocation, |
| 873 int exit_code) { | 696 int exit_code) { |
| 874 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 697 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 875 | 698 |
| 876 sw_reporter_process->OnReporterDone(); | |
| 877 | |
| 878 base::Time now = Now(); | 699 base::Time now = Now(); |
| 879 base::TimeDelta reporter_running_time = now - reporter_start_time; | 700 base::TimeDelta reporter_running_time = now - reporter_start_time; |
| 880 | 701 |
| 881 // Don't continue the current queue of reporters if one failed to launch. | 702 // Don't continue the current queue of reporters if one failed to launch. |
| 882 if (exit_code == kReporterNotLaunchedExitCode) | 703 if (exit_code == kReporterNotLaunchedExitCode) |
| 883 current_invocations_ = SwReporterQueue(); | 704 current_invocations_ = SwReporterQueue(); |
| 884 | 705 |
| 885 // As soon as we're not running this queue, schedule the next overall queue | 706 // As soon as we're not running this queue, schedule the next overall queue |
| 886 // run after the regular delay. (If there was a failure it's not worth | 707 // run after the regular delay. (If there was a failure it's not worth |
| 887 // retrying earlier, risking running too often if it always fails, since | 708 // retrying earlier, risking running too often if it always fails, since |
| 888 // not many users fail here.) | 709 // not many users fail here.) |
| 889 if (current_invocations_.empty()) { | 710 if (current_invocations_.empty()) { |
| 890 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 711 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 891 FROM_HERE, | 712 FROM_HERE, |
| 892 base::Bind(&ReporterRunner::TryToRun, base::Unretained(this)), | 713 base::Bind(&ReporterRunner::TryToRun, base::Unretained(this)), |
| 893 base::TimeDelta::FromDays(days_between_reporter_runs_)); | 714 base::TimeDelta::FromDays(days_between_reporter_runs_)); |
| 894 } else { | 715 } else { |
| 895 ScheduleNextInvocation(); | 716 ScheduleNextInvocation(); |
| 896 } | 717 } |
| 897 | 718 |
| 898 // If the reporter failed to launch, do not process the results. (The exit | 719 // If the reporter failed to launch, do not process the results. (The exit |
| 899 // code itself doesn't need to be logged in this case because | 720 // code itself doesn't need to be logged in this case because |
| 900 // SW_REPORTER_FAILED_TO_START is logged in | 721 // SW_REPORTER_FAILED_TO_START is logged in |
| 901 // |LaunchAndWaitForExitOnBackgroundThread|.) | 722 // |LaunchAndWaitForExitOnBackgroundThread|.) |
| 902 if (exit_code == kReporterNotLaunchedExitCode) | 723 if (exit_code == kReporterNotLaunchedExitCode) |
| 903 return; | 724 return; |
| 904 | 725 |
| 905 const auto& finished_invocation = sw_reporter_process->invocation(); | |
| 906 UMAHistogramReporter uma(finished_invocation.suffix); | 726 UMAHistogramReporter uma(finished_invocation.suffix); |
| 907 uma.ReportVersion(version); | 727 uma.ReportVersion(version); |
| 908 uma.ReportExitCode(exit_code); | 728 uma.ReportExitCode(exit_code); |
| 909 uma.ReportEngineErrorCode(); | 729 uma.ReportEngineErrorCode(); |
| 910 uma.ReportFoundUwS(); | 730 uma.ReportFoundUwS(); |
| 911 | 731 |
| 912 PrefService* local_state = g_browser_process->local_state(); | 732 PrefService* local_state = g_browser_process->local_state(); |
| 913 if (local_state) { | 733 if (local_state) { |
| 914 if (finished_invocation.BehaviourIsSupported( | 734 if (finished_invocation.BehaviourIsSupported( |
| 915 SwReporterInvocation::BEHAVIOUR_LOG_EXIT_CODE_TO_PREFS)) { | 735 SwReporterInvocation::BEHAVIOUR_LOG_EXIT_CODE_TO_PREFS)) { |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1167 return srt_cleaner_key.Open(HKEY_CURRENT_USER, cleaner_key_path.c_str(), | 987 return srt_cleaner_key.Open(HKEY_CURRENT_USER, cleaner_key_path.c_str(), |
| 1168 KEY_QUERY_VALUE) == ERROR_SUCCESS && | 988 KEY_QUERY_VALUE) == ERROR_SUCCESS && |
| 1169 srt_cleaner_key.GetValueCount() > 0; | 989 srt_cleaner_key.GetValueCount() > 0; |
| 1170 } | 990 } |
| 1171 | 991 |
| 1172 void SetSwReporterTestingDelegate(SwReporterTestingDelegate* delegate) { | 992 void SetSwReporterTestingDelegate(SwReporterTestingDelegate* delegate) { |
| 1173 g_testing_delegate_ = delegate; | 993 g_testing_delegate_ = delegate; |
| 1174 } | 994 } |
| 1175 | 995 |
| 1176 } // namespace safe_browsing | 996 } // namespace safe_browsing |
| OLD | NEW |