Implement protocol.registerFileProtocol
This commit is contained in:
		
					parent
					
						
							
								337460cdc2
							
						
					
				
			
			
				commit
				
					
						d2681d2ba1
					
				
			
		
					 8 changed files with 383 additions and 88 deletions
				
			
		| 
						 | 
				
			
			@ -8,6 +8,7 @@
 | 
			
		|||
#include "atom/browser/atom_browser_context.h"
 | 
			
		||||
#include "atom/browser/atom_browser_main_parts.h"
 | 
			
		||||
#include "atom/browser/net/url_request_string_job.h"
 | 
			
		||||
#include "atom/browser/net/url_request_async_asar_job.h"
 | 
			
		||||
#include "atom/common/native_mate_converters/callback.h"
 | 
			
		||||
#include "native_mate/dictionary.h"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -46,7 +47,9 @@ mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder(
 | 
			
		|||
  return mate::ObjectTemplateBuilder(isolate)
 | 
			
		||||
      .SetMethod("registerStandardSchemes", &Protocol::RegisterStandardSchemes)
 | 
			
		||||
      .SetMethod("registerStringProtocol",
 | 
			
		||||
                 &Protocol::RegisterProtocol<URLRequestStringJob>);
 | 
			
		||||
                 &Protocol::RegisterProtocol<URLRequestStringJob>)
 | 
			
		||||
      .SetMethod("registerFileProtocol",
 | 
			
		||||
                 &Protocol::RegisterProtocol<UrlRequestAsyncAsarJob>);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Protocol::RegisterStandardSchemes(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -64,14 +64,16 @@ app.once 'ready', ->
 | 
			
		|||
  catch e
 | 
			
		||||
 | 
			
		||||
  # The chrome-extension: can map a extension URL request to real file path.
 | 
			
		||||
  # protocol.registerProtocol 'chrome-extension', (request) ->
 | 
			
		||||
  #   parsed = url.parse request.url
 | 
			
		||||
  #   return unless parsed.hostname and parsed.path?
 | 
			
		||||
  #   return unless /extension-\d+/.test parsed.hostname
 | 
			
		||||
  chromeExtensionHandler = (request, callback) ->
 | 
			
		||||
    parsed = url.parse request.url
 | 
			
		||||
    return callback() unless parsed.hostname and parsed.path?
 | 
			
		||||
    return callback() unless /extension-\d+/.test parsed.hostname
 | 
			
		||||
 | 
			
		||||
  #   directory = getPathForHost parsed.hostname
 | 
			
		||||
  #   return unless directory?
 | 
			
		||||
  #   return new protocol.RequestFileJob(path.join(directory, parsed.path))
 | 
			
		||||
    directory = getPathForHost parsed.hostname
 | 
			
		||||
    return callback() unless directory?
 | 
			
		||||
    callback path.join(directory, parsed.path)
 | 
			
		||||
  protocol.registerFileProtocol 'chrome-extension', chromeExtensionHandler, ->
 | 
			
		||||
    console.error 'Unable to register chrome-extension protocol'
 | 
			
		||||
 | 
			
		||||
  BrowserWindow::_loadDevToolsExtensions = (extensionInfoArray) ->
 | 
			
		||||
    @devToolsWebContents?.executeJavaScript "DevToolsAPI.addExtensions(#{JSON.stringify(extensionInfoArray)});"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,45 +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 "atom/common/asar/asar_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 {
 | 
			
		||||
 | 
			
		||||
// 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) {}
 | 
			
		||||
| 
						 | 
				
			
			@ -56,8 +22,9 @@ net::URLRequestJob* AsarProtocolHandler::MaybeCreateJob(
 | 
			
		|||
    net::NetworkDelegate* network_delegate) const {
 | 
			
		||||
  base::FilePath full_path;
 | 
			
		||||
  net::FileURLToFilePath(request->url(), &full_path);
 | 
			
		||||
  return CreateJobFromPath(full_path, request, network_delegate,
 | 
			
		||||
                           file_task_runner_);
 | 
			
		||||
  URLRequestAsarJob* job = new URLRequestAsarJob(request, network_delegate);
 | 
			
		||||
  job->Initialize(file_task_runner_, full_path);
 | 
			
		||||
  return job;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool AsarProtocolHandler::IsSafeRedirectTarget(const GURL& location) const {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,47 +6,126 @@
 | 
			
		|||
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#include "base/bind.h"
 | 
			
		||||
#include "base/files/file_util.h"
 | 
			
		||||
#include "base/strings/string_util.h"
 | 
			
		||||
#include "base/synchronization/lock.h"
 | 
			
		||||
#include "base/task_runner.h"
 | 
			
		||||
#include "atom/common/asar/archive.h"
 | 
			
		||||
#include "atom/common/asar/asar_util.h"
 | 
			
		||||
#include "net/base/file_stream.h"
 | 
			
		||||
#include "net/base/filename_util.h"
 | 
			
		||||
#include "net/base/io_buffer.h"
 | 
			
		||||
#include "net/base/load_flags.h"
 | 
			
		||||
#include "net/base/mime_util.h"
 | 
			
		||||
#include "net/base/net_errors.h"
 | 
			
		||||
#include "net/filter/filter.h"
 | 
			
		||||
#include "net/http/http_util.h"
 | 
			
		||||
#include "net/url_request/url_request_status.h"
 | 
			
		||||
 | 
			
		||||
#if defined(OS_WIN)
 | 
			
		||||
#include "base/win/shortcut.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace asar {
 | 
			
		||||
 | 
			
		||||
URLRequestAsarJob::FileMetaInfo::FileMetaInfo()
 | 
			
		||||
    : file_size(0),
 | 
			
		||||
      mime_type_result(false),
 | 
			
		||||
      file_exists(false),
 | 
			
		||||
      is_directory(false) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
URLRequestAsarJob::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::NetworkDelegate* network_delegate)
 | 
			
		||||
    : net::URLRequestJob(request, network_delegate),
 | 
			
		||||
      archive_(archive),
 | 
			
		||||
      file_path_(file_path),
 | 
			
		||||
      file_info_(file_info),
 | 
			
		||||
      stream_(new net::FileStream(file_task_runner)),
 | 
			
		||||
      type_(TYPE_ERROR),
 | 
			
		||||
      remaining_bytes_(0),
 | 
			
		||||
      file_task_runner_(file_task_runner),
 | 
			
		||||
      weak_ptr_factory_(this) {}
 | 
			
		||||
 | 
			
		||||
URLRequestAsarJob::~URLRequestAsarJob() {}
 | 
			
		||||
 | 
			
		||||
void URLRequestAsarJob::Start() {
 | 
			
		||||
  remaining_bytes_ = static_cast<int64>(file_info_.size);
 | 
			
		||||
void URLRequestAsarJob::Initialize(
 | 
			
		||||
    const scoped_refptr<base::TaskRunner> file_task_runner,
 | 
			
		||||
    const base::FilePath& file_path) {
 | 
			
		||||
  // Determine whether it is an asar file.
 | 
			
		||||
  base::FilePath asar_path, relative_path;
 | 
			
		||||
  if (!GetAsarArchivePath(file_path, &asar_path, &relative_path)) {
 | 
			
		||||
    InitializeFileJob(file_task_runner, file_path);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int flags = base::File::FLAG_OPEN |
 | 
			
		||||
              base::File::FLAG_READ |
 | 
			
		||||
              base::File::FLAG_ASYNC;
 | 
			
		||||
  int rv = stream_->Open(archive_->path(), flags,
 | 
			
		||||
                         base::Bind(&URLRequestAsarJob::DidOpen,
 | 
			
		||||
                                    weak_ptr_factory_.GetWeakPtr()));
 | 
			
		||||
  if (rv != net::ERR_IO_PENDING)
 | 
			
		||||
    DidOpen(rv);
 | 
			
		||||
  std::shared_ptr<Archive> archive = GetOrCreateAsarArchive(asar_path);
 | 
			
		||||
  Archive::FileInfo file_info;
 | 
			
		||||
  if (!archive || !archive->GetFileInfo(relative_path, &file_info)) {
 | 
			
		||||
    type_ = TYPE_ERROR;
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (file_info.unpacked) {
 | 
			
		||||
    base::FilePath real_path;
 | 
			
		||||
    archive->CopyFileOut(relative_path, &real_path);
 | 
			
		||||
    InitializeFileJob(file_task_runner, real_path);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  InitializeAsarJob(file_task_runner, archive, relative_path, file_info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void URLRequestAsarJob::InitializeAsarJob(
 | 
			
		||||
    const scoped_refptr<base::TaskRunner> file_task_runner,
 | 
			
		||||
    std::shared_ptr<Archive> archive,
 | 
			
		||||
    const base::FilePath& file_path,
 | 
			
		||||
    const Archive::FileInfo& file_info) {
 | 
			
		||||
  type_ = TYPE_ASAR;
 | 
			
		||||
  file_task_runner_ = file_task_runner;
 | 
			
		||||
  stream_.reset(new net::FileStream(file_task_runner_));
 | 
			
		||||
  archive_ = archive;
 | 
			
		||||
  file_path_ = file_path;
 | 
			
		||||
  file_info_ = file_info;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void URLRequestAsarJob::InitializeFileJob(
 | 
			
		||||
    const scoped_refptr<base::TaskRunner> file_task_runner,
 | 
			
		||||
    const base::FilePath& file_path) {
 | 
			
		||||
  type_ = TYPE_FILE;
 | 
			
		||||
  file_task_runner_ = file_task_runner;
 | 
			
		||||
  stream_.reset(new net::FileStream(file_task_runner_));
 | 
			
		||||
  file_path_ = file_path;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void URLRequestAsarJob::Start() {
 | 
			
		||||
  if (type_ == TYPE_ASAR) {
 | 
			
		||||
    remaining_bytes_ = static_cast<int64>(file_info_.size);
 | 
			
		||||
 | 
			
		||||
    int flags = base::File::FLAG_OPEN |
 | 
			
		||||
                base::File::FLAG_READ |
 | 
			
		||||
                base::File::FLAG_ASYNC;
 | 
			
		||||
    int rv = stream_->Open(archive_->path(), flags,
 | 
			
		||||
                           base::Bind(&URLRequestAsarJob::DidOpen,
 | 
			
		||||
                                      weak_ptr_factory_.GetWeakPtr()));
 | 
			
		||||
    if (rv != net::ERR_IO_PENDING)
 | 
			
		||||
      DidOpen(rv);
 | 
			
		||||
  } else if (type_ == TYPE_FILE) {
 | 
			
		||||
    FileMetaInfo* meta_info = new FileMetaInfo();
 | 
			
		||||
    file_task_runner_->PostTaskAndReply(
 | 
			
		||||
        FROM_HERE,
 | 
			
		||||
        base::Bind(&URLRequestAsarJob::FetchMetaInfo, file_path_,
 | 
			
		||||
                   base::Unretained(meta_info)),
 | 
			
		||||
        base::Bind(&URLRequestAsarJob::DidFetchMetaInfo,
 | 
			
		||||
                   weak_ptr_factory_.GetWeakPtr(),
 | 
			
		||||
                   base::Owned(meta_info)));
 | 
			
		||||
  } else {
 | 
			
		||||
    NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
 | 
			
		||||
                                           net::ERR_FILE_NOT_FOUND));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void URLRequestAsarJob::Kill() {
 | 
			
		||||
  stream_.reset();
 | 
			
		||||
  weak_ptr_factory_.InvalidateWeakPtrs();
 | 
			
		||||
 | 
			
		||||
  URLRequestJob::Kill();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -85,8 +164,97 @@ bool URLRequestAsarJob::ReadRawData(net::IOBuffer* dest,
 | 
			
		|||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool URLRequestAsarJob::IsRedirectResponse(GURL* location,
 | 
			
		||||
                                           int* http_status_code) {
 | 
			
		||||
  if (type_ != TYPE_FILE)
 | 
			
		||||
    return false;
 | 
			
		||||
#if defined(OS_WIN)
 | 
			
		||||
  // Follow a Windows shortcut.
 | 
			
		||||
  // We just resolve .lnk file, ignore others.
 | 
			
		||||
  if (!LowerCaseEqualsASCII(file_path_.Extension(), ".lnk"))
 | 
			
		||||
    return false;
 | 
			
		||||
 | 
			
		||||
  base::FilePath new_path = file_path_;
 | 
			
		||||
  bool resolved;
 | 
			
		||||
  resolved = base::win::ResolveShortcut(new_path, &new_path, NULL);
 | 
			
		||||
 | 
			
		||||
  // If shortcut is not resolved succesfully, do not redirect.
 | 
			
		||||
  if (!resolved)
 | 
			
		||||
    return false;
 | 
			
		||||
 | 
			
		||||
  *location = net::FilePathToFileURL(new_path);
 | 
			
		||||
  *http_status_code = 301;
 | 
			
		||||
  return true;
 | 
			
		||||
#else
 | 
			
		||||
  return false;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
net::Filter* URLRequestAsarJob::SetupFilter() const {
 | 
			
		||||
  // Bug 9936 - .svgz files needs to be decompressed.
 | 
			
		||||
  return LowerCaseEqualsASCII(file_path_.Extension(), ".svgz")
 | 
			
		||||
      ? net::Filter::GZipFactory() : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool URLRequestAsarJob::GetMimeType(std::string* mime_type) const {
 | 
			
		||||
  return net::GetMimeTypeFromFile(file_path_, mime_type);
 | 
			
		||||
  if (type_ == TYPE_ASAR) {
 | 
			
		||||
    return net::GetMimeTypeFromFile(file_path_, mime_type);
 | 
			
		||||
  } else {
 | 
			
		||||
    if (meta_info_.mime_type_result) {
 | 
			
		||||
      *mime_type = meta_info_.mime_type;
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void URLRequestAsarJob::SetExtraRequestHeaders(
 | 
			
		||||
    const net::HttpRequestHeaders& headers) {
 | 
			
		||||
  std::string range_header;
 | 
			
		||||
  if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) {
 | 
			
		||||
    // We only care about "Range" header here.
 | 
			
		||||
    std::vector<net::HttpByteRange> ranges;
 | 
			
		||||
    if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) {
 | 
			
		||||
      if (ranges.size() == 1) {
 | 
			
		||||
        byte_range_ = ranges[0];
 | 
			
		||||
      } else {
 | 
			
		||||
        NotifyDone(net::URLRequestStatus(
 | 
			
		||||
            net::URLRequestStatus::FAILED,
 | 
			
		||||
            net::ERR_REQUEST_RANGE_NOT_SATISFIABLE));
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void URLRequestAsarJob::FetchMetaInfo(const base::FilePath& file_path,
 | 
			
		||||
                                      FileMetaInfo* meta_info) {
 | 
			
		||||
  base::File::Info file_info;
 | 
			
		||||
  meta_info->file_exists = base::GetFileInfo(file_path, &file_info);
 | 
			
		||||
  if (meta_info->file_exists) {
 | 
			
		||||
    meta_info->file_size = file_info.size;
 | 
			
		||||
    meta_info->is_directory = file_info.is_directory;
 | 
			
		||||
  }
 | 
			
		||||
  // On Windows GetMimeTypeFromFile() goes to the registry. Thus it should be
 | 
			
		||||
  // done in WorkerPool.
 | 
			
		||||
  meta_info->mime_type_result =
 | 
			
		||||
      net::GetMimeTypeFromFile(file_path, &meta_info->mime_type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void URLRequestAsarJob::DidFetchMetaInfo(const FileMetaInfo* meta_info) {
 | 
			
		||||
  meta_info_ = *meta_info;
 | 
			
		||||
  if (!meta_info_.file_exists || meta_info_.is_directory) {
 | 
			
		||||
    DidOpen(net::ERR_FILE_NOT_FOUND);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int flags = base::File::FLAG_OPEN |
 | 
			
		||||
              base::File::FLAG_READ |
 | 
			
		||||
              base::File::FLAG_ASYNC;
 | 
			
		||||
  int rv = stream_->Open(file_path_, flags,
 | 
			
		||||
                         base::Bind(&URLRequestAsarJob::DidOpen,
 | 
			
		||||
                                    weak_ptr_factory_.GetWeakPtr()));
 | 
			
		||||
  if (rv != net::ERR_IO_PENDING)
 | 
			
		||||
    DidOpen(rv);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void URLRequestAsarJob::DidOpen(int result) {
 | 
			
		||||
| 
						 | 
				
			
			@ -95,24 +263,59 @@ void URLRequestAsarJob::DidOpen(int result) {
 | 
			
		|||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int rv = stream_->Seek(base::File::FROM_BEGIN,
 | 
			
		||||
                         file_info_.offset,
 | 
			
		||||
                         base::Bind(&URLRequestAsarJob::DidSeek,
 | 
			
		||||
                                    weak_ptr_factory_.GetWeakPtr()));
 | 
			
		||||
  if (rv != net::ERR_IO_PENDING) {
 | 
			
		||||
    // stream_->Seek() failed, so pass an intentionally erroneous value
 | 
			
		||||
    // into DidSeek().
 | 
			
		||||
    DidSeek(-1);
 | 
			
		||||
  if (type_ == TYPE_ASAR) {
 | 
			
		||||
    int rv = stream_->Seek(base::File::FROM_BEGIN,
 | 
			
		||||
                           file_info_.offset,
 | 
			
		||||
                           base::Bind(&URLRequestAsarJob::DidSeek,
 | 
			
		||||
                                      weak_ptr_factory_.GetWeakPtr()));
 | 
			
		||||
    if (rv != net::ERR_IO_PENDING) {
 | 
			
		||||
      // stream_->Seek() failed, so pass an intentionally erroneous value
 | 
			
		||||
      // into DidSeek().
 | 
			
		||||
      DidSeek(-1);
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    if (!byte_range_.ComputeBounds(meta_info_.file_size)) {
 | 
			
		||||
      NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
 | 
			
		||||
                 net::ERR_REQUEST_RANGE_NOT_SATISFIABLE));
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    remaining_bytes_ = byte_range_.last_byte_position() -
 | 
			
		||||
                       byte_range_.first_byte_position() + 1;
 | 
			
		||||
 | 
			
		||||
    if (remaining_bytes_ > 0 && byte_range_.first_byte_position() != 0) {
 | 
			
		||||
      int rv = stream_->Seek(base::File::FROM_BEGIN,
 | 
			
		||||
                             byte_range_.first_byte_position(),
 | 
			
		||||
                             base::Bind(&URLRequestAsarJob::DidSeek,
 | 
			
		||||
                                        weak_ptr_factory_.GetWeakPtr()));
 | 
			
		||||
      if (rv != net::ERR_IO_PENDING) {
 | 
			
		||||
        // stream_->Seek() failed, so pass an intentionally erroneous value
 | 
			
		||||
        // into DidSeek().
 | 
			
		||||
        DidSeek(-1);
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      // We didn't need to call stream_->Seek() at all, so we pass to DidSeek()
 | 
			
		||||
      // the value that would mean seek success. This way we skip the code
 | 
			
		||||
      // handling seek failure.
 | 
			
		||||
      DidSeek(byte_range_.first_byte_position());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void URLRequestAsarJob::DidSeek(int64 result) {
 | 
			
		||||
  if (result != static_cast<int64>(file_info_.offset)) {
 | 
			
		||||
    NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
 | 
			
		||||
                                     net::ERR_REQUEST_RANGE_NOT_SATISFIABLE));
 | 
			
		||||
    return;
 | 
			
		||||
  if (type_ == TYPE_ASAR) {
 | 
			
		||||
    if (result != static_cast<int64>(file_info_.offset)) {
 | 
			
		||||
      NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
 | 
			
		||||
                                       net::ERR_REQUEST_RANGE_NOT_SATISFIABLE));
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    if (result != byte_range_.first_byte_position()) {
 | 
			
		||||
      NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
 | 
			
		||||
                                       net::ERR_REQUEST_RANGE_NOT_SATISFIABLE));
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  set_expected_content_size(remaining_bytes_);
 | 
			
		||||
  NotifyHeadersComplete();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,10 +8,12 @@
 | 
			
		|||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#include "atom/browser/net/js_asker.h"
 | 
			
		||||
#include "atom/common/asar/archive.h"
 | 
			
		||||
#include "base/files/file_path.h"
 | 
			
		||||
#include "base/memory/ref_counted.h"
 | 
			
		||||
#include "base/memory/weak_ptr.h"
 | 
			
		||||
#include "net/http/http_byte_range.h"
 | 
			
		||||
#include "net/url_request/url_request_job.h"
 | 
			
		||||
 | 
			
		||||
namespace base {
 | 
			
		||||
| 
						 | 
				
			
			@ -34,11 +36,20 @@ net::URLRequestJob* CreateJobFromPath(
 | 
			
		|||
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::NetworkDelegate* network_delegate);
 | 
			
		||||
 | 
			
		||||
  void Initialize(const scoped_refptr<base::TaskRunner> file_task_runner,
 | 
			
		||||
                  const base::FilePath& file_path);
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  virtual ~URLRequestAsarJob();
 | 
			
		||||
 | 
			
		||||
  void InitializeAsarJob(const scoped_refptr<base::TaskRunner> file_task_runner,
 | 
			
		||||
                         std::shared_ptr<Archive> archive,
 | 
			
		||||
                         const base::FilePath& file_path,
 | 
			
		||||
                         const Archive::FileInfo& file_info);
 | 
			
		||||
  void InitializeFileJob(const scoped_refptr<base::TaskRunner> file_task_runner,
 | 
			
		||||
                         const base::FilePath& file_path);
 | 
			
		||||
 | 
			
		||||
  // net::URLRequestJob:
 | 
			
		||||
  void Start() override;
 | 
			
		||||
| 
						 | 
				
			
			@ -46,12 +57,39 @@ class URLRequestAsarJob : public net::URLRequestJob {
 | 
			
		|||
  bool ReadRawData(net::IOBuffer* buf,
 | 
			
		||||
                   int buf_size,
 | 
			
		||||
                   int* bytes_read) override;
 | 
			
		||||
  bool IsRedirectResponse(GURL* location, int* http_status_code) override;
 | 
			
		||||
  net::Filter* SetupFilter() const override;
 | 
			
		||||
  bool GetMimeType(std::string* mime_type) const override;
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  virtual ~URLRequestAsarJob();
 | 
			
		||||
  void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override;
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  // Meta information about the file. It's used as a member in the
 | 
			
		||||
  // URLRequestFileJob and also passed between threads because disk access is
 | 
			
		||||
  // necessary to obtain it.
 | 
			
		||||
  struct FileMetaInfo {
 | 
			
		||||
    FileMetaInfo();
 | 
			
		||||
 | 
			
		||||
    // Size of the file.
 | 
			
		||||
    int64 file_size;
 | 
			
		||||
    // Mime type associated with the file.
 | 
			
		||||
    std::string mime_type;
 | 
			
		||||
    // Result returned from GetMimeTypeFromFile(), i.e. flag showing whether
 | 
			
		||||
    // obtaining of the mime type was successful.
 | 
			
		||||
    bool mime_type_result;
 | 
			
		||||
    // Flag showing whether the file exists.
 | 
			
		||||
    bool file_exists;
 | 
			
		||||
    // Flag showing whether the file name actually refers to a directory.
 | 
			
		||||
    bool is_directory;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // Fetches file info on a background thread.
 | 
			
		||||
  static void FetchMetaInfo(const base::FilePath& file_path,
 | 
			
		||||
                            FileMetaInfo* meta_info);
 | 
			
		||||
 | 
			
		||||
  // Callback after fetching file info on a background thread.
 | 
			
		||||
  void DidFetchMetaInfo(const FileMetaInfo* meta_info);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  // Callback after opening file on a background thread.
 | 
			
		||||
  void DidOpen(int result);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -62,14 +100,24 @@ class URLRequestAsarJob : public net::URLRequestJob {
 | 
			
		|||
  // Callback after data is asynchronously read from the file into |buf|.
 | 
			
		||||
  void DidRead(scoped_refptr<net::IOBuffer> buf, int result);
 | 
			
		||||
 | 
			
		||||
  // The type of this job.
 | 
			
		||||
  enum JobType {
 | 
			
		||||
    TYPE_ERROR,
 | 
			
		||||
    TYPE_ASAR,
 | 
			
		||||
    TYPE_FILE,
 | 
			
		||||
  };
 | 
			
		||||
  JobType type_;
 | 
			
		||||
 | 
			
		||||
  std::shared_ptr<Archive> archive_;
 | 
			
		||||
  base::FilePath file_path_;
 | 
			
		||||
  Archive::FileInfo file_info_;
 | 
			
		||||
 | 
			
		||||
  scoped_ptr<net::FileStream> stream_;
 | 
			
		||||
  int64 remaining_bytes_;
 | 
			
		||||
  FileMetaInfo meta_info_;
 | 
			
		||||
  scoped_refptr<base::TaskRunner> file_task_runner_;
 | 
			
		||||
 | 
			
		||||
  const scoped_refptr<base::TaskRunner> file_task_runner_;
 | 
			
		||||
  net::HttpByteRange byte_range_;
 | 
			
		||||
  int64 remaining_bytes_;
 | 
			
		||||
 | 
			
		||||
  base::WeakPtrFactory<URLRequestAsarJob> weak_ptr_factory_;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										40
									
								
								atom/browser/net/url_request_async_asar_job.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								atom/browser/net/url_request_async_asar_job.cc
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
// Copyright (c) 2014 GitHub, Inc.
 | 
			
		||||
// Use of this source code is governed by the MIT license that can be
 | 
			
		||||
// found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
#include "atom/browser/net/url_request_async_asar_job.h"
 | 
			
		||||
 | 
			
		||||
namespace atom {
 | 
			
		||||
 | 
			
		||||
UrlRequestAsyncAsarJob::UrlRequestAsyncAsarJob(
 | 
			
		||||
    net::URLRequest* request,
 | 
			
		||||
    net::NetworkDelegate* network_delegate,
 | 
			
		||||
    v8::Isolate* isolate,
 | 
			
		||||
    const JavaScriptHandler& handler)
 | 
			
		||||
    : JsAsker<asar::URLRequestAsarJob>(request, network_delegate, isolate,
 | 
			
		||||
                                       handler) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UrlRequestAsyncAsarJob::StartAsync(scoped_ptr<base::Value> options) {
 | 
			
		||||
  base::FilePath::StringType file_path;
 | 
			
		||||
  if (options->IsType(base::Value::TYPE_DICTIONARY)) {
 | 
			
		||||
    static_cast<base::DictionaryValue*>(options.get())->GetString(
 | 
			
		||||
        "path", &file_path);
 | 
			
		||||
  } else if (options->IsType(base::Value::TYPE_STRING)) {
 | 
			
		||||
    options->GetAsString(&file_path);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (file_path.empty()) {
 | 
			
		||||
    NotifyStartError(net::URLRequestStatus(
 | 
			
		||||
          net::URLRequestStatus::FAILED, net::ERR_NOT_IMPLEMENTED));
 | 
			
		||||
  } else {
 | 
			
		||||
    asar::URLRequestAsarJob::Initialize(
 | 
			
		||||
        content::BrowserThread::GetBlockingPool()->
 | 
			
		||||
            GetTaskRunnerWithShutdownBehavior(
 | 
			
		||||
                base::SequencedWorkerPool::SKIP_ON_SHUTDOWN),
 | 
			
		||||
        base::FilePath(file_path));
 | 
			
		||||
    asar::URLRequestAsarJob::Start();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace atom
 | 
			
		||||
							
								
								
									
										30
									
								
								atom/browser/net/url_request_async_asar_job.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								atom/browser/net/url_request_async_asar_job.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
// Copyright (c) 2015 GitHub, Inc.
 | 
			
		||||
// Use of this source code is governed by the MIT license that can be
 | 
			
		||||
// found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
#ifndef ATOM_BROWSER_NET_URL_REQUEST_ASYNC_ASAR_JOB_H_
 | 
			
		||||
#define ATOM_BROWSER_NET_URL_REQUEST_ASYNC_ASAR_JOB_H_
 | 
			
		||||
 | 
			
		||||
#include "atom/browser/net/asar/url_request_asar_job.h"
 | 
			
		||||
#include "atom/browser/net/js_asker.h"
 | 
			
		||||
 | 
			
		||||
namespace atom {
 | 
			
		||||
 | 
			
		||||
// Like URLRequestAsarJob, but asks the JavaScript handler for file path.
 | 
			
		||||
class UrlRequestAsyncAsarJob : public JsAsker<asar::URLRequestAsarJob> {
 | 
			
		||||
 public:
 | 
			
		||||
  UrlRequestAsyncAsarJob(net::URLRequest* request,
 | 
			
		||||
                         net::NetworkDelegate* network_delegate,
 | 
			
		||||
                         v8::Isolate* isolate,
 | 
			
		||||
                         const JavaScriptHandler& handler);
 | 
			
		||||
 | 
			
		||||
  // JsAsker:
 | 
			
		||||
  void StartAsync(scoped_ptr<base::Value> options) override;
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  DISALLOW_COPY_AND_ASSIGN(UrlRequestAsyncAsarJob);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace atom
 | 
			
		||||
 | 
			
		||||
#endif  // ATOM_BROWSER_NET_URL_REQUEST_ASYNC_ASAR_JOB_H_
 | 
			
		||||
| 
						 | 
				
			
			@ -156,6 +156,8 @@
 | 
			
		|||
      'atom/browser/net/http_protocol_handler.h',
 | 
			
		||||
      'atom/browser/net/js_asker.cc',
 | 
			
		||||
      'atom/browser/net/js_asker.h',
 | 
			
		||||
      'atom/browser/net/url_request_async_asar_job.cc',
 | 
			
		||||
      'atom/browser/net/url_request_async_asar_job.h',
 | 
			
		||||
      'atom/browser/net/url_request_string_job.cc',
 | 
			
		||||
      'atom/browser/net/url_request_string_job.h',
 | 
			
		||||
      'atom/browser/net/url_request_buffer_job.cc',
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue