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
;
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
32 chrome::HostDesktopType desktop_type
= chrome::GetActiveDesktop();
33 Browser
* browser
= chrome::FindLastActiveWithHostDesktopType(desktop_type
);
37 Profile
* profile
= browser
->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
);
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;
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
{
76 : url_fetcher_(net::URLFetcher::Create(0,
77 GURL(GetSRTDownloadURL()),
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
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
);
131 namespace safe_browsing
{
133 void FetchSRTAndDisplayBubble() {
134 // All the work happens in the self-deleting class above.
138 } // namespace safe_browsing