Merge pull request #3250 from atom/basic-auth
Add support for basic auth
This commit is contained in:
commit
f13a02e4fa
19 changed files with 520 additions and 104 deletions
|
@ -13,11 +13,13 @@
|
||||||
|
|
||||||
#include "atom/browser/api/atom_api_menu.h"
|
#include "atom/browser/api/atom_api_menu.h"
|
||||||
#include "atom/browser/api/atom_api_session.h"
|
#include "atom/browser/api/atom_api_session.h"
|
||||||
|
#include "atom/browser/api/atom_api_web_contents.h"
|
||||||
#include "atom/browser/atom_browser_context.h"
|
#include "atom/browser/atom_browser_context.h"
|
||||||
#include "atom/browser/atom_browser_main_parts.h"
|
#include "atom/browser/atom_browser_main_parts.h"
|
||||||
#include "atom/browser/browser.h"
|
#include "atom/browser/browser.h"
|
||||||
#include "atom/browser/api/atom_api_web_contents.h"
|
#include "atom/browser/login_handler.h"
|
||||||
#include "atom/common/native_mate_converters/callback.h"
|
#include "atom/common/native_mate_converters/callback.h"
|
||||||
|
#include "atom/common/native_mate_converters/content_converter.h"
|
||||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||||
#include "atom/common/node_includes.h"
|
#include "atom/common/node_includes.h"
|
||||||
#include "atom/common/options_switches.h"
|
#include "atom/common/options_switches.h"
|
||||||
|
@ -132,8 +134,6 @@ void OnClientCertificateSelected(
|
||||||
v8::Isolate* isolate,
|
v8::Isolate* isolate,
|
||||||
std::shared_ptr<content::ClientCertificateDelegate> delegate,
|
std::shared_ptr<content::ClientCertificateDelegate> delegate,
|
||||||
mate::Arguments* args) {
|
mate::Arguments* args) {
|
||||||
v8::Locker locker(isolate);
|
|
||||||
v8::HandleScope handle_scope(isolate);
|
|
||||||
mate::Dictionary cert_data;
|
mate::Dictionary cert_data;
|
||||||
if (!(args->Length() == 1 && args->GetNext(&cert_data))) {
|
if (!(args->Length() == 1 && args->GetNext(&cert_data))) {
|
||||||
args->ThrowError();
|
args->ThrowError();
|
||||||
|
@ -147,10 +147,18 @@ void OnClientCertificateSelected(
|
||||||
net::X509Certificate::CreateCertificateListFromBytes(
|
net::X509Certificate::CreateCertificateListFromBytes(
|
||||||
encoded_data.data(), encoded_data.size(),
|
encoded_data.data(), encoded_data.size(),
|
||||||
net::X509Certificate::FORMAT_AUTO);
|
net::X509Certificate::FORMAT_AUTO);
|
||||||
|
|
||||||
delegate->ContinueWithCertificate(certs[0].get());
|
delegate->ContinueWithCertificate(certs[0].get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PassLoginInformation(scoped_refptr<LoginHandler> login_handler,
|
||||||
|
mate::Arguments* args) {
|
||||||
|
base::string16 username, password;
|
||||||
|
if (args->GetNext(&username) && args->GetNext(&password))
|
||||||
|
login_handler->Login(username, password);
|
||||||
|
else
|
||||||
|
login_handler->CancelAuth();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
App::App() {
|
App::App() {
|
||||||
|
@ -233,6 +241,31 @@ void App::OnSelectCertificate(
|
||||||
cert_request_info->client_certs[0].get());
|
cert_request_info->client_certs[0].get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void App::OnLogin(LoginHandler* login_handler) {
|
||||||
|
// Convert the args explicitly since they will be passed for twice.
|
||||||
|
v8::Locker locker(isolate());
|
||||||
|
v8::HandleScope handle_scope(isolate());
|
||||||
|
auto web_contents =
|
||||||
|
WebContents::CreateFrom(isolate(), login_handler->GetWebContents());
|
||||||
|
auto request = mate::ConvertToV8(isolate(), login_handler->request());
|
||||||
|
auto auth_info = mate::ConvertToV8(isolate(), login_handler->auth_info());
|
||||||
|
auto callback = mate::ConvertToV8(
|
||||||
|
isolate(),
|
||||||
|
base::Bind(&PassLoginInformation, make_scoped_refptr(login_handler)));
|
||||||
|
|
||||||
|
bool prevent_default =
|
||||||
|
Emit("login", web_contents, request, auth_info, callback);
|
||||||
|
|
||||||
|
// Also pass it to WebContents.
|
||||||
|
if (!prevent_default)
|
||||||
|
prevent_default =
|
||||||
|
web_contents->Emit("login", request, auth_info, callback);
|
||||||
|
|
||||||
|
// Default behavior is to always cancel the auth.
|
||||||
|
if (!prevent_default)
|
||||||
|
login_handler->CancelAuth();
|
||||||
|
}
|
||||||
|
|
||||||
void App::OnGpuProcessCrashed(base::TerminationStatus exit_code) {
|
void App::OnGpuProcessCrashed(base::TerminationStatus exit_code) {
|
||||||
Emit("gpu-process-crashed");
|
Emit("gpu-process-crashed");
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,7 @@ class App : public mate::EventEmitter,
|
||||||
content::WebContents* web_contents,
|
content::WebContents* web_contents,
|
||||||
net::SSLCertRequestInfo* cert_request_info,
|
net::SSLCertRequestInfo* cert_request_info,
|
||||||
scoped_ptr<content::ClientCertificateDelegate> delegate) override;
|
scoped_ptr<content::ClientCertificateDelegate> delegate) override;
|
||||||
|
void OnLogin(LoginHandler* login_handler) override;
|
||||||
|
|
||||||
// content::GpuDataManagerObserver:
|
// content::GpuDataManagerObserver:
|
||||||
void OnGpuProcessCrashed(base::TerminationStatus exit_code) override;
|
void OnGpuProcessCrashed(base::TerminationStatus exit_code) override;
|
||||||
|
|
|
@ -12,27 +12,12 @@
|
||||||
#include "atom/browser/net/url_request_fetch_job.h"
|
#include "atom/browser/net/url_request_fetch_job.h"
|
||||||
#include "atom/browser/net/url_request_string_job.h"
|
#include "atom/browser/net/url_request_string_job.h"
|
||||||
#include "atom/common/native_mate_converters/callback.h"
|
#include "atom/common/native_mate_converters/callback.h"
|
||||||
|
#include "atom/common/native_mate_converters/content_converter.h"
|
||||||
#include "atom/common/node_includes.h"
|
#include "atom/common/node_includes.h"
|
||||||
#include "native_mate/dictionary.h"
|
#include "native_mate/dictionary.h"
|
||||||
|
|
||||||
using content::BrowserThread;
|
using content::BrowserThread;
|
||||||
|
|
||||||
namespace mate {
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct Converter<const net::URLRequest*> {
|
|
||||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
|
||||||
const net::URLRequest* val) {
|
|
||||||
return mate::ObjectTemplateBuilder(isolate)
|
|
||||||
.SetValue("method", val->method())
|
|
||||||
.SetValue("url", val->url().spec())
|
|
||||||
.SetValue("referrer", val->referrer())
|
|
||||||
.Build()->NewInstance();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace mate
|
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
namespace api {
|
namespace api {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include "atom/browser/atom_resource_dispatcher_host_delegate.h"
|
#include "atom/browser/atom_resource_dispatcher_host_delegate.h"
|
||||||
|
|
||||||
|
#include "atom/browser/login_handler.h"
|
||||||
#include "atom/common/platform_util.h"
|
#include "atom/common/platform_util.h"
|
||||||
#include "content/public/browser/browser_thread.h"
|
#include "content/public/browser/browser_thread.h"
|
||||||
#include "net/base/escape.h"
|
#include "net/base/escape.h"
|
||||||
|
@ -29,4 +30,11 @@ bool AtomResourceDispatcherHostDelegate::HandleExternalProtocol(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
content::ResourceDispatcherHostLoginDelegate*
|
||||||
|
AtomResourceDispatcherHostDelegate::CreateLoginDelegate(
|
||||||
|
net::AuthChallengeInfo* auth_info,
|
||||||
|
net::URLRequest* request) {
|
||||||
|
return new LoginHandler(auth_info, request);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace atom
|
} // namespace atom
|
||||||
|
|
|
@ -21,6 +21,9 @@ class AtomResourceDispatcherHostDelegate
|
||||||
bool is_main_frame,
|
bool is_main_frame,
|
||||||
ui::PageTransition transition,
|
ui::PageTransition transition,
|
||||||
bool has_user_gesture) override;
|
bool has_user_gesture) override;
|
||||||
|
content::ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
|
||||||
|
net::AuthChallengeInfo* auth_info,
|
||||||
|
net::URLRequest* request) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace atom
|
} // namespace atom
|
||||||
|
|
|
@ -134,6 +134,10 @@ void Browser::ClientCertificateSelector(
|
||||||
delegate.Pass()));
|
delegate.Pass()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Browser::RequestLogin(LoginHandler* login_handler) {
|
||||||
|
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnLogin(login_handler));
|
||||||
|
}
|
||||||
|
|
||||||
void Browser::NotifyAndShutdown() {
|
void Browser::NotifyAndShutdown() {
|
||||||
if (is_shutdown_)
|
if (is_shutdown_)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -29,6 +29,8 @@ class MenuModel;
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
|
class LoginHandler;
|
||||||
|
|
||||||
// This class is used for control application-wide operations.
|
// This class is used for control application-wide operations.
|
||||||
class Browser : public WindowListObserver {
|
class Browser : public WindowListObserver {
|
||||||
public:
|
public:
|
||||||
|
@ -122,6 +124,9 @@ class Browser : public WindowListObserver {
|
||||||
net::SSLCertRequestInfo* cert_request_info,
|
net::SSLCertRequestInfo* cert_request_info,
|
||||||
scoped_ptr<content::ClientCertificateDelegate> delegate);
|
scoped_ptr<content::ClientCertificateDelegate> delegate);
|
||||||
|
|
||||||
|
// Request basic auth login.
|
||||||
|
void RequestLogin(LoginHandler* login_handler);
|
||||||
|
|
||||||
void AddObserver(BrowserObserver* obs) {
|
void AddObserver(BrowserObserver* obs) {
|
||||||
observers_.AddObserver(obs);
|
observers_.AddObserver(obs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ class SSLCertRequestInfo;
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
|
class LoginHandler;
|
||||||
|
|
||||||
class BrowserObserver {
|
class BrowserObserver {
|
||||||
public:
|
public:
|
||||||
// The browser is about to close all windows.
|
// The browser is about to close all windows.
|
||||||
|
@ -57,6 +59,9 @@ class BrowserObserver {
|
||||||
net::SSLCertRequestInfo* cert_request_info,
|
net::SSLCertRequestInfo* cert_request_info,
|
||||||
scoped_ptr<content::ClientCertificateDelegate> delegate) {}
|
scoped_ptr<content::ClientCertificateDelegate> delegate) {}
|
||||||
|
|
||||||
|
// The browser requests HTTP login.
|
||||||
|
virtual void OnLogin(LoginHandler* login_handler) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~BrowserObserver() {}
|
virtual ~BrowserObserver() {}
|
||||||
};
|
};
|
||||||
|
|
109
atom/browser/login_handler.cc
Normal file
109
atom/browser/login_handler.cc
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
// 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/login_handler.h"
|
||||||
|
|
||||||
|
#include "atom/browser/browser.h"
|
||||||
|
#include "content/public/browser/browser_thread.h"
|
||||||
|
#include "content/public/browser/render_frame_host.h"
|
||||||
|
#include "content/public/browser/resource_dispatcher_host.h"
|
||||||
|
#include "content/public/browser/resource_request_info.h"
|
||||||
|
#include "content/public/browser/web_contents.h"
|
||||||
|
#include "net/base/auth.h"
|
||||||
|
#include "net/url_request/url_request.h"
|
||||||
|
|
||||||
|
using content::BrowserThread;
|
||||||
|
|
||||||
|
namespace atom {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Helper to remove the ref from an net::URLRequest to the LoginHandler.
|
||||||
|
// Should only be called from the IO thread, since it accesses an
|
||||||
|
// net::URLRequest.
|
||||||
|
void ResetLoginHandlerForRequest(net::URLRequest* request) {
|
||||||
|
content::ResourceDispatcherHost::Get()->ClearLoginDelegateForRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
LoginHandler::LoginHandler(net::AuthChallengeInfo* auth_info,
|
||||||
|
net::URLRequest* request)
|
||||||
|
: handled_auth_(false),
|
||||||
|
auth_info_(auth_info),
|
||||||
|
request_(request),
|
||||||
|
render_process_host_id_(0),
|
||||||
|
render_frame_id_(0) {
|
||||||
|
content::ResourceRequestInfo::ForRequest(request_)->GetAssociatedRenderFrame(
|
||||||
|
&render_process_host_id_, &render_frame_id_);
|
||||||
|
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
||||||
|
base::Bind(&Browser::RequestLogin,
|
||||||
|
base::Unretained(Browser::Get()),
|
||||||
|
make_scoped_refptr(this)));
|
||||||
|
}
|
||||||
|
|
||||||
|
LoginHandler::~LoginHandler() {
|
||||||
|
}
|
||||||
|
|
||||||
|
content::WebContents* LoginHandler::GetWebContents() const {
|
||||||
|
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||||
|
|
||||||
|
content::RenderFrameHost* rfh = content::RenderFrameHost::FromID(
|
||||||
|
render_process_host_id_, render_frame_id_);
|
||||||
|
return content::WebContents::FromRenderFrameHost(rfh);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoginHandler::Login(const base::string16& username,
|
||||||
|
const base::string16& password) {
|
||||||
|
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||||
|
if (TestAndSetAuthHandled())
|
||||||
|
return;
|
||||||
|
BrowserThread::PostTask(
|
||||||
|
BrowserThread::IO, FROM_HERE,
|
||||||
|
base::Bind(&LoginHandler::DoLogin, this, username, password));
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoginHandler::CancelAuth() {
|
||||||
|
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||||
|
if (TestAndSetAuthHandled())
|
||||||
|
return;
|
||||||
|
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||||
|
base::Bind(&LoginHandler::DoCancelAuth, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoginHandler::OnRequestCancelled() {
|
||||||
|
TestAndSetAuthHandled();
|
||||||
|
request_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marks authentication as handled and returns the previous handled state.
|
||||||
|
bool LoginHandler::TestAndSetAuthHandled() {
|
||||||
|
base::AutoLock lock(handled_auth_lock_);
|
||||||
|
bool was_handled = handled_auth_;
|
||||||
|
handled_auth_ = true;
|
||||||
|
return was_handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoginHandler::DoCancelAuth() {
|
||||||
|
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||||
|
|
||||||
|
if (request_) {
|
||||||
|
request_->CancelAuth();
|
||||||
|
// Verify that CancelAuth doesn't destroy the request via our delegate.
|
||||||
|
DCHECK(request_ != nullptr);
|
||||||
|
ResetLoginHandlerForRequest(request_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoginHandler::DoLogin(const base::string16& username,
|
||||||
|
const base::string16& password) {
|
||||||
|
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||||
|
|
||||||
|
if (request_) {
|
||||||
|
request_->SetAuth(net::AuthCredentials(username, password));
|
||||||
|
ResetLoginHandlerForRequest(request_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace atom
|
76
atom/browser/login_handler.h
Normal file
76
atom/browser/login_handler.h
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
// 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_LOGIN_HANDLER_H_
|
||||||
|
#define ATOM_BROWSER_LOGIN_HANDLER_H_
|
||||||
|
|
||||||
|
#include "base/strings/string16.h"
|
||||||
|
#include "base/synchronization/lock.h"
|
||||||
|
#include "content/public/browser/resource_dispatcher_host_login_delegate.h"
|
||||||
|
|
||||||
|
namespace content {
|
||||||
|
class WebContents;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace net {
|
||||||
|
class AuthChallengeInfo;
|
||||||
|
class URLRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace atom {
|
||||||
|
|
||||||
|
// Handles the HTTP basic auth, must be created on IO thread.
|
||||||
|
class LoginHandler : public content::ResourceDispatcherHostLoginDelegate {
|
||||||
|
public:
|
||||||
|
LoginHandler(net::AuthChallengeInfo* auth_info, net::URLRequest* request);
|
||||||
|
|
||||||
|
// Returns the WebContents associated with the request, must be called on UI
|
||||||
|
// thread.
|
||||||
|
content::WebContents* GetWebContents() const;
|
||||||
|
|
||||||
|
// The auth is cancelled, must be called on UI thread.
|
||||||
|
void CancelAuth();
|
||||||
|
|
||||||
|
// Login with |username| and |password|, must be called on UI thread.
|
||||||
|
void Login(const base::string16& username, const base::string16& password);
|
||||||
|
|
||||||
|
const net::AuthChallengeInfo* auth_info() const { return auth_info_.get(); }
|
||||||
|
const net::URLRequest* request() const { return request_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~LoginHandler() override;
|
||||||
|
|
||||||
|
// content::ResourceDispatcherHostLoginDelegate:
|
||||||
|
void OnRequestCancelled() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Must be called on IO thread.
|
||||||
|
void DoCancelAuth();
|
||||||
|
void DoLogin(const base::string16& username, const base::string16& password);
|
||||||
|
|
||||||
|
// Marks authentication as handled and returns the previous handled
|
||||||
|
// state.
|
||||||
|
bool TestAndSetAuthHandled();
|
||||||
|
|
||||||
|
// True if we've handled auth (Login or CancelAuth has been called).
|
||||||
|
bool handled_auth_;
|
||||||
|
mutable base::Lock handled_auth_lock_;
|
||||||
|
|
||||||
|
// Who/where/what asked for the authentication.
|
||||||
|
scoped_refptr<net::AuthChallengeInfo> auth_info_;
|
||||||
|
|
||||||
|
// The request that wants login data.
|
||||||
|
// This should only be accessed on the IO loop.
|
||||||
|
net::URLRequest* request_;
|
||||||
|
|
||||||
|
// Cached from the net::URLRequest, in case it goes NULL on us.
|
||||||
|
int render_process_host_id_;
|
||||||
|
int render_frame_id_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(LoginHandler);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace atom
|
||||||
|
|
||||||
|
#endif // ATOM_BROWSER_LOGIN_HANDLER_H_
|
|
@ -8,7 +8,6 @@
|
||||||
|
|
||||||
#include "atom/common/native_mate_converters/callback.h"
|
#include "atom/common/native_mate_converters/callback.h"
|
||||||
#include "atom/common/native_mate_converters/v8_value_converter.h"
|
#include "atom/common/native_mate_converters/v8_value_converter.h"
|
||||||
#include "native_mate/function_template.h"
|
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
|
@ -16,34 +15,14 @@ namespace internal {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct CallbackHolder {
|
|
||||||
ResponseCallback callback;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Cached JavaScript version of |HandlerCallback|.
|
|
||||||
v8::Persistent<v8::FunctionTemplate> g_handler_callback_;
|
|
||||||
|
|
||||||
// The callback which is passed to |handler|.
|
// The callback which is passed to |handler|.
|
||||||
void HandlerCallback(v8::Isolate* isolate,
|
void HandlerCallback(const ResponseCallback& callback, mate::Arguments* args) {
|
||||||
v8::Local<v8::External> external,
|
|
||||||
v8::Local<v8::Object> state,
|
|
||||||
mate::Arguments* args) {
|
|
||||||
// Check if the callback has already been called.
|
|
||||||
v8::Local<v8::String> called_symbol = mate::StringToSymbol(isolate, "called");
|
|
||||||
if (state->Has(called_symbol))
|
|
||||||
return; // no nothing
|
|
||||||
else
|
|
||||||
state->Set(called_symbol, v8::Boolean::New(isolate, true));
|
|
||||||
|
|
||||||
// If there is no argument passed then we failed.
|
// If there is no argument passed then we failed.
|
||||||
scoped_ptr<CallbackHolder> holder(
|
|
||||||
static_cast<CallbackHolder*>(external->Value()));
|
|
||||||
CHECK(holder);
|
|
||||||
v8::Local<v8::Value> value;
|
v8::Local<v8::Value> value;
|
||||||
if (!args->GetNext(&value)) {
|
if (!args->GetNext(&value)) {
|
||||||
content::BrowserThread::PostTask(
|
content::BrowserThread::PostTask(
|
||||||
content::BrowserThread::IO, FROM_HERE,
|
content::BrowserThread::IO, FROM_HERE,
|
||||||
base::Bind(holder->callback, false, nullptr));
|
base::Bind(callback, false, nullptr));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,42 +32,7 @@ void HandlerCallback(v8::Isolate* isolate,
|
||||||
scoped_ptr<base::Value> options(converter.FromV8Value(value, context));
|
scoped_ptr<base::Value> options(converter.FromV8Value(value, context));
|
||||||
content::BrowserThread::PostTask(
|
content::BrowserThread::PostTask(
|
||||||
content::BrowserThread::IO, FROM_HERE,
|
content::BrowserThread::IO, FROM_HERE,
|
||||||
base::Bind(holder->callback, true, base::Passed(&options)));
|
base::Bind(callback, true, base::Passed(&options)));
|
||||||
}
|
|
||||||
|
|
||||||
// func.bind(func, arg1, arg2).
|
|
||||||
// NB(zcbenz): Using C++11 version crashes VS.
|
|
||||||
v8::Local<v8::Value> BindFunctionWith(v8::Isolate* isolate,
|
|
||||||
v8::Local<v8::Context> context,
|
|
||||||
v8::Local<v8::Function> func,
|
|
||||||
v8::Local<v8::Value> arg1,
|
|
||||||
v8::Local<v8::Value> arg2) {
|
|
||||||
v8::MaybeLocal<v8::Value> bind = func->Get(mate::StringToV8(isolate, "bind"));
|
|
||||||
CHECK(!bind.IsEmpty());
|
|
||||||
v8::Local<v8::Function> bind_func =
|
|
||||||
v8::Local<v8::Function>::Cast(bind.ToLocalChecked());
|
|
||||||
v8::Local<v8::Value> converted[] = { func, arg1, arg2 };
|
|
||||||
return bind_func->Call(
|
|
||||||
context, func, arraysize(converted), converted).ToLocalChecked();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate the callback that will be passed to |handler|.
|
|
||||||
v8::MaybeLocal<v8::Value> GenerateCallback(v8::Isolate* isolate,
|
|
||||||
v8::Local<v8::Context> context,
|
|
||||||
const ResponseCallback& callback) {
|
|
||||||
// The FunctionTemplate is cached.
|
|
||||||
if (g_handler_callback_.IsEmpty())
|
|
||||||
g_handler_callback_.Reset(
|
|
||||||
isolate,
|
|
||||||
mate::CreateFunctionTemplate(isolate, base::Bind(&HandlerCallback)));
|
|
||||||
|
|
||||||
v8::Local<v8::FunctionTemplate> handler_callback =
|
|
||||||
v8::Local<v8::FunctionTemplate>::New(isolate, g_handler_callback_);
|
|
||||||
CallbackHolder* holder = new CallbackHolder;
|
|
||||||
holder->callback = callback;
|
|
||||||
return BindFunctionWith(isolate, context, handler_callback->GetFunction(),
|
|
||||||
v8::External::New(isolate, holder),
|
|
||||||
v8::Object::New(isolate));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -102,16 +46,9 @@ void AskForOptions(v8::Isolate* isolate,
|
||||||
v8::HandleScope handle_scope(isolate);
|
v8::HandleScope handle_scope(isolate);
|
||||||
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
||||||
v8::Context::Scope context_scope(context);
|
v8::Context::Scope context_scope(context);
|
||||||
// We don't convert the callback to C++ directly because creating
|
handler.Run(request,
|
||||||
// FunctionTemplate will cause memory leak since V8 never releases it. So we
|
mate::ConvertToV8(isolate,
|
||||||
// have to create the function object in JavaScript to work around it.
|
base::Bind(&HandlerCallback, callback)));
|
||||||
v8::MaybeLocal<v8::Value> wrapped_callback = GenerateCallback(
|
|
||||||
isolate, context, callback);
|
|
||||||
if (wrapped_callback.IsEmpty()) {
|
|
||||||
callback.Run(false, nullptr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
handler.Run(request, wrapped_callback.ToLocalChecked());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsErrorOptions(base::Value* value, int* error) {
|
bool IsErrorOptions(base::Value* value, int* error) {
|
||||||
|
|
78
atom/common/native_mate_converters/callback.cc
Normal file
78
atom/common/native_mate_converters/callback.cc
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
// Copyright (c) 2015 GitHub, Inc. All rights reserved.
|
||||||
|
// Use of this source code is governed by the MIT license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "atom/common/native_mate_converters/callback.h"
|
||||||
|
|
||||||
|
namespace mate {
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct TranslaterHolder {
|
||||||
|
Translater translater;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Cached JavaScript version of |CallTranslater|.
|
||||||
|
v8::Persistent<v8::FunctionTemplate> g_call_translater;
|
||||||
|
|
||||||
|
void CallTranslater(v8::Local<v8::External> external,
|
||||||
|
v8::Local<v8::Object> state,
|
||||||
|
mate::Arguments* args) {
|
||||||
|
v8::Isolate* isolate = args->isolate();
|
||||||
|
|
||||||
|
// Check if the callback has already been called.
|
||||||
|
v8::Local<v8::String> called_symbol = mate::StringToSymbol(isolate, "called");
|
||||||
|
if (state->Has(called_symbol)) {
|
||||||
|
args->ThrowError("callback can only be called for once");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
state->Set(called_symbol, v8::Boolean::New(isolate, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
TranslaterHolder* holder = static_cast<TranslaterHolder*>(external->Value());
|
||||||
|
holder->translater.Run(args);
|
||||||
|
delete holder;
|
||||||
|
}
|
||||||
|
|
||||||
|
// func.bind(func, arg1).
|
||||||
|
// NB(zcbenz): Using C++11 version crashes VS.
|
||||||
|
v8::Local<v8::Value> BindFunctionWith(v8::Isolate* isolate,
|
||||||
|
v8::Local<v8::Context> context,
|
||||||
|
v8::Local<v8::Function> func,
|
||||||
|
v8::Local<v8::Value> arg1,
|
||||||
|
v8::Local<v8::Value> arg2) {
|
||||||
|
v8::MaybeLocal<v8::Value> bind = func->Get(mate::StringToV8(isolate, "bind"));
|
||||||
|
CHECK(!bind.IsEmpty());
|
||||||
|
v8::Local<v8::Function> bind_func =
|
||||||
|
v8::Local<v8::Function>::Cast(bind.ToLocalChecked());
|
||||||
|
v8::Local<v8::Value> converted[] = { func, arg1, arg2 };
|
||||||
|
return bind_func->Call(
|
||||||
|
context, func, arraysize(converted), converted).ToLocalChecked();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
v8::Local<v8::Value> CreateFunctionFromTranslater(
|
||||||
|
v8::Isolate* isolate, const Translater& translater) {
|
||||||
|
// The FunctionTemplate is cached.
|
||||||
|
if (g_call_translater.IsEmpty())
|
||||||
|
g_call_translater.Reset(
|
||||||
|
isolate,
|
||||||
|
mate::CreateFunctionTemplate(isolate, base::Bind(&CallTranslater)));
|
||||||
|
|
||||||
|
v8::Local<v8::FunctionTemplate> call_translater =
|
||||||
|
v8::Local<v8::FunctionTemplate>::New(isolate, g_call_translater);
|
||||||
|
TranslaterHolder* holder = new TranslaterHolder;
|
||||||
|
holder->translater = translater;
|
||||||
|
return BindFunctionWith(isolate,
|
||||||
|
isolate->GetCurrentContext(),
|
||||||
|
call_translater->GetFunction(),
|
||||||
|
v8::External::New(isolate, holder),
|
||||||
|
v8::Object::New(isolate));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
} // namespace mate
|
|
@ -20,6 +20,7 @@ namespace internal {
|
||||||
|
|
||||||
typedef scoped_refptr<RefCountedPersistent<v8::Function> > SafeV8Function;
|
typedef scoped_refptr<RefCountedPersistent<v8::Function> > SafeV8Function;
|
||||||
|
|
||||||
|
// Helper to invoke a V8 function with C++ parameters.
|
||||||
template <typename Sig>
|
template <typename Sig>
|
||||||
struct V8FunctionInvoker {};
|
struct V8FunctionInvoker {};
|
||||||
|
|
||||||
|
@ -81,13 +82,36 @@ struct V8FunctionInvoker<ReturnType(ArgTypes...)> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Helper to pass a C++ funtion to JavaScript.
|
||||||
|
using Translater = base::Callback<void(Arguments* args)>;
|
||||||
|
v8::Local<v8::Value> CreateFunctionFromTranslater(
|
||||||
|
v8::Isolate* isolate, const Translater& translater);
|
||||||
|
|
||||||
|
// Calls callback with Arguments.
|
||||||
|
template <typename Sig>
|
||||||
|
struct NativeFunctionInvoker {};
|
||||||
|
|
||||||
|
template <typename ReturnType, typename... ArgTypes>
|
||||||
|
struct NativeFunctionInvoker<ReturnType(ArgTypes...)> {
|
||||||
|
static void Go(base::Callback<ReturnType(ArgTypes...)> val, Arguments* args) {
|
||||||
|
using Indices = typename IndicesGenerator<sizeof...(ArgTypes)>::type;
|
||||||
|
Invoker<Indices, ArgTypes...> invoker(args, 0);
|
||||||
|
if (invoker.IsOK())
|
||||||
|
invoker.DispatchToCallback(val);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
template<typename Sig>
|
template<typename Sig>
|
||||||
struct Converter<base::Callback<Sig> > {
|
struct Converter<base::Callback<Sig>> {
|
||||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||||
const base::Callback<Sig>& val) {
|
const base::Callback<Sig>& val) {
|
||||||
return CreateFunctionTemplate(isolate, val)->GetFunction();
|
// We don't use CreateFunctionTemplate here because it creates a new
|
||||||
|
// FunctionTemplate everytime, which is cached by V8 and causes leaks.
|
||||||
|
internal::Translater translater = base::Bind(
|
||||||
|
&internal::NativeFunctionInvoker<Sig>::Go, val);
|
||||||
|
return internal::CreateFunctionFromTranslater(isolate, translater);
|
||||||
}
|
}
|
||||||
static bool FromV8(v8::Isolate* isolate,
|
static bool FromV8(v8::Isolate* isolate,
|
||||||
v8::Local<v8::Value> val,
|
v8::Local<v8::Value> val,
|
||||||
|
|
34
atom/common/native_mate_converters/content_converter.cc
Normal file
34
atom/common/native_mate_converters/content_converter.cc
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// 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/common/native_mate_converters/content_converter.h"
|
||||||
|
|
||||||
|
#include "native_mate/dictionary.h"
|
||||||
|
#include "net/url_request/url_request.h"
|
||||||
|
|
||||||
|
namespace mate {
|
||||||
|
|
||||||
|
// static
|
||||||
|
v8::Local<v8::Value> Converter<const net::URLRequest*>::ToV8(
|
||||||
|
v8::Isolate* isolate, const net::URLRequest* val) {
|
||||||
|
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
|
||||||
|
dict.Set("method", val->method());
|
||||||
|
dict.Set("url", val->url().spec());
|
||||||
|
dict.Set("referrer", val->referrer());
|
||||||
|
return mate::ConvertToV8(isolate, dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
v8::Local<v8::Value> Converter<const net::AuthChallengeInfo*>::ToV8(
|
||||||
|
v8::Isolate* isolate, const net::AuthChallengeInfo* val) {
|
||||||
|
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
|
||||||
|
dict.Set("isProxy", val->is_proxy);
|
||||||
|
dict.Set("scheme", val->scheme);
|
||||||
|
dict.Set("host", val->challenger.host());
|
||||||
|
dict.Set("port", static_cast<uint32_t>(val->challenger.port()));
|
||||||
|
dict.Set("realm", val->realm);
|
||||||
|
return mate::ConvertToV8(isolate, dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mate
|
31
atom/common/native_mate_converters/content_converter.h
Normal file
31
atom/common/native_mate_converters/content_converter.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// 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_COMMON_NATIVE_MATE_CONVERTERS_CONTENT_CONVERTER_H_
|
||||||
|
#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_CONTENT_CONVERTER_H_
|
||||||
|
|
||||||
|
#include "native_mate/converter.h"
|
||||||
|
|
||||||
|
namespace net {
|
||||||
|
class AuthChallengeInfo;
|
||||||
|
class URLRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace mate {
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct Converter<const net::URLRequest*> {
|
||||||
|
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||||
|
const net::URLRequest* val);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct Converter<const net::AuthChallengeInfo*> {
|
||||||
|
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||||
|
const net::AuthChallengeInfo* val);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mate
|
||||||
|
|
||||||
|
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_CONTENT_CONVERTER_H_
|
|
@ -133,18 +133,23 @@ Emitted when a new [browserWindow](browser-window.md) is created.
|
||||||
|
|
||||||
### Event: 'select-certificate'
|
### Event: 'select-certificate'
|
||||||
|
|
||||||
Emitted when a client certificate is requested.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
* `event` Event
|
* `event` Event
|
||||||
* `webContents` [WebContents](browser-window.md#class-webcontents)
|
* `webContents` [WebContents](web-contents.md)
|
||||||
* `url` String
|
* `url` URL
|
||||||
* `certificateList` [Objects]
|
* `certificateList` [Objects]
|
||||||
* `data` PEM encoded data
|
* `data` PEM encoded data
|
||||||
* `issuerName` Issuer's Common Name
|
* `issuerName` Issuer's Common Name
|
||||||
* `callback` Function
|
* `callback` Function
|
||||||
|
|
||||||
|
Emitted when a client certificate is requested.
|
||||||
|
|
||||||
|
The `url` corresponds to the navigation entry requesting the client certificate
|
||||||
|
and `callback` needs to be called with an entry filtered from the list. Using
|
||||||
|
`event.preventDefault()` prevents the application from using the first
|
||||||
|
certificate from the store.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
app.on('select-certificate', function(event, host, url, list, callback) {
|
app.on('select-certificate', function(event, host, url, list, callback) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
@ -152,10 +157,36 @@ app.on('select-certificate', function(event, host, url, list, callback) {
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
The `url` corresponds to the navigation entry requesting the client certificate
|
### Event: 'login'
|
||||||
and `callback` needs to be called with an entry filtered from the list. Using
|
|
||||||
`event.preventDefault()` prevents the application from using the first
|
Returns:
|
||||||
certificate from the store.
|
|
||||||
|
* `event` Event
|
||||||
|
* `webContents` [WebContents](web-contents.md)
|
||||||
|
* `request` Object
|
||||||
|
* `method` String
|
||||||
|
* `url` URL
|
||||||
|
* `referrer` URL
|
||||||
|
* `authInfo` Object
|
||||||
|
* `isProxy` Boolean
|
||||||
|
* `scheme` String
|
||||||
|
* `host` String
|
||||||
|
* `port` Integer
|
||||||
|
* `realm` String
|
||||||
|
* `callback` Function
|
||||||
|
|
||||||
|
Emitted when `webContents` wants to do basic auth.
|
||||||
|
|
||||||
|
The default behavior is to cancel all authentications, to override this you
|
||||||
|
should prevent the default behavior with `event.preventDefault()` and call
|
||||||
|
`callback(username, password)` with the credentials.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
app.on('login', function(event, webContents, request, authInfo, callback) {
|
||||||
|
event.preventDefault();
|
||||||
|
callback('username', 'secret');
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
### Event: 'gpu-process-crashed'
|
### Event: 'gpu-process-crashed'
|
||||||
|
|
||||||
|
|
|
@ -167,6 +167,27 @@ Emitted when DevTools is closed.
|
||||||
|
|
||||||
Emitted when DevTools is focused / opened.
|
Emitted when DevTools is focused / opened.
|
||||||
|
|
||||||
|
### Event: 'login'
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
* `event` Event
|
||||||
|
* `request` Object
|
||||||
|
* `method` String
|
||||||
|
* `url` URL
|
||||||
|
* `referrer` URL
|
||||||
|
* `authInfo` Object
|
||||||
|
* `isProxy` Boolean
|
||||||
|
* `scheme` String
|
||||||
|
* `host` String
|
||||||
|
* `port` Integer
|
||||||
|
* `realm` String
|
||||||
|
* `callback` Function
|
||||||
|
|
||||||
|
Emitted when `webContents` wants to do basic auth.
|
||||||
|
|
||||||
|
The usage is the same with [the `login` event of `app`](app.md#event-login).
|
||||||
|
|
||||||
## Instance Methods
|
## Instance Methods
|
||||||
|
|
||||||
The `webContents` object has the following instance methods:
|
The `webContents` object has the following instance methods:
|
||||||
|
|
|
@ -150,6 +150,8 @@
|
||||||
'atom/browser/common_web_contents_delegate.h',
|
'atom/browser/common_web_contents_delegate.h',
|
||||||
'atom/browser/javascript_environment.cc',
|
'atom/browser/javascript_environment.cc',
|
||||||
'atom/browser/javascript_environment.h',
|
'atom/browser/javascript_environment.h',
|
||||||
|
'atom/browser/login_handler.cc',
|
||||||
|
'atom/browser/login_handler.h',
|
||||||
'atom/browser/mac/atom_application.h',
|
'atom/browser/mac/atom_application.h',
|
||||||
'atom/browser/mac/atom_application.mm',
|
'atom/browser/mac/atom_application.mm',
|
||||||
'atom/browser/mac/atom_application_delegate.h',
|
'atom/browser/mac/atom_application_delegate.h',
|
||||||
|
@ -302,7 +304,10 @@
|
||||||
'atom/common/native_mate_converters/accelerator_converter.h',
|
'atom/common/native_mate_converters/accelerator_converter.h',
|
||||||
'atom/common/native_mate_converters/blink_converter.cc',
|
'atom/common/native_mate_converters/blink_converter.cc',
|
||||||
'atom/common/native_mate_converters/blink_converter.h',
|
'atom/common/native_mate_converters/blink_converter.h',
|
||||||
|
'atom/common/native_mate_converters/callback.cc',
|
||||||
'atom/common/native_mate_converters/callback.h',
|
'atom/common/native_mate_converters/callback.h',
|
||||||
|
'atom/common/native_mate_converters/content_converter.cc',
|
||||||
|
'atom/common/native_mate_converters/content_converter.h',
|
||||||
'atom/common/native_mate_converters/file_path_converter.h',
|
'atom/common/native_mate_converters/file_path_converter.h',
|
||||||
'atom/common/native_mate_converters/gfx_converter.cc',
|
'atom/common/native_mate_converters/gfx_converter.cc',
|
||||||
'atom/common/native_mate_converters/gfx_converter.h',
|
'atom/common/native_mate_converters/gfx_converter.h',
|
||||||
|
|
|
@ -23,9 +23,12 @@ describe 'protocol module', ->
|
||||||
|
|
||||||
it 'does not crash when handler is called twice', (done) ->
|
it 'does not crash when handler is called twice', (done) ->
|
||||||
doubleHandler = (request, callback) ->
|
doubleHandler = (request, callback) ->
|
||||||
|
try
|
||||||
callback(text)
|
callback(text)
|
||||||
callback()
|
callback()
|
||||||
|
catch
|
||||||
protocol.registerStringProtocol protocolName, doubleHandler, (error) ->
|
protocol.registerStringProtocol protocolName, doubleHandler, (error) ->
|
||||||
|
return done(error) if error
|
||||||
$.ajax
|
$.ajax
|
||||||
url: "#{protocolName}://fake-host"
|
url: "#{protocolName}://fake-host"
|
||||||
success: (data) ->
|
success: (data) ->
|
||||||
|
@ -36,6 +39,7 @@ describe 'protocol module', ->
|
||||||
|
|
||||||
it 'sends error when callback is called with nothing', (done) ->
|
it 'sends error when callback is called with nothing', (done) ->
|
||||||
protocol.registerBufferProtocol protocolName, emptyHandler, (error) ->
|
protocol.registerBufferProtocol protocolName, emptyHandler, (error) ->
|
||||||
|
return done(error) if error
|
||||||
$.ajax
|
$.ajax
|
||||||
url: "#{protocolName}://fake-host"
|
url: "#{protocolName}://fake-host"
|
||||||
success: (data) ->
|
success: (data) ->
|
||||||
|
@ -48,6 +52,7 @@ describe 'protocol module', ->
|
||||||
handler = (request, callback) ->
|
handler = (request, callback) ->
|
||||||
setImmediate -> callback(text)
|
setImmediate -> callback(text)
|
||||||
protocol.registerStringProtocol protocolName, handler, (error) ->
|
protocol.registerStringProtocol protocolName, handler, (error) ->
|
||||||
|
return done(error) if error
|
||||||
$.ajax
|
$.ajax
|
||||||
url: "#{protocolName}://fake-host"
|
url: "#{protocolName}://fake-host"
|
||||||
success: (data) ->
|
success: (data) ->
|
||||||
|
@ -66,6 +71,7 @@ describe 'protocol module', ->
|
||||||
it 'sends string as response', (done) ->
|
it 'sends string as response', (done) ->
|
||||||
handler = (request, callback) -> callback(text)
|
handler = (request, callback) -> callback(text)
|
||||||
protocol.registerStringProtocol protocolName, handler, (error) ->
|
protocol.registerStringProtocol protocolName, handler, (error) ->
|
||||||
|
return done(error) if error
|
||||||
$.ajax
|
$.ajax
|
||||||
url: "#{protocolName}://fake-host"
|
url: "#{protocolName}://fake-host"
|
||||||
success: (data) ->
|
success: (data) ->
|
||||||
|
@ -77,6 +83,7 @@ describe 'protocol module', ->
|
||||||
it 'sends object as response', (done) ->
|
it 'sends object as response', (done) ->
|
||||||
handler = (request, callback) -> callback(data: text, mimeType: 'text/html')
|
handler = (request, callback) -> callback(data: text, mimeType: 'text/html')
|
||||||
protocol.registerStringProtocol protocolName, handler, (error) ->
|
protocol.registerStringProtocol protocolName, handler, (error) ->
|
||||||
|
return done(error) if error
|
||||||
$.ajax
|
$.ajax
|
||||||
url: "#{protocolName}://fake-host"
|
url: "#{protocolName}://fake-host"
|
||||||
success: (data, statux, request) ->
|
success: (data, statux, request) ->
|
||||||
|
@ -88,6 +95,7 @@ describe 'protocol module', ->
|
||||||
it 'fails when sending object other than string', (done) ->
|
it 'fails when sending object other than string', (done) ->
|
||||||
handler = (request, callback) -> callback(new Date)
|
handler = (request, callback) -> callback(new Date)
|
||||||
protocol.registerBufferProtocol protocolName, handler, (error) ->
|
protocol.registerBufferProtocol protocolName, handler, (error) ->
|
||||||
|
return done(error) if error
|
||||||
$.ajax
|
$.ajax
|
||||||
url: "#{protocolName}://fake-host"
|
url: "#{protocolName}://fake-host"
|
||||||
success: (data) ->
|
success: (data) ->
|
||||||
|
@ -102,6 +110,7 @@ describe 'protocol module', ->
|
||||||
it 'sends Buffer as response', (done) ->
|
it 'sends Buffer as response', (done) ->
|
||||||
handler = (request, callback) -> callback(buffer)
|
handler = (request, callback) -> callback(buffer)
|
||||||
protocol.registerBufferProtocol protocolName, handler, (error) ->
|
protocol.registerBufferProtocol protocolName, handler, (error) ->
|
||||||
|
return done(error) if error
|
||||||
$.ajax
|
$.ajax
|
||||||
url: "#{protocolName}://fake-host"
|
url: "#{protocolName}://fake-host"
|
||||||
success: (data) ->
|
success: (data) ->
|
||||||
|
@ -113,6 +122,7 @@ describe 'protocol module', ->
|
||||||
it 'sends object as response', (done) ->
|
it 'sends object as response', (done) ->
|
||||||
handler = (request, callback) -> callback(data: buffer, mimeType: 'text/html')
|
handler = (request, callback) -> callback(data: buffer, mimeType: 'text/html')
|
||||||
protocol.registerBufferProtocol protocolName, handler, (error) ->
|
protocol.registerBufferProtocol protocolName, handler, (error) ->
|
||||||
|
return done(error) if error
|
||||||
$.ajax
|
$.ajax
|
||||||
url: "#{protocolName}://fake-host"
|
url: "#{protocolName}://fake-host"
|
||||||
success: (data, statux, request) ->
|
success: (data, statux, request) ->
|
||||||
|
@ -124,6 +134,7 @@ describe 'protocol module', ->
|
||||||
it 'fails when sending string', (done) ->
|
it 'fails when sending string', (done) ->
|
||||||
handler = (request, callback) -> callback(text)
|
handler = (request, callback) -> callback(text)
|
||||||
protocol.registerBufferProtocol protocolName, handler, (error) ->
|
protocol.registerBufferProtocol protocolName, handler, (error) ->
|
||||||
|
return done(error) if error
|
||||||
$.ajax
|
$.ajax
|
||||||
url: "#{protocolName}://fake-host"
|
url: "#{protocolName}://fake-host"
|
||||||
success: (data) ->
|
success: (data) ->
|
||||||
|
@ -142,6 +153,7 @@ describe 'protocol module', ->
|
||||||
it 'sends file path as response', (done) ->
|
it 'sends file path as response', (done) ->
|
||||||
handler = (request, callback) -> callback(filePath)
|
handler = (request, callback) -> callback(filePath)
|
||||||
protocol.registerFileProtocol protocolName, handler, (error) ->
|
protocol.registerFileProtocol protocolName, handler, (error) ->
|
||||||
|
return done(error) if error
|
||||||
$.ajax
|
$.ajax
|
||||||
url: "#{protocolName}://fake-host"
|
url: "#{protocolName}://fake-host"
|
||||||
success: (data) ->
|
success: (data) ->
|
||||||
|
@ -153,6 +165,7 @@ describe 'protocol module', ->
|
||||||
it 'sends object as response', (done) ->
|
it 'sends object as response', (done) ->
|
||||||
handler = (request, callback) -> callback(path: filePath)
|
handler = (request, callback) -> callback(path: filePath)
|
||||||
protocol.registerFileProtocol protocolName, handler, (error) ->
|
protocol.registerFileProtocol protocolName, handler, (error) ->
|
||||||
|
return done(error) if error
|
||||||
$.ajax
|
$.ajax
|
||||||
url: "#{protocolName}://fake-host"
|
url: "#{protocolName}://fake-host"
|
||||||
success: (data, statux, request) ->
|
success: (data, statux, request) ->
|
||||||
|
@ -164,6 +177,7 @@ describe 'protocol module', ->
|
||||||
it 'can send normal file', (done) ->
|
it 'can send normal file', (done) ->
|
||||||
handler = (request, callback) -> callback(normalPath)
|
handler = (request, callback) -> callback(normalPath)
|
||||||
protocol.registerFileProtocol protocolName, handler, (error) ->
|
protocol.registerFileProtocol protocolName, handler, (error) ->
|
||||||
|
return done(error) if error
|
||||||
$.ajax
|
$.ajax
|
||||||
url: "#{protocolName}://fake-host"
|
url: "#{protocolName}://fake-host"
|
||||||
success: (data) ->
|
success: (data) ->
|
||||||
|
@ -176,6 +190,7 @@ describe 'protocol module', ->
|
||||||
fakeFilePath = path.join __dirname, 'fixtures', 'asar', 'a.asar', 'not-exist'
|
fakeFilePath = path.join __dirname, 'fixtures', 'asar', 'a.asar', 'not-exist'
|
||||||
handler = (request, callback) -> callback(fakeFilePath)
|
handler = (request, callback) -> callback(fakeFilePath)
|
||||||
protocol.registerBufferProtocol protocolName, handler, (error) ->
|
protocol.registerBufferProtocol protocolName, handler, (error) ->
|
||||||
|
return done(error) if error
|
||||||
$.ajax
|
$.ajax
|
||||||
url: "#{protocolName}://fake-host"
|
url: "#{protocolName}://fake-host"
|
||||||
success: (data) ->
|
success: (data) ->
|
||||||
|
@ -187,6 +202,7 @@ describe 'protocol module', ->
|
||||||
it 'fails when sending unsupported content', (done) ->
|
it 'fails when sending unsupported content', (done) ->
|
||||||
handler = (request, callback) -> callback(new Date)
|
handler = (request, callback) -> callback(new Date)
|
||||||
protocol.registerBufferProtocol protocolName, handler, (error) ->
|
protocol.registerBufferProtocol protocolName, handler, (error) ->
|
||||||
|
return done(error) if error
|
||||||
$.ajax
|
$.ajax
|
||||||
url: "#{protocolName}://fake-host"
|
url: "#{protocolName}://fake-host"
|
||||||
success: (data) ->
|
success: (data) ->
|
||||||
|
@ -206,6 +222,7 @@ describe 'protocol module', ->
|
||||||
url = "http://127.0.0.1:#{port}"
|
url = "http://127.0.0.1:#{port}"
|
||||||
handler = (request, callback) -> callback({url})
|
handler = (request, callback) -> callback({url})
|
||||||
protocol.registerHttpProtocol protocolName, handler, (error) ->
|
protocol.registerHttpProtocol protocolName, handler, (error) ->
|
||||||
|
return done(error) if error
|
||||||
$.ajax
|
$.ajax
|
||||||
url: "#{protocolName}://fake-host"
|
url: "#{protocolName}://fake-host"
|
||||||
success: (data) ->
|
success: (data) ->
|
||||||
|
@ -217,6 +234,7 @@ describe 'protocol module', ->
|
||||||
it 'fails when sending invalid url', (done) ->
|
it 'fails when sending invalid url', (done) ->
|
||||||
handler = (request, callback) -> callback({url: 'url'})
|
handler = (request, callback) -> callback({url: 'url'})
|
||||||
protocol.registerHttpProtocol protocolName, handler, (error) ->
|
protocol.registerHttpProtocol protocolName, handler, (error) ->
|
||||||
|
return done(error) if error
|
||||||
$.ajax
|
$.ajax
|
||||||
url: "#{protocolName}://fake-host"
|
url: "#{protocolName}://fake-host"
|
||||||
success: (data) ->
|
success: (data) ->
|
||||||
|
@ -228,6 +246,7 @@ describe 'protocol module', ->
|
||||||
it 'fails when sending unsupported content', (done) ->
|
it 'fails when sending unsupported content', (done) ->
|
||||||
handler = (request, callback) -> callback(new Date)
|
handler = (request, callback) -> callback(new Date)
|
||||||
protocol.registerHttpProtocol protocolName, handler, (error) ->
|
protocol.registerHttpProtocol protocolName, handler, (error) ->
|
||||||
|
return done(error) if error
|
||||||
$.ajax
|
$.ajax
|
||||||
url: "#{protocolName}://fake-host"
|
url: "#{protocolName}://fake-host"
|
||||||
success: (data) ->
|
success: (data) ->
|
||||||
|
@ -285,9 +304,12 @@ describe 'protocol module', ->
|
||||||
|
|
||||||
it 'does not crash when handler is called twice', (done) ->
|
it 'does not crash when handler is called twice', (done) ->
|
||||||
doubleHandler = (request, callback) ->
|
doubleHandler = (request, callback) ->
|
||||||
|
try
|
||||||
callback(text)
|
callback(text)
|
||||||
callback()
|
callback()
|
||||||
|
catch
|
||||||
protocol.interceptStringProtocol 'http', doubleHandler, (error) ->
|
protocol.interceptStringProtocol 'http', doubleHandler, (error) ->
|
||||||
|
return done(error) if error
|
||||||
$.ajax
|
$.ajax
|
||||||
url: 'http://fake-host'
|
url: 'http://fake-host'
|
||||||
success: (data) ->
|
success: (data) ->
|
||||||
|
@ -298,6 +320,7 @@ describe 'protocol module', ->
|
||||||
|
|
||||||
it 'sends error when callback is called with nothing', (done) ->
|
it 'sends error when callback is called with nothing', (done) ->
|
||||||
protocol.interceptBufferProtocol 'http', emptyHandler, (error) ->
|
protocol.interceptBufferProtocol 'http', emptyHandler, (error) ->
|
||||||
|
return done(error) if error
|
||||||
$.ajax
|
$.ajax
|
||||||
url: 'http://fake-host'
|
url: 'http://fake-host'
|
||||||
success: (data) ->
|
success: (data) ->
|
||||||
|
@ -310,6 +333,7 @@ describe 'protocol module', ->
|
||||||
it 'can intercept http protocol', (done) ->
|
it 'can intercept http protocol', (done) ->
|
||||||
handler = (request, callback) -> callback(text)
|
handler = (request, callback) -> callback(text)
|
||||||
protocol.interceptStringProtocol 'http', handler, (error) ->
|
protocol.interceptStringProtocol 'http', handler, (error) ->
|
||||||
|
return done(error) if error
|
||||||
$.ajax
|
$.ajax
|
||||||
url: 'http://fake-host'
|
url: 'http://fake-host'
|
||||||
success: (data) ->
|
success: (data) ->
|
||||||
|
@ -322,6 +346,7 @@ describe 'protocol module', ->
|
||||||
handler = (request, callback) ->
|
handler = (request, callback) ->
|
||||||
callback({mimeType: 'application/json', data: '{"value": 1}'})
|
callback({mimeType: 'application/json', data: '{"value": 1}'})
|
||||||
protocol.interceptStringProtocol 'http', handler, (error) ->
|
protocol.interceptStringProtocol 'http', handler, (error) ->
|
||||||
|
return done(error) if error
|
||||||
$.ajax
|
$.ajax
|
||||||
url: 'http://fake-host'
|
url: 'http://fake-host'
|
||||||
success: (data) ->
|
success: (data) ->
|
||||||
|
@ -335,6 +360,7 @@ describe 'protocol module', ->
|
||||||
it 'can intercept http protocol', (done) ->
|
it 'can intercept http protocol', (done) ->
|
||||||
handler = (request, callback) -> callback(new Buffer(text))
|
handler = (request, callback) -> callback(new Buffer(text))
|
||||||
protocol.interceptBufferProtocol 'http', handler, (error) ->
|
protocol.interceptBufferProtocol 'http', handler, (error) ->
|
||||||
|
return done(error) if error
|
||||||
$.ajax
|
$.ajax
|
||||||
url: 'http://fake-host'
|
url: 'http://fake-host'
|
||||||
success: (data) ->
|
success: (data) ->
|
||||||
|
|
Loading…
Add table
Reference in a new issue