Merge branch 'master' into publish-prebuilt
This commit is contained in:
commit
c8e2e37146
30 changed files with 201 additions and 67 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -14,6 +14,7 @@
|
||||||
*.vcxproj.filters
|
*.vcxproj.filters
|
||||||
*.vcxproj.user
|
*.vcxproj.user
|
||||||
*.xcodeproj
|
*.xcodeproj
|
||||||
|
node_modules/
|
||||||
/.idea/
|
/.idea/
|
||||||
/brightray/brightray.opensdf
|
/brightray/brightray.opensdf
|
||||||
/brightray/brightray.sdf
|
/brightray/brightray.sdf
|
||||||
|
@ -25,7 +26,6 @@
|
||||||
/build/
|
/build/
|
||||||
/dist/
|
/dist/
|
||||||
/external_binaries/
|
/external_binaries/
|
||||||
node_modules
|
|
||||||
/out/
|
/out/
|
||||||
/vendor/.gclient
|
/vendor/.gclient
|
||||||
/vendor/debian_jessie_amd64-sysroot/
|
/vendor/debian_jessie_amd64-sysroot/
|
||||||
|
|
|
@ -3,6 +3,9 @@ git:
|
||||||
notifications:
|
notifications:
|
||||||
email: false
|
email: false
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- export BOTO_CONFIG=/dev/null
|
||||||
|
|
||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- "4"
|
- "4"
|
||||||
|
|
|
@ -57,6 +57,23 @@ void AutoUpdater::OnError(const std::string& message) {
|
||||||
message);
|
message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AutoUpdater::OnError(const std::string& message,
|
||||||
|
const int code, const std::string& domain) {
|
||||||
|
v8::Locker locker(isolate());
|
||||||
|
v8::HandleScope handle_scope(isolate());
|
||||||
|
auto error = v8::Exception::Error(mate::StringToV8(isolate(), message));
|
||||||
|
auto errorObject = error->ToObject(
|
||||||
|
isolate()->GetCurrentContext()).ToLocalChecked();
|
||||||
|
|
||||||
|
// add two new params for better error handling
|
||||||
|
errorObject->Set(mate::StringToV8(isolate(), "code"),
|
||||||
|
v8::Integer::New(isolate(), code));
|
||||||
|
errorObject->Set(mate::StringToV8(isolate(), "domain"),
|
||||||
|
mate::StringToV8(isolate(), domain));
|
||||||
|
|
||||||
|
mate::EmitEvent(isolate(), GetWrapper(), "error", errorObject, message);
|
||||||
|
}
|
||||||
|
|
||||||
void AutoUpdater::OnCheckingForUpdate() {
|
void AutoUpdater::OnCheckingForUpdate() {
|
||||||
Emit("checking-for-update");
|
Emit("checking-for-update");
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,8 @@ class AutoUpdater : public mate::EventEmitter<AutoUpdater>,
|
||||||
|
|
||||||
// Delegate implementations.
|
// Delegate implementations.
|
||||||
void OnError(const std::string& error) override;
|
void OnError(const std::string& error) override;
|
||||||
|
void OnError(const std::string& message, const int code,
|
||||||
|
const std::string& domain);
|
||||||
void OnCheckingForUpdate() override;
|
void OnCheckingForUpdate() override;
|
||||||
void OnUpdateAvailable() override;
|
void OnUpdateAvailable() override;
|
||||||
void OnUpdateNotAvailable() override;
|
void OnUpdateNotAvailable() override;
|
||||||
|
|
|
@ -152,7 +152,8 @@ void Initialize(v8::Local<v8::Object> exports,
|
||||||
|
|
||||||
mate::Dictionary browser_view(
|
mate::Dictionary browser_view(
|
||||||
isolate, BrowserView::GetConstructor(isolate)->GetFunction());
|
isolate, BrowserView::GetConstructor(isolate)->GetFunction());
|
||||||
|
browser_view.SetMethod("fromId",
|
||||||
|
&mate::TrackableObject<BrowserView>::FromWeakMapID);
|
||||||
mate::Dictionary dict(isolate, exports);
|
mate::Dictionary dict(isolate, exports);
|
||||||
dict.Set("BrowserView", browser_view);
|
dict.Set("BrowserView", browser_view);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,9 @@ class Delegate {
|
||||||
// An error happened.
|
// An error happened.
|
||||||
virtual void OnError(const std::string& error) {}
|
virtual void OnError(const std::string& error) {}
|
||||||
|
|
||||||
|
virtual void OnError(const std::string& error, const int code,
|
||||||
|
const std::string& domain) {}
|
||||||
|
|
||||||
// Checking to see if there is an update
|
// Checking to see if there is an update
|
||||||
virtual void OnCheckingForUpdate() {}
|
virtual void OnCheckingForUpdate() {}
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ void AutoUpdater::CheckForUpdates() {
|
||||||
delegate->OnUpdateNotAvailable();
|
delegate->OnUpdateNotAvailable();
|
||||||
}
|
}
|
||||||
} error:^(NSError *error) {
|
} error:^(NSError *error) {
|
||||||
NSMutableString* failureString =
|
NSMutableString *failureString =
|
||||||
[NSMutableString stringWithString:error.localizedDescription];
|
[NSMutableString stringWithString:error.localizedDescription];
|
||||||
if (error.localizedFailureReason) {
|
if (error.localizedFailureReason) {
|
||||||
[failureString appendString:@": "];
|
[failureString appendString:@": "];
|
||||||
|
@ -116,7 +116,8 @@ void AutoUpdater::CheckForUpdates() {
|
||||||
[failureString appendString:@" "];
|
[failureString appendString:@" "];
|
||||||
[failureString appendString:error.localizedRecoverySuggestion];
|
[failureString appendString:error.localizedRecoverySuggestion];
|
||||||
}
|
}
|
||||||
delegate->OnError(base::SysNSStringToUTF8(failureString));
|
delegate->OnError(base::SysNSStringToUTF8(failureString), error.code,
|
||||||
|
base::SysNSStringToUTF8(error.domain));
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +126,8 @@ void AutoUpdater::QuitAndInstall() {
|
||||||
if (g_update_available) {
|
if (g_update_available) {
|
||||||
[[g_updater relaunchToInstallUpdate] subscribeError:^(NSError* error) {
|
[[g_updater relaunchToInstallUpdate] subscribeError:^(NSError* error) {
|
||||||
if (delegate)
|
if (delegate)
|
||||||
delegate->OnError(base::SysNSStringToUTF8(error.localizedDescription));
|
delegate->OnError(base::SysNSStringToUTF8(error.localizedDescription),
|
||||||
|
error.code, base::SysNSStringToUTF8(error.domain));
|
||||||
}];
|
}];
|
||||||
} else {
|
} else {
|
||||||
if (delegate)
|
if (delegate)
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "base/strings/string_util.h"
|
#include "base/strings/string_util.h"
|
||||||
#include "base/synchronization/lock.h"
|
#include "base/synchronization/lock.h"
|
||||||
#include "base/task_runner.h"
|
#include "base/task_runner.h"
|
||||||
|
#include "base/threading/thread_task_runner_handle.h"
|
||||||
#include "net/base/file_stream.h"
|
#include "net/base/file_stream.h"
|
||||||
#include "net/base/filename_util.h"
|
#include "net/base/filename_util.h"
|
||||||
#include "net/base/io_buffer.h"
|
#include "net/base/io_buffer.h"
|
||||||
|
@ -119,8 +120,11 @@ void URLRequestAsarJob::Start() {
|
||||||
weak_ptr_factory_.GetWeakPtr(),
|
weak_ptr_factory_.GetWeakPtr(),
|
||||||
base::Owned(meta_info)));
|
base::Owned(meta_info)));
|
||||||
} else {
|
} else {
|
||||||
NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
|
base::ThreadTaskRunnerHandle::Get()->PostTask(
|
||||||
net::ERR_FILE_NOT_FOUND));
|
FROM_HERE,
|
||||||
|
base::Bind(&URLRequestAsarJob::DidOpen,
|
||||||
|
weak_ptr_factory_.GetWeakPtr(),
|
||||||
|
net::ERR_FILE_NOT_FOUND));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,6 @@ class URLRequestAsarJob : public net::URLRequestJob {
|
||||||
// Callback after fetching file info on a background thread.
|
// Callback after fetching file info on a background thread.
|
||||||
void DidFetchMetaInfo(const FileMetaInfo* meta_info);
|
void DidFetchMetaInfo(const FileMetaInfo* meta_info);
|
||||||
|
|
||||||
|
|
||||||
// Callback after opening file on a background thread.
|
// Callback after opening file on a background thread.
|
||||||
void DidOpen(int result);
|
void DidOpen(int result);
|
||||||
|
|
||||||
|
|
|
@ -165,6 +165,18 @@ void SetMenuItemID(DbusmenuMenuitem* item, int id) {
|
||||||
g_object_set_data(G_OBJECT(item), "menu-id", GINT_TO_POINTER(id + 1));
|
g_object_set_data(G_OBJECT(item), "menu-id", GINT_TO_POINTER(id + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string GetMenuModelStatus(AtomMenuModel* model) {
|
||||||
|
std::string ret;
|
||||||
|
for (int i = 0; i < model->GetItemCount(); ++i) {
|
||||||
|
int status = model->GetTypeAt(i) | (model->IsVisibleAt(i) << 3)
|
||||||
|
| (model->IsEnabledAt(i) << 4)
|
||||||
|
| (model->IsItemCheckedAt(i) << 5);
|
||||||
|
ret += base::StringPrintf(
|
||||||
|
"%s-%X\n", base::UTF16ToUTF8(model->GetLabelAt(i)).c_str(), status);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
GlobalMenuBarX11::GlobalMenuBarX11(NativeWindowViews* window)
|
GlobalMenuBarX11::GlobalMenuBarX11(NativeWindowViews* window)
|
||||||
|
@ -309,6 +321,16 @@ void GlobalMenuBarX11::OnSubMenuShow(DbusmenuMenuitem* item) {
|
||||||
if (!model || !GetMenuItemID(item, &id))
|
if (!model || !GetMenuItemID(item, &id))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Do not update menu if the submenu has not been changed.
|
||||||
|
std::string status = GetMenuModelStatus(model);
|
||||||
|
char* old = static_cast<char*>(g_object_get_data(G_OBJECT(item), "status"));
|
||||||
|
if (old && status == old)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Save the new status.
|
||||||
|
g_object_set_data_full(G_OBJECT(item), "status", g_strdup(status.c_str()),
|
||||||
|
g_free);
|
||||||
|
|
||||||
// Clear children.
|
// Clear children.
|
||||||
GList *children = menuitem_take_children(item);
|
GList *children = menuitem_take_children(item);
|
||||||
g_list_foreach(children, reinterpret_cast<GFunc>(g_object_unref), NULL);
|
g_list_foreach(children, reinterpret_cast<GFunc>(g_object_unref), NULL);
|
||||||
|
|
|
@ -268,11 +268,10 @@ v8::Local<v8::Value> NativeImage::ToPNG(mate::Arguments* args) {
|
||||||
|
|
||||||
const SkBitmap bitmap =
|
const SkBitmap bitmap =
|
||||||
image_.AsImageSkia().GetRepresentation(scale_factor).sk_bitmap();
|
image_.AsImageSkia().GetRepresentation(scale_factor).sk_bitmap();
|
||||||
std::unique_ptr<std::vector<unsigned char>> encoded(
|
std::vector<unsigned char> encoded;
|
||||||
new std::vector<unsigned char>());
|
gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &encoded);
|
||||||
gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, encoded.get());
|
const char* data = reinterpret_cast<char*>(encoded.data());
|
||||||
const char* data = reinterpret_cast<char*>(encoded->data());
|
size_t size = encoded.size();
|
||||||
size_t size = encoded->size();
|
|
||||||
return node::Buffer::Copy(args->isolate(), data, size).ToLocalChecked();
|
return node::Buffer::Copy(args->isolate(), data, size).ToLocalChecked();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,6 +291,8 @@ v8::Local<v8::Value> NativeImage::ToBitmap(mate::Arguments* args) {
|
||||||
v8::Local<v8::Value> NativeImage::ToJPEG(v8::Isolate* isolate, int quality) {
|
v8::Local<v8::Value> NativeImage::ToJPEG(v8::Isolate* isolate, int quality) {
|
||||||
std::vector<unsigned char> output;
|
std::vector<unsigned char> output;
|
||||||
gfx::JPEG1xEncodedDataFromImage(image_, quality, &output);
|
gfx::JPEG1xEncodedDataFromImage(image_, quality, &output);
|
||||||
|
if (output.empty())
|
||||||
|
return node::Buffer::New(isolate, 0).ToLocalChecked();
|
||||||
return node::Buffer::Copy(
|
return node::Buffer::Copy(
|
||||||
isolate,
|
isolate,
|
||||||
reinterpret_cast<const char*>(&output.front()),
|
reinterpret_cast<const char*>(&output.front()),
|
||||||
|
|
|
@ -56,7 +56,8 @@ struct V8FunctionInvoker<v8::Local<v8::Value>(ArgTypes...)> {
|
||||||
v8::Local<v8::Context> context = holder->CreationContext();
|
v8::Local<v8::Context> context = holder->CreationContext();
|
||||||
v8::Context::Scope context_scope(context);
|
v8::Context::Scope context_scope(context);
|
||||||
std::vector<v8::Local<v8::Value>> args { ConvertToV8(isolate, raw)... };
|
std::vector<v8::Local<v8::Value>> args { ConvertToV8(isolate, raw)... };
|
||||||
v8::Local<v8::Value> ret(holder->Call(holder, args.size(), &args.front()));
|
v8::Local<v8::Value> ret(holder->Call(
|
||||||
|
holder, args.size(), args.empty() ? nullptr : &args.front()));
|
||||||
return handle_scope.Escape(ret);
|
return handle_scope.Escape(ret);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -76,7 +77,8 @@ struct V8FunctionInvoker<void(ArgTypes...)> {
|
||||||
v8::Local<v8::Context> context = holder->CreationContext();
|
v8::Local<v8::Context> context = holder->CreationContext();
|
||||||
v8::Context::Scope context_scope(context);
|
v8::Context::Scope context_scope(context);
|
||||||
std::vector<v8::Local<v8::Value>> args { ConvertToV8(isolate, raw)... };
|
std::vector<v8::Local<v8::Value>> args { ConvertToV8(isolate, raw)... };
|
||||||
holder->Call(holder, args.size(), &args.front());
|
holder->Call(
|
||||||
|
holder, args.size(), args.empty() ? nullptr : &args.front());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -97,8 +99,8 @@ struct V8FunctionInvoker<ReturnType(ArgTypes...)> {
|
||||||
v8::Context::Scope context_scope(context);
|
v8::Context::Scope context_scope(context);
|
||||||
std::vector<v8::Local<v8::Value>> args { ConvertToV8(isolate, raw)... };
|
std::vector<v8::Local<v8::Value>> args { ConvertToV8(isolate, raw)... };
|
||||||
v8::Local<v8::Value> result;
|
v8::Local<v8::Value> result;
|
||||||
auto maybe_result =
|
auto maybe_result = holder->Call(
|
||||||
holder->Call(context, holder, args.size(), &args.front());
|
context, holder, args.size(), args.empty() ? nullptr : &args.front());
|
||||||
if (maybe_result.ToLocal(&result))
|
if (maybe_result.ToLocal(&result))
|
||||||
Converter<ReturnType>::FromV8(isolate, result, &ret);
|
Converter<ReturnType>::FromV8(isolate, result, &ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -132,7 +132,12 @@ void AtomRendererClient::WillReleaseScriptContext(
|
||||||
node_bindings_->set_uv_env(nullptr);
|
node_bindings_->set_uv_env(nullptr);
|
||||||
|
|
||||||
// Destroy the node environment.
|
// Destroy the node environment.
|
||||||
node::FreeEnvironment(env);
|
// This is disabled because pending async tasks may still use the environment
|
||||||
|
// and would cause crashes later. Node does not seem to clear all async tasks
|
||||||
|
// when the environment is destroyed.
|
||||||
|
// node::FreeEnvironment(env);
|
||||||
|
|
||||||
|
// AtomBindings is tracking node environments.
|
||||||
atom_bindings_->EnvironmentDestroyed(env);
|
atom_bindings_->EnvironmentDestroyed(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -203,12 +203,12 @@
|
||||||
'BasicRuntimeChecks': '3', # 3 = all checks enabled, 0 = off
|
'BasicRuntimeChecks': '3', # 3 = all checks enabled, 0 = off
|
||||||
},
|
},
|
||||||
'VCLinkerTool': {
|
'VCLinkerTool': {
|
||||||
'OptimizeReferences': 2, # /OPT:REF
|
'OptimizeReferences': 2, # /OPT:REF
|
||||||
'EnableCOMDATFolding': 2, # /OPT:ICF
|
'EnableCOMDATFolding': 2, # /OPT:ICF
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'conditions': [
|
'conditions': [
|
||||||
['OS=="linux"', {
|
['OS=="linux" and target_arch=="x64"', {
|
||||||
'defines': [
|
'defines': [
|
||||||
'_GLIBCXX_DEBUG',
|
'_GLIBCXX_DEBUG',
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Class: BrowserView
|
## Class: BrowserView
|
||||||
|
|
||||||
> Create and control views.
|
> Create and control views.
|
||||||
|
|
||||||
|
@ -38,6 +38,14 @@ view.webContents.loadURL('https://electron.atom.io')
|
||||||
* `options` Object (optional)
|
* `options` Object (optional)
|
||||||
* `webPreferences` Object (optional) - See [BrowserWindow](browser-window.md).
|
* `webPreferences` Object (optional) - See [BrowserWindow](browser-window.md).
|
||||||
|
|
||||||
|
### Static Methods
|
||||||
|
|
||||||
|
#### `BrowserView.fromId(id)`
|
||||||
|
|
||||||
|
* `id` Integer
|
||||||
|
|
||||||
|
Returns `BrowserView` - The view with the given `id`.
|
||||||
|
|
||||||
### Instance Properties
|
### Instance Properties
|
||||||
|
|
||||||
Objects created with `new BrowserView` have the following properties:
|
Objects created with `new BrowserView` have the following properties:
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# Class: Menu
|
## Class: Menu
|
||||||
|
|
||||||
|
|
||||||
> Create native application menus and context menus.
|
> Create native application menus and context menus.
|
||||||
|
|
||||||
|
|
|
@ -22,12 +22,12 @@ Process: [Main](../tutorial/quick-start.md#main-process)
|
||||||
|
|
||||||
The following properties are available on instances of `TouchBarScrubber`:
|
The following properties are available on instances of `TouchBarScrubber`:
|
||||||
|
|
||||||
#### `touchBarSegmentedControl.items`
|
#### `touchBarScrubber.items`
|
||||||
|
|
||||||
A `ScrubberItem[]` array representing the items in this scrubber. Updating this value immediately
|
A `ScrubberItem[]` array representing the items in this scrubber. Updating this value immediately
|
||||||
updates the control in the touch bar. Updating deep properties inside this array **does not update the touch bar**.
|
updates the control in the touch bar. Updating deep properties inside this array **does not update the touch bar**.
|
||||||
|
|
||||||
#### `touchBarSegmentedControl.selectedStyle`
|
#### `touchBarScrubber.selectedStyle`
|
||||||
|
|
||||||
A `String` representing the style that selected items in the scrubber should have. Updating this value immediately
|
A `String` representing the style that selected items in the scrubber should have. Updating this value immediately
|
||||||
updates the control in the touch bar. Possible values:
|
updates the control in the touch bar. Possible values:
|
||||||
|
@ -36,7 +36,7 @@ updates the control in the touch bar. Possible values:
|
||||||
* `outline` - Maps to `[NSScrubberSelectionStyle outlineOverlayStyle]`
|
* `outline` - Maps to `[NSScrubberSelectionStyle outlineOverlayStyle]`
|
||||||
* `null` - Actually null, not a string, removes all styles
|
* `null` - Actually null, not a string, removes all styles
|
||||||
|
|
||||||
#### `touchBarSegmentedControl.overlayStyle`
|
#### `touchBarScrubber.overlayStyle`
|
||||||
|
|
||||||
A `String` representing the style that selected items in the scrubber should have. This style is overlayed on top
|
A `String` representing the style that selected items in the scrubber should have. This style is overlayed on top
|
||||||
of the scrubber item instead of being placed behind it. Updating this value immediately updates the control in the
|
of the scrubber item instead of being placed behind it. Updating this value immediately updates the control in the
|
||||||
|
@ -46,12 +46,12 @@ touch bar. Possible values:
|
||||||
* `outline` - Maps to `[NSScrubberSelectionStyle outlineOverlayStyle]`
|
* `outline` - Maps to `[NSScrubberSelectionStyle outlineOverlayStyle]`
|
||||||
* `null` - Actually null, not a string, removes all styles
|
* `null` - Actually null, not a string, removes all styles
|
||||||
|
|
||||||
#### `touchBarSegmentedControl.showArrowButtons`
|
#### `touchBarScrubber.showArrowButtons`
|
||||||
|
|
||||||
A `Boolean` representing whether to show the left / right selection arrows in this scrubber. Updating this value
|
A `Boolean` representing whether to show the left / right selection arrows in this scrubber. Updating this value
|
||||||
immediately updates the control in the touch bar.
|
immediately updates the control in the touch bar.
|
||||||
|
|
||||||
#### `touchBarSegmentedControl.mode`
|
#### `touchBarScrubber.mode`
|
||||||
|
|
||||||
A `String` representing the mode of this scrubber. Updating this value immediately
|
A `String` representing the mode of this scrubber. Updating this value immediately
|
||||||
updates the control in the touch bar. Possible values:
|
updates the control in the touch bar. Possible values:
|
||||||
|
@ -59,7 +59,7 @@ updates the control in the touch bar. Possible values:
|
||||||
* `fixed` - Maps to `NSScrubberModeFixed`
|
* `fixed` - Maps to `NSScrubberModeFixed`
|
||||||
* `free` - Maps to `NSScrubberModeFree`
|
* `free` - Maps to `NSScrubberModeFree`
|
||||||
|
|
||||||
#### `touchBarSegmentedControl.continuous`
|
#### `touchBarScrubber.continuous`
|
||||||
|
|
||||||
A `Boolean` representing whether this scrubber is continuous or not. Updating this value immediately
|
A `Boolean` representing whether this scrubber is continuous or not. Updating this value immediately
|
||||||
updates the control in the touch bar.
|
updates the control in the touch bar.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Class: TouchBar
|
## Class: TouchBar
|
||||||
|
|
||||||
> Create TouchBar layouts for native macOS applications
|
> Create TouchBar layouts for native macOS applications
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,10 @@ Follow the guidelines below for building Electron on Linux.
|
||||||
* Python 2.7.x. Some distributions like CentOS 6.x still use Python 2.6.x
|
* Python 2.7.x. Some distributions like CentOS 6.x still use Python 2.6.x
|
||||||
so you may need to check your Python version with `python -V`.
|
so you may need to check your Python version with `python -V`.
|
||||||
* Node.js. There are various ways to install Node. You can download
|
* Node.js. There are various ways to install Node. You can download
|
||||||
source code from [Node.js](http://nodejs.org) and compile from source.
|
source code from [nodejs.org](http://nodejs.org) and compile it.
|
||||||
Doing so permits installing Node on your own home directory as a standard user.
|
Doing so permits installing Node on your own home directory as a standard user.
|
||||||
Or try repositories such as [NodeSource](https://nodesource.com/blog/nodejs-v012-iojs-and-the-nodesource-linux-repositories).
|
Or try repositories such as [NodeSource](https://nodesource.com/blog/nodejs-v012-iojs-and-the-nodesource-linux-repositories).
|
||||||
* Clang 3.4 or later.
|
* [clang](https://clang.llvm.org/get_started.html) 3.4 or later.
|
||||||
* Development headers of GTK+ and libnotify.
|
* Development headers of GTK+ and libnotify.
|
||||||
|
|
||||||
On Ubuntu, install the following libraries:
|
On Ubuntu, install the following libraries:
|
||||||
|
@ -48,7 +48,7 @@ managers such as pacman. Or one can compile from source code.
|
||||||
## Getting the Code
|
## Getting the Code
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ git clone https://github.com/electron/electron.git
|
$ git clone https://github.com/electron/electron
|
||||||
```
|
```
|
||||||
|
|
||||||
## Bootstrapping
|
## Bootstrapping
|
||||||
|
@ -60,7 +60,7 @@ Downloading certain files can take a long time. Notice that we are using
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ cd electron
|
$ cd electron
|
||||||
$ ./script/bootstrap.py -v
|
$ ./script/bootstrap.py --verbose
|
||||||
```
|
```
|
||||||
|
|
||||||
### Cross compilation
|
### Cross compilation
|
||||||
|
@ -73,7 +73,7 @@ $ sudo apt-get install libc6-dev-armhf-cross linux-libc-dev-armhf-cross \
|
||||||
g++-arm-linux-gnueabihf
|
g++-arm-linux-gnueabihf
|
||||||
```
|
```
|
||||||
|
|
||||||
And to cross compile for `arm` or `ia32` targets, you should pass the
|
And to cross-compile for `arm` or `ia32` targets, you should pass the
|
||||||
`--target_arch` parameter to the `bootstrap.py` script:
|
`--target_arch` parameter to the `bootstrap.py` script:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@ -98,7 +98,7 @@ $ ./script/create-dist.py
|
||||||
```
|
```
|
||||||
|
|
||||||
This will put a working distribution with much smaller file sizes in
|
This will put a working distribution with much smaller file sizes in
|
||||||
the `dist` directory. After running the create-dist.py script, you
|
the `dist` directory. After running the `create-dist.py` script, you
|
||||||
may want to remove the 1.3+ gigabyte binary which is still in `out/R`.
|
may want to remove the 1.3+ gigabyte binary which is still in `out/R`.
|
||||||
|
|
||||||
You can also build the `Debug` target only:
|
You can also build the `Debug` target only:
|
||||||
|
@ -143,17 +143,29 @@ See [Build System Overview: Tests](build-system-overview.md#tests)
|
||||||
## Advanced topics
|
## Advanced topics
|
||||||
|
|
||||||
The default building configuration is targeted for major desktop Linux
|
The default building configuration is targeted for major desktop Linux
|
||||||
distributions, to build for a specific distribution or device, following
|
distributions. To build for a specific distribution or device, the following
|
||||||
information may help you.
|
information may help you.
|
||||||
|
|
||||||
### Building `libchromiumcontent` locally
|
### Building `libchromiumcontent` locally
|
||||||
|
|
||||||
To avoid using the prebuilt binaries of `libchromiumcontent`, you can pass the
|
To avoid using the prebuilt binaries of `libchromiumcontent`, you can build `libchromiumcontent` locally. To do so, follow these steps:
|
||||||
`--build_libchromiumcontent` switch to `bootstrap.py` script:
|
1. Install [depot_tools](https://chromium.googlesource.com/chromium/src/+/master/docs/linux_build_instructions.md#Install)
|
||||||
|
2. Install [additional build dependencies](https://chromium.googlesource.com/chromium/src/+/master/docs/linux_build_instructions.md#Install-additional-build-dependencies)
|
||||||
|
3. Fetch the git submodules:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ git submodule update --init --recursive
|
||||||
|
```
|
||||||
|
4. Copy the .gclient config file
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ ./script/bootstrap.py -v --build_libchromiumcontent
|
$ cp vendor/libchromiumcontent/.gclient .
|
||||||
```
|
```
|
||||||
|
5. Pass the `--build_libchromiumcontent` switch to `bootstrap.py` script:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ ./script/bootstrap.py -v --build_libchromiumcontent
|
||||||
|
```
|
||||||
|
|
||||||
Note that by default the `shared_library` configuration is not built, so you can
|
Note that by default the `shared_library` configuration is not built, so you can
|
||||||
only build `Release` version of Electron if you use this mode:
|
only build `Release` version of Electron if you use this mode:
|
||||||
|
@ -164,10 +176,12 @@ $ ./script/build.py -c R
|
||||||
|
|
||||||
### Using system `clang` instead of downloaded `clang` binaries
|
### Using system `clang` instead of downloaded `clang` binaries
|
||||||
|
|
||||||
By default Electron is built with prebuilt `clang` binaries provided by Chromium
|
By default Electron is built with prebuilt
|
||||||
project. If for some reason you want to build with the `clang` installed in your
|
[`clang`](https://clang.llvm.org/get_started.html) binaries provided by the
|
||||||
system, you can call `bootstrap.py` with `--clang_dir=<path>` switch. By passing
|
Chromium project. If for some reason you want to build with the `clang`
|
||||||
it the build script will assume the `clang` binaries reside in `<path>/bin/`.
|
installed in your system, you can call `bootstrap.py` with `--clang_dir=<path>`
|
||||||
|
switch. By passing it the build script will assume the `clang` binaries reside
|
||||||
|
in `<path>/bin/`.
|
||||||
|
|
||||||
For example if you installed `clang` under `/user/local/bin/clang`:
|
For example if you installed `clang` under `/user/local/bin/clang`:
|
||||||
|
|
||||||
|
@ -176,7 +190,7 @@ $ ./script/bootstrap.py -v --build_libchromiumcontent --clang_dir /usr/local
|
||||||
$ ./script/build.py -c R
|
$ ./script/build.py -c R
|
||||||
```
|
```
|
||||||
|
|
||||||
### Using other compilers other than `clang`
|
### Using compilers other than `clang`
|
||||||
|
|
||||||
To build Electron with compilers like `g++`, you first need to disable `clang`
|
To build Electron with compilers like `g++`, you first need to disable `clang`
|
||||||
with `--disable_clang` switch first, and then set `CC` and `CXX` environment
|
with `--disable_clang` switch first, and then set `CC` and `CXX` environment
|
||||||
|
@ -209,4 +223,4 @@ custom the building configurations:
|
||||||
* `LDFLAGS`
|
* `LDFLAGS`
|
||||||
|
|
||||||
The environment variables have to be set when executing the `bootstrap.py`
|
The environment variables have to be set when executing the `bootstrap.py`
|
||||||
script, it won't work in the `build.py` script.
|
script, it won't work in the `build.py` script.
|
|
@ -12,11 +12,9 @@ The ASAR format was created primarily to improve performance on Windows... TODO
|
||||||
|
|
||||||
### Brightray
|
### Brightray
|
||||||
|
|
||||||
Brightray is a static library that makes [libchromiumcontent]
|
Brightray [was](https://github.com/electron-archive/brightray) a static library
|
||||||
easier to use in applications.
|
that made [libchromiumcontent] easier to use in applications. It is now
|
||||||
|
deprecated and has been merged into Electron's codebase.
|
||||||
Brightray is a low-level dependency of Electron that does not concern the
|
|
||||||
majority of Electron users.
|
|
||||||
|
|
||||||
### CRT
|
### CRT
|
||||||
|
|
||||||
|
@ -44,8 +42,10 @@ serialized JSON messages between the [main] and [renderer] processes.
|
||||||
|
|
||||||
### libchromiumcontent
|
### libchromiumcontent
|
||||||
|
|
||||||
A single, shared library that includes the Chromium Content module and all its
|
A shared library that includes the [Chromium Content module] and all its
|
||||||
dependencies (e.g., Blink, [V8], etc.).
|
dependencies (e.g., Blink, [V8], etc.). Also referred to as "libcc".
|
||||||
|
|
||||||
|
- [github.com/electron/libchromiumcontent](https://github.com/electron/libchromiumcontent)
|
||||||
|
|
||||||
### main process
|
### main process
|
||||||
|
|
||||||
|
@ -142,8 +142,17 @@ available in "core".
|
||||||
### V8
|
### V8
|
||||||
|
|
||||||
V8 is Google's open source JavaScript engine. It is written in C++ and is
|
V8 is Google's open source JavaScript engine. It is written in C++ and is
|
||||||
used in Google Chrome. V8 can run
|
used in Google Chrome. V8 can run standalone, or can be embedded into any C++ application.
|
||||||
standalone, or can be embedded into any C++ application.
|
|
||||||
|
Electron builds V8 as part of Chromium and then points Node to that V8 when
|
||||||
|
building it.
|
||||||
|
|
||||||
|
V8's version numbers always correspond to those of Google Chrome. Chrome 59
|
||||||
|
includes V8 5.9, Chrome 58 includes V8 5.8, etc.
|
||||||
|
|
||||||
|
- [developers.google.com/v8](https://developers.google.com/v8)
|
||||||
|
- [nodejs.org/api/v8.html](https://nodejs.org/api/v8.html)
|
||||||
|
- [docs/development/v8-development.md](development/v8-development.md)
|
||||||
|
|
||||||
### webview
|
### webview
|
||||||
|
|
||||||
|
@ -157,11 +166,12 @@ embedded content.
|
||||||
[addons]: https://nodejs.org/api/addons.html
|
[addons]: https://nodejs.org/api/addons.html
|
||||||
[asar]: https://github.com/electron/asar
|
[asar]: https://github.com/electron/asar
|
||||||
[autoUpdater]: api/auto-updater.md
|
[autoUpdater]: api/auto-updater.md
|
||||||
|
[Chromium Content module]: https://www.chromium.org/developers/content-module
|
||||||
[electron-builder]: https://github.com/electron-userland/electron-builder
|
[electron-builder]: https://github.com/electron-userland/electron-builder
|
||||||
[libchromiumcontent]: #libchromiumcontent
|
[libchromiumcontent]: #libchromiumcontent
|
||||||
[Mac App Store Submission Guide]: tutorial/mac-app-store-submission-guide.md
|
[Mac App Store Submission Guide]: tutorial/mac-app-store-submission-guide.md
|
||||||
[main]: #main-process
|
[main]: #main-process
|
||||||
[renderer]: #renderer-process
|
[renderer]: #renderer-process
|
||||||
[Using Native Node Modules]: tutorial/using-native-node-modules.md
|
|
||||||
[userland]: #userland
|
[userland]: #userland
|
||||||
|
[Using Native Node Modules]: tutorial/using-native-node-modules.md
|
||||||
[V8]: #v8
|
[V8]: #v8
|
||||||
|
|
|
@ -292,7 +292,7 @@ TouchBar.TouchBarScrubber = class TouchBarScrubber extends TouchBarItem {
|
||||||
this._addLiveProperty('overlayStyle', overlayStyle || null)
|
this._addLiveProperty('overlayStyle', overlayStyle || null)
|
||||||
this._addLiveProperty('showArrowButtons', showArrowButtons || false)
|
this._addLiveProperty('showArrowButtons', showArrowButtons || false)
|
||||||
this._addLiveProperty('mode', mode || 'free')
|
this._addLiveProperty('mode', mode || 'free')
|
||||||
this._addLiveProperty('continuous', continuous || true)
|
this._addLiveProperty('continuous', typeof continuous === 'undefined' ? true : continuous)
|
||||||
|
|
||||||
if (typeof select === 'function' || typeof highlight === 'function') {
|
if (typeof select === 'function' || typeof highlight === 'function') {
|
||||||
if (select == null) select = () => {}
|
if (select == null) select = () => {}
|
||||||
|
|
|
@ -18,14 +18,20 @@ LINUX_DEPS = [
|
||||||
'libnotify-dev',
|
'libnotify-dev',
|
||||||
'libnss3-dev',
|
'libnss3-dev',
|
||||||
'libxtst-dev',
|
'libxtst-dev',
|
||||||
|
]
|
||||||
|
|
||||||
|
LINUX_DEPS_NO_ARM = [
|
||||||
'gcc-multilib',
|
'gcc-multilib',
|
||||||
'g++-multilib',
|
'g++-multilib',
|
||||||
]
|
]
|
||||||
|
|
||||||
LINUX_DEPS_ARM = [
|
LINUX_DEPS_ARM = [
|
||||||
'libc6-dev-armhf-cross',
|
'binutils-aarch64-linux-gnu',
|
||||||
'linux-libc-dev-armhf-cross',
|
'libc6-dev-armhf-cross',
|
||||||
'g++-arm-linux-gnueabihf',
|
'linux-libc-dev-armhf-cross',
|
||||||
|
'g++-arm-linux-gnueabihf',
|
||||||
|
'g++-4.8-multilib-arm-linux-gnueabihf',
|
||||||
|
'gcc-4.8-multilib-arm-linux-gnueabihf',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,6 +59,8 @@ def main():
|
||||||
deps = LINUX_DEPS
|
deps = LINUX_DEPS
|
||||||
if target_arch == 'arm':
|
if target_arch == 'arm':
|
||||||
deps += LINUX_DEPS_ARM
|
deps += LINUX_DEPS_ARM
|
||||||
|
else:
|
||||||
|
deps += LINUX_DEPS_NO_ARM
|
||||||
execute(['sudo', 'apt-get', 'install'] + deps)
|
execute(['sudo', 'apt-get', 'install'] + deps)
|
||||||
|
|
||||||
execute(['sh', '-e', '/etc/init.d/xvfb', 'start'])
|
execute(['sh', '-e', '/etc/init.d/xvfb', 'start'])
|
||||||
|
|
|
@ -81,6 +81,14 @@ def parse_args():
|
||||||
help='Run tests in CI mode',
|
help='Run tests in CI mode',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
required=False)
|
required=False)
|
||||||
|
parser.add_argument('-g', '--grep',
|
||||||
|
help='Only run tests matching <pattern>',
|
||||||
|
metavar='pattern',
|
||||||
|
required=False)
|
||||||
|
parser.add_argument('-i', '--invert',
|
||||||
|
help='Inverts --grep matches',
|
||||||
|
action='store_true',
|
||||||
|
required=False)
|
||||||
parser.add_argument('-v', '--verbose',
|
parser.add_argument('-v', '--verbose',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Prints the output of the subprocesses')
|
help='Prints the output of the subprocesses')
|
||||||
|
|
|
@ -208,7 +208,7 @@ describe('app module', function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('app.importCertificate', function () {
|
xdescribe('app.importCertificate', function () {
|
||||||
if (process.platform !== 'linux') return
|
if (process.platform !== 'linux') return
|
||||||
|
|
||||||
var w = null
|
var w = null
|
||||||
|
@ -405,7 +405,7 @@ describe('app module', function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('select-client-certificate event', function () {
|
xdescribe('select-client-certificate event', function () {
|
||||||
let w = null
|
let w = null
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
|
|
|
@ -100,4 +100,14 @@ describe('BrowserView module', function () {
|
||||||
assert.ok(!view.webContents.getOwnerBrowserWindow())
|
assert.ok(!view.webContents.getOwnerBrowserWindow())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('BrowserView.fromId()', function () {
|
||||||
|
it('returns the view with given id', function () {
|
||||||
|
view = new BrowserView()
|
||||||
|
w.setBrowserView(view)
|
||||||
|
assert.notEqual(view.id, null)
|
||||||
|
let view2 = BrowserView.fromId(view.id)
|
||||||
|
assert.equal(view2.webContents.id, view.webContents.id)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1144,13 +1144,16 @@ describe('BrowserWindow module', function () {
|
||||||
w.loadURL('file://' + path.join(fixtures, 'api', 'sandbox.html?window-events'))
|
w.loadURL('file://' + path.join(fixtures, 'api', 'sandbox.html?window-events'))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('works for web contents events', function (done) {
|
it('works for stop events', function (done) {
|
||||||
waitForEvents(w.webContents, [
|
waitForEvents(w.webContents, [
|
||||||
'did-navigate',
|
'did-navigate',
|
||||||
'did-fail-load',
|
'did-fail-load',
|
||||||
'did-stop-loading'
|
'did-stop-loading'
|
||||||
], done)
|
], done)
|
||||||
w.loadURL('file://' + path.join(fixtures, 'api', 'sandbox.html?webcontents-stop'))
|
w.loadURL('file://' + path.join(fixtures, 'api', 'sandbox.html?webcontents-stop'))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('works for web contents events', function (done) {
|
||||||
waitForEvents(w.webContents, [
|
waitForEvents(w.webContents, [
|
||||||
'did-finish-load',
|
'did-finish-load',
|
||||||
'did-frame-finish-load',
|
'did-frame-finish-load',
|
||||||
|
|
|
@ -12,7 +12,7 @@ const {remote} = require('electron')
|
||||||
const {app, BrowserWindow, crashReporter} = remote.require('electron')
|
const {app, BrowserWindow, crashReporter} = remote.require('electron')
|
||||||
|
|
||||||
describe('crashReporter module', function () {
|
describe('crashReporter module', function () {
|
||||||
if (process.mas) {
|
if (process.mas || process.env.DISABLE_CRASH_REPORTER_TESTS) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -590,6 +590,12 @@ describe('webContents module', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('destroy()', () => {
|
describe('destroy()', () => {
|
||||||
|
// Destroying webContents in its event listener is going to crash when
|
||||||
|
// Electron is built in Debug mode.
|
||||||
|
if (process.platform !== 'darwin') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let server
|
let server
|
||||||
|
|
||||||
before(function (done) {
|
before(function (done) {
|
||||||
|
|
|
@ -62,16 +62,17 @@
|
||||||
if (query.invert) mocha.invert();
|
if (query.invert) mocha.invert();
|
||||||
|
|
||||||
// Read all test files.
|
// Read all test files.
|
||||||
var walker = require('walkdir').walk(require('path').dirname(__dirname), {
|
var walker = require('walkdir').walk(path.dirname(__dirname), {
|
||||||
no_recurse: true
|
no_recurse: true
|
||||||
});
|
});
|
||||||
|
|
||||||
walker.on('file', function(file) {
|
walker.on('file', function(file) {
|
||||||
if (/-spec\.js$/.test(file))
|
if (/-spec\.js$/.test(file) && !file.includes('api-crash-reporter-spec.js'))
|
||||||
mocha.addFile(file);
|
mocha.addFile(file);
|
||||||
});
|
});
|
||||||
|
|
||||||
walker.on('end', function() {
|
walker.on('end', function() {
|
||||||
|
mocha.addFile(path.resolve(__dirname, '..', 'api-crash-reporter-spec.js'))
|
||||||
var runner = mocha.run(function() {
|
var runner = mocha.run(function() {
|
||||||
if (isCi && runner.hasOnly) {
|
if (isCi && runner.hasOnly) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -141,6 +141,10 @@ app.on('ready', function () {
|
||||||
})
|
})
|
||||||
if (chosen === 0) window.destroy()
|
if (chosen === 0) window.destroy()
|
||||||
})
|
})
|
||||||
|
window.webContents.on('crashed', function () {
|
||||||
|
console.error('Renderer process crashed')
|
||||||
|
process.exit(1)
|
||||||
|
})
|
||||||
|
|
||||||
// For session's download test, listen 'will-download' event in browser, and
|
// For session's download test, listen 'will-download' event in browser, and
|
||||||
// reply the result to renderer for verifying
|
// reply the result to renderer for verifying
|
||||||
|
|
Loading…
Reference in a new issue