Disallow launching unknown apps via browser client.
CVE-2018-1000006
This commit is contained in:
parent
32a1395bcf
commit
c49cb29ddf
17 changed files with 1553 additions and 101 deletions
|
@ -10,7 +10,7 @@
|
||||||
#if defined(OS_MACOSX)
|
#if defined(OS_MACOSX)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
__attribute__((visibility("default")))
|
__attribute__((visibility("default")))
|
||||||
int AtomMain(int argc, const char* argv[]);
|
int AtomMain(int argc, char* argv[]);
|
||||||
|
|
||||||
__attribute__((visibility("default")))
|
__attribute__((visibility("default")))
|
||||||
int AtomInitializeICUandStartNode(int argc, char *argv[]);
|
int AtomInitializeICUandStartNode(int argc, char *argv[]);
|
||||||
|
|
|
@ -15,11 +15,11 @@
|
||||||
#include "content/public/app/content_main.h"
|
#include "content/public/app/content_main.h"
|
||||||
|
|
||||||
#if defined(OS_MACOSX)
|
#if defined(OS_MACOSX)
|
||||||
int AtomMain(int argc, const char* argv[]) {
|
int AtomMain(int argc, char* argv[]) {
|
||||||
atom::AtomMainDelegate delegate;
|
atom::AtomMainDelegate delegate;
|
||||||
content::ContentMainParams params(&delegate);
|
content::ContentMainParams params(&delegate);
|
||||||
params.argc = argc;
|
params.argc = argc;
|
||||||
params.argv = argv;
|
params.argv = const_cast<const char**>(argv);
|
||||||
atom::AtomCommandLine::Init(argc, argv);
|
atom::AtomCommandLine::Init(argc, argv);
|
||||||
return content::ContentMain(params);
|
return content::ContentMain(params);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
|
|
||||||
#include "atom/app/atom_main.h"
|
#include "atom/app/atom_main.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <cstdlib>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
#include <windows.h> // windows.h must be included first
|
#include <windows.h> // windows.h must be included first
|
||||||
|
@ -15,9 +16,11 @@
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
|
|
||||||
#include "atom/app/atom_main_delegate.h"
|
#include "atom/app/atom_main_delegate.h"
|
||||||
|
#include "atom/app/command_line_args.h"
|
||||||
#include "atom/common/crash_reporter/win/crash_service_main.h"
|
#include "atom/common/crash_reporter/win/crash_service_main.h"
|
||||||
#include "base/environment.h"
|
#include "base/environment.h"
|
||||||
#include "base/process/launch.h"
|
#include "base/process/launch.h"
|
||||||
|
#include "base/strings/utf_string_conversions.h"
|
||||||
#include "base/win/windows_version.h"
|
#include "base/win/windows_version.h"
|
||||||
#include "content/public/app/sandbox_helper_win.h"
|
#include "content/public/app/sandbox_helper_win.h"
|
||||||
#include "sandbox/win/src/sandbox_types.h"
|
#include "sandbox/win/src/sandbox_types.h"
|
||||||
|
@ -52,18 +55,23 @@ bool IsEnvSet(const char* name) {
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
||||||
int argc = 0;
|
struct Arguments {
|
||||||
wchar_t** wargv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
|
int argc = 0;
|
||||||
|
wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
|
||||||
|
|
||||||
bool run_as_node = IsEnvSet(kRunAsNode);
|
~Arguments() { LocalFree(argv); }
|
||||||
|
} arguments;
|
||||||
|
|
||||||
|
if (!arguments.argv)
|
||||||
|
return -1;
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
// Don't display assert dialog boxes in CI test runs
|
// Don't display assert dialog boxes in CI test runs
|
||||||
static const auto kCI = "ELECTRON_CI";
|
static const auto kCI = "ELECTRON_CI";
|
||||||
bool is_ci = IsEnvSet(kCI);
|
bool is_ci = IsEnvSet(kCI);
|
||||||
if (!is_ci) {
|
if (!is_ci) {
|
||||||
for (int i = 0; i < argc; ++i) {
|
for (int i = 0; i < arguments.argc; ++i) {
|
||||||
if (!_wcsicmp(wargv[i], L"--ci")) {
|
if (!_wcsicmp(arguments.argv[i], L"--ci")) {
|
||||||
is_ci = true;
|
is_ci = true;
|
||||||
_putenv_s(kCI, "1"); // set flag for child processes
|
_putenv_s(kCI, "1"); // set flag for child processes
|
||||||
break;
|
break;
|
||||||
|
@ -81,44 +89,12 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool run_as_node = IsEnvSet(kRunAsNode);
|
||||||
|
|
||||||
// Make sure the output is printed to console.
|
// Make sure the output is printed to console.
|
||||||
if (run_as_node || !IsEnvSet("ELECTRON_NO_ATTACH_CONSOLE"))
|
if (run_as_node || !IsEnvSet("ELECTRON_NO_ATTACH_CONSOLE"))
|
||||||
base::RouteStdioToConsole(false);
|
base::RouteStdioToConsole(false);
|
||||||
|
|
||||||
// Convert argv to to UTF8
|
|
||||||
char** argv = new char*[argc];
|
|
||||||
for (int i = 0; i < argc; i++) {
|
|
||||||
// Compute the size of the required buffer
|
|
||||||
DWORD size = WideCharToMultiByte(CP_UTF8,
|
|
||||||
0,
|
|
||||||
wargv[i],
|
|
||||||
-1,
|
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
NULL);
|
|
||||||
if (size == 0) {
|
|
||||||
// This should never happen.
|
|
||||||
fprintf(stderr, "Could not convert arguments to utf8.");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
// Do the actual conversion
|
|
||||||
argv[i] = new char[size];
|
|
||||||
DWORD result = WideCharToMultiByte(CP_UTF8,
|
|
||||||
0,
|
|
||||||
wargv[i],
|
|
||||||
-1,
|
|
||||||
argv[i],
|
|
||||||
size,
|
|
||||||
NULL,
|
|
||||||
NULL);
|
|
||||||
if (result == 0) {
|
|
||||||
// This should never happen.
|
|
||||||
fprintf(stderr, "Could not convert arguments to utf8.");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef DEBUG
|
#ifndef DEBUG
|
||||||
// Chromium has its own TLS subsystem which supports automatic destruction
|
// Chromium has its own TLS subsystem which supports automatic destruction
|
||||||
// of thread-local data, and also depends on memory allocation routines
|
// of thread-local data, and also depends on memory allocation routines
|
||||||
|
@ -139,14 +115,23 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (run_as_node) {
|
if (run_as_node) {
|
||||||
// Now that argv conversion is done, we can finally start.
|
std::vector<char*> argv(arguments.argc);
|
||||||
|
std::transform(
|
||||||
|
arguments.argv, arguments.argv + arguments.argc, argv.begin(),
|
||||||
|
[](auto& a) { return _strdup(base::WideToUTF8(a).c_str()); });
|
||||||
|
|
||||||
base::AtExitManager atexit_manager;
|
base::AtExitManager atexit_manager;
|
||||||
base::i18n::InitializeICU();
|
base::i18n::InitializeICU();
|
||||||
return atom::NodeMain(argc, argv);
|
auto ret = atom::NodeMain(argv.size(), argv.data());
|
||||||
|
std::for_each(argv.begin(), argv.end(), free);
|
||||||
|
return ret;
|
||||||
} else if (IsEnvSet("ELECTRON_INTERNAL_CRASH_SERVICE")) {
|
} else if (IsEnvSet("ELECTRON_INTERNAL_CRASH_SERVICE")) {
|
||||||
return crash_service::Main(cmd);
|
return crash_service::Main(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!atom::CheckCommandLineArguments(arguments.argc, arguments.argv))
|
||||||
|
return -1;
|
||||||
|
|
||||||
sandbox::SandboxInterfaceInfo sandbox_info = {0};
|
sandbox::SandboxInterfaceInfo sandbox_info = {0};
|
||||||
content::InitializeSandboxInfo(&sandbox_info);
|
content::InitializeSandboxInfo(&sandbox_info);
|
||||||
atom::AtomMainDelegate delegate;
|
atom::AtomMainDelegate delegate;
|
||||||
|
@ -154,33 +139,32 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
||||||
content::ContentMainParams params(&delegate);
|
content::ContentMainParams params(&delegate);
|
||||||
params.instance = instance;
|
params.instance = instance;
|
||||||
params.sandbox_info = &sandbox_info;
|
params.sandbox_info = &sandbox_info;
|
||||||
atom::AtomCommandLine::Init(argc, argv);
|
atom::AtomCommandLine::Init(arguments.argc, arguments.argv);
|
||||||
atom::AtomCommandLine::InitW(argc, wargv);
|
|
||||||
return content::ContentMain(params);
|
return content::ContentMain(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(OS_LINUX) // defined(OS_WIN)
|
#elif defined(OS_LINUX) // defined(OS_WIN)
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
if (IsEnvSet(kRunAsNode)) {
|
if (IsEnvSet(kRunAsNode)) {
|
||||||
base::i18n::InitializeICU();
|
base::i18n::InitializeICU();
|
||||||
base::AtExitManager atexit_manager;
|
base::AtExitManager atexit_manager;
|
||||||
return atom::NodeMain(argc, const_cast<char**>(argv));
|
return atom::NodeMain(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
atom::AtomMainDelegate delegate;
|
atom::AtomMainDelegate delegate;
|
||||||
content::ContentMainParams params(&delegate);
|
content::ContentMainParams params(&delegate);
|
||||||
params.argc = argc;
|
params.argc = argc;
|
||||||
params.argv = argv;
|
params.argv = const_cast<const char**>(argv);
|
||||||
atom::AtomCommandLine::Init(argc, argv);
|
atom::AtomCommandLine::Init(argc, argv);
|
||||||
return content::ContentMain(params);
|
return content::ContentMain(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // defined(OS_LINUX)
|
#else // defined(OS_LINUX)
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
if (IsEnvSet(kRunAsNode)) {
|
if (IsEnvSet(kRunAsNode)) {
|
||||||
return AtomInitializeICUandStartNode(argc, const_cast<char**>(argv));
|
return AtomInitializeICUandStartNode(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
return AtomMain(argc, argv);
|
return AtomMain(argc, argv);
|
||||||
|
|
1411
atom/app/command_line_args.cc
Normal file
1411
atom/app/command_line_args.cc
Normal file
File diff suppressed because it is too large
Load diff
17
atom/app/command_line_args.h
Normal file
17
atom/app/command_line_args.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// Copyright (c) 2018 GitHub, Inc.
|
||||||
|
// Use of this source code is governed by the MIT license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef ATOM_APP_COMMAND_LINE_ARGS_H_
|
||||||
|
#define ATOM_APP_COMMAND_LINE_ARGS_H_
|
||||||
|
|
||||||
|
#include "base/command_line.h"
|
||||||
|
|
||||||
|
namespace atom {
|
||||||
|
|
||||||
|
bool CheckCommandLineArguments(int argc, base::CommandLine::CharType** argv);
|
||||||
|
|
||||||
|
} // namespace atom
|
||||||
|
|
||||||
|
#endif // ATOM_APP_COMMAND_LINE_ARGS_H_
|
||||||
|
|
|
@ -897,11 +897,7 @@ bool App::Relaunch(mate::Arguments* js_args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!override_argv) {
|
if (!override_argv) {
|
||||||
#if defined(OS_WIN)
|
|
||||||
const relauncher::StringVector& argv = atom::AtomCommandLine::wargv();
|
|
||||||
#else
|
|
||||||
const relauncher::StringVector& argv = atom::AtomCommandLine::argv();
|
const relauncher::StringVector& argv = atom::AtomCommandLine::argv();
|
||||||
#endif
|
|
||||||
return relauncher::RelaunchApp(argv);
|
return relauncher::RelaunchApp(argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "content/public/browser/resource_dispatcher_host.h"
|
#include "content/public/browser/resource_dispatcher_host.h"
|
||||||
#include "content/public/browser/site_instance.h"
|
#include "content/public/browser/site_instance.h"
|
||||||
#include "content/public/browser/web_contents.h"
|
#include "content/public/browser/web_contents.h"
|
||||||
|
#include "content/public/common/content_paths.h"
|
||||||
#include "content/public/common/content_switches.h"
|
#include "content/public/common/content_switches.h"
|
||||||
#include "content/public/common/resource_request_body.h"
|
#include "content/public/common/resource_request_body.h"
|
||||||
#include "content/public/common/url_constants.h"
|
#include "content/public/common/url_constants.h"
|
||||||
|
@ -237,6 +238,11 @@ void AtomBrowserClient::OverrideSiteInstanceForNavigation(
|
||||||
void AtomBrowserClient::AppendExtraCommandLineSwitches(
|
void AtomBrowserClient::AppendExtraCommandLineSwitches(
|
||||||
base::CommandLine* command_line,
|
base::CommandLine* command_line,
|
||||||
int process_id) {
|
int process_id) {
|
||||||
|
// Make sure we're about to launch a known executable
|
||||||
|
base::FilePath child_path;
|
||||||
|
PathService::Get(content::CHILD_PROCESS_EXE, &child_path);
|
||||||
|
CHECK(base::MakeAbsoluteFilePath(command_line->GetProgram()) == child_path);
|
||||||
|
|
||||||
std::string process_type =
|
std::string process_type =
|
||||||
command_line->GetSwitchValueASCII(::switches::kProcessType);
|
command_line->GetSwitchValueASCII(::switches::kProcessType);
|
||||||
if (process_type != ::switches::kRendererProcess)
|
if (process_type != ::switches::kRendererProcess)
|
||||||
|
|
|
@ -140,11 +140,7 @@ bool RelaunchAppWithHelper(const base::FilePath& helper,
|
||||||
}
|
}
|
||||||
|
|
||||||
int RelauncherMain(const content::MainFunctionParams& main_parameters) {
|
int RelauncherMain(const content::MainFunctionParams& main_parameters) {
|
||||||
#if defined(OS_WIN)
|
|
||||||
const StringVector& argv = atom::AtomCommandLine::wargv();
|
|
||||||
#else
|
|
||||||
const StringVector& argv = atom::AtomCommandLine::argv();
|
const StringVector& argv = atom::AtomCommandLine::argv();
|
||||||
#endif
|
|
||||||
|
|
||||||
if (argv.size() < 4 || argv[1] != internal::kRelauncherTypeArg) {
|
if (argv.size() < 4 || argv[1] != internal::kRelauncherTypeArg) {
|
||||||
LOG(ERROR) << "relauncher process invoked with unexpected arguments";
|
LOG(ERROR) << "relauncher process invoked with unexpected arguments";
|
||||||
|
|
|
@ -10,31 +10,22 @@
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
// static
|
// static
|
||||||
std::vector<std::string> AtomCommandLine::argv_;
|
base::CommandLine::StringVector AtomCommandLine::argv_;
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
// static
|
|
||||||
std::vector<std::wstring> AtomCommandLine::wargv_;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void AtomCommandLine::Init(int argc, const char* const* argv) {
|
void AtomCommandLine::Init(int argc, base::CommandLine::CharType** argv) {
|
||||||
|
DCHECK(argv_.empty());
|
||||||
|
|
||||||
|
// NOTE: uv_setup_args does nothing on Windows, so we don't need to call it.
|
||||||
|
// Otherwise we'd have to convert the arguments from UTF16.
|
||||||
|
#if !defined(OS_WIN)
|
||||||
// Hack around with the argv pointer. Used for process.title = "blah"
|
// Hack around with the argv pointer. Used for process.title = "blah"
|
||||||
char** new_argv = uv_setup_args(argc, const_cast<char**>(argv));
|
argv = uv_setup_args(argc, argv);
|
||||||
for (int i = 0; i < argc; ++i) {
|
|
||||||
argv_.push_back(new_argv[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
// static
|
|
||||||
void AtomCommandLine::InitW(int argc, const wchar_t* const* argv) {
|
|
||||||
for (int i = 0; i < argc; ++i) {
|
|
||||||
wargv_.push_back(argv[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
argv_.assign(argv, argv + argc);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(OS_LINUX)
|
#if defined(OS_LINUX)
|
||||||
// static
|
// static
|
||||||
void AtomCommandLine::InitializeFromCommandLine() {
|
void AtomCommandLine::InitializeFromCommandLine() {
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "base/command_line.h"
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
|
|
||||||
|
@ -16,13 +17,9 @@ namespace atom {
|
||||||
// Singleton to remember the original "argc" and "argv".
|
// Singleton to remember the original "argc" and "argv".
|
||||||
class AtomCommandLine {
|
class AtomCommandLine {
|
||||||
public:
|
public:
|
||||||
static void Init(int argc, const char* const* argv);
|
static const base::CommandLine::StringVector& argv() { return argv_; }
|
||||||
static std::vector<std::string> argv() { return argv_; }
|
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
static void Init(int argc, base::CommandLine::CharType** argv);
|
||||||
static void InitW(int argc, const wchar_t* const* argv);
|
|
||||||
static std::vector<std::wstring> wargv() { return wargv_; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(OS_LINUX)
|
#if defined(OS_LINUX)
|
||||||
// On Linux the command line has to be read from base::CommandLine since
|
// On Linux the command line has to be read from base::CommandLine since
|
||||||
|
@ -31,11 +28,7 @@ class AtomCommandLine {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::vector<std::string> argv_;
|
static base::CommandLine::StringVector argv_;
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
static std::vector<std::wstring> wargv_;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(AtomCommandLine);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(AtomCommandLine);
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include "atom/common/node_bindings.h"
|
#include "atom/common/node_bindings.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -17,6 +18,7 @@
|
||||||
#include "base/files/file_path.h"
|
#include "base/files/file_path.h"
|
||||||
#include "base/path_service.h"
|
#include "base/path_service.h"
|
||||||
#include "base/run_loop.h"
|
#include "base/run_loop.h"
|
||||||
|
#include "base/strings/utf_string_conversions.h"
|
||||||
#include "base/threading/thread_task_runner_handle.h"
|
#include "base/threading/thread_task_runner_handle.h"
|
||||||
#include "base/trace_event/trace_event.h"
|
#include "base/trace_event/trace_event.h"
|
||||||
#include "content/public/browser/browser_thread.h"
|
#include "content/public/browser/browser_thread.h"
|
||||||
|
@ -179,7 +181,14 @@ void NodeBindings::Initialize() {
|
||||||
|
|
||||||
node::Environment* NodeBindings::CreateEnvironment(
|
node::Environment* NodeBindings::CreateEnvironment(
|
||||||
v8::Handle<v8::Context> context) {
|
v8::Handle<v8::Context> context) {
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
auto& atom_args = AtomCommandLine::argv();
|
||||||
|
std::vector<std::string> args(atom_args.size());
|
||||||
|
std::transform(atom_args.cbegin(), atom_args.cend(), args.begin(),
|
||||||
|
[](auto& a) { return base::WideToUTF8(a); });
|
||||||
|
#else
|
||||||
auto args = AtomCommandLine::argv();
|
auto args = AtomCommandLine::argv();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Feed node the path to initialization script.
|
// Feed node the path to initialization script.
|
||||||
base::FilePath::StringType process_type;
|
base::FilePath::StringType process_type;
|
||||||
|
@ -199,8 +208,7 @@ node::Environment* NodeBindings::CreateEnvironment(
|
||||||
resources_path.Append(FILE_PATH_LITERAL("electron.asar"))
|
resources_path.Append(FILE_PATH_LITERAL("electron.asar"))
|
||||||
.Append(process_type)
|
.Append(process_type)
|
||||||
.Append(FILE_PATH_LITERAL("init.js"));
|
.Append(FILE_PATH_LITERAL("init.js"));
|
||||||
std::string script_path_str = script_path.AsUTF8Unsafe();
|
args.insert(args.begin() + 1, script_path.AsUTF8Unsafe());
|
||||||
args.insert(args.begin() + 1, script_path_str.c_str());
|
|
||||||
|
|
||||||
std::unique_ptr<const char*[]> c_argv = StringVectorToArgArray(args);
|
std::unique_ptr<const char*[]> c_argv = StringVectorToArgArray(args);
|
||||||
node::Environment* env = node::CreateEnvironment(
|
node::Environment* env = node::CreateEnvironment(
|
||||||
|
|
|
@ -32,7 +32,7 @@ the hostname and the port number 'hostname:port'.
|
||||||
* `redirect` String (optional) - The redirect mode for this request. Should be
|
* `redirect` String (optional) - The redirect mode for this request. Should be
|
||||||
one of `follow`, `error` or `manual`. Defaults to `follow`. When mode is `error`,
|
one of `follow`, `error` or `manual`. Defaults to `follow`. When mode is `error`,
|
||||||
any redirection will be aborted. When mode is `manual` the redirection will be
|
any redirection will be aborted. When mode is `manual` the redirection will be
|
||||||
deferred until [`request.followRedirect`](#requestfollowRedirect) is invoked. Listen for the [`redirect`](#event-redirect) event in
|
deferred until [`request.followRedirect`](#requestfollowredirect) is invoked. Listen for the [`redirect`](#event-redirect) event in
|
||||||
this mode to get more details about the redirect request.
|
this mode to get more details about the redirect request.
|
||||||
|
|
||||||
`options` properties such as `protocol`, `host`, `hostname`, `port` and `path`
|
`options` properties such as `protocol`, `host`, `hostname`, `port` and `path`
|
||||||
|
@ -137,7 +137,7 @@ Returns:
|
||||||
* `responseHeaders` Object
|
* `responseHeaders` Object
|
||||||
|
|
||||||
Emitted when there is redirection and the mode is `manual`. Calling
|
Emitted when there is redirection and the mode is `manual`. Calling
|
||||||
[`request.followRedirect`](#requestfollowRedirect) will continue with the redirection.
|
[`request.followRedirect`](#requestfollowredirect) will continue with the redirection.
|
||||||
|
|
||||||
### Instance Properties
|
### Instance Properties
|
||||||
|
|
||||||
|
|
|
@ -291,7 +291,7 @@ Calling `event.preventDefault` will prevent the page `keydown`/`keyup` events
|
||||||
and the menu shortcuts.
|
and the menu shortcuts.
|
||||||
|
|
||||||
To only prevent the menu shortcuts, use
|
To only prevent the menu shortcuts, use
|
||||||
[`setIgnoreMenuShortcuts`](#contentssetignoremenushortcuts):
|
[`setIgnoreMenuShortcuts`](#contentssetignoremenushortcutsignore-experimental):
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const {BrowserWindow} = require('electron')
|
const {BrowserWindow} = require('electron')
|
||||||
|
|
|
@ -528,7 +528,7 @@ can be obtained by subscribing to [`found-in-page`](webview-tag.md#event-found-i
|
||||||
### `<webview>.stopFindInPage(action)`
|
### `<webview>.stopFindInPage(action)`
|
||||||
|
|
||||||
* `action` String - Specifies the action to take place when ending
|
* `action` String - Specifies the action to take place when ending
|
||||||
[`<webview>.findInPage`](webview-tag.md#webviewtagfindinpage) request.
|
[`<webview>.findInPage`](#webviewfindinpagetext-options) request.
|
||||||
* `clearSelection` - Clear the selection.
|
* `clearSelection` - Clear the selection.
|
||||||
* `keepSelection` - Translate the selection into a normal selection.
|
* `keepSelection` - Translate the selection into a normal selection.
|
||||||
* `activateSelection` - Focus and click the selection node.
|
* `activateSelection` - Focus and click the selection node.
|
||||||
|
@ -579,7 +579,7 @@ Send an asynchronous message to renderer process via `channel`, you can also
|
||||||
send arbitrary arguments. The renderer process can handle the message by
|
send arbitrary arguments. The renderer process can handle the message by
|
||||||
listening to the `channel` event with the [`ipcRenderer`](ipc-renderer.md) module.
|
listening to the `channel` event with the [`ipcRenderer`](ipc-renderer.md) module.
|
||||||
|
|
||||||
See [webContents.send](web-contents.md#webcontentssendchannel-args) for
|
See [webContents.send](web-contents.md#contentssendchannel-arg1-arg2-) for
|
||||||
examples.
|
examples.
|
||||||
|
|
||||||
### `<webview>.sendInputEvent(event)`
|
### `<webview>.sendInputEvent(event)`
|
||||||
|
@ -588,7 +588,7 @@ examples.
|
||||||
|
|
||||||
Sends an input `event` to the page.
|
Sends an input `event` to the page.
|
||||||
|
|
||||||
See [webContents.sendInputEvent](web-contents.md#webcontentssendinputeventevent)
|
See [webContents.sendInputEvent](web-contents.md#contentssendinputeventevent)
|
||||||
for detailed description of `event` object.
|
for detailed description of `event` object.
|
||||||
|
|
||||||
### `<webview>.setZoomFactor(factor)`
|
### `<webview>.setZoomFactor(factor)`
|
||||||
|
@ -752,7 +752,7 @@ Returns:
|
||||||
* `finalUpdate` Boolean
|
* `finalUpdate` Boolean
|
||||||
|
|
||||||
Fired when a result is available for
|
Fired when a result is available for
|
||||||
[`webview.findInPage`](webview-tag.md#webviewtagfindinpage) request.
|
[`webview.findInPage`](#webviewfindinpagetext-options) request.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const webview = document.querySelector('webview')
|
const webview = document.querySelector('webview')
|
||||||
|
|
|
@ -15,7 +15,7 @@ To ensure that your JavaScript is in compliance with the Electron coding
|
||||||
style, run `npm run lint-js`, which will run `standard` against both
|
style, run `npm run lint-js`, which will run `standard` against both
|
||||||
Electron itself as well as the unit tests. If you are using an editor
|
Electron itself as well as the unit tests. If you are using an editor
|
||||||
with a plugin/addon system, you might want to use one of the many
|
with a plugin/addon system, you might want to use one of the many
|
||||||
[StandardJS addons](standard-addons) to be informed of coding style
|
[StandardJS addons][standard-addons] to be informed of coding style
|
||||||
violations before you ever commit them.
|
violations before you ever commit them.
|
||||||
|
|
||||||
To run `standard` with parameters, run `npm run lint-js --` followed by
|
To run `standard` with parameters, run `npm run lint-js --` followed by
|
||||||
|
|
|
@ -99,6 +99,8 @@
|
||||||
'atom/app/atom_main_delegate.cc',
|
'atom/app/atom_main_delegate.cc',
|
||||||
'atom/app/atom_main_delegate.h',
|
'atom/app/atom_main_delegate.h',
|
||||||
'atom/app/atom_main_delegate_mac.mm',
|
'atom/app/atom_main_delegate_mac.mm',
|
||||||
|
'atom/app/command_line_args.cc',
|
||||||
|
'atom/app/command_line_args.h',
|
||||||
'atom/app/node_main.cc',
|
'atom/app/node_main.cc',
|
||||||
'atom/app/node_main.h',
|
'atom/app/node_main.h',
|
||||||
'atom/app/uv_task_runner.cc',
|
'atom/app/uv_task_runner.cc',
|
||||||
|
|
|
@ -634,6 +634,54 @@ describe('app module', () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('app launch through uri', () => {
|
||||||
|
before(function () {
|
||||||
|
if (process.platform !== 'win32') {
|
||||||
|
this.skip()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not launch for blacklisted argument', function (done) {
|
||||||
|
const appPath = path.join(__dirname, 'fixtures', 'api', 'quit-app')
|
||||||
|
// App should exit with non 123 code.
|
||||||
|
const first = ChildProcess.spawn(remote.process.execPath, [appPath, 'electron-test://?', '--no-sandbox', '--gpu-launcher=cmd.exe /c start calc'])
|
||||||
|
first.once('exit', (code) => {
|
||||||
|
assert.notEqual(code, 123)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('launches successfully for multiple uris in cmd args', function (done) {
|
||||||
|
const appPath = path.join(__dirname, 'fixtures', 'api', 'quit-app')
|
||||||
|
// App should exit with code 123.
|
||||||
|
const first = ChildProcess.spawn(remote.process.execPath, [appPath, 'http://electronjs.org', 'electron-test://testdata'])
|
||||||
|
first.once('exit', (code) => {
|
||||||
|
assert.equal(code, 123)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not launch for encoded space', function (done) {
|
||||||
|
const appPath = path.join(__dirname, 'fixtures', 'api', 'quit-app')
|
||||||
|
// App should exit with non 123 code.
|
||||||
|
const first = ChildProcess.spawn(remote.process.execPath, [appPath, 'electron-test://?', '--no-sandbox', '--gpu-launcher%20"cmd.exe /c start calc'])
|
||||||
|
first.once('exit', (code) => {
|
||||||
|
assert.notEqual(code, 123)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('launches successfully for argnames similar to blacklisted ones', function (done) {
|
||||||
|
const appPath = path.join(__dirname, 'fixtures', 'api', 'quit-app')
|
||||||
|
// inspect is blacklisted, but inspector should work, and app launch should succeed
|
||||||
|
const first = ChildProcess.spawn(remote.process.execPath, [appPath, 'electron-test://?', '--inspector'])
|
||||||
|
first.once('exit', (code) => {
|
||||||
|
assert.equal(code, 123)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('getFileIcon() API', () => {
|
describe('getFileIcon() API', () => {
|
||||||
const iconPath = path.join(__dirname, 'fixtures/assets/icon.ico')
|
const iconPath = path.join(__dirname, 'fixtures/assets/icon.ico')
|
||||||
const sizes = {
|
const sizes = {
|
||||||
|
|
Loading…
Reference in a new issue