Skip to content

Commit

Permalink
fix: use render client id to track deleted render process hosts
Browse files Browse the repository at this point in the history
Instead of relying on OS process id, which may not be unique
when a process is reused, we rely on the renderer client id
passed by the content layer when starting the renderer process
which is guaranteed to be unique for the lifetime of the app.
  • Loading branch information
deepak1556 committed Sep 10, 2018
1 parent 7252692 commit ad2c876
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 30 deletions.
4 changes: 1 addition & 3 deletions atom/browser/api/atom_api_web_contents.cc
Expand Up @@ -56,7 +56,6 @@
#include "atom/common/native_mate_converters/value_converter.h"
#include "atom/common/options_switches.h"
#include "base/message_loop/message_loop.h"
#include "base/process/process_handle.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
Expand Down Expand Up @@ -777,8 +776,7 @@ void WebContents::RenderViewCreated(content::RenderViewHost* render_view_host) {
}

void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) {
Emit("render-view-deleted", render_view_host->GetProcess()->GetID(),
base::GetProcId(render_view_host->GetProcess()->GetHandle()));
Emit("render-view-deleted", render_view_host->GetProcess()->GetID());
}

void WebContents::RenderProcessGone(base::TerminationStatus status) {
Expand Down
36 changes: 18 additions & 18 deletions atom/renderer/renderer_client_base.cc
Expand Up @@ -16,13 +16,13 @@
#include "atom/renderer/content_settings_observer.h"
#include "atom/renderer/preferences_manager.h"
#include "base/command_line.h"
#include "base/process/process.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "chrome/renderer/media/chrome_key_systems.h"
#include "chrome/renderer/printing/print_web_view_helper.h"
#include "chrome/renderer/tts_dispatcher.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h"
#include "native_mate/dictionary.h"
Expand Down Expand Up @@ -50,14 +50,6 @@
#include "chrome/renderer/pepper/pepper_helper.h"
#endif // defined(ENABLE_PEPPER_FLASH)

// 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 {
Expand All @@ -71,8 +63,8 @@ v8::Local<v8::Value> GetRenderProcessPreferences(
return v8::Null(isolate);
}

std::vector<std::string> ParseSchemesCLISwitch(const char* switch_name) {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
std::vector<std::string> ParseSchemesCLISwitch(base::CommandLine* command_line,
const char* switch_name) {
std::string custom_schemes = command_line->GetSwitchValueASCII(switch_name);
return base::SplitString(custom_schemes, ",", base::TRIM_WHITESPACE,
base::SPLIT_WANT_NONEMPTY);
Expand All @@ -81,24 +73,31 @@ std::vector<std::string> ParseSchemesCLISwitch(const char* switch_name) {
} // namespace

RendererClientBase::RendererClientBase() {
auto* command_line = base::CommandLine::ForCurrentProcess();
// Parse --standard-schemes=scheme1,scheme2
std::vector<std::string> standard_schemes_list =
ParseSchemesCLISwitch(switches::kStandardSchemes);
ParseSchemesCLISwitch(command_line, switches::kStandardSchemes);
for (const std::string& scheme : standard_schemes_list)
url::AddStandardScheme(scheme.c_str(), url::SCHEME_WITHOUT_PORT);
isolated_world_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kContextIsolation);
// We rely on the unique process host id which is notified to the
// renderer process via command line switch from the content layer,
// if this switch is removed from the content layer for some reason,
// we should define our own.
DCHECK(command_line->HasSwitch(::switches::kRendererClientId));
renderer_client_id_ =
command_line->GetSwitchValueASCII(::switches::kRendererClientId);
}

RendererClientBase::~RendererClientBase() {}

void RendererClientBase::DidCreateScriptContext(
v8::Handle<v8::Context> context,
content::RenderFrame* render_frame) {
// global.setHidden("contextId", `${processId}-${++next_context_id_}`)
std::string context_id = base::StringPrintf(
"%" CrPRIdPid "-%d", base::GetProcId(base::Process::Current().Handle()),
++next_context_id_);
// global.setHidden("contextId", `${processHostId}-${++next_context_id_}`)
auto context_id = base::StringPrintf("%s-%d", renderer_client_id_.c_str(),
++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);
Expand All @@ -116,6 +115,8 @@ void RendererClientBase::AddRenderBindings(
}

void RendererClientBase::RenderThreadStarted() {
auto* command_line = base::CommandLine::ForCurrentProcess();

blink::WebCustomElement::AddEmbedderCustomElementName("webview");
blink::WebCustomElement::AddEmbedderCustomElementName("browserplugin");

Expand All @@ -137,7 +138,7 @@ void RendererClientBase::RenderThreadStarted() {

// Parse --secure-schemes=scheme1,scheme2
std::vector<std::string> secure_schemes_list =
ParseSchemesCLISwitch(switches::kSecureSchemes);
ParseSchemesCLISwitch(command_line, switches::kSecureSchemes);
for (const std::string& scheme : secure_schemes_list)
blink::SchemeRegistry::RegisterURLSchemeAsSecure(
WTF::String::FromUTF8(scheme.data(), scheme.length()));
Expand All @@ -151,7 +152,6 @@ void RendererClientBase::RenderThreadStarted() {

#if defined(OS_WIN)
// Set ApplicationUserModelID in renderer process.
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
base::string16 app_id =
command_line->GetSwitchValueNative(switches::kAppUserModelId);
if (!app_id.empty()) {
Expand Down
2 changes: 1 addition & 1 deletion atom/renderer/renderer_client_base.h
Expand Up @@ -56,7 +56,7 @@ class RendererClientBase : public content::ContentRendererClient {
std::unique_ptr<PreferencesManager> preferences_manager_;
ChromeKeySystemsProvider key_systems_provider_;
bool isolated_world_;

std::string renderer_client_id_;
// An increasing ID used for indentifying an V8 context in this process.
int next_context_id_ = 0;
};
Expand Down
12 changes: 5 additions & 7 deletions lib/browser/objects-registry.js
Expand Up @@ -87,9 +87,6 @@ class ObjectsRegistry {

// Private: Dereference the object from store.
dereference (id) {
// FIXME(MarshallOfSound): We should remove this once remote deref works well
if (process.env.ELECTRON_DISABLE_REMOTE_DEREFERENCING) return

let pointer = this.storage[id]
if (pointer == null) {
return
Expand All @@ -103,10 +100,11 @@ class ObjectsRegistry {

// Private: Clear the storage when renderer process is destroyed.
registerDeleteListener (webContents, contextId) {
// contextId => ${OSProcessId}-${contextCount}
const OSProcessId = contextId.split('-')[0]
const listener = (event, deletedProcessId, deletedOSProcessId) => {
if (deletedOSProcessId && deletedOSProcessId.toString() === OSProcessId) {
// contextId => ${processHostId}-${contextCount}
const processHostId = contextId.split('-')[0]
const listener = (event, deletedProcessHostId) => {
if (deletedProcessHostId &&
deletedProcessHostId.toString() === processHostId) {
webContents.removeListener('render-view-deleted', listener)
this.clear(webContents, contextId)
}
Expand Down
2 changes: 1 addition & 1 deletion spec/fixtures/api/render-view-deleted.html
Expand Up @@ -17,7 +17,7 @@
}

// This should trigger a dereference and a remote getURL call should fail
contents.emit('render-view-deleted', {}, '', contents.getOSProcessId())
contents.emit('render-view-deleted', {}, contents.getProcessId())
try {
contents.getURL()
ipcRenderer.send('error-message', 'No error thrown')
Expand Down

0 comments on commit ad2c876

Please sign in to comment.