refactor: ginify Session (#23569)

This commit is contained in:
Jeremy Apthorp 2020-05-19 10:18:12 -07:00 committed by GitHub
parent 3f3a760a01
commit de44d28c8e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 135 additions and 111 deletions

View file

@ -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');

View file

@ -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);
};

View file

@ -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

View file

@ -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:

View file

@ -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))

View file

@ -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);
}

View file

@ -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,

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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');
});
});
});

View file

@ -73,7 +73,7 @@ ifdescribe(features.isBuiltinSpellCheckerEnabled())('spellchecker', () => {
afterEach(async () => {
if (ses) {
await ses.clearStorageData();
ses.destroy();
ses = null as any;
}
});