electron/atom/browser/api/atom_api_protocol.h

192 lines
6.6 KiB
C
Raw Normal View History

// Copyright (c) 2013 GitHub, Inc.
2014-04-25 09:49:37 +00:00
// Use of this source code is governed by the MIT license that can be
2013-08-24 07:26:10 +00:00
// found in the LICENSE file.
#ifndef ATOM_BROWSER_API_ATOM_API_PROTOCOL_H_
#define ATOM_BROWSER_API_ATOM_API_PROTOCOL_H_
2013-08-24 08:38:19 +00:00
#include <string>
#include <map>
#include <vector>
2013-08-24 08:38:19 +00:00
#include "atom/browser/net/atom_url_request_job_factory.h"
2014-04-21 08:33:32 +00:00
#include "base/callback.h"
2015-08-13 12:10:05 +00:00
#include "base/containers/scoped_ptr_hash_map.h"
#include "content/public/browser/browser_thread.h"
2015-08-12 13:32:52 +00:00
#include "native_mate/arguments.h"
#include "native_mate/dictionary.h"
2014-04-21 08:33:32 +00:00
#include "native_mate/handle.h"
#include "native_mate/wrappable.h"
2014-04-21 08:33:32 +00:00
namespace net {
class URLRequest;
class URLRequestContextGetter;
2014-04-21 08:33:32 +00:00
}
2013-08-24 07:26:10 +00:00
namespace atom {
2015-06-18 08:59:03 +00:00
class AtomBrowserContext;
2014-04-21 08:33:32 +00:00
class AtomURLRequestJobFactory;
2013-08-24 07:26:10 +00:00
namespace api {
2016-05-08 11:14:14 +00:00
class Protocol : public mate::Wrappable<Protocol> {
2013-08-24 07:26:10 +00:00
public:
using Handler =
base::Callback<void(const net::URLRequest*, v8::Local<v8::Value>)>;
using CompletionCallback = base::Callback<void(v8::Local<v8::Value>)>;
2015-08-13 11:33:53 +00:00
using BooleanCallback = base::Callback<void(bool)>;
2015-07-09 09:18:45 +00:00
2016-05-08 11:14:14 +00:00
static mate::Handle<Protocol> Create(
v8::Isolate* isolate, AtomBrowserContext* browser_context);
2014-04-21 08:33:32 +00:00
2016-04-25 01:17:54 +00:00
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype);
2014-04-21 08:33:32 +00:00
2016-04-25 01:17:54 +00:00
protected:
2016-05-08 11:14:14 +00:00
Protocol(v8::Isolate* isolate, AtomBrowserContext* browser_context);
2013-08-24 07:26:10 +00:00
private:
// Possible errors.
enum ProtocolError {
PROTOCOL_OK, // no error
PROTOCOL_FAIL, // operation failed, should never occur
PROTOCOL_REGISTERED,
PROTOCOL_NOT_REGISTERED,
PROTOCOL_INTERCEPTED,
PROTOCOL_NOT_INTERCEPTED,
};
2014-04-21 08:33:32 +00:00
// The protocol handler that will create a protocol handler for certain
// request job.
template<typename RequestJob>
class CustomProtocolHandler
: public net::URLRequestJobFactory::ProtocolHandler {
public:
CustomProtocolHandler(
v8::Isolate* isolate,
net::URLRequestContextGetter* request_context,
const Handler& handler)
: isolate_(isolate),
request_context_(request_context),
handler_(handler) {}
~CustomProtocolHandler() override {}
net::URLRequestJob* MaybeCreateJob(
net::URLRequest* request,
net::NetworkDelegate* network_delegate) const override {
RequestJob* request_job = new RequestJob(request, network_delegate);
request_job->SetHandlerInfo(isolate_, request_context_, handler_);
return request_job;
}
private:
v8::Isolate* isolate_;
net::URLRequestContextGetter* request_context_;
Protocol::Handler handler_;
DISALLOW_COPY_AND_ASSIGN(CustomProtocolHandler);
};
2015-07-05 17:53:07 +00:00
// Register schemes that can handle service worker.
void RegisterServiceWorkerSchemes(const std::vector<std::string>& schemes);
// Register the protocol with certain request job.
template<typename RequestJob>
2015-08-13 11:26:18 +00:00
void RegisterProtocol(const std::string& scheme,
const Handler& handler,
2015-08-13 11:26:18 +00:00
mate::Arguments* args) {
CompletionCallback callback;
args->GetNext(&callback);
content::BrowserThread::PostTaskAndReplyWithResult(
content::BrowserThread::IO, FROM_HERE,
base::Bind(&Protocol::RegisterProtocolInIO<RequestJob>,
base::Unretained(this), scheme, handler),
base::Bind(&Protocol::OnIOCompleted,
base::Unretained(this), callback));
}
template<typename RequestJob>
ProtocolError RegisterProtocolInIO(const std::string& scheme,
const Handler& handler) {
if (job_factory_->IsHandledProtocol(scheme))
return PROTOCOL_REGISTERED;
2016-05-23 01:59:39 +00:00
std::unique_ptr<CustomProtocolHandler<RequestJob>> protocol_handler(
new CustomProtocolHandler<RequestJob>(
isolate(), request_context_getter_, handler));
2016-03-08 14:28:53 +00:00
if (job_factory_->SetProtocolHandler(scheme, std::move(protocol_handler)))
return PROTOCOL_OK;
else
return PROTOCOL_FAIL;
}
2015-08-13 11:33:53 +00:00
// Unregister the protocol handler that handles |scheme|.
2015-08-13 11:26:18 +00:00
void UnregisterProtocol(const std::string& scheme, mate::Arguments* args);
ProtocolError UnregisterProtocolInIO(const std::string& scheme);
2015-08-12 13:32:52 +00:00
2015-08-13 11:33:53 +00:00
// Whether the protocol has handler registered.
void IsProtocolHandled(const std::string& scheme,
2015-08-13 11:33:53 +00:00
const BooleanCallback& callback);
bool IsProtocolHandledInIO(const std::string& scheme);
2015-08-13 11:33:53 +00:00
2015-08-13 12:10:05 +00:00
// Replace the protocol handler with a new one.
template<typename RequestJob>
void InterceptProtocol(const std::string& scheme,
const Handler& handler,
mate::Arguments* args) {
CompletionCallback callback;
args->GetNext(&callback);
content::BrowserThread::PostTaskAndReplyWithResult(
content::BrowserThread::IO, FROM_HERE,
base::Bind(&Protocol::InterceptProtocolInIO<RequestJob>,
base::Unretained(this), scheme, handler),
base::Bind(&Protocol::OnIOCompleted,
base::Unretained(this), callback));
}
template<typename RequestJob>
ProtocolError InterceptProtocolInIO(const std::string& scheme,
const Handler& handler) {
if (!job_factory_->IsHandledProtocol(scheme))
return PROTOCOL_NOT_REGISTERED;
// It is possible a protocol is handled but can not be intercepted.
if (!job_factory_->HasProtocolHandler(scheme))
return PROTOCOL_FAIL;
if (ContainsKey(original_protocols_, scheme))
return PROTOCOL_INTERCEPTED;
2016-05-23 01:59:39 +00:00
std::unique_ptr<CustomProtocolHandler<RequestJob>> protocol_handler(
2015-08-13 12:10:05 +00:00
new CustomProtocolHandler<RequestJob>(
isolate(), request_context_getter_, handler));
original_protocols_.set(
scheme,
2016-03-08 14:28:53 +00:00
job_factory_->ReplaceProtocol(scheme, std::move(protocol_handler)));
2015-08-13 12:10:05 +00:00
return PROTOCOL_OK;
}
2015-08-13 12:19:02 +00:00
// Restore the |scheme| to its original protocol handler.
void UninterceptProtocol(const std::string& scheme, mate::Arguments* args);
ProtocolError UninterceptProtocolInIO(const std::string& scheme);
// Convert error code to JS exception and call the callback.
void OnIOCompleted(const CompletionCallback& callback, ProtocolError error);
// Convert error code to string.
std::string ErrorCodeToString(ProtocolError error);
2013-08-30 02:15:15 +00:00
net::URLRequestContextGetter* request_context_getter_;
2015-08-13 12:10:05 +00:00
// Map that stores the original protocols of schemes.
using OriginalProtocolsMap = base::ScopedPtrHashMap<
std::string,
2016-05-23 01:59:39 +00:00
std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>>;
2015-08-13 12:10:05 +00:00
OriginalProtocolsMap original_protocols_;
AtomURLRequestJobFactory* job_factory_; // weak ref
2013-08-30 02:15:15 +00:00
2014-04-21 08:33:32 +00:00
DISALLOW_COPY_AND_ASSIGN(Protocol);
2013-08-24 07:26:10 +00:00
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_PROTOCOL_H_