diff --git a/atom/browser/net/asar/asar_protocol_handler.cc b/atom/browser/net/asar/asar_protocol_handler.cc index a1cbfd7f7e8a..69df5367b9dc 100644 --- a/atom/browser/net/asar/asar_protocol_handler.cc +++ b/atom/browser/net/asar/asar_protocol_handler.cc @@ -5,7 +5,11 @@ #include "atom/browser/net/asar/asar_protocol_handler.h" #include "atom/browser/net/asar/url_request_asar_job.h" +#include "atom/common/asar/archive.h" +#include "base/stl_util.h" #include "net/base/filename_util.h" +#include "net/base/net_errors.h" +#include "net/url_request/url_request_error_job.h" #include "net/url_request/url_request_file_job.h" namespace asar { @@ -51,14 +55,24 @@ net::URLRequestJob* AsarProtocolHandler::MaybeCreateJob( base::FilePath full_path; net::FileURLToFilePath(request->url(), &full_path); - // Create asar:// job when the path contains "xxx.asar/". + // Create asar:// job when the path contains "xxx.asar/", otherwise treat the + // URL request as file://. base::FilePath asar_path, relative_path; - if (GetAsarPath(full_path, &asar_path, &relative_path)) - return new URLRequestAsarJob(request, network_delegate, asar_path, - relative_path, file_task_runner_); - else + if (!GetAsarPath(full_path, &asar_path, &relative_path)) return new net::URLRequestFileJob(request, network_delegate, full_path, file_task_runner_); + + // Create a cache of Archive. + if (!ContainsKey(archives_, asar_path)) { + scoped_refptr archive(new Archive(asar_path)); + if (!archive->Init()) + return new net::URLRequestErrorJob(request, network_delegate, + net::ERR_FILE_NOT_FOUND); + archives_[asar_path] = archive; + } + + return new URLRequestAsarJob(request, network_delegate, archives_[asar_path], + relative_path, file_task_runner_); } bool AsarProtocolHandler::IsSafeRedirectTarget(const GURL& location) const { diff --git a/atom/browser/net/asar/asar_protocol_handler.h b/atom/browser/net/asar/asar_protocol_handler.h index bdf26e064452..24d8cc991380 100644 --- a/atom/browser/net/asar/asar_protocol_handler.h +++ b/atom/browser/net/asar/asar_protocol_handler.h @@ -5,6 +5,8 @@ #ifndef ATOM_BROWSER_NET_ASAR_ASAR_PROTOCOL_HANDLER_H_ #define ATOM_BROWSER_NET_ASAR_ASAR_PROTOCOL_HANDLER_H_ +#include "base/containers/hash_tables.h" +#include "base/files/file_path.h" #include "base/memory/ref_counted.h" #include "net/url_request/url_request_job_factory.h" @@ -14,6 +16,8 @@ class TaskRunner; namespace asar { +class Archive; + class AsarProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler { public: explicit AsarProtocolHandler( @@ -29,6 +33,9 @@ class AsarProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler { private: const scoped_refptr file_task_runner_; + mutable base::hash_map > archives_; + DISALLOW_COPY_AND_ASSIGN(AsarProtocolHandler); }; diff --git a/atom/browser/net/asar/url_request_asar_job.cc b/atom/browser/net/asar/url_request_asar_job.cc index a4875a145fd1..99c4abd7c44e 100644 --- a/atom/browser/net/asar/url_request_asar_job.cc +++ b/atom/browser/net/asar/url_request_asar_job.cc @@ -17,11 +17,11 @@ namespace asar { URLRequestAsarJob::URLRequestAsarJob( net::URLRequest* request, net::NetworkDelegate* network_delegate, - const base::FilePath& asar_path, + const scoped_refptr& archive, const base::FilePath& file_path, const scoped_refptr& file_task_runner) : net::URLRequestJob(request, network_delegate), - archive_(asar_path), + archive_(archive), file_path_(file_path), stream_(new net::FileStream(file_task_runner)), remaining_bytes_(0), @@ -31,7 +31,7 @@ URLRequestAsarJob::URLRequestAsarJob( URLRequestAsarJob::~URLRequestAsarJob() {} void URLRequestAsarJob::Start() { - if (!archive_.Init() || !archive_.GetFileInfo(file_path_, &file_info_)) { + if (!archive_->GetFileInfo(file_path_, &file_info_)) { NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FILE_NOT_FOUND)); return; @@ -42,7 +42,7 @@ void URLRequestAsarJob::Start() { int flags = base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_ASYNC; - int rv = stream_->Open(archive_.path(), flags, + int rv = stream_->Open(archive_->path(), flags, base::Bind(&URLRequestAsarJob::DidOpen, weak_ptr_factory_.GetWeakPtr())); if (rv != net::ERR_IO_PENDING) diff --git a/atom/browser/net/asar/url_request_asar_job.h b/atom/browser/net/asar/url_request_asar_job.h index b85aa3c6f420..a15ba97cf597 100644 --- a/atom/browser/net/asar/url_request_asar_job.h +++ b/atom/browser/net/asar/url_request_asar_job.h @@ -27,7 +27,7 @@ class URLRequestAsarJob : public net::URLRequestJob { public: URLRequestAsarJob(net::URLRequest* request, net::NetworkDelegate* network_delegate, - const base::FilePath& asar_path, + const scoped_refptr& archive, const base::FilePath& file_path, const scoped_refptr& file_task_runner); @@ -53,12 +53,13 @@ class URLRequestAsarJob : public net::URLRequestJob { // Callback after data is asynchronously read from the file into |buf|. void DidRead(scoped_refptr buf, int result); - Archive archive_; + const scoped_refptr archive_; Archive::FileInfo file_info_; base::FilePath file_path_; scoped_ptr stream_; int64 remaining_bytes_; + const scoped_refptr file_task_runner_; base::WeakPtrFactory weak_ptr_factory_; diff --git a/atom/common/asar/archive.h b/atom/common/asar/archive.h index c4cde803bfdc..b4619acf33e1 100644 --- a/atom/common/asar/archive.h +++ b/atom/common/asar/archive.h @@ -6,6 +6,7 @@ #define ATOM_COMMON_ASAR_ARCHIVE_H_ #include "base/files/file_path.h" +#include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" namespace base { @@ -14,7 +15,7 @@ class DictionaryValue; namespace asar { -class Archive { +class Archive : public base::RefCounted { public: struct FileInfo { uint32 size; @@ -22,7 +23,6 @@ class Archive { }; explicit Archive(const base::FilePath& path); - virtual ~Archive(); // Read and parse the header. bool Init(); @@ -33,6 +33,9 @@ class Archive { base::FilePath path() const { return path_; } private: + friend class base::RefCounted; + virtual ~Archive(); + base::FilePath path_; uint32 header_size_; scoped_ptr header_;