1 // Copyright 2013 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 "base/files/file_util.h"
6 #include "chrome/browser/extensions/api/image_writer_private/error_messages.h"
7 #include "chrome/browser/extensions/api/image_writer_private/operation_manager.h"
8 #include "chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h"
9 #include "content/public/browser/browser_thread.h"
10 #include "net/url_request/url_fetcher.h"
12 namespace extensions
{
13 namespace image_writer
{
15 using content::BrowserThread
;
17 WriteFromUrlOperation::WriteFromUrlOperation(
18 base::WeakPtr
<OperationManager
> manager
,
19 const ExtensionId
& extension_id
,
20 net::URLRequestContextGetter
* request_context
,
22 const std::string
& hash
,
23 const std::string
& device_path
)
24 : Operation(manager
, extension_id
, device_path
),
25 request_context_(request_context
),
28 download_continuation_() {}
30 WriteFromUrlOperation::~WriteFromUrlOperation() {
33 void WriteFromUrlOperation::StartImpl() {
34 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
36 GetDownloadTarget(base::Bind(
37 &WriteFromUrlOperation::Download
,
40 &WriteFromUrlOperation::VerifyDownload
,
43 &WriteFromUrlOperation::Unzip
,
45 base::Bind(&WriteFromUrlOperation::Write
,
47 base::Bind(&WriteFromUrlOperation::VerifyWrite
,
49 base::Bind(&WriteFromUrlOperation::Finish
,
53 void WriteFromUrlOperation::GetDownloadTarget(
54 const base::Closure
& continuation
) {
55 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
60 if (url_
.ExtractFileName().empty()) {
61 if (!base::CreateTemporaryFileInDir(temp_dir_
.path(), &image_path_
)) {
62 Error(error::kTempFileError
);
66 base::FilePath file_name
=
67 base::FilePath::FromUTF8Unsafe(url_
.ExtractFileName());
68 image_path_
= temp_dir_
.path().Append(file_name
);
71 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
, continuation
);
74 void WriteFromUrlOperation::Download(const base::Closure
& continuation
) {
75 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
81 download_continuation_
= continuation
;
83 SetStage(image_writer_api::STAGE_DOWNLOAD
);
85 // Store the URL fetcher on this object so that it is destroyed before this
87 url_fetcher_
= net::URLFetcher::Create(url_
, net::URLFetcher::GET
, this);
89 url_fetcher_
->SetRequestContext(request_context_
);
90 url_fetcher_
->SaveResponseToFileAtPath(
92 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
95 base::Bind(&WriteFromUrlOperation::DestroyUrlFetcher
, this));
97 url_fetcher_
->Start();
100 void WriteFromUrlOperation::DestroyUrlFetcher() { url_fetcher_
.reset(); }
102 void WriteFromUrlOperation::OnURLFetchUploadProgress(
103 const net::URLFetcher
* source
,
109 void WriteFromUrlOperation::OnURLFetchDownloadProgress(
110 const net::URLFetcher
* source
,
113 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
116 url_fetcher_
.reset(NULL
);
119 int progress
= (kProgressComplete
* current
) / total
;
121 SetProgress(progress
);
124 void WriteFromUrlOperation::OnURLFetchComplete(const net::URLFetcher
* source
) {
125 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
127 if (source
->GetStatus().is_success() && source
->GetResponseCode() == 200) {
128 SetProgress(kProgressComplete
);
130 download_continuation_
.Run();
132 // Remove the reference to ourselves in this closure.
133 download_continuation_
= base::Closure();
135 Error(error::kDownloadInterrupted
);
139 void WriteFromUrlOperation::VerifyDownload(const base::Closure
& continuation
) {
140 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
146 // Skip verify if no hash.
148 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
, continuation
);
152 SetStage(image_writer_api::STAGE_VERIFYDOWNLOAD
);
160 &WriteFromUrlOperation::VerifyDownloadCompare
, this, continuation
));
163 void WriteFromUrlOperation::VerifyDownloadCompare(
164 const base::Closure
& continuation
,
165 const std::string
& download_hash
) {
166 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
167 if (download_hash
!= hash_
) {
168 Error(error::kDownloadHashError
);
172 BrowserThread::PostTask(
176 &WriteFromUrlOperation::VerifyDownloadComplete
, this, continuation
));
179 void WriteFromUrlOperation::VerifyDownloadComplete(
180 const base::Closure
& continuation
) {
181 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
186 SetProgress(kProgressComplete
);
187 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
, continuation
);
190 } // namespace image_writer
191 } // namespace extensions