refactor: ginify Session (#23569)
This commit is contained in:
parent
3f3a760a01
commit
de44d28c8e
11 changed files with 135 additions and 111 deletions
|
@ -2,7 +2,6 @@ import * as url from 'url';
|
|||
import { Readable, Writable } from 'stream';
|
||||
import { app } from 'electron';
|
||||
import { ClientRequestConstructorOptions, UploadProgress } from 'electron/main';
|
||||
const { Session } = process.electronBinding('session');
|
||||
const { net, Net, isValidHeaderName, isValidHeaderValue, createURLLoader } = process.electronBinding('net');
|
||||
|
||||
const kSupportedProtocols = new Set(['http:', 'https:']);
|
||||
|
@ -250,7 +249,8 @@ function parseOptions (optionsIn: ClientRequestConstructorOptions | string): Nod
|
|||
}
|
||||
}
|
||||
if (options.session) {
|
||||
if (options.session instanceof Session) {
|
||||
// Weak check, but it should be enough to catch 99% of accidental misuses.
|
||||
if (options.session.constructor && options.session.constructor.name === 'Session') {
|
||||
urlLoaderOptions.session = options.session;
|
||||
} else {
|
||||
throw new TypeError('`session` should be an instance of the Session class');
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
const { EventEmitter } = require('events');
|
||||
const { app, deprecate } = require('electron');
|
||||
const { fromPartition, Session } = process.electronBinding('session');
|
||||
const { fromPartition } = process.electronBinding('session');
|
||||
|
||||
// Public API.
|
||||
Object.defineProperties(exports, {
|
||||
|
@ -15,9 +15,3 @@ Object.defineProperties(exports, {
|
|||
value: fromPartition
|
||||
}
|
||||
});
|
||||
|
||||
Object.setPrototypeOf(Session.prototype, EventEmitter.prototype);
|
||||
|
||||
Session.prototype._init = function () {
|
||||
app.emit('session-created', this);
|
||||
};
|
||||
|
|
|
@ -1448,9 +1448,15 @@ v8::Local<v8::Value> App::GetDockAPI(v8::Isolate* isolate) {
|
|||
}
|
||||
#endif
|
||||
|
||||
// static
|
||||
App* App::Get() {
|
||||
static base::NoDestructor<App> app(v8::Isolate::GetCurrent());
|
||||
return app.get();
|
||||
}
|
||||
|
||||
// static
|
||||
gin::Handle<App> App::Create(v8::Isolate* isolate) {
|
||||
return gin::CreateHandle(isolate, new App(isolate));
|
||||
return gin::CreateHandle(isolate, Get());
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -56,6 +56,7 @@ class App : public ElectronBrowserClient::Delegate,
|
|||
base::RepeatingCallback<void(v8::Local<v8::Value>, const gfx::Image&)>;
|
||||
|
||||
static gin::Handle<App> Create(v8::Isolate* isolate);
|
||||
static App* Get();
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
@ -71,8 +72,9 @@ class App : public ElectronBrowserClient::Delegate,
|
|||
void RenderProcessReady(content::RenderProcessHost* host);
|
||||
void RenderProcessDisconnected(base::ProcessId host_pid);
|
||||
|
||||
protected:
|
||||
explicit App(v8::Isolate* isolate);
|
||||
|
||||
private:
|
||||
~App() override;
|
||||
|
||||
// BrowserObserver:
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/no_destructor.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "mojo/public/cpp/system/data_pipe.h"
|
||||
#include "mojo/public/cpp/system/simple_watcher.h"
|
||||
|
@ -27,7 +28,10 @@ namespace {
|
|||
int g_next_id = 0;
|
||||
|
||||
// Map that manages all the DataPipeHolder objects.
|
||||
KeyWeakMap<std::string> g_weak_map;
|
||||
KeyWeakMap<std::string>& AllDataPipeHolders() {
|
||||
static base::NoDestructor<KeyWeakMap<std::string>> weak_map;
|
||||
return *weak_map.get();
|
||||
}
|
||||
|
||||
// Utility class to read from data pipe.
|
||||
class DataPipeReader {
|
||||
|
@ -164,15 +168,15 @@ gin::Handle<DataPipeHolder> DataPipeHolder::Create(
|
|||
v8::Isolate* isolate,
|
||||
const network::DataElement& element) {
|
||||
auto handle = gin::CreateHandle(isolate, new DataPipeHolder(element));
|
||||
g_weak_map.Set(isolate, handle->id(),
|
||||
handle->GetWrapper(isolate).ToLocalChecked());
|
||||
AllDataPipeHolders().Set(isolate, handle->id(),
|
||||
handle->GetWrapper(isolate).ToLocalChecked());
|
||||
return handle;
|
||||
}
|
||||
|
||||
// static
|
||||
gin::Handle<DataPipeHolder> DataPipeHolder::From(v8::Isolate* isolate,
|
||||
const std::string& id) {
|
||||
v8::MaybeLocal<v8::Object> object = g_weak_map.Get(isolate, id);
|
||||
v8::MaybeLocal<v8::Object> object = AllDataPipeHolders().Get(isolate, id);
|
||||
if (!object.IsEmpty()) {
|
||||
gin::Handle<DataPipeHolder> handle;
|
||||
if (gin::ConvertFromV8(isolate, object.ToLocalChecked(), &handle))
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "content/public/browser/download_manager_delegate.h"
|
||||
#include "content/public/browser/network_service_instance.h"
|
||||
#include "content/public/browser/storage_partition.h"
|
||||
#include "gin/arguments.h"
|
||||
#include "mojo/public/cpp/bindings/pending_remote.h"
|
||||
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
|
||||
#include "net/base/completion_repeating_callback.h"
|
||||
|
@ -41,6 +42,7 @@
|
|||
#include "net/http/http_cache.h"
|
||||
#include "services/network/network_service.h"
|
||||
#include "services/network/public/cpp/features.h"
|
||||
#include "shell/browser/api/electron_api_app.h"
|
||||
#include "shell/browser/api/electron_api_cookies.h"
|
||||
#include "shell/browser/api/electron_api_data_pipe_holder.h"
|
||||
#include "shell/browser/api/electron_api_download_item.h"
|
||||
|
@ -186,9 +188,6 @@ namespace {
|
|||
|
||||
const char kPersistPrefix[] = "persist:";
|
||||
|
||||
// Referenced session objects.
|
||||
std::map<uint32_t, v8::Global<v8::Value>> g_sessions;
|
||||
|
||||
void DownloadIdCallback(content::DownloadManager* download_manager,
|
||||
const base::FilePath& path,
|
||||
const std::vector<GURL>& url_chain,
|
||||
|
@ -247,8 +246,18 @@ class DictionaryObserver final : public SpellcheckCustomDictionary::Observer {
|
|||
};
|
||||
#endif // BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
||||
|
||||
struct UserDataLink : base::SupportsUserData::Data {
|
||||
explicit UserDataLink(Session* ses) : session(ses) {}
|
||||
|
||||
Session* session;
|
||||
};
|
||||
|
||||
const void* kElectronApiSessionKey = &kElectronApiSessionKey;
|
||||
|
||||
} // namespace
|
||||
|
||||
gin::WrapperInfo Session::kWrapperInfo = {gin::kEmbedderNativeGin};
|
||||
|
||||
Session::Session(v8::Isolate* isolate, ElectronBrowserContext* browser_context)
|
||||
: network_emulation_token_(base::UnguessableToken::Create()),
|
||||
browser_context_(browser_context) {
|
||||
|
@ -260,8 +269,8 @@ Session::Session(v8::Isolate* isolate, ElectronBrowserContext* browser_context)
|
|||
|
||||
protocol_.Reset(isolate, Protocol::Create(isolate, browser_context).ToV8());
|
||||
|
||||
Init(isolate);
|
||||
AttachAsUserData(browser_context);
|
||||
browser_context->SetUserData(kElectronApiSessionKey,
|
||||
std::make_unique<UserDataLink>(this));
|
||||
|
||||
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
||||
SpellcheckService* service =
|
||||
|
@ -283,8 +292,6 @@ Session::~Session() {
|
|||
service->SetHunspellObserver(nullptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
g_sessions.erase(weak_map_id());
|
||||
}
|
||||
|
||||
void Session::OnDownloadCreated(content::DownloadManager* manager,
|
||||
|
@ -292,9 +299,10 @@ void Session::OnDownloadCreated(content::DownloadManager* manager,
|
|||
if (item->IsSavePackageDownload())
|
||||
return;
|
||||
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
auto handle = DownloadItem::FromOrCreate(isolate(), item);
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
v8::Locker locker(isolate);
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
auto handle = DownloadItem::FromOrCreate(isolate, item);
|
||||
if (item->GetState() == download::DownloadItem::INTERRUPTED)
|
||||
handle->SetSavePath(item->GetTargetFilePath());
|
||||
content::WebContents* web_contents =
|
||||
|
@ -321,7 +329,7 @@ void Session::OnHunspellDictionaryDownloadFailure(const std::string& language) {
|
|||
}
|
||||
#endif
|
||||
|
||||
v8::Local<v8::Promise> Session::ResolveProxy(gin_helper::Arguments* args) {
|
||||
v8::Local<v8::Promise> Session::ResolveProxy(gin::Arguments* args) {
|
||||
v8::Isolate* isolate = args->isolate();
|
||||
gin_helper::Promise<std::string> promise(isolate);
|
||||
v8::Local<v8::Promise> handle = promise.GetHandle();
|
||||
|
@ -374,7 +382,7 @@ v8::Local<v8::Promise> Session::ClearCache() {
|
|||
return handle;
|
||||
}
|
||||
|
||||
v8::Local<v8::Promise> Session::ClearStorageData(gin_helper::Arguments* args) {
|
||||
v8::Local<v8::Promise> Session::ClearStorageData(gin::Arguments* args) {
|
||||
v8::Isolate* isolate = args->isolate();
|
||||
gin_helper::Promise<void> promise(isolate);
|
||||
v8::Local<v8::Promise> handle = promise.GetHandle();
|
||||
|
@ -404,7 +412,7 @@ void Session::FlushStorageData() {
|
|||
storage_partition->Flush();
|
||||
}
|
||||
|
||||
v8::Local<v8::Promise> Session::SetProxy(gin_helper::Arguments* args) {
|
||||
v8::Local<v8::Promise> Session::SetProxy(gin::Arguments* args) {
|
||||
v8::Isolate* isolate = args->isolate();
|
||||
gin_helper::Promise<void> promise(isolate);
|
||||
v8::Local<v8::Promise> handle = promise.GetHandle();
|
||||
|
@ -477,10 +485,10 @@ void Session::DisableNetworkEmulation() {
|
|||
}
|
||||
|
||||
void Session::SetCertVerifyProc(v8::Local<v8::Value> val,
|
||||
gin_helper::Arguments* args) {
|
||||
gin::Arguments* args) {
|
||||
CertVerifierClient::CertVerifyProc proc;
|
||||
if (!(val->IsNull() || gin::ConvertFromV8(args->isolate(), val, &proc))) {
|
||||
args->ThrowError("Must pass null or function");
|
||||
args->ThrowTypeError("Must pass null or function");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -500,7 +508,7 @@ void Session::SetCertVerifyProc(v8::Local<v8::Value> val,
|
|||
}
|
||||
|
||||
void Session::SetPermissionRequestHandler(v8::Local<v8::Value> val,
|
||||
gin_helper::Arguments* args) {
|
||||
gin::Arguments* args) {
|
||||
auto* permission_manager = static_cast<ElectronPermissionManager*>(
|
||||
browser_context()->GetPermissionControllerDelegate());
|
||||
if (val->IsNull()) {
|
||||
|
@ -510,7 +518,7 @@ void Session::SetPermissionRequestHandler(v8::Local<v8::Value> val,
|
|||
}
|
||||
auto handler = std::make_unique<ElectronPermissionManager::RequestHandler>();
|
||||
if (!gin::ConvertFromV8(args->isolate(), val, handler.get())) {
|
||||
args->ThrowError("Must pass null or function");
|
||||
args->ThrowTypeError("Must pass null or function");
|
||||
return;
|
||||
}
|
||||
permission_manager->SetPermissionRequestHandler(base::BindRepeating(
|
||||
|
@ -527,10 +535,10 @@ void Session::SetPermissionRequestHandler(v8::Local<v8::Value> val,
|
|||
}
|
||||
|
||||
void Session::SetPermissionCheckHandler(v8::Local<v8::Value> val,
|
||||
gin_helper::Arguments* args) {
|
||||
gin::Arguments* args) {
|
||||
ElectronPermissionManager::CheckHandler handler;
|
||||
if (!(val->IsNull() || gin::ConvertFromV8(args->isolate(), val, &handler))) {
|
||||
args->ThrowError("Must pass null or function");
|
||||
args->ThrowTypeError("Must pass null or function");
|
||||
return;
|
||||
}
|
||||
auto* permission_manager = static_cast<ElectronPermissionManager*>(
|
||||
|
@ -538,8 +546,7 @@ void Session::SetPermissionCheckHandler(v8::Local<v8::Value> val,
|
|||
permission_manager->SetPermissionCheckHandler(handler);
|
||||
}
|
||||
|
||||
v8::Local<v8::Promise> Session::ClearHostResolverCache(
|
||||
gin_helper::Arguments* args) {
|
||||
v8::Local<v8::Promise> Session::ClearHostResolverCache(gin::Arguments* args) {
|
||||
v8::Isolate* isolate = args->isolate();
|
||||
gin_helper::Promise<void> promise(isolate);
|
||||
v8::Local<v8::Promise> handle = promise.GetHandle();
|
||||
|
@ -580,7 +587,7 @@ void Session::AllowNTLMCredentialsForDomains(const std::string& domains) {
|
|||
}
|
||||
|
||||
void Session::SetUserAgent(const std::string& user_agent,
|
||||
gin_helper::Arguments* args) {
|
||||
gin::Arguments* args) {
|
||||
browser_context_->SetUserAgent(user_agent);
|
||||
content::BrowserContext::GetDefaultStoragePartition(browser_context_.get())
|
||||
->GetNetworkContext()
|
||||
|
@ -629,14 +636,15 @@ void Session::CreateInterruptedDownload(const gin_helper::Dictionary& options) {
|
|||
options.Get("lastModified", &last_modified);
|
||||
options.Get("eTag", &etag);
|
||||
options.Get("startTime", &start_time);
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
if (path.empty() || url_chain.empty() || length == 0) {
|
||||
isolate()->ThrowException(v8::Exception::Error(gin::StringToV8(
|
||||
isolate(), "Must pass non-empty path, urlChain and length.")));
|
||||
isolate->ThrowException(v8::Exception::Error(gin::StringToV8(
|
||||
isolate, "Must pass non-empty path, urlChain and length.")));
|
||||
return;
|
||||
}
|
||||
if (offset >= length) {
|
||||
isolate()->ThrowException(v8::Exception::Error(gin::StringToV8(
|
||||
isolate(), "Must pass an offset value less than length.")));
|
||||
isolate->ThrowException(v8::Exception::Error(gin::StringToV8(
|
||||
isolate, "Must pass an offset value less than length.")));
|
||||
return;
|
||||
}
|
||||
auto* download_manager =
|
||||
|
@ -662,7 +670,8 @@ std::vector<base::FilePath::StringType> Session::GetPreloads() const {
|
|||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
v8::Local<v8::Promise> Session::LoadExtension(
|
||||
const base::FilePath& extension_path) {
|
||||
gin_helper::Promise<const extensions::Extension*> promise(isolate());
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
gin_helper::Promise<const extensions::Extension*> promise(isolate);
|
||||
v8::Local<v8::Promise> handle = promise.GetHandle();
|
||||
if (browser_context()->IsOffTheRecord()) {
|
||||
promise.RejectWithErrorMessage(
|
||||
|
@ -704,10 +713,11 @@ v8::Local<v8::Value> Session::GetExtension(const std::string& extension_id) {
|
|||
auto* registry = extensions::ExtensionRegistry::Get(browser_context());
|
||||
const extensions::Extension* extension =
|
||||
registry->GetInstalledExtension(extension_id);
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
if (extension) {
|
||||
return gin::ConvertToV8(isolate(), extension);
|
||||
return gin::ConvertToV8(isolate, extension);
|
||||
} else {
|
||||
return v8::Null(isolate());
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -719,7 +729,7 @@ v8::Local<v8::Value> Session::GetAllExtensions() {
|
|||
if (extension->location() != extensions::Manifest::COMPONENT)
|
||||
extensions_vector.emplace_back(extension.get());
|
||||
}
|
||||
return gin::ConvertToV8(isolate(), extensions_vector);
|
||||
return gin::ConvertToV8(v8::Isolate::GetCurrent(), extensions_vector);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -771,10 +781,11 @@ static void StartPreconnectOnUI(
|
|||
}
|
||||
|
||||
void Session::Preconnect(const gin_helper::Dictionary& options,
|
||||
gin_helper::Arguments* args) {
|
||||
gin::Arguments* args) {
|
||||
GURL url;
|
||||
if (!options.Get("url", &url) || !url.is_valid()) {
|
||||
args->ThrowError("Must pass non-empty valid url to session.preconnect.");
|
||||
args->ThrowTypeError(
|
||||
"Must pass non-empty valid url to session.preconnect.");
|
||||
return;
|
||||
}
|
||||
int num_sockets_to_preconnect = 1;
|
||||
|
@ -783,7 +794,7 @@ void Session::Preconnect(const gin_helper::Dictionary& options,
|
|||
const int kMaxSocketsToPreconnect = 6;
|
||||
if (num_sockets_to_preconnect < kMinSocketsToPreconnect ||
|
||||
num_sockets_to_preconnect > kMaxSocketsToPreconnect) {
|
||||
args->ThrowError(
|
||||
args->ThrowTypeError(
|
||||
base::StringPrintf("numSocketsToPreconnect is outside range [%d,%d]",
|
||||
kMinSocketsToPreconnect, kMaxSocketsToPreconnect));
|
||||
return;
|
||||
|
@ -833,7 +844,8 @@ void SetSpellCheckerDictionaryDownloadURL(gin_helper::ErrorThrower thrower,
|
|||
}
|
||||
|
||||
v8::Local<v8::Promise> Session::ListWordsInSpellCheckerDictionary() {
|
||||
gin_helper::Promise<std::set<std::string>> promise(isolate());
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
gin_helper::Promise<std::set<std::string>> promise(isolate);
|
||||
v8::Local<v8::Promise> handle = promise.GetHandle();
|
||||
|
||||
SpellcheckService* spellcheck =
|
||||
|
@ -898,21 +910,32 @@ bool Session::RemoveWordFromSpellCheckerDictionary(const std::string& word) {
|
|||
}
|
||||
#endif // BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
||||
|
||||
// static
|
||||
Session* Session::FromBrowserContext(content::BrowserContext* context) {
|
||||
UserDataLink* data =
|
||||
static_cast<UserDataLink*>(context->GetUserData(kElectronApiSessionKey));
|
||||
return data ? data->session : nullptr;
|
||||
}
|
||||
|
||||
// static
|
||||
gin::Handle<Session> Session::CreateFrom(
|
||||
v8::Isolate* isolate,
|
||||
ElectronBrowserContext* browser_context) {
|
||||
auto* existing = TrackableObject::FromWrappedClass(isolate, browser_context);
|
||||
Session* existing = FromBrowserContext(browser_context);
|
||||
if (existing)
|
||||
return gin::CreateHandle(isolate, static_cast<Session*>(existing));
|
||||
return gin::CreateHandle(isolate, existing);
|
||||
|
||||
auto handle =
|
||||
gin::CreateHandle(isolate, new Session(isolate, browser_context));
|
||||
|
||||
// The Sessions should never be garbage collected, since the common pattern is
|
||||
// to use partition strings, instead of using the Session object directly.
|
||||
g_sessions[handle->weak_map_id()] =
|
||||
v8::Global<v8::Value>(isolate, handle.ToV8());
|
||||
handle->Pin(isolate);
|
||||
ElectronBrowserMainParts::Get()->RegisterDestructionCallback(
|
||||
base::BindOnce([](Session* session) { delete session; }, handle.get()));
|
||||
|
||||
App::Get()->EmitCustomEvent("session-created",
|
||||
handle.ToV8().As<v8::Object>());
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
@ -937,12 +960,10 @@ gin::Handle<Session> Session::FromPartition(v8::Isolate* isolate,
|
|||
return CreateFrom(isolate, browser_context.get());
|
||||
}
|
||||
|
||||
// static
|
||||
void Session::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(gin::StringToV8(isolate, "Session"));
|
||||
gin_helper::Destroyable::MakeDestroyable(isolate, prototype);
|
||||
gin_helper::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
gin::ObjectTemplateBuilder Session::GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) {
|
||||
return gin_helper::EventEmitterMixin<Session>::GetObjectTemplateBuilder(
|
||||
isolate)
|
||||
.SetMethod("resolveProxy", &Session::ResolveProxy)
|
||||
.SetMethod("getCacheSize", &Session::GetCacheSize)
|
||||
.SetMethod("clearCache", &Session::ClearCache)
|
||||
|
@ -998,6 +1019,10 @@ void Session::BuildPrototype(v8::Isolate* isolate,
|
|||
.SetProperty("webRequest", &Session::WebRequest);
|
||||
}
|
||||
|
||||
const char* Session::GetTypeName() {
|
||||
return "Session";
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace electron
|
||||
|
@ -1010,9 +1035,9 @@ using electron::api::ServiceWorkerContext;
|
|||
using electron::api::Session;
|
||||
|
||||
v8::Local<v8::Value> FromPartition(const std::string& partition,
|
||||
gin_helper::Arguments* args) {
|
||||
gin::Arguments* args) {
|
||||
if (!electron::Browser::Get()->is_ready()) {
|
||||
args->ThrowError("Session can only be received when app is ready");
|
||||
args->ThrowTypeError("Session can only be received when app is ready");
|
||||
return v8::Null(args->isolate());
|
||||
}
|
||||
base::DictionaryValue options;
|
||||
|
@ -1027,9 +1052,6 @@ void Initialize(v8::Local<v8::Object> exports,
|
|||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
gin_helper::Dictionary dict(isolate, exports);
|
||||
dict.Set(
|
||||
"Session",
|
||||
Session::GetConstructor(isolate)->GetFunction(context).ToLocalChecked());
|
||||
dict.SetMethod("fromPartition", &FromPartition);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,9 +12,13 @@
|
|||
#include "content/public/browser/download_manager.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
#include "gin/handle.h"
|
||||
#include "gin/wrappable.h"
|
||||
#include "shell/browser/event_emitter_mixin.h"
|
||||
#include "shell/browser/net/resolve_proxy_helper.h"
|
||||
#include "shell/common/gin_helper/error_thrower.h"
|
||||
#include "shell/common/gin_helper/function_template_extensions.h"
|
||||
#include "shell/common/gin_helper/pinnable.h"
|
||||
#include "shell/common/gin_helper/promise.h"
|
||||
#include "shell/common/gin_helper/trackable_object.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
||||
#include "chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h" // nogncheck
|
||||
|
@ -30,6 +34,10 @@ namespace gin_helper {
|
|||
class Dictionary;
|
||||
}
|
||||
|
||||
namespace gin {
|
||||
class Arguments;
|
||||
}
|
||||
|
||||
namespace net {
|
||||
class ProxyConfig;
|
||||
}
|
||||
|
@ -40,7 +48,9 @@ class ElectronBrowserContext;
|
|||
|
||||
namespace api {
|
||||
|
||||
class Session : public gin_helper::TrackableObject<Session>,
|
||||
class Session : public gin::Wrappable<Session>,
|
||||
public gin_helper::Pinnable<Session>,
|
||||
public gin_helper::EventEmitterMixin<Session>,
|
||||
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
||||
public SpellcheckHunspellDictionary::Observer,
|
||||
#endif
|
||||
|
@ -51,6 +61,8 @@ class Session : public gin_helper::TrackableObject<Session>,
|
|||
v8::Isolate* isolate,
|
||||
ElectronBrowserContext* browser_context);
|
||||
|
||||
static Session* FromBrowserContext(content::BrowserContext* context);
|
||||
|
||||
// Gets the Session of |partition|.
|
||||
static gin::Handle<Session> FromPartition(
|
||||
v8::Isolate* isolate,
|
||||
|
@ -61,30 +73,31 @@ class Session : public gin_helper::TrackableObject<Session>,
|
|||
return browser_context_.get();
|
||||
}
|
||||
|
||||
// gin_helper::TrackableObject:
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
// gin::Wrappable
|
||||
static gin::WrapperInfo kWrapperInfo;
|
||||
gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) override;
|
||||
const char* GetTypeName() override;
|
||||
|
||||
// Methods.
|
||||
v8::Local<v8::Promise> ResolveProxy(gin_helper::Arguments* args);
|
||||
v8::Local<v8::Promise> ResolveProxy(gin::Arguments* args);
|
||||
v8::Local<v8::Promise> GetCacheSize();
|
||||
v8::Local<v8::Promise> ClearCache();
|
||||
v8::Local<v8::Promise> ClearStorageData(gin_helper::Arguments* args);
|
||||
v8::Local<v8::Promise> ClearStorageData(gin::Arguments* args);
|
||||
void FlushStorageData();
|
||||
v8::Local<v8::Promise> SetProxy(gin_helper::Arguments* args);
|
||||
v8::Local<v8::Promise> SetProxy(gin::Arguments* args);
|
||||
void SetDownloadPath(const base::FilePath& path);
|
||||
void EnableNetworkEmulation(const gin_helper::Dictionary& options);
|
||||
void DisableNetworkEmulation();
|
||||
void SetCertVerifyProc(v8::Local<v8::Value> proc,
|
||||
gin_helper::Arguments* args);
|
||||
void SetCertVerifyProc(v8::Local<v8::Value> proc, gin::Arguments* args);
|
||||
void SetPermissionRequestHandler(v8::Local<v8::Value> val,
|
||||
gin_helper::Arguments* args);
|
||||
gin::Arguments* args);
|
||||
void SetPermissionCheckHandler(v8::Local<v8::Value> val,
|
||||
gin_helper::Arguments* args);
|
||||
v8::Local<v8::Promise> ClearHostResolverCache(gin_helper::Arguments* args);
|
||||
gin::Arguments* args);
|
||||
v8::Local<v8::Promise> ClearHostResolverCache(gin::Arguments* args);
|
||||
v8::Local<v8::Promise> ClearAuthCache();
|
||||
void AllowNTLMCredentialsForDomains(const std::string& domains);
|
||||
void SetUserAgent(const std::string& user_agent, gin_helper::Arguments* args);
|
||||
void SetUserAgent(const std::string& user_agent, gin::Arguments* args);
|
||||
std::string GetUserAgent();
|
||||
bool IsPersistent();
|
||||
v8::Local<v8::Promise> GetBlobData(v8::Isolate* isolate,
|
||||
|
@ -98,8 +111,7 @@ class Session : public gin_helper::TrackableObject<Session>,
|
|||
v8::Local<v8::Value> ServiceWorkerContext(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> WebRequest(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> NetLog(v8::Isolate* isolate);
|
||||
void Preconnect(const gin_helper::Dictionary& options,
|
||||
gin_helper::Arguments* args);
|
||||
void Preconnect(const gin_helper::Dictionary& options, gin::Arguments* args);
|
||||
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
||||
base::Value GetSpellCheckerLanguages();
|
||||
void SetSpellCheckerLanguages(gin_helper::ErrorThrower thrower,
|
||||
|
|
|
@ -59,6 +59,8 @@ class EventEmitterMixin {
|
|||
data->GetFunctionTemplate(wrapper_info);
|
||||
if (constructor.IsEmpty()) {
|
||||
constructor = v8::FunctionTemplate::New(isolate);
|
||||
constructor->SetClassName(
|
||||
gin::StringToV8(isolate, static_cast<T*>(this)->GetTypeName()));
|
||||
constructor->Inherit(internal::GetEventEmitterTemplate(isolate));
|
||||
data->SetFunctionTemplate(wrapper_info, constructor);
|
||||
}
|
||||
|
|
|
@ -32,9 +32,7 @@ void NetworkHintsHandlerImpl::Preconnect(const GURL& url,
|
|||
if (!browser_context_) {
|
||||
return;
|
||||
}
|
||||
auto* session = electron::api::Session::FromWrappedClass(
|
||||
v8::Isolate::GetCurrent(),
|
||||
static_cast<electron::ElectronBrowserContext*>(browser_context_));
|
||||
auto* session = electron::api::Session::FromBrowserContext(browser_context_);
|
||||
if (session) {
|
||||
session->Emit("preconnect", url, allow_credentials);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import * as https from 'https';
|
|||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as ChildProcess from 'child_process';
|
||||
import { session, BrowserWindow, net, ipcMain, Session } from 'electron/main';
|
||||
import { app, session, BrowserWindow, net, ipcMain, Session } from 'electron/main';
|
||||
import * as send from 'send';
|
||||
import * as auth from 'basic-auth';
|
||||
import { closeAllWindows } from './window-helpers';
|
||||
|
@ -28,29 +28,6 @@ describe('session module', () => {
|
|||
it('returns existing session with same partition', () => {
|
||||
expect(session.fromPartition('test')).to.equal(session.fromPartition('test'));
|
||||
});
|
||||
|
||||
// TODO(codebytere): remove in Electron v8.0.0
|
||||
it.skip('created session is ref-counted (functions)', () => {
|
||||
const partition = 'test2';
|
||||
const userAgent = 'test-agent';
|
||||
const ses1 = session.fromPartition(partition);
|
||||
ses1.setUserAgent(userAgent);
|
||||
expect(ses1.getUserAgent()).to.equal(userAgent);
|
||||
ses1.destroy();
|
||||
const ses2 = session.fromPartition(partition);
|
||||
expect(ses2.getUserAgent()).to.not.equal(userAgent);
|
||||
});
|
||||
|
||||
it.skip('created session is ref-counted', () => {
|
||||
const partition = 'test2';
|
||||
const userAgent = 'test-agent';
|
||||
const ses1 = session.fromPartition(partition);
|
||||
ses1.setUserAgent(userAgent);
|
||||
expect(ses1.getUserAgent()).to.equal(userAgent);
|
||||
ses1.destroy();
|
||||
const ses2 = session.fromPartition(partition);
|
||||
expect(ses2.getUserAgent()).to.not.equal(userAgent);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ses.cookies', () => {
|
||||
|
@ -370,9 +347,7 @@ describe('session module', () => {
|
|||
if (server) {
|
||||
server.close();
|
||||
}
|
||||
if (customSession) {
|
||||
customSession.destroy();
|
||||
}
|
||||
customSession = null as any;
|
||||
});
|
||||
|
||||
it('allows configuring proxy settings', async () => {
|
||||
|
@ -966,4 +941,13 @@ describe('session module', () => {
|
|||
expect(headers!['user-agent']).to.equal(userAgent);
|
||||
});
|
||||
});
|
||||
|
||||
describe('session-created event', () => {
|
||||
it('is emitted when a session is created', async () => {
|
||||
const eventEmitted = new Promise<Session>(resolve => app.once('session-created', resolve));
|
||||
session.fromPartition('' + Math.random());
|
||||
const s = await eventEmitted;
|
||||
expect(s.constructor.name).to.equal('Session');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -73,7 +73,7 @@ ifdescribe(features.isBuiltinSpellCheckerEnabled())('spellchecker', () => {
|
|||
afterEach(async () => {
|
||||
if (ses) {
|
||||
await ses.clearStorageData();
|
||||
ses.destroy();
|
||||
ses = null as any;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue