Merge pull request #13734 from electron/backport-13727-3-0-x
fix: use context counter as contextId (backport 3-0-x)
This commit is contained in:
commit
8bd5c1f858
9 changed files with 51 additions and 39 deletions
|
@ -12,20 +12,10 @@
|
||||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||||
#include "atom/common/node_includes.h"
|
#include "atom/common/node_includes.h"
|
||||||
#include "base/hash.h"
|
#include "base/hash.h"
|
||||||
#include "base/process/process_handle.h"
|
|
||||||
#include "base/strings/stringprintf.h"
|
|
||||||
#include "native_mate/dictionary.h"
|
#include "native_mate/dictionary.h"
|
||||||
#include "url/origin.h"
|
#include "url/origin.h"
|
||||||
#include "v8/include/v8-profiler.h"
|
#include "v8/include/v8-profiler.h"
|
||||||
|
|
||||||
// This is defined in later versions of Chromium, remove this if you see
|
|
||||||
// compiler complaining duplicate defines.
|
|
||||||
#if defined(OS_WIN) || defined(OS_FUCHSIA)
|
|
||||||
#define CrPRIdPid "ld"
|
|
||||||
#else
|
|
||||||
#define CrPRIdPid "d"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
|
|
||||||
// The hash function used by DoubleIDWeakMap.
|
// The hash function used by DoubleIDWeakMap.
|
||||||
|
@ -100,16 +90,6 @@ int32_t GetObjectHash(v8::Local<v8::Object> object) {
|
||||||
return object->GetIdentityHash();
|
return object->GetIdentityHash();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetContextID(v8::Isolate* isolate) {
|
|
||||||
// When a page is reloaded, V8 and blink may have optimizations that do not
|
|
||||||
// free blink::WebLocalFrame and v8::Context and reuse them for the new page,
|
|
||||||
// while we always recreate node::Environment when a page is loaded.
|
|
||||||
// So the only reliable way to return an identity for a page, is to return the
|
|
||||||
// address of the node::Environment instance.
|
|
||||||
node::Environment* env = node::Environment::GetCurrent(isolate);
|
|
||||||
return base::StringPrintf("%" CrPRIdPid "-%p", base::GetCurrentProcId(), env);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TakeHeapSnapshot(v8::Isolate* isolate) {
|
void TakeHeapSnapshot(v8::Isolate* isolate) {
|
||||||
isolate->GetHeapProfiler()->TakeHeapSnapshot();
|
isolate->GetHeapProfiler()->TakeHeapSnapshot();
|
||||||
}
|
}
|
||||||
|
@ -132,7 +112,6 @@ void Initialize(v8::Local<v8::Object> exports,
|
||||||
dict.SetMethod("setHiddenValue", &SetHiddenValue);
|
dict.SetMethod("setHiddenValue", &SetHiddenValue);
|
||||||
dict.SetMethod("deleteHiddenValue", &DeleteHiddenValue);
|
dict.SetMethod("deleteHiddenValue", &DeleteHiddenValue);
|
||||||
dict.SetMethod("getObjectHash", &GetObjectHash);
|
dict.SetMethod("getObjectHash", &GetObjectHash);
|
||||||
dict.SetMethod("getContextId", &GetContextID);
|
|
||||||
dict.SetMethod("takeHeapSnapshot", &TakeHeapSnapshot);
|
dict.SetMethod("takeHeapSnapshot", &TakeHeapSnapshot);
|
||||||
dict.SetMethod("setRemoteCallbackFreer", &atom::RemoteCallbackFreer::BindTo);
|
dict.SetMethod("setRemoteCallbackFreer", &atom::RemoteCallbackFreer::BindTo);
|
||||||
dict.SetMethod("setRemoteObjectFreer", &atom::RemoteObjectFreer::BindTo);
|
dict.SetMethod("setRemoteObjectFreer", &atom::RemoteObjectFreer::BindTo);
|
||||||
|
|
|
@ -79,6 +79,8 @@ void AtomRendererClient::RunScriptsAtDocumentEnd(
|
||||||
void AtomRendererClient::DidCreateScriptContext(
|
void AtomRendererClient::DidCreateScriptContext(
|
||||||
v8::Handle<v8::Context> context,
|
v8::Handle<v8::Context> context,
|
||||||
content::RenderFrame* render_frame) {
|
content::RenderFrame* render_frame) {
|
||||||
|
RendererClientBase::DidCreateScriptContext(context, render_frame);
|
||||||
|
|
||||||
// Only allow node integration for the main frame, unless it is a devtools
|
// Only allow node integration for the main frame, unless it is a devtools
|
||||||
// extension page.
|
// extension page.
|
||||||
if (!render_frame->IsMainFrame() && !IsDevToolsExtension(render_frame))
|
if (!render_frame->IsMainFrame() && !IsDevToolsExtension(render_frame))
|
||||||
|
|
|
@ -153,6 +153,8 @@ void AtomSandboxedRendererClient::RenderViewCreated(
|
||||||
void AtomSandboxedRendererClient::DidCreateScriptContext(
|
void AtomSandboxedRendererClient::DidCreateScriptContext(
|
||||||
v8::Handle<v8::Context> context,
|
v8::Handle<v8::Context> context,
|
||||||
content::RenderFrame* render_frame) {
|
content::RenderFrame* render_frame) {
|
||||||
|
RendererClientBase::DidCreateScriptContext(context, render_frame);
|
||||||
|
|
||||||
// Only allow preload for the main frame or
|
// Only allow preload for the main frame or
|
||||||
// For devtools we still want to run the preload_bundle script
|
// For devtools we still want to run the preload_bundle script
|
||||||
if (!render_frame->IsMainFrame() && !IsDevTools(render_frame))
|
if (!render_frame->IsMainFrame() && !IsDevTools(render_frame))
|
||||||
|
|
|
@ -17,7 +17,9 @@
|
||||||
#include "atom/renderer/guest_view_container.h"
|
#include "atom/renderer/guest_view_container.h"
|
||||||
#include "atom/renderer/preferences_manager.h"
|
#include "atom/renderer/preferences_manager.h"
|
||||||
#include "base/command_line.h"
|
#include "base/command_line.h"
|
||||||
|
#include "base/process/process_handle.h"
|
||||||
#include "base/strings/string_split.h"
|
#include "base/strings/string_split.h"
|
||||||
|
#include "base/strings/stringprintf.h"
|
||||||
#include "chrome/renderer/media/chrome_key_systems.h"
|
#include "chrome/renderer/media/chrome_key_systems.h"
|
||||||
#include "chrome/renderer/pepper/pepper_helper.h"
|
#include "chrome/renderer/pepper/pepper_helper.h"
|
||||||
#include "chrome/renderer/printing/print_web_view_helper.h"
|
#include "chrome/renderer/printing/print_web_view_helper.h"
|
||||||
|
@ -46,6 +48,14 @@
|
||||||
#include "atom/common/atom_constants.h"
|
#include "atom/common/atom_constants.h"
|
||||||
#endif // defined(ENABLE_PDF_VIEWER)
|
#endif // defined(ENABLE_PDF_VIEWER)
|
||||||
|
|
||||||
|
// This is defined in later versions of Chromium, remove this if you see
|
||||||
|
// compiler complaining duplicate defines.
|
||||||
|
#if defined(OS_WIN) || defined(OS_FUCHSIA)
|
||||||
|
#define CrPRIdPid "ld"
|
||||||
|
#else
|
||||||
|
#define CrPRIdPid "d"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -80,6 +90,19 @@ RendererClientBase::RendererClientBase() {
|
||||||
|
|
||||||
RendererClientBase::~RendererClientBase() {}
|
RendererClientBase::~RendererClientBase() {}
|
||||||
|
|
||||||
|
void RendererClientBase::DidCreateScriptContext(
|
||||||
|
v8::Handle<v8::Context> context,
|
||||||
|
content::RenderFrame* render_frame) {
|
||||||
|
// global.setHidden("contextId", `${processId}-${++nextContextId}`)
|
||||||
|
std::string context_id = base::StringPrintf(
|
||||||
|
"%" CrPRIdPid "-%d", base::GetCurrentProcId(), ++next_context_id_);
|
||||||
|
v8::Isolate* isolate = context->GetIsolate();
|
||||||
|
v8::Local<v8::String> key = mate::StringToSymbol(isolate, "contextId");
|
||||||
|
v8::Local<v8::Private> private_key = v8::Private::ForApi(isolate, key);
|
||||||
|
v8::Local<v8::Value> value = mate::ConvertToV8(isolate, context_id);
|
||||||
|
context->Global()->SetPrivate(context, private_key, value);
|
||||||
|
}
|
||||||
|
|
||||||
void RendererClientBase::AddRenderBindings(
|
void RendererClientBase::AddRenderBindings(
|
||||||
v8::Isolate* isolate,
|
v8::Isolate* isolate,
|
||||||
v8::Local<v8::Object> binding_object) {
|
v8::Local<v8::Object> binding_object) {
|
||||||
|
|
|
@ -21,7 +21,7 @@ class RendererClientBase : public content::ContentRendererClient {
|
||||||
~RendererClientBase() override;
|
~RendererClientBase() override;
|
||||||
|
|
||||||
virtual void DidCreateScriptContext(v8::Handle<v8::Context> context,
|
virtual void DidCreateScriptContext(v8::Handle<v8::Context> context,
|
||||||
content::RenderFrame* render_frame) = 0;
|
content::RenderFrame* render_frame);
|
||||||
virtual void WillReleaseScriptContext(v8::Handle<v8::Context> context,
|
virtual void WillReleaseScriptContext(v8::Handle<v8::Context> context,
|
||||||
content::RenderFrame* render_frame) = 0;
|
content::RenderFrame* render_frame) = 0;
|
||||||
virtual void DidClearWindowObject(content::RenderFrame* render_frame);
|
virtual void DidClearWindowObject(content::RenderFrame* render_frame);
|
||||||
|
@ -57,6 +57,9 @@ class RendererClientBase : public content::ContentRendererClient {
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<PreferencesManager> preferences_manager_;
|
std::unique_ptr<PreferencesManager> preferences_manager_;
|
||||||
bool isolated_world_;
|
bool isolated_world_;
|
||||||
|
|
||||||
|
// An increasing ID used for indentifying an V8 context in this process.
|
||||||
|
int next_context_id_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace atom
|
} // namespace atom
|
||||||
|
|
|
@ -11,7 +11,7 @@ class ObjectsRegistry {
|
||||||
this.storage = {}
|
this.storage = {}
|
||||||
|
|
||||||
// Stores the IDs of objects referenced by WebContents.
|
// Stores the IDs of objects referenced by WebContents.
|
||||||
// (webContentsId) => [id]
|
// (webContentsContextId) => [id]
|
||||||
this.owners = {}
|
this.owners = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,9 +22,10 @@ class ObjectsRegistry {
|
||||||
const id = this.saveToStorage(obj)
|
const id = this.saveToStorage(obj)
|
||||||
|
|
||||||
// Add object to the set of referenced objects.
|
// Add object to the set of referenced objects.
|
||||||
let owner = this.owners[contextId]
|
const webContentsContextId = `${webContents.id}-${contextId}`
|
||||||
|
let owner = this.owners[webContentsContextId]
|
||||||
if (!owner) {
|
if (!owner) {
|
||||||
owner = this.owners[contextId] = new Set()
|
owner = this.owners[webContentsContextId] = new Set()
|
||||||
this.registerDeleteListener(webContents, contextId)
|
this.registerDeleteListener(webContents, contextId)
|
||||||
}
|
}
|
||||||
if (!owner.has(id)) {
|
if (!owner.has(id)) {
|
||||||
|
@ -44,8 +45,9 @@ class ObjectsRegistry {
|
||||||
// Dereference an object according to its ID.
|
// Dereference an object according to its ID.
|
||||||
// Note that an object may be double-freed (cleared when page is reloaded, and
|
// Note that an object may be double-freed (cleared when page is reloaded, and
|
||||||
// then garbage collected in old page).
|
// then garbage collected in old page).
|
||||||
remove (contextId, id) {
|
remove (webContents, contextId, id) {
|
||||||
let owner = this.owners[contextId]
|
const webContentsContextId = `${webContents.id}-${contextId}`
|
||||||
|
let owner = this.owners[webContentsContextId]
|
||||||
if (owner) {
|
if (owner) {
|
||||||
// Remove the reference in owner.
|
// Remove the reference in owner.
|
||||||
owner.delete(id)
|
owner.delete(id)
|
||||||
|
@ -55,13 +57,14 @@ class ObjectsRegistry {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear all references to objects refrenced by the WebContents.
|
// Clear all references to objects refrenced by the WebContents.
|
||||||
clear (contextId) {
|
clear (webContents, contextId) {
|
||||||
let owner = this.owners[contextId]
|
const webContentsContextId = `${webContents.id}-${contextId}`
|
||||||
|
let owner = this.owners[webContentsContextId]
|
||||||
if (!owner) return
|
if (!owner) return
|
||||||
|
|
||||||
for (let id of owner) this.dereference(id)
|
for (let id of owner) this.dereference(id)
|
||||||
|
|
||||||
delete this.owners[contextId]
|
delete this.owners[webContentsContextId]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private: Saves the object into storage and assigns an ID for it.
|
// Private: Saves the object into storage and assigns an ID for it.
|
||||||
|
@ -91,13 +94,13 @@ class ObjectsRegistry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private: Clear the storage when webContents is reloaded/navigated.
|
// Private: Clear the storage when renderer process is destoryed.
|
||||||
registerDeleteListener (webContents, contextId) {
|
registerDeleteListener (webContents, contextId) {
|
||||||
const processId = webContents.getProcessId()
|
const processId = webContents.getProcessId()
|
||||||
const listener = (event, deletedProcessId) => {
|
const listener = (event, deletedProcessId) => {
|
||||||
if (deletedProcessId === processId) {
|
if (deletedProcessId === processId) {
|
||||||
webContents.removeListener('render-view-deleted', listener)
|
webContents.removeListener('render-view-deleted', listener)
|
||||||
this.clear(contextId)
|
this.clear(webContents, contextId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
webContents.on('render-view-deleted', listener)
|
webContents.on('render-view-deleted', listener)
|
||||||
|
|
|
@ -394,12 +394,12 @@ ipcMain.on('ELECTRON_BROWSER_MEMBER_GET', function (event, contextId, id, name)
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.on('ELECTRON_BROWSER_DEREFERENCE', function (event, contextId, id) {
|
ipcMain.on('ELECTRON_BROWSER_DEREFERENCE', function (event, contextId, id) {
|
||||||
objectsRegistry.remove(contextId, id)
|
objectsRegistry.remove(event.sender, contextId, id)
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.on('ELECTRON_BROWSER_CONTEXT_RELEASE', (e, contextId) => {
|
ipcMain.on('ELECTRON_BROWSER_CONTEXT_RELEASE', (event, contextId) => {
|
||||||
objectsRegistry.clear(contextId)
|
objectsRegistry.clear(event.sender, contextId)
|
||||||
e.returnValue = null
|
event.returnValue = null
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.on('ELECTRON_BROWSER_GUEST_WEB_CONTENTS', function (event, contextId, guestInstanceId) {
|
ipcMain.on('ELECTRON_BROWSER_GUEST_WEB_CONTENTS', function (event, contextId, guestInstanceId) {
|
||||||
|
|
|
@ -10,7 +10,7 @@ const callbacksRegistry = new CallbacksRegistry()
|
||||||
const remoteObjectCache = v8Util.createIDWeakMap()
|
const remoteObjectCache = v8Util.createIDWeakMap()
|
||||||
|
|
||||||
// An unique ID that can represent current context.
|
// An unique ID that can represent current context.
|
||||||
const contextId = v8Util.getContextId()
|
const contextId = v8Util.getHiddenValue(global, 'contextId')
|
||||||
|
|
||||||
// Notify the main process when current context is going to be released.
|
// Notify the main process when current context is going to be released.
|
||||||
// Note that when the renderer process is destroyed, the message may not be
|
// Note that when the renderer process is destroyed, the message may not be
|
||||||
|
|
|
@ -9,7 +9,7 @@ const webViewConstants = require('./web-view-constants')
|
||||||
const hasProp = {}.hasOwnProperty
|
const hasProp = {}.hasOwnProperty
|
||||||
|
|
||||||
// An unique ID that can represent current context.
|
// An unique ID that can represent current context.
|
||||||
const contextId = v8Util.getContextId()
|
const contextId = v8Util.getHiddenValue(global, 'contextId')
|
||||||
|
|
||||||
// ID generator.
|
// ID generator.
|
||||||
let nextId = 0
|
let nextId = 0
|
||||||
|
|
Loading…
Reference in a new issue