diff --git a/atom/browser/api/atom_api_protocol.cc b/atom/browser/api/atom_api_protocol.cc index 083ea32b2010..eede89233201 100644 --- a/atom/browser/api/atom_api_protocol.cc +++ b/atom/browser/api/atom_api_protocol.cc @@ -8,6 +8,7 @@ #include "atom/browser/net/adapter_request_job.h" #include "atom/browser/net/atom_url_request_job_factory.h" #include "atom/common/native_mate_converters/file_path_converter.h" +#include "atom/common/native_mate_converters/gurl_converter.h" #include "content/public/browser/browser_thread.h" #include "native_mate/callback.h" #include "native_mate/dictionary.h" @@ -123,6 +124,14 @@ class CustomProtocolRequestJob : public AdapterRequestJob { base::Bind(&AdapterRequestJob::CreateErrorJobAndStart, GetWeakPtr(), error)); return; + } else if (name == "RequestHttpJob") { + GURL url; + dict.Get("url", &url); + + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, + base::Bind(&AdapterRequestJob::CreateHttpJobAndStart, + GetWeakPtr(), url)); + return; } } diff --git a/atom/browser/api/lib/protocol.coffee b/atom/browser/api/lib/protocol.coffee index c2db7800c08d..bbd2499a8371 100644 --- a/atom/browser/api/lib/protocol.coffee +++ b/atom/browser/api/lib/protocol.coffee @@ -34,4 +34,8 @@ protocol.RequestErrorJob = class RequestErrorJob constructor: (@error) -> +protocol.RequestHttpJob = +class RequestHttpJob + constructor: (@url) -> + module.exports = protocol diff --git a/atom/browser/net/adapter_request_job.cc b/atom/browser/net/adapter_request_job.cc index af3b02f150f4..258416e2f42a 100644 --- a/atom/browser/net/adapter_request_job.cc +++ b/atom/browser/net/adapter_request_job.cc @@ -4,8 +4,10 @@ #include "atom/browser/net/adapter_request_job.h" +#include "atom/browser/atom_browser_context.h" #include "base/threading/sequenced_worker_pool.h" #include "atom/browser/net/url_request_buffer_job.h" +#include "atom/browser/net/url_request_fetch_job.h" #include "atom/browser/net/url_request_string_job.h" #include "atom/browser/net/asar/url_request_asar_job.h" #include "atom/common/asar/asar_util.h" @@ -104,6 +106,11 @@ void AdapterRequestJob::CreateFileJobAndStart(const base::FilePath& path) { real_job_->Start(); } +void AdapterRequestJob::CreateHttpJobAndStart(const GURL& url) { + real_job_ = new URLRequestFetchJob(request(), network_delegate(), url); + real_job_->Start(); +} + void AdapterRequestJob::CreateJobFromProtocolHandlerAndStart() { real_job_ = protocol_handler_->MaybeCreateJob(request(), network_delegate()); diff --git a/atom/browser/net/adapter_request_job.h b/atom/browser/net/adapter_request_job.h index d87207464c08..1ecc82230b76 100644 --- a/atom/browser/net/adapter_request_job.h +++ b/atom/browser/net/adapter_request_job.h @@ -9,6 +9,7 @@ #include "base/memory/ref_counted_memory.h" #include "base/memory/weak_ptr.h" +#include "net/url_request/url_request_context.h" #include "net/url_request/url_request_job.h" #include "net/url_request/url_request_job_factory.h" #include "v8/include/v8.h" @@ -56,6 +57,7 @@ class AdapterRequestJob : public net::URLRequestJob { const std::string& charset, scoped_refptr data); void CreateFileJobAndStart(const base::FilePath& path); + void CreateHttpJobAndStart(const GURL& url); void CreateJobFromProtocolHandlerAndStart(); private: diff --git a/atom/browser/net/url_request_fetch_job.cc b/atom/browser/net/url_request_fetch_job.cc new file mode 100644 index 000000000000..081e85f28f32 --- /dev/null +++ b/atom/browser/net/url_request_fetch_job.cc @@ -0,0 +1,90 @@ +// Copyright (c) 2015 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_fetch_job.h" + +#include + +#include "atom/browser/atom_browser_context.h" +#include "net/base/io_buffer.h" +#include "net/base/net_errors.h" +#include "net/url_request/url_request_status.h" + +namespace atom { + +URLRequestFetchJob::URLRequestFetchJob( + net::URLRequest* request, + net::NetworkDelegate* network_delegate, + const GURL& url) + : net::URLRequestJob(request, network_delegate), + url_(url), + weak_ptr_factory_(this) {} + +URLRequestFetchJob::~URLRequestFetchJob() {} + +void URLRequestFetchJob::Start() { + net::URLFetcher* fetcher = net::URLFetcher::Create(url_, + net::URLFetcher::GET, + this); + auto context = AtomBrowserContext::Get()->url_request_context_getter(); + fetcher->SetRequestContext(context); + fetcher->SaveResponseWithWriter(scoped_ptr( + this)); + fetcher->Start(); +} + +void URLRequestFetchJob::Kill() { + weak_ptr_factory_.InvalidateWeakPtrs(); + URLRequestJob::Kill(); +} + +bool URLRequestFetchJob::ReadRawData(net::IOBuffer* dest, + int dest_size, + int* bytes_read) { + if (!dest_size) { + *bytes_read = 0; + return true; + } + + int to_read = dest_size < buffer_->BytesRemaining() ? + dest_size : buffer_->BytesRemaining(); + memcpy(dest->data(), buffer_->data(), to_read); + buffer_->DidConsume(to_read); + if (!buffer_->BytesRemaining()) { + NotifyReadComplete(buffer_->size()); + return true; + } + + *bytes_read = to_read; + return false; +} + +void URLRequestFetchJob::OnURLFetchComplete(const net::URLFetcher* source) { + if (!source->GetStatus().is_success()) + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, + source->GetResponseCode())); + + NotifyHeadersComplete(); +} + + +int URLRequestFetchJob::Initialize(const net::CompletionCallback& callback) { + if (buffer_) + buffer_->Release(); + return net::OK; +} + +int URLRequestFetchJob::Write(net::IOBuffer* buffer, + int num_bytes, + const net::CompletionCallback& calback) { + buffer_ = new net::DrainableIOBuffer(buffer, num_bytes); + set_expected_content_size(num_bytes); + return num_bytes; +} + +int URLRequestFetchJob::Finish(const net::CompletionCallback& callback) { + return net::OK; +} + +} // namespace atom diff --git a/atom/browser/net/url_request_fetch_job.h b/atom/browser/net/url_request_fetch_job.h new file mode 100644 index 000000000000..e955341c7d50 --- /dev/null +++ b/atom/browser/net/url_request_fetch_job.h @@ -0,0 +1,57 @@ +// 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_FETCH_JOB_H_ +#define ATOM_BROWSER_NET_URL_REQUEST_FETCH_JOB_H_ + +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "net/base/io_buffer.h" +#include "net/url_request/url_fetcher.h" +#include "net/url_request/url_fetcher_delegate.h" +#include "net/url_request/url_fetcher_response_writer.h" +#include "net/url_request/url_request_job.h" + +namespace atom { + +class URLRequestFetchJob : public net::URLRequestJob, + public net::URLFetcherDelegate, + public net::URLFetcherResponseWriter { + public: + URLRequestFetchJob(net::URLRequest* request, + net::NetworkDelegate* network_delegate, + const GURL& url); + + // net::URLRequestJob: + void Start() override; + void Kill() override; + bool ReadRawData(net::IOBuffer* buf, + int buf_size, + int* bytes_read) override; + + // net::URLFetcherDelegate: + void OnURLFetchComplete(const net::URLFetcher* source) override; + + // net::URLFetchResponseWriter: + int Initialize(const net::CompletionCallback& callback) override; + int Write(net::IOBuffer* buffer, + int num_bytes, + const net::CompletionCallback& callback) override; + int Finish(const net::CompletionCallback& callback) override; + + protected: + virtual ~URLRequestFetchJob(); + + private: + GURL url_; + scoped_refptr buffer_; + + base::WeakPtrFactory weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(URLRequestFetchJob); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_NET_URL_REQUEST_FETCH_JOB_H_ diff --git a/filenames.gypi b/filenames.gypi index 6ece2ba634c7..ab523c188beb 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -147,11 +147,13 @@ 'atom/browser/net/atom_url_request_job_factory.cc', 'atom/browser/net/atom_url_request_job_factory.h', 'atom/browser/net/http_protocol_handler.cc', - 'atom/browser/net/http_protocol_handler.h', + 'atom/browser/net/http_protocol_handler.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', 'atom/browser/net/url_request_buffer_job.h', + 'atom/browser/net/url_request_fetch_job.cc', + 'atom/browser/net/url_request_fetch_job.h', 'atom/browser/ui/accelerator_util.cc', 'atom/browser/ui/accelerator_util.h', 'atom/browser/ui/accelerator_util_mac.mm', diff --git a/spec/api-protocol-spec.coffee b/spec/api-protocol-spec.coffee index 5a7bda16555d..e3cc98cd7c4e 100644 --- a/spec/api-protocol-spec.coffee +++ b/spec/api-protocol-spec.coffee @@ -1,5 +1,6 @@ assert = require 'assert' ipc = require 'ipc' +http = require 'http' path = require 'path' remote = require 'remote' protocol = remote.require 'protocol' @@ -73,6 +74,28 @@ describe 'protocol module', -> protocol.unregisterProtocol 'atom-error-job' done() + it 'returns RequestHttpJob should send respone', (done) -> + server = http.createServer (req, res) -> + res.writeHead(200, {'Content-Type': 'text/plain'}) + res.end('hello') + server.close() + server.listen 0, '127.0.0.1', -> + {port} = server.address() + url = "http://127.0.0.1:#{port}" + job = new protocol.RequestHttpJob(url) + handler = remote.createFunctionWithReturnValue job + protocol.registerProtocol 'atom-http-job', handler + + $.ajax + url: 'atom-http-job://fake-host' + success: (data) -> + assert.equal data, 'hello' + protocol.unregisterProtocol 'atom-http-job' + done() + error: (xhr, errorType, error) -> + assert false, 'Got error: ' + errorType + ' ' + error + protocol.unregisterProtocol 'atom-http-job' + it 'returns RequestBufferJob should send buffer', (done) -> data = new Buffer("hello") job = new protocol.RequestBufferJob(data: data)