From 912bac698c59151e36228ae7bb5edd9717ecc1e2 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 25 Aug 2013 12:36:06 +0800 Subject: [PATCH] Allow returning string in custom protocols. --- browser/api/atom_api_protocol.cc | 109 +++++++++++++++++++++++++------ spec/api/protocol.coffee | 11 ++++ spec/main.js | 13 ++++ 3 files changed, 113 insertions(+), 20 deletions(-) diff --git a/browser/api/atom_api_protocol.cc b/browser/api/atom_api_protocol.cc index 247718fe289f..40d1d8024256 100644 --- a/browser/api/atom_api_protocol.cc +++ b/browser/api/atom_api_protocol.cc @@ -35,6 +35,38 @@ net::URLRequestJobFactoryImpl* GetRequestJobFactory() { return job_factory; } +class URLRequestStringJob : public net::URLRequestSimpleJob { + public: + URLRequestStringJob(net::URLRequest* request, + net::NetworkDelegate* network_delegate, + const std::string& mime_type, + const std::string& charset, + const std::string& data) + : net::URLRequestSimpleJob(request, network_delegate), + mime_type_(mime_type), + charset_(charset), + data_(data) { + } + + // URLRequestSimpleJob: + virtual int GetData(std::string* mime_type, + std::string* charset, + std::string* data, + const net::CompletionCallback& callback) const OVERRIDE { + *mime_type = mime_type_; + *charset = charset_; + *data = data_; + return net::OK; + } + + private: + std::string mime_type_; + std::string charset_; + std::string data_; + + DISALLOW_COPY_AND_ASSIGN(URLRequestStringJob); +}; + // Ask JS which type of job it wants, and then delegate corresponding methods. class AdapterRequestJob : public net::URLRequestJob { public: @@ -45,6 +77,7 @@ class AdapterRequestJob : public net::URLRequestJob { } protected: + // net::URLRequestJob: virtual void Start() OVERRIDE { DCHECK(!real_job_); content::BrowserThread::PostTask( @@ -65,8 +98,8 @@ class AdapterRequestJob : public net::URLRequestJob { DCHECK(real_job_); // The ReadRawData is a protected method. switch (type_) { - case FILE_JOB: - return static_cast(real_job_.get())-> + case REQUEST_STRING_JOB: + return static_cast(real_job_.get())-> ReadRawData(buf, buf_size, bytes_read); default: return net::URLRequestJob::ReadRawData(buf, buf_size, bytes_read); @@ -96,9 +129,9 @@ class AdapterRequestJob : public net::URLRequestJob { private: enum JOB_TYPE { - ERROR_JOB, - STRING_JOB, - FILE_JOB, + REQUEST_ERROR_JOB, + REQUEST_STRING_JOB, + REQUEST_FILE_JOB, }; void GetJobTypeInUI() { @@ -115,36 +148,72 @@ class AdapterRequestJob : public net::URLRequestJob { // Determine the type of the job we are going to create. if (result->IsString()) { - type_ = STRING_JOB; - data_ = *v8::String::Utf8Value(result); - } else { - type_ = ERROR_JOB; - error_code_ = net::ERR_NOT_IMPLEMENTED; + std::string data = *v8::String::Utf8Value(result); + content::BrowserThread::PostTask( + content::BrowserThread::IO, + FROM_HERE, + base::Bind(&AdapterRequestJob::CreateStringJobAndStart, + weak_factory_.GetWeakPtr(), + "text/plain", + "UTF-8", + data)); + return; + } else if (result->IsObject()) { + v8::Handle obj = result->ToObject(); + std::string name = *v8::String::Utf8Value(obj->GetConstructorName()); + if (name == "RequestStringJob") { + std::string mime_type = *v8::String::Utf8Value(obj->Get( + v8::String::New("mimeType"))); + std::string charset = *v8::String::Utf8Value(obj->Get( + v8::String::New("charset"))); + std::string data = *v8::String::Utf8Value(obj->Get( + v8::String::New("data"))); + + content::BrowserThread::PostTask( + content::BrowserThread::IO, + FROM_HERE, + base::Bind(&AdapterRequestJob::CreateStringJobAndStart, + weak_factory_.GetWeakPtr(), + mime_type, + charset, + data)); + return; + } } - // Go back to the IO thread. + // Fallback to the not implemented error. content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, - base::Bind(&AdapterRequestJob::CreateJobAndStart, - weak_factory_.GetWeakPtr())); + base::Bind(&AdapterRequestJob::CreateErrorJobAndStart, + weak_factory_.GetWeakPtr(), + net::ERR_NOT_IMPLEMENTED)); } - void CreateJobAndStart() { + void CreateErrorJobAndStart(int error_code) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + + type_ = REQUEST_ERROR_JOB; real_job_ = new net::URLRequestErrorJob( - request(), network_delegate(), net::ERR_NOT_IMPLEMENTED); + request(), network_delegate(), error_code); + real_job_->Start(); + } + + void CreateStringJobAndStart(const std::string& mime_type, + const std::string& charset, + const std::string& data) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + + type_ = REQUEST_STRING_JOB; + real_job_ = new URLRequestStringJob( + request(), network_delegate(), mime_type, charset, data); real_job_->Start(); } scoped_refptr real_job_; + // Type of the delegated url request job. JOB_TYPE type_; - int error_code_; - base::FilePath file_path_; - std::string mime_type_; - std::string charset_; - std::string data_; base::WeakPtrFactory weak_factory_; diff --git a/spec/api/protocol.coffee b/spec/api/protocol.coffee index 5ca7ed1bc8de..5be7b4a46875 100644 --- a/spec/api/protocol.coffee +++ b/spec/api/protocol.coffee @@ -1,4 +1,5 @@ assert = require 'assert' +ipc = require 'ipc' protocol = require('remote').require 'protocol' describe 'protocol API', -> @@ -18,3 +19,13 @@ describe 'protocol API', -> it 'throws error when scheme does not exist', -> unregister = -> protocol.unregisterProtocol 'test3' assert.throws unregister, /The scheme has not been registered/ + + describe 'registered protocol callback', -> + it 'returns string should send the string as request content', (done) -> + $.ajax + url: 'atom-string://something' + success: (data) -> + assert.equal data, 'atom-string://something' + done() + error: (xhr, errorType, error) -> + console.log xhr, errorType, error diff --git a/spec/main.js b/spec/main.js index 6c2669355ca5..ba05d6fdd0b3 100644 --- a/spec/main.js +++ b/spec/main.js @@ -22,6 +22,10 @@ ipc.on('process.exit', function(pid, rid, code) { process.exit(code); }); +ipc.on('eval', function(ev, pid, rid, script) { + ev.result = eval(script); +}); + process.on('uncaughtException', function() { window.openDevTools(); }); @@ -30,6 +34,15 @@ app.on('window-all-closed', function() { app.terminate(); }); +app.on('will-finish-launching', function() { + // Reigster some protocols, used by the protocol spec. + // FIXME(zcbenz): move this to somewhere else. + var protocol = require('protocol'); + protocol.registerProtocol('atom-string', function(url) { + return url; + }); +}); + app.on('finish-launching', function() { window = new BrowserWindow({ title: 'atom-shell tests',