1d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// found in the LICENSE file. 4a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 6d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "chrome/browser/extensions/api/image_writer_private/error_messages.h" 7d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "chrome/browser/extensions/api/image_writer_private/operation_manager.h" 8d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h" 958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/url_request/url_fetcher.h" 11a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 12a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)namespace extensions { 13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace image_writer { 14a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using content::BrowserThread; 1658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 17d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)WriteFromUrlOperation::WriteFromUrlOperation( 1868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::WeakPtr<OperationManager> manager, 19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const ExtensionId& extension_id, 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) net::URLRequestContextGetter* request_context, 21d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) GURL url, 22d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::string& hash, 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& device_path) 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : Operation(manager, extension_id, device_path), 25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) request_context_(request_context), 2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) url_(url), 2758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) hash_(hash), 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) download_continuation_() {} 29a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 30a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)WriteFromUrlOperation::~WriteFromUrlOperation() { 3158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WriteFromUrlOperation::StartImpl() { 34effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::FILE); 3558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GetDownloadTarget(base::Bind( 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &WriteFromUrlOperation::Download, 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) this, 39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind( 40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &WriteFromUrlOperation::VerifyDownload, 41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) this, 42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind( 43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &WriteFromUrlOperation::Unzip, 44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) this, 45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&WriteFromUrlOperation::Write, 46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) this, 47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&WriteFromUrlOperation::VerifyWrite, 48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) this, 49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&WriteFromUrlOperation::Finish, 50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) this))))))); 5158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 5258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WriteFromUrlOperation::GetDownloadTarget( 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const base::Closure& continuation) { 55effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::FILE); 5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (IsCancelled()) { 5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 5858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 5958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (url_.ExtractFileName() == "") { 61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!base::CreateTemporaryFileInDir(temp_dir_.path(), &image_path_)) { 62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Error(error::kTempFileError); 63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else { 66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::FilePath file_name = 67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::FilePath::FromUTF8Unsafe(url_.ExtractFileName()); 68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) image_path_ = temp_dir_.path().Append(file_name); 6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, continuation); 7258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 7358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WriteFromUrlOperation::Download(const base::Closure& continuation) { 75effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::FILE); 7658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (IsCancelled()) { 7858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 8058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) download_continuation_ = continuation; 8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SetStage(image_writer_api::STAGE_DOWNLOAD); 8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Store the URL fetcher on this object so that it is destroyed before this 86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // object is. 87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) url_fetcher_.reset(net::URLFetcher::Create(url_, net::URLFetcher::GET, this)); 8858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) url_fetcher_->SetRequestContext(request_context_); 90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) url_fetcher_->SaveResponseToFileAtPath( 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) image_path_, 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); 9358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) AddCleanUpFunction( 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&WriteFromUrlOperation::DestroyUrlFetcher, this)); 9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) url_fetcher_->Start(); 9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WriteFromUrlOperation::DestroyUrlFetcher() { url_fetcher_.reset(); } 10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WriteFromUrlOperation::OnURLFetchUploadProgress( 103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const net::URLFetcher* source, 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int64 current, 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int64 total) { 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // No-op 10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WriteFromUrlOperation::OnURLFetchDownloadProgress( 110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const net::URLFetcher* source, 111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int64 current, 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int64 total) { 113effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::FILE); 11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (IsCancelled()) { 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) url_fetcher_.reset(NULL); 11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int progress = (kProgressComplete * current) / total; 12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SetProgress(progress); 12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WriteFromUrlOperation::OnURLFetchComplete(const net::URLFetcher* source) { 125effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::FILE); 12658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (source->GetStatus().is_success() && source->GetResponseCode() == 200) { 128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SetProgress(kProgressComplete); 12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) download_continuation_.Run(); 13168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Remove the reference to ourselves in this closure. 133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) download_continuation_ = base::Closure(); 134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Error(error::kDownloadInterrupted); 13668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 13768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 13868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WriteFromUrlOperation::VerifyDownload(const base::Closure& continuation) { 140effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::FILE); 14168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 14258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (IsCancelled()) { 14358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 14458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 14558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Skip verify if no hash. 14758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (hash_.empty()) { 148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, continuation); 14958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 15058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 15158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 15268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) SetStage(image_writer_api::STAGE_VERIFYDOWNLOAD); 15358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 15458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) GetMD5SumOfFile( 155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) image_path_, 15658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 0, 15758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 0, 15868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) kProgressComplete, 159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind( 160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &WriteFromUrlOperation::VerifyDownloadCompare, this, continuation)); 16158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 16258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 16358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void WriteFromUrlOperation::VerifyDownloadCompare( 164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const base::Closure& continuation, 165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& download_hash) { 166effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::FILE); 167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (download_hash != hash_) { 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Error(error::kDownloadHashError); 16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 17158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 17258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) BrowserThread::PostTask( 17358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) BrowserThread::FILE, 17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) FROM_HERE, 175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind( 176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &WriteFromUrlOperation::VerifyDownloadComplete, this, continuation)); 17758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WriteFromUrlOperation::VerifyDownloadComplete( 180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const base::Closure& continuation) { 181effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::FILE); 18258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (IsCancelled()) { 18358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 18558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 18668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) SetProgress(kProgressComplete); 187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, continuation); 188a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 189a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 190d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} // namespace image_writer 191a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} // namespace extensions 192