Add domain request detection to incident reporting service.
[chromium-blink-merge.git] / chrome / browser / safe_browsing / srt_fetcher_win.cc
blobbbb40bb7d73f57141585b1bc35b70bbc8bc276cb
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
3 // found in the LICENSE file.
5 #include "chrome/browser/safe_browsing/srt_fetcher_win.h"
7 #include "base/files/file_path.h"
8 #include "base/metrics/field_trial.h"
9 #include "chrome/browser/browser_process.h"
10 #include "chrome/browser/safe_browsing/srt_field_trial_win.h"
11 #include "chrome/browser/safe_browsing/srt_global_error_win.h"
12 #include "chrome/browser/ui/browser_finder.h"
13 #include "chrome/browser/ui/global_error/global_error_service.h"
14 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "net/base/load_flags.h"
17 #include "net/http/http_status_code.h"
18 #include "net/url_request/url_fetcher.h"
19 #include "net/url_request/url_fetcher_delegate.h"
20 #include "net/url_request/url_request_context_getter.h"
22 using content::BrowserThread;
23 using safe_browsing::GetSRTDownloadURL;
25 namespace {
27 void DisplaySRTPrompt(const base::FilePath& download_path) {
28 // Find the last active browser, which may be NULL, in which case we won't
29 // show the prompt this time and will wait until the next run of the
30 // reporter. We can't use other ways of finding a browser because we don't
31 // have a profile.
32 chrome::HostDesktopType desktop_type = chrome::GetActiveDesktop();
33 Browser* browser = chrome::FindLastActiveWithHostDesktopType(desktop_type);
34 if (!browser)
35 return;
37 Profile* profile = browser->profile();
38 DCHECK(profile);
40 // Make sure we have a tabbed browser since we need to anchor the bubble to
41 // the toolbar's wrench menu. Create one if none exist already.
42 if (browser->type() != Browser::TYPE_TABBED) {
43 browser = chrome::FindTabbedBrowser(profile, false, desktop_type);
44 if (!browser)
45 browser = new Browser(Browser::CreateParams(profile, desktop_type));
47 GlobalErrorService* global_error_service =
48 GlobalErrorServiceFactory::GetForProfile(profile);
49 SRTGlobalError* global_error =
50 new SRTGlobalError(global_error_service, download_path);
52 // Ownership of |global_error| is passed to the service. The error removes
53 // itself from the service and self-destructs when done.
54 global_error_service->AddGlobalError(global_error);
56 // Do not try to show bubble if another GlobalError is already showing
57 // one. The bubble will be shown once the others have been dismissed.
58 bool need_to_show_bubble = true;
59 for (GlobalError* error : global_error_service->errors()) {
60 if (error->GetBubbleView()) {
61 need_to_show_bubble = false;
62 break;
65 if (need_to_show_bubble)
66 global_error->ShowBubbleView(browser);
69 // Class that will attempt to download the SRT, showing the SRT notification
70 // bubble when the download operation is complete. Instances of SRTFetcher own
71 // themselves, they will self-delete on completion of the network request when
72 // OnURLFetchComplete is called.
73 class SRTFetcher : public net::URLFetcherDelegate {
74 public:
75 SRTFetcher()
76 : url_fetcher_(net::URLFetcher::Create(0,
77 GURL(GetSRTDownloadURL()),
78 net::URLFetcher::GET,
79 this)) {
80 url_fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE);
81 url_fetcher_->SetMaxRetriesOn5xx(3);
82 url_fetcher_->SaveResponseToTemporaryFile(
83 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
84 url_fetcher_->SetRequestContext(
85 g_browser_process->system_request_context());
86 url_fetcher_->Start();
89 // net::URLFetcherDelegate:
90 void OnURLFetchComplete(const net::URLFetcher* source) override {
91 // Take ownership of the fetcher in this scope (source == url_fetcher_).
92 DCHECK_EQ(url_fetcher_.get(), source);
94 base::FilePath download_path;
95 if (source->GetStatus().is_success() &&
96 source->GetResponseCode() == net::HTTP_OK) {
97 if (source->GetResponseAsFilePath(true, &download_path)) {
98 DCHECK(!download_path.empty());
102 // Even if the fetch could not be completed, still display the prompt. In
103 // this case, the prompt will fall back to visiting the download page.
104 // TODO(mad): Consider implementing another layer of retries / alternate
105 // fetching mechanisms. http://crbug.com/460293
106 // TODO(mad): In the event the browser is closed before the prompt displays,
107 // we will wait until the next scanner run to re-display it.
108 // Improve this. http://crbug.com/460295
109 DisplaySRTPrompt(download_path);
111 // Explicitly destroy the url_fetcher_ to avoid destruction races.
112 url_fetcher_.reset();
114 // At this point, the url_fetcher_ is gone and this SRTFetcher instance is
115 // no longer needed.
116 delete this;
119 private:
120 ~SRTFetcher() override {}
122 // The underlying URL fetcher. The instance is alive from construction through
123 // OnURLFetchComplete.
124 scoped_ptr<net::URLFetcher> url_fetcher_;
126 DISALLOW_COPY_AND_ASSIGN(SRTFetcher);
129 } // namespace
131 namespace safe_browsing {
133 void FetchSRTAndDisplayBubble() {
134 // All the work happens in the self-deleting class above.
135 new SRTFetcher();
138 } // namespace safe_browsing