1 // Copyright 2014 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/chromeos/customization/customization_wallpaper_downloader.h"
10 #include "base/files/file_util.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "net/base/load_flags.h"
13 #include "net/http/http_status_code.h"
14 #include "net/url_request/url_fetcher.h"
15 #include "net/url_request/url_request_context_getter.h"
20 // This is temporary file suffix (for downloading or resizing).
21 const char kTemporarySuffix
[] = ".tmp";
23 // Sleep between wallpaper retries (used multiplied by squared retry number).
24 const unsigned kRetrySleepSeconds
= 10;
26 // Retry is infinite with increasing intervals. When calculated delay becomes
27 // longer than maximum (kMaxRetrySleepSeconds) it is set to the maximum.
28 const double kMaxRetrySleepSeconds
= 6 * 3600; // 6 hours
30 void CreateWallpaperDirectory(const base::FilePath
& wallpaper_dir
,
32 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
35 *success
= CreateDirectoryAndGetError(wallpaper_dir
, NULL
);
37 NOTREACHED() << "Failed to create directory '" << wallpaper_dir
.value()
42 void RenameTemporaryFile(const base::FilePath
& from
,
43 const base::FilePath
& to
,
45 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
48 base::File::Error error
;
49 if (base::ReplaceFile(from
, to
, &error
)) {
53 << "Failed to rename temporary file of Customized Wallpaper. error="
61 CustomizationWallpaperDownloader::CustomizationWallpaperDownloader(
62 net::URLRequestContextGetter
* url_context_getter
,
63 const GURL
& wallpaper_url
,
64 const base::FilePath
& wallpaper_dir
,
65 const base::FilePath
& wallpaper_downloaded_file
,
66 base::Callback
<void(bool success
, const GURL
&)>
67 on_wallpaper_fetch_completed
)
68 : url_context_getter_(url_context_getter
),
69 wallpaper_url_(wallpaper_url
),
70 wallpaper_dir_(wallpaper_dir
),
71 wallpaper_downloaded_file_(wallpaper_downloaded_file
),
72 wallpaper_temporary_file_(wallpaper_downloaded_file
.value() +
75 retry_delay_(base::TimeDelta::FromSeconds(kRetrySleepSeconds
)),
76 on_wallpaper_fetch_completed_(on_wallpaper_fetch_completed
),
78 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
81 CustomizationWallpaperDownloader::~CustomizationWallpaperDownloader() {
82 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
85 void CustomizationWallpaperDownloader::StartRequest() {
86 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
87 DCHECK(wallpaper_url_
.is_valid());
90 net::URLFetcher::Create(wallpaper_url_
, net::URLFetcher::GET
, this);
91 url_fetcher_
->SetRequestContext(url_context_getter_
.get());
92 url_fetcher_
->SetLoadFlags(net::LOAD_BYPASS_CACHE
|
93 net::LOAD_DISABLE_CACHE
|
94 net::LOAD_DO_NOT_SAVE_COOKIES
|
95 net::LOAD_DO_NOT_SEND_COOKIES
|
96 net::LOAD_DO_NOT_SEND_AUTH_DATA
);
97 base::SequencedWorkerPool
* blocking_pool
=
98 content::BrowserThread::GetBlockingPool();
99 url_fetcher_
->SaveResponseToFileAtPath(
100 wallpaper_temporary_file_
,
101 blocking_pool
->GetSequencedTaskRunner(blocking_pool
->GetSequenceToken()));
102 url_fetcher_
->Start();
105 void CustomizationWallpaperDownloader::Retry() {
106 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
109 const double delay_seconds
= std::min(
110 kMaxRetrySleepSeconds
,
111 static_cast<double>(retries_
) * retries_
* retry_delay_
.InSecondsF());
112 const base::TimeDelta delay
= base::TimeDelta::FromSecondsD(delay_seconds
);
114 VLOG(1) << "Schedule Customized Wallpaper download in " << delay
.InSecondsF()
115 << " seconds (retry = " << retries_
<< ").";
116 retry_current_delay_
= delay
;
117 request_scheduled_
.Start(
118 FROM_HERE
, delay
, this, &CustomizationWallpaperDownloader::StartRequest
);
121 void CustomizationWallpaperDownloader::Start() {
122 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
123 scoped_ptr
<bool> success(new bool(false));
125 base::Closure mkdir_closure
= base::Bind(&CreateWallpaperDirectory
,
127 base::Unretained(success
.get()));
128 base::Closure on_created_closure
=
129 base::Bind(&CustomizationWallpaperDownloader::OnWallpaperDirectoryCreated
,
130 weak_factory_
.GetWeakPtr(),
131 base::Passed(success
.Pass()));
132 if (!content::BrowserThread::PostBlockingPoolTaskAndReply(
133 FROM_HERE
, mkdir_closure
, on_created_closure
)) {
134 LOG(WARNING
) << "Failed to start Customized Wallpaper download.";
138 void CustomizationWallpaperDownloader::OnWallpaperDirectoryCreated(
139 scoped_ptr
<bool> success
) {
140 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
145 void CustomizationWallpaperDownloader::OnURLFetchComplete(
146 const net::URLFetcher
* source
) {
147 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
148 DCHECK_EQ(url_fetcher_
.get(), source
);
150 const net::URLRequestStatus status
= source
->GetStatus();
151 const int response_code
= source
->GetResponseCode();
153 const bool server_error
=
154 !status
.is_success() ||
155 (response_code
>= net::HTTP_INTERNAL_SERVER_ERROR
&&
156 response_code
< (net::HTTP_INTERNAL_SERVER_ERROR
+ 100));
158 VLOG(1) << "CustomizationWallpaperDownloader::OnURLFetchComplete(): status="
162 url_fetcher_
.reset();
167 base::FilePath response_path
;
168 url_fetcher_
->GetResponseAsFilePath(true, &response_path
);
169 url_fetcher_
.reset();
171 scoped_ptr
<bool> success(new bool(false));
173 base::Closure rename_closure
= base::Bind(&RenameTemporaryFile
,
175 wallpaper_downloaded_file_
,
176 base::Unretained(success
.get()));
177 base::Closure on_rename_closure
=
178 base::Bind(&CustomizationWallpaperDownloader::OnTemporaryFileRenamed
,
179 weak_factory_
.GetWeakPtr(),
180 base::Passed(success
.Pass()));
181 if (!content::BrowserThread::PostBlockingPoolTaskAndReply(
182 FROM_HERE
, rename_closure
, on_rename_closure
)) {
184 << "Failed to start Customized Wallpaper Rename DownloadedFile.";
185 on_wallpaper_fetch_completed_
.Run(false, wallpaper_url_
);
189 void CustomizationWallpaperDownloader::OnTemporaryFileRenamed(
190 scoped_ptr
<bool> success
) {
191 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
192 on_wallpaper_fetch_completed_
.Run(*success
, wallpaper_url_
);
195 } // namespace chromeos