From de44d28c8e790d72249865eedfc6c81a4d874ccb Mon Sep 17 00:00:00 2001 From: Jeremy Apthorp Date: Tue, 19 May 2020 10:18:12 -0700 Subject: [PATCH] refactor: ginify Session (#23569) --- lib/browser/api/net.ts | 4 +- lib/browser/api/session.js | 8 +- shell/browser/api/electron_api_app.cc | 8 +- shell/browser/api/electron_api_app.h | 4 +- .../api/electron_api_data_pipe_holder.cc | 12 +- shell/browser/api/electron_api_session.cc | 120 +++++++++++------- shell/browser/api/electron_api_session.h | 44 ++++--- shell/browser/event_emitter_mixin.h | 2 + shell/browser/network_hints_handler_impl.cc | 4 +- spec-main/api-session-spec.ts | 38 ++---- spec-main/spellchecker-spec.ts | 2 +- 11 files changed, 135 insertions(+), 111 deletions(-) diff --git a/lib/browser/api/net.ts b/lib/browser/api/net.ts index 8b83aaa1ae3..6753850da95 100644 --- a/lib/browser/api/net.ts +++ b/lib/browser/api/net.ts @@ -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'); diff --git a/lib/browser/api/session.js b/lib/browser/api/session.js index 28b8b9192ec..fee2680bd27 100644 --- a/lib/browser/api/session.js +++ b/lib/browser/api/session.js @@ -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); -}; diff --git a/shell/browser/api/electron_api_app.cc b/shell/browser/api/electron_api_app.cc index e79fc439d48..5ca71f785c4 100644 --- a/shell/browser/api/electron_api_app.cc +++ b/shell/browser/api/electron_api_app.cc @@ -1448,9 +1448,15 @@ v8::Local App::GetDockAPI(v8::Isolate* isolate) { } #endif +// static +App* App::Get() { + static base::NoDestructor app(v8::Isolate::GetCurrent()); + return app.get(); +} + // static gin::Handle App::Create(v8::Isolate* isolate) { - return gin::CreateHandle(isolate, new App(isolate)); + return gin::CreateHandle(isolate, Get()); } // static diff --git a/shell/browser/api/electron_api_app.h b/shell/browser/api/electron_api_app.h index 8088a9abd0c..52380508039 100644 --- a/shell/browser/api/electron_api_app.h +++ b/shell/browser/api/electron_api_app.h @@ -56,6 +56,7 @@ class App : public ElectronBrowserClient::Delegate, base::RepeatingCallback, const gfx::Image&)>; static gin::Handle Create(v8::Isolate* isolate); + static App* Get(); static void BuildPrototype(v8::Isolate* isolate, v8::Local 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: diff --git a/shell/browser/api/electron_api_data_pipe_holder.cc b/shell/browser/api/electron_api_data_pipe_holder.cc index 176b8872044..23e29ecdfff 100644 --- a/shell/browser/api/electron_api_data_pipe_holder.cc +++ b/shell/browser/api/electron_api_data_pipe_holder.cc @@ -8,6 +8,7 @@ #include #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 g_weak_map; +KeyWeakMap& AllDataPipeHolders() { + static base::NoDestructor> weak_map; + return *weak_map.get(); +} // Utility class to read from data pipe. class DataPipeReader { @@ -164,15 +168,15 @@ gin::Handle 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::From(v8::Isolate* isolate, const std::string& id) { - v8::MaybeLocal object = g_weak_map.Get(isolate, id); + v8::MaybeLocal object = AllDataPipeHolders().Get(isolate, id); if (!object.IsEmpty()) { gin::Handle handle; if (gin::ConvertFromV8(isolate, object.ToLocalChecked(), &handle)) diff --git a/shell/browser/api/electron_api_session.cc b/shell/browser/api/electron_api_session.cc index 5d94a042472..68dc77efc95 100644 --- a/shell/browser/api/electron_api_session.cc +++ b/shell/browser/api/electron_api_session.cc @@ -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> g_sessions; - void DownloadIdCallback(content::DownloadManager* download_manager, const base::FilePath& path, const std::vector& 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(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 Session::ResolveProxy(gin_helper::Arguments* args) { +v8::Local Session::ResolveProxy(gin::Arguments* args) { v8::Isolate* isolate = args->isolate(); gin_helper::Promise promise(isolate); v8::Local handle = promise.GetHandle(); @@ -374,7 +382,7 @@ v8::Local Session::ClearCache() { return handle; } -v8::Local Session::ClearStorageData(gin_helper::Arguments* args) { +v8::Local Session::ClearStorageData(gin::Arguments* args) { v8::Isolate* isolate = args->isolate(); gin_helper::Promise promise(isolate); v8::Local handle = promise.GetHandle(); @@ -404,7 +412,7 @@ void Session::FlushStorageData() { storage_partition->Flush(); } -v8::Local Session::SetProxy(gin_helper::Arguments* args) { +v8::Local Session::SetProxy(gin::Arguments* args) { v8::Isolate* isolate = args->isolate(); gin_helper::Promise promise(isolate); v8::Local handle = promise.GetHandle(); @@ -477,10 +485,10 @@ void Session::DisableNetworkEmulation() { } void Session::SetCertVerifyProc(v8::Local 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 val, } void Session::SetPermissionRequestHandler(v8::Local val, - gin_helper::Arguments* args) { + gin::Arguments* args) { auto* permission_manager = static_cast( browser_context()->GetPermissionControllerDelegate()); if (val->IsNull()) { @@ -510,7 +518,7 @@ void Session::SetPermissionRequestHandler(v8::Local val, } auto handler = std::make_unique(); 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 val, } void Session::SetPermissionCheckHandler(v8::Local 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( @@ -538,8 +546,7 @@ void Session::SetPermissionCheckHandler(v8::Local val, permission_manager->SetPermissionCheckHandler(handler); } -v8::Local Session::ClearHostResolverCache( - gin_helper::Arguments* args) { +v8::Local Session::ClearHostResolverCache(gin::Arguments* args) { v8::Isolate* isolate = args->isolate(); gin_helper::Promise promise(isolate); v8::Local 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 Session::GetPreloads() const { #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS) v8::Local Session::LoadExtension( const base::FilePath& extension_path) { - gin_helper::Promise promise(isolate()); + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + gin_helper::Promise promise(isolate); v8::Local handle = promise.GetHandle(); if (browser_context()->IsOffTheRecord()) { promise.RejectWithErrorMessage( @@ -704,10 +713,11 @@ v8::Local 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 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 Session::ListWordsInSpellCheckerDictionary() { - gin_helper::Promise> promise(isolate()); + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + gin_helper::Promise> promise(isolate); v8::Local 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(context->GetUserData(kElectronApiSessionKey)); + return data ? data->session : nullptr; +} + // static gin::Handle 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(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(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()); return handle; } @@ -937,12 +960,10 @@ gin::Handle Session::FromPartition(v8::Isolate* isolate, return CreateFrom(isolate, browser_context.get()); } -// static -void Session::BuildPrototype(v8::Isolate* isolate, - v8::Local 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::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 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 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); } diff --git a/shell/browser/api/electron_api_session.h b/shell/browser/api/electron_api_session.h index 32f781b56d9..31d22622ee4 100644 --- a/shell/browser/api/electron_api_session.h +++ b/shell/browser/api/electron_api_session.h @@ -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, +class Session : public gin::Wrappable, + public gin_helper::Pinnable, + public gin_helper::EventEmitterMixin, #if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER) public SpellcheckHunspellDictionary::Observer, #endif @@ -51,6 +61,8 @@ class Session : public gin_helper::TrackableObject, v8::Isolate* isolate, ElectronBrowserContext* browser_context); + static Session* FromBrowserContext(content::BrowserContext* context); + // Gets the Session of |partition|. static gin::Handle FromPartition( v8::Isolate* isolate, @@ -61,30 +73,31 @@ class Session : public gin_helper::TrackableObject, return browser_context_.get(); } - // gin_helper::TrackableObject: - static void BuildPrototype(v8::Isolate* isolate, - v8::Local prototype); + // gin::Wrappable + static gin::WrapperInfo kWrapperInfo; + gin::ObjectTemplateBuilder GetObjectTemplateBuilder( + v8::Isolate* isolate) override; + const char* GetTypeName() override; // Methods. - v8::Local ResolveProxy(gin_helper::Arguments* args); + v8::Local ResolveProxy(gin::Arguments* args); v8::Local GetCacheSize(); v8::Local ClearCache(); - v8::Local ClearStorageData(gin_helper::Arguments* args); + v8::Local ClearStorageData(gin::Arguments* args); void FlushStorageData(); - v8::Local SetProxy(gin_helper::Arguments* args); + v8::Local SetProxy(gin::Arguments* args); void SetDownloadPath(const base::FilePath& path); void EnableNetworkEmulation(const gin_helper::Dictionary& options); void DisableNetworkEmulation(); - void SetCertVerifyProc(v8::Local proc, - gin_helper::Arguments* args); + void SetCertVerifyProc(v8::Local proc, gin::Arguments* args); void SetPermissionRequestHandler(v8::Local val, - gin_helper::Arguments* args); + gin::Arguments* args); void SetPermissionCheckHandler(v8::Local val, - gin_helper::Arguments* args); - v8::Local ClearHostResolverCache(gin_helper::Arguments* args); + gin::Arguments* args); + v8::Local ClearHostResolverCache(gin::Arguments* args); v8::Local 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 GetBlobData(v8::Isolate* isolate, @@ -98,8 +111,7 @@ class Session : public gin_helper::TrackableObject, v8::Local ServiceWorkerContext(v8::Isolate* isolate); v8::Local WebRequest(v8::Isolate* isolate); v8::Local 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, diff --git a/shell/browser/event_emitter_mixin.h b/shell/browser/event_emitter_mixin.h index 0bcb3ea13f2..abf943c3360 100644 --- a/shell/browser/event_emitter_mixin.h +++ b/shell/browser/event_emitter_mixin.h @@ -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(this)->GetTypeName())); constructor->Inherit(internal::GetEventEmitterTemplate(isolate)); data->SetFunctionTemplate(wrapper_info, constructor); } diff --git a/shell/browser/network_hints_handler_impl.cc b/shell/browser/network_hints_handler_impl.cc index 3cce9c4b673..aa550fb4e69 100644 --- a/shell/browser/network_hints_handler_impl.cc +++ b/shell/browser/network_hints_handler_impl.cc @@ -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(browser_context_)); + auto* session = electron::api::Session::FromBrowserContext(browser_context_); if (session) { session->Emit("preconnect", url, allow_credentials); } diff --git a/spec-main/api-session-spec.ts b/spec-main/api-session-spec.ts index bad8634afc6..f9a3865b7f4 100644 --- a/spec-main/api-session-spec.ts +++ b/spec-main/api-session-spec.ts @@ -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(resolve => app.once('session-created', resolve)); + session.fromPartition('' + Math.random()); + const s = await eventEmitted; + expect(s.constructor.name).to.equal('Session'); + }); + }); }); diff --git a/spec-main/spellchecker-spec.ts b/spec-main/spellchecker-spec.ts index d106595882b..1c13d31220f 100644 --- a/spec-main/spellchecker-spec.ts +++ b/spec-main/spellchecker-spec.ts @@ -73,7 +73,7 @@ ifdescribe(features.isBuiltinSpellCheckerEnabled())('spellchecker', () => { afterEach(async () => { if (ses) { await ses.clearStorageData(); - ses.destroy(); + ses = null as any; } });