Recognize asar archive with unpacked files
This commit is contained in:
parent
dc82553fc3
commit
b5a8cfb704
9 changed files with 84 additions and 55 deletions
|
@ -100,32 +100,13 @@ void AdapterRequestJob::CreateBufferJobAndStart(const std::string& mime_type,
|
|||
|
||||
void AdapterRequestJob::CreateFileJobAndStart(const base::FilePath& path) {
|
||||
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
|
||||
|
||||
base::FilePath asar_path, relative_path;
|
||||
if (!asar::GetAsarArchivePath(path, &asar_path, &relative_path)) {
|
||||
real_job_ = new net::URLRequestFileJob(
|
||||
request(),
|
||||
network_delegate(),
|
||||
real_job_ = asar::CreateJobFromPath(
|
||||
path,
|
||||
content::BrowserThread::GetBlockingPool()->
|
||||
GetTaskRunnerWithShutdownBehavior(
|
||||
base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
|
||||
} else {
|
||||
auto archive = asar::GetOrCreateAsarArchive(asar_path);
|
||||
if (archive)
|
||||
real_job_ = new asar::URLRequestAsarJob(
|
||||
request(),
|
||||
network_delegate(),
|
||||
archive,
|
||||
relative_path,
|
||||
content::BrowserThread::GetBlockingPool()->
|
||||
GetTaskRunnerWithShutdownBehavior(
|
||||
base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
|
||||
else
|
||||
real_job_ = new net::URLRequestErrorJob(
|
||||
request(), network_delegate(), net::ERR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
real_job_->Start();
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,36 @@
|
|||
|
||||
namespace asar {
|
||||
|
||||
// static
|
||||
net::URLRequestJob* CreateJobFromPath(
|
||||
const base::FilePath& full_path,
|
||||
net::URLRequest* request,
|
||||
net::NetworkDelegate* network_delegate,
|
||||
const scoped_refptr<base::TaskRunner> file_task_runner) {
|
||||
// Create asar:// job when the path contains "xxx.asar/", otherwise treat the
|
||||
// URL request as file://.
|
||||
base::FilePath asar_path, relative_path;
|
||||
if (!GetAsarArchivePath(full_path, &asar_path, &relative_path))
|
||||
return new net::URLRequestFileJob(request, network_delegate, full_path,
|
||||
file_task_runner);
|
||||
|
||||
std::shared_ptr<Archive> archive = GetOrCreateAsarArchive(asar_path);
|
||||
Archive::FileInfo file_info;
|
||||
if (!archive || !archive->GetFileInfo(relative_path, &file_info))
|
||||
return new net::URLRequestErrorJob(request, network_delegate,
|
||||
net::ERR_FILE_NOT_FOUND);
|
||||
|
||||
if (file_info.unpacked) {
|
||||
base::FilePath real_path;
|
||||
archive->CopyFileOut(relative_path, &real_path);
|
||||
return new net::URLRequestFileJob(request, network_delegate, real_path,
|
||||
file_task_runner);
|
||||
}
|
||||
|
||||
return new URLRequestAsarJob(request, network_delegate, archive,
|
||||
relative_path, file_info, file_task_runner);
|
||||
}
|
||||
|
||||
AsarProtocolHandler::AsarProtocolHandler(
|
||||
const scoped_refptr<base::TaskRunner>& file_task_runner)
|
||||
: file_task_runner_(file_task_runner) {}
|
||||
|
@ -26,21 +56,8 @@ net::URLRequestJob* AsarProtocolHandler::MaybeCreateJob(
|
|||
net::NetworkDelegate* network_delegate) const {
|
||||
base::FilePath full_path;
|
||||
net::FileURLToFilePath(request->url(), &full_path);
|
||||
|
||||
// Create asar:// job when the path contains "xxx.asar/", otherwise treat the
|
||||
// URL request as file://.
|
||||
base::FilePath asar_path, relative_path;
|
||||
if (!GetAsarArchivePath(full_path, &asar_path, &relative_path))
|
||||
return new net::URLRequestFileJob(request, network_delegate, full_path,
|
||||
return CreateJobFromPath(full_path, request, network_delegate,
|
||||
file_task_runner_);
|
||||
|
||||
std::shared_ptr<Archive> archive = GetOrCreateAsarArchive(asar_path);
|
||||
if (!archive)
|
||||
return new net::URLRequestErrorJob(request, network_delegate,
|
||||
net::ERR_FILE_NOT_FOUND);
|
||||
|
||||
return new URLRequestAsarJob(request, network_delegate, archive,
|
||||
relative_path, file_task_runner_);
|
||||
}
|
||||
|
||||
bool AsarProtocolHandler::IsSafeRedirectTarget(const GURL& location) const {
|
||||
|
|
|
@ -19,10 +19,12 @@ URLRequestAsarJob::URLRequestAsarJob(
|
|||
net::NetworkDelegate* network_delegate,
|
||||
std::shared_ptr<Archive> archive,
|
||||
const base::FilePath& file_path,
|
||||
const Archive::FileInfo& file_info,
|
||||
const scoped_refptr<base::TaskRunner>& file_task_runner)
|
||||
: net::URLRequestJob(request, network_delegate),
|
||||
archive_(archive),
|
||||
file_path_(file_path),
|
||||
file_info_(file_info),
|
||||
stream_(new net::FileStream(file_task_runner)),
|
||||
remaining_bytes_(0),
|
||||
file_task_runner_(file_task_runner),
|
||||
|
@ -31,12 +33,6 @@ URLRequestAsarJob::URLRequestAsarJob(
|
|||
URLRequestAsarJob::~URLRequestAsarJob() {}
|
||||
|
||||
void URLRequestAsarJob::Start() {
|
||||
if (!archive_ || !archive_->GetFileInfo(file_path_, &file_info_)) {
|
||||
NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
|
||||
net::ERR_FILE_NOT_FOUND));
|
||||
return;
|
||||
}
|
||||
|
||||
remaining_bytes_ = static_cast<int64>(file_info_.size);
|
||||
|
||||
int flags = base::File::FLAG_OPEN |
|
||||
|
|
|
@ -24,12 +24,20 @@ class FileStream;
|
|||
|
||||
namespace asar {
|
||||
|
||||
// Createa a request job according to the file path.
|
||||
net::URLRequestJob* CreateJobFromPath(
|
||||
const base::FilePath& full_path,
|
||||
net::URLRequest* request,
|
||||
net::NetworkDelegate* network_delegate,
|
||||
const scoped_refptr<base::TaskRunner> file_task_runner);
|
||||
|
||||
class URLRequestAsarJob : public net::URLRequestJob {
|
||||
public:
|
||||
URLRequestAsarJob(net::URLRequest* request,
|
||||
net::NetworkDelegate* network_delegate,
|
||||
std::shared_ptr<Archive> archive,
|
||||
const base::FilePath& file_path,
|
||||
const Archive::FileInfo& file_info,
|
||||
const scoped_refptr<base::TaskRunner>& file_task_runner);
|
||||
|
||||
// net::URLRequestJob:
|
||||
|
@ -55,8 +63,8 @@ class URLRequestAsarJob : public net::URLRequestJob {
|
|||
void DidRead(scoped_refptr<net::IOBuffer> buf, int result);
|
||||
|
||||
std::shared_ptr<Archive> archive_;
|
||||
Archive::FileInfo file_info_;
|
||||
base::FilePath file_path_;
|
||||
Archive::FileInfo file_info_;
|
||||
|
||||
scoped_ptr<net::FileStream> stream_;
|
||||
int64 remaining_bytes_;
|
||||
|
|
|
@ -41,6 +41,7 @@ class Archive : public mate::Wrappable {
|
|||
return v8::False(isolate);
|
||||
mate::Dictionary dict(isolate, v8::Object::New(isolate));
|
||||
dict.Set("size", info.size);
|
||||
dict.Set("unpacked", info.unpacked);
|
||||
dict.Set("offset", info.offset);
|
||||
return dict.GetHandle();
|
||||
}
|
||||
|
|
|
@ -81,18 +81,22 @@ bool GetNodeFromPath(std::string path,
|
|||
bool FillFileInfoWithNode(Archive::FileInfo* info,
|
||||
uint32 header_size,
|
||||
const base::DictionaryValue* node) {
|
||||
int size;
|
||||
if (!node->GetInteger("size", &size))
|
||||
return false;
|
||||
info->size = static_cast<uint32>(size);
|
||||
|
||||
info->unpacked = false;
|
||||
if (node->GetBoolean("unpacked", &info->unpacked) && info->unpacked)
|
||||
return true;
|
||||
|
||||
std::string offset;
|
||||
if (!node->GetString("offset", &offset))
|
||||
return false;
|
||||
if (!base::StringToUint64(offset, &info->offset))
|
||||
return false;
|
||||
|
||||
int size;
|
||||
if (!node->GetInteger("size", &size))
|
||||
return false;
|
||||
|
||||
info->offset += header_size;
|
||||
info->size = static_cast<uint32>(size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -240,6 +244,11 @@ bool Archive::CopyFileOut(const base::FilePath& path, base::FilePath* out) {
|
|||
if (!GetFileInfo(path, &info))
|
||||
return false;
|
||||
|
||||
if (info.unpacked) {
|
||||
*out = path_.AddExtension(FILE_PATH_LITERAL("unpacked")).Append(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
scoped_ptr<ScopedTemporaryFile> temp_file(new ScopedTemporaryFile);
|
||||
if (!temp_file->InitFromFile(path_, info.offset, info.size))
|
||||
return false;
|
||||
|
|
|
@ -25,6 +25,7 @@ class Archive {
|
|||
public:
|
||||
struct FileInfo {
|
||||
FileInfo() : size(0), offset(0) {}
|
||||
bool unpacked;
|
||||
uint32 size;
|
||||
uint64 offset;
|
||||
};
|
||||
|
@ -55,6 +56,7 @@ class Archive {
|
|||
bool Realpath(const base::FilePath& path, base::FilePath* realpath);
|
||||
|
||||
// Copy the file into a temporary file, and return the new path.
|
||||
// For unpacked file, this method will return its real path.
|
||||
bool CopyFileOut(const base::FilePath& path, base::FilePath* out);
|
||||
|
||||
base::FilePath path() const { return path_; }
|
||||
|
|
|
@ -71,6 +71,13 @@ bool ReadFileToString(const base::FilePath& path, std::string* contents) {
|
|||
if (!archive->GetFileInfo(relative_path, &info))
|
||||
return false;
|
||||
|
||||
if (info.unpacked) {
|
||||
base::FilePath real_path;
|
||||
// For unpacked file it will return the real path instead of doing the copy.
|
||||
archive->CopyFileOut(relative_path, &real_path);
|
||||
return base::ReadFileToString(real_path, contents);
|
||||
}
|
||||
|
||||
base::File src(asar_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
|
||||
if (!src.IsValid())
|
||||
return false;
|
||||
|
|
|
@ -218,6 +218,10 @@ exports.wrapFsWithAsar = (fs) ->
|
|||
info = archive.getFileInfo filePath
|
||||
return callback createNotFoundError(asarPath, filePath) unless info
|
||||
|
||||
if info.unpacked
|
||||
realPath = archive.copyFileOut filePath
|
||||
return fs.readFile realPath, options, callback
|
||||
|
||||
if not options
|
||||
options = encoding: null, flag: 'r'
|
||||
else if util.isString options
|
||||
|
@ -247,6 +251,10 @@ exports.wrapFsWithAsar = (fs) ->
|
|||
info = archive.getFileInfo filePath
|
||||
throw createNotFoundError(asarPath, filePath) unless info
|
||||
|
||||
if info.unpacked
|
||||
realPath = archive.copyFileOut filePath
|
||||
return fs.readFileSync realPath, options
|
||||
|
||||
if not options
|
||||
options = encoding: null, flag: 'r'
|
||||
else if util.isString options
|
||||
|
|
Loading…
Reference in a new issue