mirror of
https://github.com/electron/electron.git
synced 2026-02-26 03:01:17 -05:00
Compare commits
177 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
18fcd6990b | ||
|
|
5fe130a684 | ||
|
|
71598e15bf | ||
|
|
cd3c061448 | ||
|
|
163790d107 | ||
|
|
2fdc5780ff | ||
|
|
b76642bd10 | ||
|
|
209e24bf0f | ||
|
|
731773765e | ||
|
|
333fe87490 | ||
|
|
36f0ef703a | ||
|
|
605722c397 | ||
|
|
132c13a11b | ||
|
|
04d24f61fe | ||
|
|
8eb5e651a2 | ||
|
|
5cd0fc4d52 | ||
|
|
d12697c657 | ||
|
|
0819176cb1 | ||
|
|
7d1f6dae6f | ||
|
|
5c2bb42d49 | ||
|
|
db9615f5cd | ||
|
|
09c5da7147 | ||
|
|
4b12a95d37 | ||
|
|
200a19dad9 | ||
|
|
2ee6e43fb3 | ||
|
|
0fef09281b | ||
|
|
f91a81fe77 | ||
|
|
78eff673ec | ||
|
|
51dc8ad70a | ||
|
|
d8cd9b71b0 | ||
|
|
c78a3ff714 | ||
|
|
4642630674 | ||
|
|
a6a5d50c3f | ||
|
|
b4790a7531 | ||
|
|
9199d0df0a | ||
|
|
a84e6227ef | ||
|
|
35dcdfc492 | ||
|
|
2f4333b852 | ||
|
|
bd1fd9680f | ||
|
|
cf79f439ce | ||
|
|
e829a28947 | ||
|
|
6d756d9d13 | ||
|
|
29abfa68e9 | ||
|
|
ab98dcd7cf | ||
|
|
6494ed6b13 | ||
|
|
8893c9502a | ||
|
|
13b6ed6dc5 | ||
|
|
8aa815e6d1 | ||
|
|
719f68a44b | ||
|
|
4c48f0cd36 | ||
|
|
8ef3351846 | ||
|
|
9f0ac13edc | ||
|
|
5459137d3d | ||
|
|
52b2c0d27f | ||
|
|
89087d402d | ||
|
|
64e84b8f6a | ||
|
|
24586c1330 | ||
|
|
f8c6056eec | ||
|
|
03ab9b2686 | ||
|
|
f1a8c5a1ca | ||
|
|
488801e244 | ||
|
|
bf1765f941 | ||
|
|
994be9cdab | ||
|
|
d4e4c6ca15 | ||
|
|
47cb06e201 | ||
|
|
cac97cca0d | ||
|
|
16c08e7e37 | ||
|
|
2de5f9de6c | ||
|
|
06a3875726 | ||
|
|
1ae8bed96a | ||
|
|
2ec74b5958 | ||
|
|
72ebb2c9fe | ||
|
|
52166d2999 | ||
|
|
676cfa03a1 | ||
|
|
64a89fe755 | ||
|
|
2bd03f6eda | ||
|
|
eeaee1a0b7 | ||
|
|
fed9ef0687 | ||
|
|
75448ad7ed | ||
|
|
25db6e0bd8 | ||
|
|
cefe540ec0 | ||
|
|
8363a39a56 | ||
|
|
57ef6adbbd | ||
|
|
5ae9c633ca | ||
|
|
b6a5e927e0 | ||
|
|
625c17fa24 | ||
|
|
f776932718 | ||
|
|
55c07cec68 | ||
|
|
161dc45ec8 | ||
|
|
29827fa66b | ||
|
|
40b6a1a37c | ||
|
|
e4ae579b16 | ||
|
|
582a42f97c | ||
|
|
9a0a10e766 | ||
|
|
cd1c331112 | ||
|
|
8a2b665097 | ||
|
|
690513db7f | ||
|
|
13c1b078f9 | ||
|
|
4da7578dab | ||
|
|
c821a06e2f | ||
|
|
cd7b3dd291 | ||
|
|
bb42c2c7b6 | ||
|
|
af62b7b5c9 | ||
|
|
8f9a109fa6 | ||
|
|
05468cc3fa | ||
|
|
94d69777fa | ||
|
|
67144aaf2a | ||
|
|
d9efc3b4bf | ||
|
|
c32aac0a56 | ||
|
|
92b15c81e9 | ||
|
|
19d742de37 | ||
|
|
e8f33f51fb | ||
|
|
7f7cdbf775 | ||
|
|
7f42c0fa21 | ||
|
|
8306dc427a | ||
|
|
66b3972fbc | ||
|
|
ed244648d0 | ||
|
|
790fba598e | ||
|
|
129159c895 | ||
|
|
f4c696b922 | ||
|
|
f54506acc0 | ||
|
|
4466082592 | ||
|
|
a8256a62e0 | ||
|
|
683917ae67 | ||
|
|
a22b9be681 | ||
|
|
3b20f2aced | ||
|
|
5d23b7468e | ||
|
|
d5b47d1059 | ||
|
|
47e9deeb9a | ||
|
|
6d6e75795f | ||
|
|
cc3066e746 | ||
|
|
0fcc0f3e0a | ||
|
|
da83ba6c06 | ||
|
|
3c186946eb | ||
|
|
31beee9599 | ||
|
|
912ed2ca10 | ||
|
|
c2352d3499 | ||
|
|
3a3b05b2f0 | ||
|
|
95a8f3fc70 | ||
|
|
34cd1435b4 | ||
|
|
d4be2da70e | ||
|
|
e5c4e34ac4 | ||
|
|
6dfa7b5383 | ||
|
|
94382cbaa2 | ||
|
|
981908c336 | ||
|
|
3ee054e316 | ||
|
|
f22d4bf0c0 | ||
|
|
d46e986e80 | ||
|
|
bd6d41bd87 | ||
|
|
4457edb1d3 | ||
|
|
e920ce3e24 | ||
|
|
ce8aa073ee | ||
|
|
2396b51cb6 | ||
|
|
317406f26d | ||
|
|
67a9931b55 | ||
|
|
ad851547e0 | ||
|
|
c4cbb5ecdb | ||
|
|
b97c22d4d7 | ||
|
|
fe631e6eeb | ||
|
|
1314b7c7e5 | ||
|
|
c026863d48 | ||
|
|
51d5ef9d86 | ||
|
|
16fb847009 | ||
|
|
cd8ceec62e | ||
|
|
98a9d8a9e3 | ||
|
|
4e2f242ad0 | ||
|
|
02bdace366 | ||
|
|
6ed538b952 | ||
|
|
dfbe158ca9 | ||
|
|
fb37b5720d | ||
|
|
57ab704300 | ||
|
|
4a310ad630 | ||
|
|
a9ad783bca | ||
|
|
b5c9fe78f1 | ||
|
|
e4bb456964 | ||
|
|
b45ed8d9a2 | ||
|
|
bdf73fcd4c |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,6 +6,7 @@
|
||||
/vendor/brightray/vendor/download/
|
||||
/vendor/python_26/
|
||||
/vendor/npm/
|
||||
/vendor/.gclient
|
||||
node_modules/
|
||||
*.xcodeproj
|
||||
*.swp
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -13,3 +13,6 @@
|
||||
[submodule "vendor/native_mate"]
|
||||
path = vendor/native_mate
|
||||
url = https://github.com/zcbenz/native-mate.git
|
||||
[submodule "vendor/crashpad"]
|
||||
path = vendor/crashpad
|
||||
url = https://github.com/atom/crashpad.git
|
||||
|
||||
10
atom.gyp
10
atom.gyp
@@ -4,7 +4,7 @@
|
||||
'product_name%': 'Electron',
|
||||
'company_name%': 'GitHub, Inc',
|
||||
'company_abbr%': 'github',
|
||||
'version%': '0.27.1',
|
||||
'version%': '0.28.0',
|
||||
|
||||
'atom_source_root': '<!(["python", "tools/atom_source_root.py"])',
|
||||
},
|
||||
@@ -45,6 +45,7 @@
|
||||
'dependencies': [
|
||||
'<(project_name)_framework',
|
||||
'<(project_name)_helper',
|
||||
'vendor/breakpad/breakpad.gyp:dump_syms',
|
||||
],
|
||||
'xcode_settings': {
|
||||
'ATOM_BUNDLE_ID': 'com.<(company_abbr).<(project_name)',
|
||||
@@ -275,7 +276,8 @@
|
||||
}], # OS=="win"
|
||||
['OS=="mac"', {
|
||||
'dependencies': [
|
||||
'vendor/breakpad/breakpad.gyp:breakpad',
|
||||
'vendor/crashpad/client/client.gyp:crashpad_client',
|
||||
'vendor/crashpad/handler/handler.gyp:crashpad_handler',
|
||||
],
|
||||
}], # OS=="mac"
|
||||
['OS=="linux"', {
|
||||
@@ -430,8 +432,7 @@
|
||||
{
|
||||
'destination': '<(PRODUCT_DIR)/<(product_name) Framework.framework/Versions/A/Resources',
|
||||
'files': [
|
||||
'<(PRODUCT_DIR)/Inspector',
|
||||
'<(PRODUCT_DIR)/crash_report_sender.app',
|
||||
'<(PRODUCT_DIR)/crashpad_handler',
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -452,7 +453,6 @@
|
||||
'tools/mac/create-framework-subdir-symlinks.sh',
|
||||
'<(product_name) Framework',
|
||||
'Libraries',
|
||||
'Frameworks',
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -70,10 +70,6 @@ void Menu::MenuWillShow(ui::SimpleMenuModel* source) {
|
||||
menu_will_show_.Run();
|
||||
}
|
||||
|
||||
void Menu::AttachToWindow(Window* window) {
|
||||
window->window()->SetMenu(model_.get());
|
||||
}
|
||||
|
||||
void Menu::InsertItemAt(
|
||||
int index, int command_id, const base::string16& label) {
|
||||
model_->InsertItemAt(index, command_id, label);
|
||||
@@ -168,7 +164,6 @@ void Menu::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("isItemCheckedAt", &Menu::IsItemCheckedAt)
|
||||
.SetMethod("isEnabledAt", &Menu::IsEnabledAt)
|
||||
.SetMethod("isVisibleAt", &Menu::IsVisibleAt)
|
||||
.SetMethod("attachToWindow", &Menu::AttachToWindow)
|
||||
.SetMethod("_popup", &Menu::Popup)
|
||||
.SetMethod("_popupAt", &Menu::PopupAt);
|
||||
}
|
||||
|
||||
@@ -51,7 +51,6 @@ class Menu : public mate::Wrappable,
|
||||
void ExecuteCommand(int command_id, int event_flags) override;
|
||||
void MenuWillShow(ui::SimpleMenuModel* source) override;
|
||||
|
||||
virtual void AttachToWindow(Window* window);
|
||||
virtual void Popup(Window* window) = 0;
|
||||
virtual void PopupAt(Window* window, int x, int y) = 0;
|
||||
|
||||
@@ -99,4 +98,27 @@ class Menu : public mate::Wrappable,
|
||||
|
||||
} // namespace atom
|
||||
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<ui::SimpleMenuModel*> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
ui::SimpleMenuModel** out) {
|
||||
// null would be tranfered to NULL.
|
||||
if (val->IsNull()) {
|
||||
*out = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
atom::api::Menu* menu;
|
||||
if (!Converter<atom::api::Menu*>::FromV8(isolate, val, &menu))
|
||||
return false;
|
||||
*out = menu->model();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_API_MENU_H_
|
||||
|
||||
@@ -41,8 +41,9 @@ void PowerMonitor::OnResume() {
|
||||
// static
|
||||
v8::Local<v8::Value> PowerMonitor::Create(v8::Isolate* isolate) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
node::ThrowError("Cannot initialize \"power-monitor\" module"
|
||||
"before app is ready");
|
||||
node::ThrowError(
|
||||
isolate,
|
||||
"Cannot initialize \"power-monitor\" module before app is ready");
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
|
||||
@@ -192,28 +192,19 @@ Protocol::JsProtocolHandler Protocol::GetProtocolHandler(
|
||||
mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) {
|
||||
return mate::ObjectTemplateBuilder(isolate)
|
||||
.SetMethod("registerProtocol",
|
||||
base::Bind(&Protocol::RegisterProtocol,
|
||||
base::Unretained(this)))
|
||||
.SetMethod("unregisterProtocol",
|
||||
base::Bind(&Protocol::UnregisterProtocol,
|
||||
base::Unretained(this)))
|
||||
.SetMethod("isHandledProtocol",
|
||||
base::Bind(&Protocol::IsHandledProtocol,
|
||||
base::Unretained(this)))
|
||||
.SetMethod("interceptProtocol",
|
||||
base::Bind(&Protocol::InterceptProtocol,
|
||||
base::Unretained(this)))
|
||||
.SetMethod("uninterceptProtocol",
|
||||
base::Bind(&Protocol::UninterceptProtocol,
|
||||
base::Unretained(this)));
|
||||
.SetMethod("registerProtocol", &Protocol::RegisterProtocol)
|
||||
.SetMethod("unregisterProtocol", &Protocol::UnregisterProtocol)
|
||||
.SetMethod("isHandledProtocol", &Protocol::IsHandledProtocol)
|
||||
.SetMethod("interceptProtocol", &Protocol::InterceptProtocol)
|
||||
.SetMethod("uninterceptProtocol", &Protocol::UninterceptProtocol);
|
||||
}
|
||||
|
||||
void Protocol::RegisterProtocol(const std::string& scheme,
|
||||
void Protocol::RegisterProtocol(v8::Isolate* isolate,
|
||||
const std::string& scheme,
|
||||
const JsProtocolHandler& callback) {
|
||||
if (ContainsKey(protocol_handlers_, scheme) ||
|
||||
job_factory_->IsHandledProtocol(scheme))
|
||||
return node::ThrowError("The scheme is already registered");
|
||||
return node::ThrowError(isolate, "The scheme is already registered");
|
||||
|
||||
protocol_handlers_[scheme] = callback;
|
||||
BrowserThread::PostTask(BrowserThread::IO,
|
||||
@@ -222,10 +213,11 @@ void Protocol::RegisterProtocol(const std::string& scheme,
|
||||
base::Unretained(this), scheme));
|
||||
}
|
||||
|
||||
void Protocol::UnregisterProtocol(const std::string& scheme) {
|
||||
void Protocol::UnregisterProtocol(v8::Isolate* isolate,
|
||||
const std::string& scheme) {
|
||||
ProtocolHandlersMap::iterator it(protocol_handlers_.find(scheme));
|
||||
if (it == protocol_handlers_.end())
|
||||
return node::ThrowError("The scheme has not been registered");
|
||||
return node::ThrowError(isolate, "The scheme has not been registered");
|
||||
|
||||
protocol_handlers_.erase(it);
|
||||
BrowserThread::PostTask(BrowserThread::IO,
|
||||
@@ -238,13 +230,14 @@ bool Protocol::IsHandledProtocol(const std::string& scheme) {
|
||||
return job_factory_->IsHandledProtocol(scheme);
|
||||
}
|
||||
|
||||
void Protocol::InterceptProtocol(const std::string& scheme,
|
||||
void Protocol::InterceptProtocol(v8::Isolate* isolate,
|
||||
const std::string& scheme,
|
||||
const JsProtocolHandler& callback) {
|
||||
if (!job_factory_->HasProtocolHandler(scheme))
|
||||
return node::ThrowError("Scheme does not exist.");
|
||||
return node::ThrowError(isolate, "Scheme does not exist.");
|
||||
|
||||
if (ContainsKey(protocol_handlers_, scheme))
|
||||
return node::ThrowError("Cannot intercept custom procotols");
|
||||
return node::ThrowError(isolate, "Cannot intercept custom procotols");
|
||||
|
||||
protocol_handlers_[scheme] = callback;
|
||||
BrowserThread::PostTask(BrowserThread::IO,
|
||||
@@ -253,10 +246,11 @@ void Protocol::InterceptProtocol(const std::string& scheme,
|
||||
base::Unretained(this), scheme));
|
||||
}
|
||||
|
||||
void Protocol::UninterceptProtocol(const std::string& scheme) {
|
||||
void Protocol::UninterceptProtocol(v8::Isolate* isolate,
|
||||
const std::string& scheme) {
|
||||
ProtocolHandlersMap::iterator it(protocol_handlers_.find(scheme));
|
||||
if (it == protocol_handlers_.end())
|
||||
return node::ThrowError("The scheme has not been registered");
|
||||
return node::ThrowError(isolate, "The scheme has not been registered");
|
||||
|
||||
protocol_handlers_.erase(it);
|
||||
BrowserThread::PostTask(BrowserThread::IO,
|
||||
|
||||
@@ -43,9 +43,10 @@ class Protocol : public mate::EventEmitter {
|
||||
|
||||
// Register/unregister an networking |scheme| which would be handled by
|
||||
// |callback|.
|
||||
void RegisterProtocol(const std::string& scheme,
|
||||
void RegisterProtocol(v8::Isolate* isolate,
|
||||
const std::string& scheme,
|
||||
const JsProtocolHandler& callback);
|
||||
void UnregisterProtocol(const std::string& scheme);
|
||||
void UnregisterProtocol(v8::Isolate* isolate, const std::string& scheme);
|
||||
|
||||
// Returns whether a scheme has been registered.
|
||||
// FIXME Should accept a callback and be asynchronous so we do not have to use
|
||||
@@ -53,9 +54,10 @@ class Protocol : public mate::EventEmitter {
|
||||
bool IsHandledProtocol(const std::string& scheme);
|
||||
|
||||
// Intercept/unintercept an existing protocol handler.
|
||||
void InterceptProtocol(const std::string& scheme,
|
||||
void InterceptProtocol(v8::Isolate* isolate,
|
||||
const std::string& scheme,
|
||||
const JsProtocolHandler& callback);
|
||||
void UninterceptProtocol(const std::string& scheme);
|
||||
void UninterceptProtocol(v8::Isolate* isolate, const std::string& scheme);
|
||||
|
||||
// The networking related operations have to be done in IO thread.
|
||||
void RegisterProtocolInIO(const std::string& scheme);
|
||||
|
||||
@@ -113,13 +113,14 @@ mate::ObjectTemplateBuilder Screen::GetObjectTemplateBuilder(
|
||||
// static
|
||||
v8::Local<v8::Value> Screen::Create(v8::Isolate* isolate) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
node::ThrowError("Cannot initialize \"screen\" module before app is ready");
|
||||
node::ThrowError(isolate,
|
||||
"Cannot initialize \"screen\" module before app is ready");
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
gfx::Screen* screen = gfx::Screen::GetNativeScreen();
|
||||
if (!screen) {
|
||||
node::ThrowError("Failed to get screen information");
|
||||
node::ThrowError(isolate, "Failed to get screen information");
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,9 +32,9 @@ Tray::~Tray() {
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Wrappable* Tray::New(const gfx::Image& image) {
|
||||
mate::Wrappable* Tray::New(v8::Isolate* isolate, const gfx::Image& image) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
node::ThrowError("Cannot create Tray before app is ready");
|
||||
node::ThrowError(isolate, "Cannot create Tray before app is ready");
|
||||
return nullptr;
|
||||
}
|
||||
return new Tray(image);
|
||||
|
||||
@@ -31,7 +31,7 @@ class Menu;
|
||||
class Tray : public mate::EventEmitter,
|
||||
public TrayIconObserver {
|
||||
public:
|
||||
static mate::Wrappable* New(const gfx::Image& image);
|
||||
static mate::Wrappable* New(v8::Isolate* isolate, const gfx::Image& image);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::ObjectTemplate> prototype);
|
||||
|
||||
@@ -8,10 +8,7 @@
|
||||
|
||||
#include "atom/browser/atom_browser_client.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/atom_javascript_dialog_manager.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/web_dialog_helper.h"
|
||||
#include "atom/browser/web_view_manager.h"
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "atom/common/native_mate_converters/gfx_converter.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
@@ -21,7 +18,6 @@
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "brightray/browser/inspectable_web_contents.h"
|
||||
#include "brightray/browser/media/media_stream_devices_controller.h"
|
||||
#include "content/public/browser/favicon_status.h"
|
||||
#include "content/public/browser/guest_host.h"
|
||||
#include "content/public/browser/navigation_details.h"
|
||||
@@ -44,22 +40,47 @@
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<atom::api::SetSizeParams> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
atom::api::SetSizeParams* out) {
|
||||
mate::Dictionary params;
|
||||
if (!ConvertFromV8(isolate, val, ¶ms))
|
||||
return false;
|
||||
bool autosize;
|
||||
if (params.Get("enableAutoSize", &autosize))
|
||||
out->enable_auto_size.reset(new bool(true));
|
||||
gfx::Size size;
|
||||
if (params.Get("min", &size))
|
||||
out->min_size.reset(new gfx::Size(size));
|
||||
if (params.Get("max", &size))
|
||||
out->max_size.reset(new gfx::Size(size));
|
||||
if (params.Get("normal", &size))
|
||||
out->normal_size.reset(new gfx::Size(size));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
const int kDefaultWidth = 300;
|
||||
const int kDefaultHeight = 300;
|
||||
|
||||
v8::Persistent<v8::ObjectTemplate> template_;
|
||||
|
||||
// Get the window that has the |guest| embedded.
|
||||
NativeWindow* GetWindowFromGuest(const content::WebContents* guest) {
|
||||
WebViewManager::WebViewInfo info;
|
||||
if (WebViewManager::GetInfoForProcess(guest->GetRenderProcessHost(), &info))
|
||||
return NativeWindow::FromWebContents(info.embedder);
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
// The wrapWebContents funtion which is implemented in JavaScript
|
||||
using WrapWebContentsCallback = base::Callback<void(v8::Local<v8::Value>)>;
|
||||
WrapWebContentsCallback g_wrap_web_contents;
|
||||
|
||||
content::ServiceWorkerContext* GetServiceWorkerContext(
|
||||
const content::WebContents* web_contents) {
|
||||
@@ -68,46 +89,54 @@ content::ServiceWorkerContext* GetServiceWorkerContext(
|
||||
if (!context || !site_instance)
|
||||
return nullptr;
|
||||
|
||||
content::StoragePartition* storage_partition =
|
||||
content::BrowserContext::GetStoragePartition(
|
||||
context, site_instance);
|
||||
|
||||
DCHECK(storage_partition);
|
||||
auto storage_partition =
|
||||
content::BrowserContext::GetStoragePartition(context, site_instance);
|
||||
if (!storage_partition)
|
||||
return nullptr;
|
||||
|
||||
return storage_partition->GetServiceWorkerContext();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
WebContents::WebContents(brightray::InspectableWebContents* web_contents)
|
||||
: WebContents(web_contents->GetWebContents()) {
|
||||
inspectable_web_contents_ = web_contents;
|
||||
}
|
||||
|
||||
WebContents::WebContents(content::WebContents* web_contents)
|
||||
: content::WebContentsObserver(web_contents),
|
||||
guest_instance_id_(-1),
|
||||
element_instance_id_(-1),
|
||||
: CommonWebContentsDelegate(false),
|
||||
content::WebContentsObserver(web_contents),
|
||||
guest_opaque_(true),
|
||||
guest_host_(nullptr),
|
||||
auto_size_enabled_(false) {
|
||||
auto_size_enabled_(false),
|
||||
is_full_page_plugin_(false),
|
||||
inspectable_web_contents_(nullptr) {
|
||||
}
|
||||
|
||||
WebContents::WebContents(const mate::Dictionary& options)
|
||||
: guest_instance_id_(-1),
|
||||
element_instance_id_(-1),
|
||||
: CommonWebContentsDelegate(true),
|
||||
guest_opaque_(true),
|
||||
guest_host_(nullptr),
|
||||
auto_size_enabled_(false) {
|
||||
options.Get("guestInstanceId", &guest_instance_id_);
|
||||
|
||||
auto_size_enabled_(false),
|
||||
is_full_page_plugin_(false) {
|
||||
auto browser_context = AtomBrowserContext::Get();
|
||||
content::SiteInstance* site_instance = content::SiteInstance::CreateForURL(
|
||||
browser_context, GURL("chrome-guest://fake-host"));
|
||||
|
||||
content::WebContents::CreateParams params(browser_context, site_instance);
|
||||
bool is_guest;
|
||||
if (options.Get("isGuest", &is_guest) && is_guest)
|
||||
params.guest_delegate = this;
|
||||
params.guest_delegate = this;
|
||||
auto web_contents = content::WebContents::Create(params);
|
||||
|
||||
storage_.reset(brightray::InspectableWebContents::Create(params));
|
||||
Observe(storage_->GetWebContents());
|
||||
web_contents()->SetDelegate(this);
|
||||
NativeWindow* owner_window = nullptr;
|
||||
WebContents* embedder = nullptr;
|
||||
if (options.Get("embedder", &embedder) && embedder)
|
||||
owner_window = NativeWindow::FromWebContents(embedder->web_contents());
|
||||
|
||||
InitWithWebContents(web_contents, owner_window);
|
||||
inspectable_web_contents_ = managed_web_contents();
|
||||
|
||||
Observe(GetWebContents());
|
||||
}
|
||||
|
||||
WebContents::~WebContents() {
|
||||
@@ -155,56 +184,7 @@ content::WebContents* WebContents::OpenURLFromTab(
|
||||
if (Emit("will-navigate", params.url))
|
||||
return nullptr;
|
||||
|
||||
content::NavigationController::LoadURLParams load_url_params(params.url);
|
||||
load_url_params.referrer = params.referrer;
|
||||
load_url_params.transition_type = params.transition;
|
||||
load_url_params.extra_headers = params.extra_headers;
|
||||
load_url_params.should_replace_current_entry =
|
||||
params.should_replace_current_entry;
|
||||
load_url_params.is_renderer_initiated = params.is_renderer_initiated;
|
||||
load_url_params.transferred_global_request_id =
|
||||
params.transferred_global_request_id;
|
||||
load_url_params.should_clear_history_list = true;
|
||||
|
||||
web_contents()->GetController().LoadURLWithParams(load_url_params);
|
||||
return web_contents();
|
||||
}
|
||||
|
||||
content::JavaScriptDialogManager* WebContents::GetJavaScriptDialogManager(
|
||||
content::WebContents* source) {
|
||||
if (!dialog_manager_)
|
||||
dialog_manager_.reset(new AtomJavaScriptDialogManager);
|
||||
|
||||
return dialog_manager_.get();
|
||||
}
|
||||
|
||||
void WebContents::RunFileChooser(content::WebContents* guest,
|
||||
const content::FileChooserParams& params) {
|
||||
if (!web_dialog_helper_)
|
||||
web_dialog_helper_.reset(new WebDialogHelper(GetWindowFromGuest(guest)));
|
||||
web_dialog_helper_->RunFileChooser(guest, params);
|
||||
}
|
||||
|
||||
void WebContents::EnumerateDirectory(content::WebContents* guest,
|
||||
int request_id,
|
||||
const base::FilePath& path) {
|
||||
if (!web_dialog_helper_)
|
||||
web_dialog_helper_.reset(new WebDialogHelper(GetWindowFromGuest(guest)));
|
||||
web_dialog_helper_->EnumerateDirectory(guest, request_id, path);
|
||||
}
|
||||
|
||||
bool WebContents::CheckMediaAccessPermission(content::WebContents* web_contents,
|
||||
const GURL& security_origin,
|
||||
content::MediaStreamType type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void WebContents::RequestMediaAccessPermission(
|
||||
content::WebContents*,
|
||||
const content::MediaStreamRequest& request,
|
||||
const content::MediaResponseCallback& callback) {
|
||||
brightray::MediaStreamDevicesController controller(request, callback);
|
||||
controller.TakeAction();
|
||||
return CommonWebContentsDelegate::OpenURLFromTab(source, params);
|
||||
}
|
||||
|
||||
void WebContents::HandleKeyboardEvent(
|
||||
@@ -220,32 +200,13 @@ void WebContents::HandleKeyboardEvent(
|
||||
|
||||
void WebContents::EnterFullscreenModeForTab(content::WebContents* source,
|
||||
const GURL& origin) {
|
||||
auto window = GetWindowFromGuest(source);
|
||||
if (window) {
|
||||
window->SetHtmlApiFullscreen(true);
|
||||
window->NotifyWindowEnterHtmlFullScreen();
|
||||
source->GetRenderViewHost()->WasResized();
|
||||
Emit("enter-html-full-screen");
|
||||
}
|
||||
CommonWebContentsDelegate::EnterFullscreenModeForTab(source, origin);
|
||||
Emit("enter-html-full-screen");
|
||||
}
|
||||
|
||||
void WebContents::ExitFullscreenModeForTab(content::WebContents* source) {
|
||||
auto window = GetWindowFromGuest(source);
|
||||
if (window) {
|
||||
window->SetHtmlApiFullscreen(false);
|
||||
window->NotifyWindowLeaveHtmlFullScreen();
|
||||
source->GetRenderViewHost()->WasResized();
|
||||
Emit("leave-html-full-screen");
|
||||
}
|
||||
}
|
||||
|
||||
bool WebContents::IsFullscreenForTabOrPending(
|
||||
const content::WebContents* source) const {
|
||||
auto window = GetWindowFromGuest(source);
|
||||
if (window)
|
||||
return window->is_html_api_fullscreen();
|
||||
else
|
||||
return false;
|
||||
CommonWebContentsDelegate::ExitFullscreenModeForTab(source);
|
||||
Emit("leave-html-full-screen");
|
||||
}
|
||||
|
||||
void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) {
|
||||
@@ -315,15 +276,27 @@ void WebContents::DidGetResourceResponseStart(
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
v8::Locker locker(isolate);
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
mate::Dictionary response_headers(isolate, v8::Object::New(isolate));
|
||||
base::DictionaryValue response_headers;
|
||||
|
||||
net::HttpResponseHeaders* headers = details.headers.get();
|
||||
if (!headers)
|
||||
return;
|
||||
void* iter = nullptr;
|
||||
std::string key;
|
||||
std::string value;
|
||||
while (headers && headers->EnumerateHeaderLines(&iter, &key, &value))
|
||||
response_headers.Set(base::StringToLowerASCII(key),
|
||||
base::StringToLowerASCII(value));
|
||||
while (headers->EnumerateHeaderLines(&iter, &key, &value)) {
|
||||
key = base::StringToLowerASCII(key);
|
||||
value = base::StringToLowerASCII(value);
|
||||
if (response_headers.HasKey(key)) {
|
||||
base::ListValue* values = nullptr;
|
||||
if (response_headers.GetList(key, &values))
|
||||
values->AppendString(value);
|
||||
} else {
|
||||
scoped_ptr<base::ListValue> values(new base::ListValue());
|
||||
values->AppendString(value);
|
||||
response_headers.Set(key, values.Pass());
|
||||
}
|
||||
}
|
||||
|
||||
Emit("did-get-response-details",
|
||||
details.socket_address.IsEmpty(),
|
||||
@@ -391,15 +364,11 @@ void WebContents::RenderViewReady() {
|
||||
// WebContents::GetRenderWidgetHostView will return the RWHV of an
|
||||
// interstitial page if one is showing at this time. We only want opacity
|
||||
// to apply to web pages.
|
||||
if (guest_opaque_) {
|
||||
web_contents()
|
||||
->GetRenderViewHost()
|
||||
->GetView()
|
||||
->SetBackgroundColorToDefault();
|
||||
} else {
|
||||
web_contents()->GetRenderViewHost()->GetView()->SetBackgroundColor(
|
||||
SK_ColorTRANSPARENT);
|
||||
}
|
||||
auto render_view_host_view = web_contents()->GetRenderViewHost()->GetView();
|
||||
if (guest_opaque_)
|
||||
render_view_host_view->SetBackgroundColorToDefault();
|
||||
else
|
||||
render_view_host_view->SetBackgroundColor(SK_ColorTRANSPARENT);
|
||||
}
|
||||
|
||||
void WebContents::WebContentsDestroyed() {
|
||||
@@ -418,14 +387,6 @@ void WebContents::DidAttach(int guest_proxy_routing_id) {
|
||||
Emit("did-attach");
|
||||
}
|
||||
|
||||
void WebContents::ElementSizeChanged(const gfx::Size& size) {
|
||||
element_size_ = size;
|
||||
|
||||
// Only resize if needed.
|
||||
if (!size.IsEmpty())
|
||||
guest_host_->SizeContents(size);
|
||||
}
|
||||
|
||||
content::WebContents* WebContents::GetOwnerWebContents() const {
|
||||
return embedder_web_contents_;
|
||||
}
|
||||
@@ -445,11 +406,11 @@ void WebContents::WillAttach(content::WebContents* embedder_web_contents,
|
||||
int element_instance_id,
|
||||
bool is_full_page_plugin) {
|
||||
embedder_web_contents_ = embedder_web_contents;
|
||||
element_instance_id_ = element_instance_id;
|
||||
is_full_page_plugin_ = is_full_page_plugin;
|
||||
}
|
||||
|
||||
void WebContents::Destroy() {
|
||||
if (storage_) {
|
||||
if (is_guest() && managed_web_contents()) {
|
||||
// When force destroying the "destroyed" event is not emitted.
|
||||
WebContentsDestroyed();
|
||||
|
||||
@@ -458,7 +419,7 @@ void WebContents::Destroy() {
|
||||
guest_host_ = nullptr;
|
||||
|
||||
Observe(nullptr);
|
||||
storage_.reset();
|
||||
DestroyWebContents();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -470,12 +431,12 @@ void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) {
|
||||
content::NavigationController::LoadURLParams params(url);
|
||||
|
||||
GURL http_referrer;
|
||||
if (options.Get("httpreferrer", &http_referrer))
|
||||
if (options.Get("httpReferrer", &http_referrer))
|
||||
params.referrer = content::Referrer(http_referrer.GetAsReferrer(),
|
||||
blink::WebReferrerPolicyDefault);
|
||||
|
||||
std::string user_agent;
|
||||
if (options.Get("useragent", &user_agent))
|
||||
if (options.Get("userAgent", &user_agent))
|
||||
SetUserAgent(user_agent);
|
||||
|
||||
params.transition_type = ui::PAGE_TRANSITION_TYPED;
|
||||
@@ -543,26 +504,82 @@ void WebContents::ExecuteJavaScript(const base::string16& code) {
|
||||
web_contents()->GetMainFrame()->ExecuteJavaScript(code);
|
||||
}
|
||||
|
||||
void WebContents::OpenDevTools() {
|
||||
storage_->SetCanDock(false);
|
||||
storage_->ShowDevTools();
|
||||
void WebContents::OpenDevTools(mate::Arguments* args) {
|
||||
if (!inspectable_web_contents())
|
||||
return;
|
||||
bool detach = false;
|
||||
if (is_guest()) {
|
||||
detach = true;
|
||||
} else if (args && args->Length() == 1) {
|
||||
mate::Dictionary options;
|
||||
args->GetNext(&options) && options.Get("detach", &detach);
|
||||
}
|
||||
inspectable_web_contents()->SetCanDock(!detach);
|
||||
inspectable_web_contents()->ShowDevTools();
|
||||
}
|
||||
|
||||
void WebContents::CloseDevTools() {
|
||||
storage_->CloseDevTools();
|
||||
if (!inspectable_web_contents())
|
||||
return;
|
||||
inspectable_web_contents()->CloseDevTools();
|
||||
}
|
||||
|
||||
bool WebContents::IsDevToolsOpened() {
|
||||
return storage_->IsDevToolsViewShowing();
|
||||
if (!inspectable_web_contents())
|
||||
return false;
|
||||
return inspectable_web_contents()->IsDevToolsViewShowing();
|
||||
}
|
||||
|
||||
void WebContents::ToggleDevTools() {
|
||||
if (IsDevToolsOpened())
|
||||
CloseDevTools();
|
||||
else
|
||||
OpenDevTools(nullptr);
|
||||
}
|
||||
|
||||
void WebContents::InspectElement(int x, int y) {
|
||||
OpenDevTools();
|
||||
if (!inspectable_web_contents())
|
||||
return;
|
||||
OpenDevTools(nullptr);
|
||||
scoped_refptr<content::DevToolsAgentHost> agent(
|
||||
content::DevToolsAgentHost::GetOrCreateFor(storage_->GetWebContents()));
|
||||
content::DevToolsAgentHost::GetOrCreateFor(web_contents()));
|
||||
agent->InspectElement(x, y);
|
||||
}
|
||||
|
||||
void WebContents::InspectServiceWorker() {
|
||||
if (!inspectable_web_contents())
|
||||
return;
|
||||
for (const auto& agent_host : content::DevToolsAgentHost::GetOrCreateAll()) {
|
||||
if (agent_host->GetType() ==
|
||||
content::DevToolsAgentHost::TYPE_SERVICE_WORKER) {
|
||||
OpenDevTools(nullptr);
|
||||
inspectable_web_contents()->AttachTo(agent_host);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WebContents::HasServiceWorker(
|
||||
const base::Callback<void(bool)>& callback) {
|
||||
auto context = GetServiceWorkerContext(web_contents());
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
context->CheckHasServiceWorker(web_contents()->GetLastCommittedURL(),
|
||||
GURL::EmptyGURL(),
|
||||
callback);
|
||||
}
|
||||
|
||||
void WebContents::UnregisterServiceWorker(
|
||||
const base::Callback<void(bool)>& callback) {
|
||||
auto context = GetServiceWorkerContext(web_contents());
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
context->UnregisterServiceWorker(web_contents()->GetLastCommittedURL(),
|
||||
callback);
|
||||
}
|
||||
|
||||
void WebContents::Undo() {
|
||||
web_contents()->Undo();
|
||||
}
|
||||
@@ -612,31 +629,57 @@ bool WebContents::SendIPCMessage(const base::string16& channel,
|
||||
return Send(new AtomViewMsg_Message(routing_id(), channel, args));
|
||||
}
|
||||
|
||||
void WebContents::SetAutoSize(bool enabled,
|
||||
const gfx::Size& min_size,
|
||||
const gfx::Size& max_size) {
|
||||
void WebContents::SetSize(const SetSizeParams& params) {
|
||||
bool enable_auto_size =
|
||||
params.enable_auto_size ? *params.enable_auto_size : auto_size_enabled_;
|
||||
gfx::Size min_size = params.min_size ? *params.min_size : min_auto_size_;
|
||||
gfx::Size max_size = params.max_size ? *params.max_size : max_auto_size_;
|
||||
|
||||
if (params.normal_size)
|
||||
normal_size_ = *params.normal_size;
|
||||
|
||||
min_auto_size_ = min_size;
|
||||
min_auto_size_.SetToMin(max_size);
|
||||
max_auto_size_ = max_size;
|
||||
max_auto_size_.SetToMax(min_size);
|
||||
|
||||
enabled &= !min_auto_size_.IsEmpty() && !max_auto_size_.IsEmpty();
|
||||
if (!enabled && !auto_size_enabled_)
|
||||
return;
|
||||
|
||||
auto_size_enabled_ = enabled;
|
||||
|
||||
if (!attached())
|
||||
return;
|
||||
enable_auto_size &= !min_auto_size_.IsEmpty() && !max_auto_size_.IsEmpty();
|
||||
|
||||
content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
|
||||
if (auto_size_enabled_) {
|
||||
if (enable_auto_size) {
|
||||
// Autosize is being enabled.
|
||||
rvh->EnableAutoResize(min_auto_size_, max_auto_size_);
|
||||
normal_size_.SetSize(0, 0);
|
||||
} else {
|
||||
rvh->DisableAutoResize(element_size_);
|
||||
guest_size_ = element_size_;
|
||||
GuestSizeChangedDueToAutoSize(guest_size_, element_size_);
|
||||
// Autosize is being disabled.
|
||||
// Use default width/height if missing from partially defined normal size.
|
||||
if (normal_size_.width() && !normal_size_.height())
|
||||
normal_size_.set_height(GetDefaultSize().height());
|
||||
if (!normal_size_.width() && normal_size_.height())
|
||||
normal_size_.set_width(GetDefaultSize().width());
|
||||
|
||||
gfx::Size new_size;
|
||||
if (!normal_size_.IsEmpty()) {
|
||||
new_size = normal_size_;
|
||||
} else if (!guest_size_.IsEmpty()) {
|
||||
new_size = guest_size_;
|
||||
} else {
|
||||
new_size = GetDefaultSize();
|
||||
}
|
||||
|
||||
if (auto_size_enabled_) {
|
||||
// Autosize was previously enabled.
|
||||
rvh->DisableAutoResize(new_size);
|
||||
GuestSizeChangedDueToAutoSize(guest_size_, new_size);
|
||||
} else {
|
||||
// Autosize was already disabled.
|
||||
guest_host_->SizeContents(new_size);
|
||||
}
|
||||
|
||||
guest_size_ = new_size;
|
||||
}
|
||||
|
||||
auto_size_enabled_ = enable_auto_size;
|
||||
}
|
||||
|
||||
void WebContents::SetAllowTransparency(bool allow) {
|
||||
@@ -658,36 +701,8 @@ void WebContents::SetAllowTransparency(bool allow) {
|
||||
}
|
||||
}
|
||||
|
||||
void WebContents::HasServiceWorker(
|
||||
const base::Callback<void(bool)>& callback) {
|
||||
auto context = GetServiceWorkerContext(web_contents());
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
context->CheckHasServiceWorker(web_contents()->GetLastCommittedURL(),
|
||||
GURL::EmptyGURL(),
|
||||
callback);
|
||||
}
|
||||
|
||||
void WebContents::UnregisterServiceWorker(
|
||||
const base::Callback<void(bool)>& callback) {
|
||||
auto context = GetServiceWorkerContext(web_contents());
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
context->UnregisterServiceWorker(web_contents()->GetLastCommittedURL(),
|
||||
callback);
|
||||
}
|
||||
|
||||
void WebContents::InspectServiceWorker() {
|
||||
for (const auto& agent_host : content::DevToolsAgentHost::GetOrCreateAll()) {
|
||||
if (agent_host->GetType() ==
|
||||
content::DevToolsAgentHost::TYPE_SERVICE_WORKER) {
|
||||
OpenDevTools();
|
||||
storage_->AttachTo(agent_host);
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool WebContents::IsGuest() const {
|
||||
return is_guest();
|
||||
}
|
||||
|
||||
mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
|
||||
@@ -714,6 +729,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
|
||||
.SetMethod("openDevTools", &WebContents::OpenDevTools)
|
||||
.SetMethod("closeDevTools", &WebContents::CloseDevTools)
|
||||
.SetMethod("isDevToolsOpened", &WebContents::IsDevToolsOpened)
|
||||
.SetMethod("toggleDevTools", &WebContents::ToggleDevTools)
|
||||
.SetMethod("inspectElement", &WebContents::InspectElement)
|
||||
.SetMethod("undo", &WebContents::Undo)
|
||||
.SetMethod("redo", &WebContents::Redo)
|
||||
@@ -727,9 +743,9 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
|
||||
.SetMethod("replace", &WebContents::Replace)
|
||||
.SetMethod("replaceMisspelling", &WebContents::ReplaceMisspelling)
|
||||
.SetMethod("_send", &WebContents::SendIPCMessage)
|
||||
.SetMethod("setAutoSize", &WebContents::SetAutoSize)
|
||||
.SetMethod("setSize", &WebContents::SetSize)
|
||||
.SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency)
|
||||
.SetMethod("isGuest", &WebContents::is_guest)
|
||||
.SetMethod("isGuest", &WebContents::IsGuest)
|
||||
.SetMethod("hasServiceWorker", &WebContents::HasServiceWorker)
|
||||
.SetMethod("unregisterServiceWorker",
|
||||
&WebContents::UnregisterServiceWorker)
|
||||
@@ -760,16 +776,46 @@ void WebContents::GuestSizeChangedDueToAutoSize(const gfx::Size& old_size,
|
||||
new_size.width(), new_size.height());
|
||||
}
|
||||
|
||||
gfx::Size WebContents::GetDefaultSize() const {
|
||||
if (is_full_page_plugin_) {
|
||||
// Full page plugins default to the size of the owner's viewport.
|
||||
return embedder_web_contents_->GetRenderWidgetHostView()
|
||||
->GetVisibleViewportSize();
|
||||
} else {
|
||||
return gfx::Size(kDefaultWidth, kDefaultHeight);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<WebContents> WebContents::CreateFrom(
|
||||
v8::Isolate* isolate, brightray::InspectableWebContents* web_contents) {
|
||||
auto handle = mate::CreateHandle(isolate, new WebContents(web_contents));
|
||||
g_wrap_web_contents.Run(handle.ToV8());
|
||||
return handle;
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<WebContents> WebContents::CreateFrom(
|
||||
v8::Isolate* isolate, content::WebContents* web_contents) {
|
||||
return mate::CreateHandle(isolate, new WebContents(web_contents));
|
||||
auto handle = mate::CreateHandle(isolate, new WebContents(web_contents));
|
||||
g_wrap_web_contents.Run(handle.ToV8());
|
||||
return handle;
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Handle<WebContents> WebContents::Create(
|
||||
v8::Isolate* isolate, const mate::Dictionary& options) {
|
||||
return mate::CreateHandle(isolate, new WebContents(options));
|
||||
auto handle = mate::CreateHandle(isolate, new WebContents(options));
|
||||
g_wrap_web_contents.Run(handle.ToV8());
|
||||
return handle;
|
||||
}
|
||||
|
||||
void SetWrapWebContents(const WrapWebContentsCallback& callback) {
|
||||
g_wrap_web_contents = callback;
|
||||
}
|
||||
|
||||
void ClearWrapWebContents() {
|
||||
g_wrap_web_contents.Reset();
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
@@ -784,6 +830,8 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.SetMethod("create", &atom::api::WebContents::Create);
|
||||
dict.SetMethod("_setWrapWebContents", &atom::api::SetWrapWebContents);
|
||||
dict.SetMethod("_clearWrapWebContents", &atom::api::ClearWrapWebContents);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -9,10 +9,9 @@
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
#include "brightray/browser/default_web_contents_delegate.h"
|
||||
#include "atom/browser/common_web_contents_delegate.h"
|
||||
#include "content/public/browser/browser_plugin_guest_delegate.h"
|
||||
#include "content/public/common/favicon_url.h"
|
||||
#include "content/public/browser/web_contents_delegate.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "content/public/browser/gpu_data_manager_observer.h"
|
||||
#include "native_mate/handle.h"
|
||||
@@ -23,23 +22,39 @@ class InspectableWebContents;
|
||||
}
|
||||
|
||||
namespace mate {
|
||||
class Arguments;
|
||||
class Dictionary;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomJavaScriptDialogManager;
|
||||
class WebDialogHelper;
|
||||
|
||||
namespace api {
|
||||
|
||||
// A struct of parameters for SetSize(). The parameters are all declared as
|
||||
// scoped pointers since they are all optional. Null pointers indicate that the
|
||||
// parameter has not been provided, and the last used value should be used. Note
|
||||
// that when |enable_auto_size| is true, providing |normal_size| is not
|
||||
// meaningful. This is because the normal size of the guestview is overridden
|
||||
// whenever autosizing occurs.
|
||||
struct SetSizeParams {
|
||||
SetSizeParams() {}
|
||||
~SetSizeParams() {}
|
||||
|
||||
scoped_ptr<bool> enable_auto_size;
|
||||
scoped_ptr<gfx::Size> min_size;
|
||||
scoped_ptr<gfx::Size> max_size;
|
||||
scoped_ptr<gfx::Size> normal_size;
|
||||
};
|
||||
|
||||
class WebContents : public mate::EventEmitter,
|
||||
public content::BrowserPluginGuestDelegate,
|
||||
public content::WebContentsDelegate,
|
||||
public CommonWebContentsDelegate,
|
||||
public content::WebContentsObserver,
|
||||
public content::GpuDataManagerObserver {
|
||||
public:
|
||||
// Create from an existing WebContents.
|
||||
static mate::Handle<WebContents> CreateFrom(
|
||||
v8::Isolate* isolate, brightray::InspectableWebContents* web_contents);
|
||||
static mate::Handle<WebContents> CreateFrom(
|
||||
v8::Isolate* isolate, content::WebContents* web_contents);
|
||||
|
||||
@@ -64,13 +79,14 @@ class WebContents : public mate::EventEmitter,
|
||||
void SetUserAgent(const std::string& user_agent);
|
||||
void InsertCSS(const std::string& css);
|
||||
void ExecuteJavaScript(const base::string16& code);
|
||||
void OpenDevTools();
|
||||
void OpenDevTools(mate::Arguments* args);
|
||||
void CloseDevTools();
|
||||
bool IsDevToolsOpened();
|
||||
void ToggleDevTools();
|
||||
void InspectElement(int x, int y);
|
||||
void InspectServiceWorker();
|
||||
void HasServiceWorker(const base::Callback<void(bool)>&);
|
||||
void UnregisterServiceWorker(const base::Callback<void(bool)>&);
|
||||
void InspectServiceWorker();
|
||||
|
||||
// Editing commands.
|
||||
void Undo();
|
||||
@@ -89,25 +105,26 @@ class WebContents : public mate::EventEmitter,
|
||||
bool SendIPCMessage(const base::string16& channel,
|
||||
const base::ListValue& args);
|
||||
|
||||
// Toggles autosize mode for corresponding <webview>.
|
||||
void SetAutoSize(bool enabled,
|
||||
const gfx::Size& min_size,
|
||||
const gfx::Size& max_size);
|
||||
// Used to toggle autosize mode for this GuestView, and set both the automatic
|
||||
// and normal sizes.
|
||||
void SetSize(const SetSizeParams& params);
|
||||
|
||||
// Sets the transparency of the guest.
|
||||
void SetAllowTransparency(bool allow);
|
||||
|
||||
// Returns whether this is a guest view.
|
||||
bool is_guest() const { return guest_instance_id_ != -1; }
|
||||
bool IsGuest() const;
|
||||
|
||||
// Returns whether this guest has an associated embedder.
|
||||
bool attached() const { return !!embedder_web_contents_; }
|
||||
|
||||
content::WebContents* web_contents() const {
|
||||
return content::WebContentsObserver::web_contents();
|
||||
// Returns the current InspectableWebContents object, nullptr will be returned
|
||||
// if current WebContents can not beinspected, e.g. it is the devtools.
|
||||
brightray::InspectableWebContents* inspectable_web_contents() const {
|
||||
return inspectable_web_contents_;
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit WebContents(brightray::InspectableWebContents* web_contents);
|
||||
explicit WebContents(content::WebContents* web_contents);
|
||||
explicit WebContents(const mate::Dictionary& options);
|
||||
~WebContents();
|
||||
@@ -135,28 +152,12 @@ class WebContents : public mate::EventEmitter,
|
||||
content::WebContents* OpenURLFromTab(
|
||||
content::WebContents* source,
|
||||
const content::OpenURLParams& params) override;
|
||||
content::JavaScriptDialogManager* GetJavaScriptDialogManager(
|
||||
content::WebContents* source) override;
|
||||
void RunFileChooser(content::WebContents* web_contents,
|
||||
const content::FileChooserParams& params) override;
|
||||
void EnumerateDirectory(content::WebContents* web_contents,
|
||||
int request_id,
|
||||
const base::FilePath& path) override;
|
||||
bool CheckMediaAccessPermission(content::WebContents* web_contents,
|
||||
const GURL& security_origin,
|
||||
content::MediaStreamType type) override;
|
||||
void RequestMediaAccessPermission(
|
||||
content::WebContents*,
|
||||
const content::MediaStreamRequest&,
|
||||
const content::MediaResponseCallback&) override;
|
||||
void HandleKeyboardEvent(
|
||||
content::WebContents* source,
|
||||
const content::NativeWebKeyboardEvent& event) override;
|
||||
void EnterFullscreenModeForTab(content::WebContents* source,
|
||||
const GURL& origin) override;
|
||||
void ExitFullscreenModeForTab(content::WebContents* source) override;
|
||||
bool IsFullscreenForTabOrPending(
|
||||
const content::WebContents* source) const override;
|
||||
|
||||
// content::WebContentsObserver:
|
||||
void RenderViewDeleted(content::RenderViewHost*) override;
|
||||
@@ -196,7 +197,6 @@ class WebContents : public mate::EventEmitter,
|
||||
|
||||
// content::BrowserPluginGuestDelegate:
|
||||
void DidAttach(int guest_proxy_routing_id) final;
|
||||
void ElementSizeChanged(const gfx::Size& size) final;
|
||||
content::WebContents* GetOwnerWebContents() const final;
|
||||
void GuestSizeChanged(const gfx::Size& new_size) final;
|
||||
void SetGuestHost(content::GuestHost* guest_host) final;
|
||||
@@ -217,25 +217,20 @@ class WebContents : public mate::EventEmitter,
|
||||
const base::ListValue& args,
|
||||
IPC::Message* message);
|
||||
|
||||
// This method is invoked when the contents auto-resized to give the container
|
||||
// an opportunity to match it if it wishes.
|
||||
//
|
||||
// This gives the derived class an opportunity to inform its container element
|
||||
// or perform other actions.
|
||||
void GuestSizeChangedDueToAutoSize(const gfx::Size& old_size,
|
||||
const gfx::Size& new_size);
|
||||
|
||||
scoped_ptr<WebDialogHelper> web_dialog_helper_;
|
||||
scoped_ptr<AtomJavaScriptDialogManager> dialog_manager_;
|
||||
|
||||
// Unique ID for a guest WebContents.
|
||||
int guest_instance_id_;
|
||||
|
||||
// |element_instance_id_| is an identifer that's unique to a particular
|
||||
// element.
|
||||
int element_instance_id_;
|
||||
// Returns the default size of the guestview.
|
||||
gfx::Size GetDefaultSize() const;
|
||||
|
||||
// Stores whether the contents of the guest can be transparent.
|
||||
bool guest_opaque_;
|
||||
|
||||
// Stores the WebContents that managed by this class.
|
||||
scoped_ptr<brightray::InspectableWebContents> storage_;
|
||||
|
||||
// The WebContents that attaches this guest view.
|
||||
content::WebContents* embedder_web_contents_;
|
||||
|
||||
@@ -258,6 +253,16 @@ class WebContents : public mate::EventEmitter,
|
||||
// The minimum size constraints of the container element in autosize mode.
|
||||
gfx::Size min_auto_size_;
|
||||
|
||||
// The size that will be used when autosize mode is disabled.
|
||||
gfx::Size normal_size_;
|
||||
|
||||
// Whether the guest view is inside a plugin document.
|
||||
bool is_full_page_plugin_;
|
||||
|
||||
// Current InspectableWebContents object, can be nullptr for WebContents of
|
||||
// devtools. It is a weak reference.
|
||||
brightray::InspectableWebContents* inspectable_web_contents_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(WebContents);
|
||||
};
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "atom/browser/api/atom_api_window.h"
|
||||
|
||||
#include "atom/browser/api/atom_api_menu.h"
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
@@ -164,11 +165,32 @@ void Window::OnDevToolsFocus() {
|
||||
Emit("devtools-focused");
|
||||
}
|
||||
|
||||
void Window::OnDevToolsOpened() {
|
||||
Emit("devtools-opened");
|
||||
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
v8::Locker locker(isolate);
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
auto handle =
|
||||
WebContents::CreateFrom(isolate, window_->GetDevToolsWebContents());
|
||||
devtools_web_contents_.Reset(isolate, handle.ToV8());
|
||||
}
|
||||
|
||||
void Window::OnDevToolsClosed() {
|
||||
Emit("devtools-closed");
|
||||
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
v8::Locker locker(isolate);
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
devtools_web_contents_.Reset();
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Wrappable* Window::New(v8::Isolate* isolate,
|
||||
const mate::Dictionary& options) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
node::ThrowError("Cannot create BrowserWindow before app is ready");
|
||||
node::ThrowError(isolate,
|
||||
"Cannot create BrowserWindow before app is ready");
|
||||
return nullptr;
|
||||
}
|
||||
return new Window(options);
|
||||
@@ -355,26 +377,6 @@ bool Window::IsKiosk() {
|
||||
return window_->IsKiosk();
|
||||
}
|
||||
|
||||
void Window::OpenDevTools(bool can_dock) {
|
||||
window_->OpenDevTools(can_dock);
|
||||
}
|
||||
|
||||
void Window::CloseDevTools() {
|
||||
window_->CloseDevTools();
|
||||
}
|
||||
|
||||
bool Window::IsDevToolsOpened() {
|
||||
return window_->IsDevToolsOpened();
|
||||
}
|
||||
|
||||
void Window::InspectElement(int x, int y) {
|
||||
window_->InspectElement(x, y);
|
||||
}
|
||||
|
||||
void Window::InspectServiceWorker() {
|
||||
window_->InspectServiceWorker();
|
||||
}
|
||||
|
||||
void Window::FocusOnWebView() {
|
||||
window_->FocusOnWebView();
|
||||
}
|
||||
@@ -437,6 +439,10 @@ void Window::SetOverlayIcon(const gfx::Image& overlay,
|
||||
window_->SetOverlayIcon(overlay, description);
|
||||
}
|
||||
|
||||
void Window::SetMenu(ui::SimpleMenuModel* menu) {
|
||||
window_->SetMenu(menu);
|
||||
}
|
||||
|
||||
void Window::SetAutoHideMenuBar(bool auto_hide) {
|
||||
window_->SetAutoHideMenuBar(auto_hide);
|
||||
}
|
||||
@@ -467,13 +473,20 @@ bool Window::IsVisibleOnAllWorkspaces() {
|
||||
return window_->IsVisibleOnAllWorkspaces();
|
||||
}
|
||||
|
||||
mate::Handle<WebContents> Window::GetWebContents(v8::Isolate* isolate) const {
|
||||
return WebContents::CreateFrom(isolate, window_->GetWebContents());
|
||||
v8::Local<v8::Value> Window::WebContents(v8::Isolate* isolate) {
|
||||
if (web_contents_.IsEmpty()) {
|
||||
auto handle =
|
||||
WebContents::CreateFrom(isolate, window_->managed_web_contents());
|
||||
web_contents_.Reset(isolate, handle.ToV8());
|
||||
}
|
||||
return v8::Local<v8::Value>::New(isolate, web_contents_);
|
||||
}
|
||||
|
||||
mate::Handle<WebContents> Window::GetDevToolsWebContents(
|
||||
v8::Isolate* isolate) const {
|
||||
return WebContents::CreateFrom(isolate, window_->GetDevToolsWebContents());
|
||||
v8::Local<v8::Value> Window::DevToolsWebContents(v8::Isolate* isolate) {
|
||||
if (devtools_web_contents_.IsEmpty())
|
||||
return v8::Null(isolate);
|
||||
else
|
||||
return v8::Local<v8::Value>::New(isolate, devtools_web_contents_);
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -524,10 +537,6 @@ void Window::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("getRepresentedFilename", &Window::GetRepresentedFilename)
|
||||
.SetMethod("setDocumentEdited", &Window::SetDocumentEdited)
|
||||
.SetMethod("isDocumentEdited", &Window::IsDocumentEdited)
|
||||
.SetMethod("_openDevTools", &Window::OpenDevTools)
|
||||
.SetMethod("closeDevTools", &Window::CloseDevTools)
|
||||
.SetMethod("isDevToolsOpened", &Window::IsDevToolsOpened)
|
||||
.SetMethod("inspectElement", &Window::InspectElement)
|
||||
.SetMethod("focusOnWebView", &Window::FocusOnWebView)
|
||||
.SetMethod("blurWebView", &Window::BlurWebView)
|
||||
.SetMethod("isWebViewFocused", &Window::IsWebViewFocused)
|
||||
@@ -535,6 +544,7 @@ void Window::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("print", &Window::Print)
|
||||
.SetMethod("setProgressBar", &Window::SetProgressBar)
|
||||
.SetMethod("setOverlayIcon", &Window::SetOverlayIcon)
|
||||
.SetMethod("_setMenu", &Window::SetMenu)
|
||||
.SetMethod("setAutoHideMenuBar", &Window::SetAutoHideMenuBar)
|
||||
.SetMethod("isMenuBarAutoHide", &Window::IsMenuBarAutoHide)
|
||||
.SetMethod("setMenuBarVisibility", &Window::SetMenuBarVisibility)
|
||||
@@ -547,9 +557,8 @@ void Window::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("showDefinitionForSelection",
|
||||
&Window::ShowDefinitionForSelection)
|
||||
#endif
|
||||
.SetMethod("_getWebContents", &Window::GetWebContents)
|
||||
.SetMethod("_getDevToolsWebContents", &Window::GetDevToolsWebContents)
|
||||
.SetMethod("inspectServiceWorker", &Window::InspectServiceWorker);
|
||||
.SetProperty("webContents", &Window::WebContents)
|
||||
.SetProperty("devToolsWebContents", &Window::DevToolsWebContents);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
@@ -25,6 +25,10 @@ class Arguments;
|
||||
class Dictionary;
|
||||
}
|
||||
|
||||
namespace ui {
|
||||
class SimpleMenuModel;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class NativeWindow;
|
||||
@@ -74,6 +78,8 @@ class Window : public mate::EventEmitter,
|
||||
void OnRendererUnresponsive() override;
|
||||
void OnRendererResponsive() override;
|
||||
void OnDevToolsFocus() override;
|
||||
void OnDevToolsOpened() override;
|
||||
void OnDevToolsClosed() override;
|
||||
|
||||
private:
|
||||
// APIs for NativeWindow.
|
||||
@@ -117,11 +123,6 @@ class Window : public mate::EventEmitter,
|
||||
void SetSkipTaskbar(bool skip);
|
||||
void SetKiosk(bool kiosk);
|
||||
bool IsKiosk();
|
||||
void OpenDevTools(bool can_dock);
|
||||
void CloseDevTools();
|
||||
bool IsDevToolsOpened();
|
||||
void InspectElement(int x, int y);
|
||||
void InspectServiceWorker();
|
||||
void FocusOnWebView();
|
||||
void BlurWebView();
|
||||
bool IsWebViewFocused();
|
||||
@@ -134,6 +135,7 @@ class Window : public mate::EventEmitter,
|
||||
void SetProgressBar(double progress);
|
||||
void SetOverlayIcon(const gfx::Image& overlay,
|
||||
const std::string& description);
|
||||
void SetMenu(ui::SimpleMenuModel* menu);
|
||||
void SetAutoHideMenuBar(bool auto_hide);
|
||||
bool IsMenuBarAutoHide();
|
||||
void SetMenuBarVisibility(bool visible);
|
||||
@@ -146,9 +148,11 @@ class Window : public mate::EventEmitter,
|
||||
void SetVisibleOnAllWorkspaces(bool visible);
|
||||
bool IsVisibleOnAllWorkspaces();
|
||||
|
||||
// APIs for WebContents.
|
||||
mate::Handle<WebContents> GetWebContents(v8::Isolate* isolate) const;
|
||||
mate::Handle<WebContents> GetDevToolsWebContents(v8::Isolate* isolate) const;
|
||||
v8::Local<v8::Value> WebContents(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> DevToolsWebContents(v8::Isolate* isolate);
|
||||
|
||||
v8::Global<v8::Value> web_contents_;
|
||||
v8::Global<v8::Value> devtools_web_contents_;
|
||||
|
||||
scoped_ptr<NativeWindow> window_;
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ EventEmitter = require('events').EventEmitter
|
||||
IDWeakMap = require 'id-weak-map'
|
||||
app = require 'app'
|
||||
ipc = require 'ipc'
|
||||
wrapWebContents = require('web-contents').wrap
|
||||
|
||||
BrowserWindow = process.atomBinding('window').BrowserWindow
|
||||
BrowserWindow::__proto__ = EventEmitter.prototype
|
||||
@@ -16,10 +15,6 @@ BrowserWindow::_init = ->
|
||||
menu = app.getApplicationMenu()
|
||||
@setMenu menu if menu?
|
||||
|
||||
@webContents = @getWebContents()
|
||||
@devToolsWebContents = null
|
||||
@webContents.once 'destroyed', => @webContents = null
|
||||
|
||||
# Remember the window ID.
|
||||
Object.defineProperty this, 'id',
|
||||
value: BrowserWindow.windows.add(this)
|
||||
@@ -40,35 +35,11 @@ BrowserWindow::_init = ->
|
||||
@once 'closed', =>
|
||||
BrowserWindow.windows.remove @id if BrowserWindow.windows.has @id
|
||||
|
||||
BrowserWindow::openDevTools = (options={}) ->
|
||||
options.detach ?= false
|
||||
@_openDevTools !options.detach
|
||||
|
||||
# Force devToolsWebContents to be created.
|
||||
@devToolsWebContents = @getDevToolsWebContents()
|
||||
@devToolsWebContents.once 'destroyed', => @devToolsWebContents = null
|
||||
|
||||
# Emit devtools events.
|
||||
@devToolsWebContents.once 'did-finish-load', => @emit 'devtools-opened'
|
||||
@devToolsWebContents.once 'destroyed', => @emit 'devtools-closed'
|
||||
|
||||
BrowserWindow::toggleDevTools = ->
|
||||
if @isDevToolsOpened() then @closeDevTools() else @openDevTools()
|
||||
|
||||
BrowserWindow::getWebContents = ->
|
||||
wrapWebContents @_getWebContents()
|
||||
|
||||
BrowserWindow::getDevToolsWebContents = ->
|
||||
wrapWebContents @_getDevToolsWebContents()
|
||||
|
||||
BrowserWindow::setMenu = (menu) ->
|
||||
if process.platform is 'darwin'
|
||||
throw new Error('BrowserWindow.setMenu is not available on OS X')
|
||||
|
||||
throw new TypeError('Invalid menu') unless menu?.constructor?.name is 'Menu'
|
||||
throw new TypeError('Invalid menu') unless menu is null or menu?.constructor?.name is 'Menu'
|
||||
|
||||
@menu = menu # Keep a reference of menu in case of GC.
|
||||
@menu.attachToWindow this
|
||||
@_setMenu menu
|
||||
|
||||
BrowserWindow.getAllWindows = ->
|
||||
windows = BrowserWindow.windows
|
||||
@@ -80,11 +51,11 @@ BrowserWindow.getFocusedWindow = ->
|
||||
|
||||
BrowserWindow.fromWebContents = (webContents) ->
|
||||
windows = BrowserWindow.getAllWindows()
|
||||
return window for window in windows when webContents.equal window.webContents
|
||||
return window for window in windows when window.webContents?.equal webContents
|
||||
|
||||
BrowserWindow.fromDevToolsWebContents = (webContents) ->
|
||||
windows = BrowserWindow.getAllWindows()
|
||||
return window for window in windows when webContents.equal window.devToolsWebContents
|
||||
return window for window in windows when window.devToolsWebContents?.equal webContents
|
||||
|
||||
BrowserWindow.fromId = (id) ->
|
||||
BrowserWindow.windows.get id
|
||||
@@ -105,7 +76,12 @@ BrowserWindow::stop = -> @webContents.stop()
|
||||
BrowserWindow::getRoutingId = -> @webContents.getRoutingId()
|
||||
BrowserWindow::getProcessId = -> @webContents.getProcessId()
|
||||
BrowserWindow::isCrashed = -> @webContents.isCrashed()
|
||||
BrowserWindow::executeJavaScriptInDevTools = (code) ->
|
||||
@devToolsWebContents.executeJavaScript code
|
||||
BrowserWindow::executeJavaScriptInDevTools = (code) -> @devToolsWebContents?.executeJavaScript code
|
||||
BrowserWindow::openDevTools = -> @webContents.openDevTools.apply @webContents, arguments
|
||||
BrowserWindow::closeDevTools = -> @webContents.closeDevTools()
|
||||
BrowserWindow::isDevToolsOpened = -> @webContents.isDevToolsOpened()
|
||||
BrowserWindow::toggleDevTools = -> @webContents.toggleDevTools()
|
||||
BrowserWindow::inspectElement = -> @webContents.inspectElement.apply @webContents, arguments
|
||||
BrowserWindow::inspectServiceWorker = -> @webContents.inspectServiceWorker()
|
||||
|
||||
module.exports = BrowserWindow
|
||||
|
||||
@@ -130,10 +130,11 @@ Menu::_callMenuWillShow = ->
|
||||
|
||||
applicationMenu = null
|
||||
Menu.setApplicationMenu = (menu) ->
|
||||
throw new TypeError('Invalid menu') unless menu?.constructor is Menu
|
||||
throw new TypeError('Invalid menu') unless menu is null or menu.constructor is Menu
|
||||
applicationMenu = menu # Keep a reference.
|
||||
|
||||
if process.platform is 'darwin'
|
||||
return if menu is null
|
||||
menu._callMenuWillShow()
|
||||
bindings.setApplicationMenu menu
|
||||
else
|
||||
|
||||
@@ -3,9 +3,7 @@ NavigationController = require './navigation-controller'
|
||||
binding = process.atomBinding 'web_contents'
|
||||
ipc = require 'ipc'
|
||||
|
||||
module.exports.wrap = (webContents) ->
|
||||
return null unless webContents.isAlive()
|
||||
|
||||
wrapWebContents = (webContents) ->
|
||||
# webContents is an EventEmitter.
|
||||
webContents.__proto__ = EventEmitter.prototype
|
||||
|
||||
@@ -62,5 +60,8 @@ module.exports.wrap = (webContents) ->
|
||||
|
||||
webContents
|
||||
|
||||
binding._setWrapWebContents wrapWebContents
|
||||
process.once 'exit', binding._clearWrapWebContents
|
||||
|
||||
module.exports.create = (options={}) ->
|
||||
@wrap binding.create(options)
|
||||
binding.create(options)
|
||||
|
||||
@@ -8,24 +8,26 @@
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "atom/browser/atom_quota_permission_context.h"
|
||||
#include "atom/browser/atom_resource_dispatcher_host_delegate.h"
|
||||
#include "atom/browser/atom_speech_recognition_manager_delegate.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/web_view_manager.h"
|
||||
#include "atom/browser/window_list.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "chrome/browser/printing/printing_message_filter.h"
|
||||
#include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h"
|
||||
#include "chrome/browser/speech/tts_message_filter.h"
|
||||
#include "content/public/browser/browser_ppapi_host.h"
|
||||
#include "content/public/browser/client_certificate_delegate.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "content/public/browser/resource_dispatcher_host.h"
|
||||
#include "content/public/browser/site_instance.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "content/public/common/web_preferences.h"
|
||||
#include "net/cert/x509_certificate.h"
|
||||
#include "net/ssl/ssl_cert_request_info.h"
|
||||
#include "ppapi/host/ppapi_host.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
|
||||
@@ -33,25 +35,58 @@ namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
// The default routing id of WebContents.
|
||||
// In Electron each RenderProcessHost only has one WebContents, so this ID is
|
||||
// same for every WebContents.
|
||||
int kDefaultRoutingID = 2;
|
||||
|
||||
// Next navigation should not restart renderer process.
|
||||
bool g_suppress_renderer_process_restart = false;
|
||||
|
||||
struct FindByProcessId {
|
||||
explicit FindByProcessId(int child_process_id)
|
||||
: child_process_id_(child_process_id) {
|
||||
}
|
||||
|
||||
bool operator() (NativeWindow* const window) {
|
||||
content::WebContents* web_contents = window->GetWebContents();
|
||||
if (!web_contents)
|
||||
return false;
|
||||
|
||||
int id = window->GetWebContents()->GetRenderProcessHost()->GetID();
|
||||
return id == child_process_id_;
|
||||
}
|
||||
|
||||
int child_process_id_;
|
||||
// Find out the owner of the child process according to |process_id|.
|
||||
enum ProcessOwner {
|
||||
OWNER_NATIVE_WINDOW,
|
||||
OWNER_GUEST_WEB_CONTENTS,
|
||||
OWNER_NONE, // it might be devtools though.
|
||||
};
|
||||
ProcessOwner GetProcessOwner(int process_id,
|
||||
NativeWindow** window,
|
||||
WebViewManager::WebViewInfo* info) {
|
||||
auto web_contents = content::WebContents::FromRenderViewHost(
|
||||
content::RenderViewHost::FromID(process_id, kDefaultRoutingID));
|
||||
if (!web_contents)
|
||||
return OWNER_NONE;
|
||||
|
||||
// First search for NativeWindow.
|
||||
for (auto native_window : *WindowList::GetInstance())
|
||||
if (web_contents == native_window->GetWebContents()) {
|
||||
*window = native_window;
|
||||
return OWNER_NATIVE_WINDOW;
|
||||
}
|
||||
|
||||
// Then search for guest WebContents.
|
||||
if (WebViewManager::GetInfoForWebContents(web_contents, info))
|
||||
return OWNER_GUEST_WEB_CONTENTS;
|
||||
|
||||
return OWNER_NONE;
|
||||
}
|
||||
|
||||
scoped_refptr<net::X509Certificate> ImportCertFromFile(
|
||||
const base::FilePath& path) {
|
||||
std::string cert_data;
|
||||
if (!base::ReadFileToString(path, &cert_data))
|
||||
return nullptr;
|
||||
|
||||
net::CertificateList certs =
|
||||
net::X509Certificate::CreateCertificateListFromBytes(
|
||||
cert_data.data(), cert_data.size(),
|
||||
net::X509Certificate::FORMAT_AUTO);
|
||||
|
||||
if (certs.empty())
|
||||
return nullptr;
|
||||
|
||||
return certs[0];
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -60,8 +95,7 @@ void AtomBrowserClient::SuppressRendererProcessRestartForOnce() {
|
||||
g_suppress_renderer_process_restart = true;
|
||||
}
|
||||
|
||||
AtomBrowserClient::AtomBrowserClient()
|
||||
: dying_render_process_(nullptr) {
|
||||
AtomBrowserClient::AtomBrowserClient() {
|
||||
}
|
||||
|
||||
AtomBrowserClient::~AtomBrowserClient() {
|
||||
@@ -83,15 +117,8 @@ content::AccessTokenStore* AtomBrowserClient::CreateAccessTokenStore() {
|
||||
return new AtomAccessTokenStore;
|
||||
}
|
||||
|
||||
void AtomBrowserClient::ResourceDispatcherHostCreated() {
|
||||
resource_dispatcher_delegate_.reset(new AtomResourceDispatcherHostDelegate);
|
||||
content::ResourceDispatcherHost::Get()->SetDelegate(
|
||||
resource_dispatcher_delegate_.get());
|
||||
}
|
||||
|
||||
void AtomBrowserClient::OverrideWebkitPrefs(
|
||||
content::RenderViewHost* render_view_host,
|
||||
content::WebPreferences* prefs) {
|
||||
content::RenderViewHost* host, content::WebPreferences* prefs) {
|
||||
prefs->javascript_enabled = true;
|
||||
prefs->web_security_enabled = true;
|
||||
prefs->javascript_can_open_windows_automatically = true;
|
||||
@@ -109,18 +136,10 @@ void AtomBrowserClient::OverrideWebkitPrefs(
|
||||
prefs->allow_displaying_insecure_content = false;
|
||||
prefs->allow_running_insecure_content = false;
|
||||
|
||||
// Turn off web security for devtools.
|
||||
auto web_contents = content::WebContents::FromRenderViewHost(
|
||||
render_view_host);
|
||||
if (web_contents && web_contents->GetURL().SchemeIs("chrome-devtools")) {
|
||||
prefs->web_security_enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Custom preferences of guest page.
|
||||
auto process = render_view_host->GetProcess();
|
||||
auto web_contents = content::WebContents::FromRenderViewHost(host);
|
||||
WebViewManager::WebViewInfo info;
|
||||
if (WebViewManager::GetInfoForProcess(process, &info)) {
|
||||
if (WebViewManager::GetInfoForWebContents(web_contents, &info)) {
|
||||
prefs->web_security_enabled = !info.disable_web_security;
|
||||
return;
|
||||
}
|
||||
@@ -144,76 +163,37 @@ void AtomBrowserClient::OverrideSiteInstanceForNavigation(
|
||||
return;
|
||||
}
|
||||
|
||||
if (current_instance->HasProcess())
|
||||
dying_render_process_ = current_instance->GetProcess();
|
||||
// Restart renderer process for all navigations except "javacript:" scheme.
|
||||
if (url.SchemeIs(url::kJavaScriptScheme))
|
||||
return;
|
||||
|
||||
|
||||
if (!url.SchemeIs(url::kJavaScriptScheme)) {
|
||||
// Restart renderer process for all navigations except javacript: scheme.
|
||||
*new_instance = content::SiteInstance::CreateForURL(browser_context, url);
|
||||
}
|
||||
*new_instance = content::SiteInstance::CreateForURL(browser_context, url);
|
||||
}
|
||||
|
||||
void AtomBrowserClient::AppendExtraCommandLineSwitches(
|
||||
base::CommandLine* command_line,
|
||||
int child_process_id) {
|
||||
int process_id) {
|
||||
std::string process_type = command_line->GetSwitchValueASCII("type");
|
||||
if (process_type != "renderer")
|
||||
return;
|
||||
|
||||
WindowList* list = WindowList::GetInstance();
|
||||
NativeWindow* window = nullptr;
|
||||
NativeWindow* window;
|
||||
WebViewManager::WebViewInfo info;
|
||||
ProcessOwner owner = GetProcessOwner(process_id, &window, &info);
|
||||
|
||||
// Find the owner of this child process.
|
||||
WindowList::const_iterator iter = std::find_if(
|
||||
list->begin(), list->end(), FindByProcessId(child_process_id));
|
||||
if (iter != list->end())
|
||||
window = *iter;
|
||||
|
||||
// If the render process is a newly started one, which means the window still
|
||||
// uses the old going-to-be-swapped render process, then we try to find the
|
||||
// window from the swapped render process.
|
||||
if (!window && dying_render_process_) {
|
||||
int dying_process_id = dying_render_process_->GetID();
|
||||
WindowList::const_iterator iter = std::find_if(
|
||||
list->begin(), list->end(), FindByProcessId(dying_process_id));
|
||||
if (iter != list->end()) {
|
||||
window = *iter;
|
||||
child_process_id = dying_process_id;
|
||||
} else {
|
||||
// It appears that the dying process doesn't belong to a BrowserWindow,
|
||||
// then it might be a guest process, if it is we should update its
|
||||
// process ID in the WebViewManager.
|
||||
auto child_process = content::RenderProcessHost::FromID(child_process_id);
|
||||
// Update the process ID in webview guests.
|
||||
WebViewManager::UpdateGuestProcessID(dying_render_process_,
|
||||
child_process);
|
||||
}
|
||||
if (owner == OWNER_NATIVE_WINDOW) {
|
||||
window->AppendExtraCommandLineSwitches(command_line);
|
||||
} else if (owner == OWNER_GUEST_WEB_CONTENTS) {
|
||||
command_line->AppendSwitchASCII(
|
||||
switches::kGuestInstanceID, base::IntToString(info.guest_instance_id));
|
||||
command_line->AppendSwitchASCII(
|
||||
switches::kNodeIntegration, info.node_integration ? "true" : "false");
|
||||
if (info.plugins)
|
||||
command_line->AppendSwitch(switches::kEnablePlugins);
|
||||
if (!info.preload_script.empty())
|
||||
command_line->AppendSwitchPath(
|
||||
switches::kPreloadScript, info.preload_script);
|
||||
}
|
||||
|
||||
if (window) {
|
||||
window->AppendExtraCommandLineSwitches(command_line, child_process_id);
|
||||
} else {
|
||||
// Append commnad line arguments for guest web view.
|
||||
auto child_process = content::RenderProcessHost::FromID(child_process_id);
|
||||
WebViewManager::WebViewInfo info;
|
||||
if (WebViewManager::GetInfoForProcess(child_process, &info)) {
|
||||
command_line->AppendSwitchASCII(
|
||||
switches::kGuestInstanceID,
|
||||
base::IntToString(info.guest_instance_id));
|
||||
command_line->AppendSwitchASCII(
|
||||
switches::kNodeIntegration,
|
||||
info.node_integration ? "true" : "false");
|
||||
if (info.plugins)
|
||||
command_line->AppendSwitch(switches::kEnablePlugins);
|
||||
if (!info.preload_script.empty())
|
||||
command_line->AppendSwitchPath(
|
||||
switches::kPreloadScript,
|
||||
info.preload_script);
|
||||
}
|
||||
}
|
||||
|
||||
dying_render_process_ = nullptr;
|
||||
}
|
||||
|
||||
void AtomBrowserClient::DidCreatePpapiPlugin(
|
||||
@@ -230,6 +210,29 @@ content::QuotaPermissionContext*
|
||||
return new AtomQuotaPermissionContext;
|
||||
}
|
||||
|
||||
void AtomBrowserClient::SelectClientCertificate(
|
||||
content::WebContents* web_contents,
|
||||
net::SSLCertRequestInfo* cert_request_info,
|
||||
scoped_ptr<content::ClientCertificateDelegate> delegate) {
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
auto cert_path = command_line->GetSwitchValueNative(
|
||||
switches::kClientCertificate);
|
||||
|
||||
// TODO(zcbenz): allow users to select certificate from
|
||||
// client_cert list. Right now defaults to first certificate
|
||||
// in the list.
|
||||
scoped_refptr<net::X509Certificate> certificate;
|
||||
if (cert_path.empty()) {
|
||||
if (!cert_request_info->client_certs.empty())
|
||||
certificate = cert_request_info->client_certs[0];
|
||||
} else {
|
||||
certificate = ImportCertFromFile(base::FilePath(cert_path));
|
||||
}
|
||||
|
||||
if (certificate.get())
|
||||
delegate->ContinueWithCertificate(certificate.get());
|
||||
}
|
||||
|
||||
brightray::BrowserMainParts* AtomBrowserClient::OverrideCreateBrowserMainParts(
|
||||
const content::MainFunctionParams&) {
|
||||
v8::V8::Initialize(); // Init V8 before creating main parts.
|
||||
|
||||
@@ -11,12 +11,15 @@
|
||||
|
||||
namespace content {
|
||||
class QuotaPermissionContext;
|
||||
class ClientCertificateDelegate;
|
||||
}
|
||||
|
||||
namespace net {
|
||||
class SSLCertRequestInfo;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomResourceDispatcherHostDelegate;
|
||||
|
||||
class AtomBrowserClient : public brightray::BrowserClient {
|
||||
public:
|
||||
AtomBrowserClient();
|
||||
@@ -31,7 +34,6 @@ class AtomBrowserClient : public brightray::BrowserClient {
|
||||
content::SpeechRecognitionManagerDelegate*
|
||||
CreateSpeechRecognitionManagerDelegate() override;
|
||||
content::AccessTokenStore* CreateAccessTokenStore() override;
|
||||
void ResourceDispatcherHostCreated() override;
|
||||
void OverrideWebkitPrefs(content::RenderViewHost* render_view_host,
|
||||
content::WebPreferences* prefs) override;
|
||||
std::string GetApplicationLocale() override;
|
||||
@@ -44,16 +46,15 @@ class AtomBrowserClient : public brightray::BrowserClient {
|
||||
int child_process_id) override;
|
||||
void DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) override;
|
||||
content::QuotaPermissionContext* CreateQuotaPermissionContext() override;
|
||||
void SelectClientCertificate(
|
||||
content::WebContents* web_contents,
|
||||
net::SSLCertRequestInfo* cert_request_info,
|
||||
scoped_ptr<content::ClientCertificateDelegate> delegate) override;
|
||||
|
||||
private:
|
||||
brightray::BrowserMainParts* OverrideCreateBrowserMainParts(
|
||||
const content::MainFunctionParams&) override;
|
||||
|
||||
scoped_ptr<AtomResourceDispatcherHostDelegate> resource_dispatcher_delegate_;
|
||||
|
||||
// The render process which would be swapped out soon.
|
||||
content::RenderProcessHost* dying_render_process_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomBrowserClient);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/atom_resource_dispatcher_host_delegate.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "content/public/browser/resource_request_info.h"
|
||||
#include "net/http/http_response_headers.h"
|
||||
#include "net/url_request/url_request.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
AtomResourceDispatcherHostDelegate::AtomResourceDispatcherHostDelegate() {
|
||||
}
|
||||
|
||||
void AtomResourceDispatcherHostDelegate::OnResponseStarted(
|
||||
net::URLRequest* request,
|
||||
content::ResourceContext* resource_context,
|
||||
content::ResourceResponse* response,
|
||||
IPC::Sender* sender) {
|
||||
// Remove the "X-Frame-Options" from response headers for devtools.
|
||||
if (request->url().SchemeIs("chrome-devtools")) {
|
||||
net::HttpResponseHeaders* response_headers = request->response_headers();
|
||||
if (response_headers && response_headers->HasHeader("x-frame-options"))
|
||||
response_headers->RemoveHeader("x-frame-options");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
@@ -1,30 +0,0 @@
|
||||
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_ATOM_RESOURCE_DISPATCHER_HOST_DELEGATE_H_
|
||||
#define ATOM_BROWSER_ATOM_RESOURCE_DISPATCHER_HOST_DELEGATE_H_
|
||||
|
||||
#include "base/compiler_specific.h"
|
||||
#include "content/public/browser/resource_dispatcher_host_delegate.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomResourceDispatcherHostDelegate
|
||||
: public content::ResourceDispatcherHostDelegate {
|
||||
public:
|
||||
AtomResourceDispatcherHostDelegate();
|
||||
|
||||
// content::ResourceDispatcherHostDelegate:
|
||||
void OnResponseStarted(net::URLRequest* request,
|
||||
content::ResourceContext* resource_context,
|
||||
content::ResourceResponse* response,
|
||||
IPC::Sender* sender) override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomResourceDispatcherHostDelegate);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_ATOM_RESOURCE_DISPATCHER_HOST_DELEGATE_H_
|
||||
342
atom/browser/common_web_contents_delegate.cc
Normal file
342
atom/browser/common_web_contents_delegate.cc
Normal file
@@ -0,0 +1,342 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/common_web_contents_delegate.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/atom_javascript_dialog_manager.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/ui/file_dialog.h"
|
||||
#include "atom/browser/web_dialog_helper.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "chrome/browser/ui/browser_dialogs.h"
|
||||
#include "content/public/browser/child_process_security_policy.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "content/public/common/renderer_preferences.h"
|
||||
#include "storage/browser/fileapi/isolated_context.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
struct FileSystem {
|
||||
FileSystem() {
|
||||
}
|
||||
FileSystem(const std::string& file_system_name,
|
||||
const std::string& root_url,
|
||||
const std::string& file_system_path)
|
||||
: file_system_name(file_system_name),
|
||||
root_url(root_url),
|
||||
file_system_path(file_system_path) {
|
||||
}
|
||||
|
||||
std::string file_system_name;
|
||||
std::string root_url;
|
||||
std::string file_system_path;
|
||||
};
|
||||
|
||||
std::string RegisterFileSystem(content::WebContents* web_contents,
|
||||
const base::FilePath& path,
|
||||
std::string* registered_name) {
|
||||
auto isolated_context = storage::IsolatedContext::GetInstance();
|
||||
std::string file_system_id = isolated_context->RegisterFileSystemForPath(
|
||||
storage::kFileSystemTypeNativeLocal,
|
||||
std::string(),
|
||||
path,
|
||||
registered_name);
|
||||
|
||||
content::ChildProcessSecurityPolicy* policy =
|
||||
content::ChildProcessSecurityPolicy::GetInstance();
|
||||
content::RenderViewHost* render_view_host = web_contents->GetRenderViewHost();
|
||||
int renderer_id = render_view_host->GetProcess()->GetID();
|
||||
policy->GrantReadFileSystem(renderer_id, file_system_id);
|
||||
policy->GrantWriteFileSystem(renderer_id, file_system_id);
|
||||
policy->GrantCreateFileForFileSystem(renderer_id, file_system_id);
|
||||
policy->GrantDeleteFromFileSystem(renderer_id, file_system_id);
|
||||
|
||||
if (!policy->CanReadFile(renderer_id, path))
|
||||
policy->GrantReadFile(renderer_id, path);
|
||||
|
||||
return file_system_id;
|
||||
}
|
||||
|
||||
FileSystem CreateFileSystemStruct(
|
||||
content::WebContents* web_contents,
|
||||
const std::string& file_system_id,
|
||||
const std::string& registered_name,
|
||||
const std::string& file_system_path) {
|
||||
const GURL origin = web_contents->GetURL().GetOrigin();
|
||||
std::string file_system_name =
|
||||
storage::GetIsolatedFileSystemName(origin, file_system_id);
|
||||
std::string root_url = storage::GetIsolatedFileSystemRootURIString(
|
||||
origin, file_system_id, registered_name);
|
||||
return FileSystem(file_system_name, root_url, file_system_path);
|
||||
}
|
||||
|
||||
base::DictionaryValue* CreateFileSystemValue(const FileSystem& file_system) {
|
||||
base::DictionaryValue* file_system_value = new base::DictionaryValue();
|
||||
file_system_value->SetString("fileSystemName", file_system.file_system_name);
|
||||
file_system_value->SetString("rootURL", file_system.root_url);
|
||||
file_system_value->SetString("fileSystemPath", file_system.file_system_path);
|
||||
return file_system_value;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
CommonWebContentsDelegate::CommonWebContentsDelegate(bool is_guest)
|
||||
: is_guest_(is_guest),
|
||||
owner_window_(nullptr),
|
||||
html_fullscreen_(false),
|
||||
native_fullscreen_(false) {
|
||||
}
|
||||
|
||||
CommonWebContentsDelegate::~CommonWebContentsDelegate() {
|
||||
}
|
||||
|
||||
void CommonWebContentsDelegate::InitWithWebContents(
|
||||
content::WebContents* web_contents,
|
||||
NativeWindow* owner_window) {
|
||||
owner_window_ = owner_window;
|
||||
web_contents->SetDelegate(this);
|
||||
|
||||
// Tell renderer to handle all navigations in browser.
|
||||
auto preferences = web_contents->GetMutableRendererPrefs();
|
||||
preferences->browser_handles_non_local_top_level_requests = true;
|
||||
preferences->browser_handles_all_top_level_requests = true;
|
||||
web_contents->GetRenderViewHost()->SyncRendererPrefs();
|
||||
|
||||
// Create InspectableWebContents.
|
||||
web_contents_.reset(brightray::InspectableWebContents::Create(web_contents));
|
||||
web_contents_->SetDelegate(this);
|
||||
}
|
||||
|
||||
void CommonWebContentsDelegate::DestroyWebContents() {
|
||||
web_contents_.reset();
|
||||
}
|
||||
|
||||
content::WebContents* CommonWebContentsDelegate::GetWebContents() const {
|
||||
if (!web_contents_)
|
||||
return nullptr;
|
||||
return web_contents_->GetWebContents();
|
||||
}
|
||||
|
||||
content::WebContents*
|
||||
CommonWebContentsDelegate::GetDevToolsWebContents() const {
|
||||
if (!web_contents_)
|
||||
return nullptr;
|
||||
return web_contents_->GetDevToolsWebContents();
|
||||
}
|
||||
|
||||
content::WebContents* CommonWebContentsDelegate::OpenURLFromTab(
|
||||
content::WebContents* source,
|
||||
const content::OpenURLParams& params) {
|
||||
content::NavigationController::LoadURLParams load_url_params(params.url);
|
||||
load_url_params.referrer = params.referrer;
|
||||
load_url_params.transition_type = params.transition;
|
||||
load_url_params.extra_headers = params.extra_headers;
|
||||
load_url_params.should_replace_current_entry =
|
||||
params.should_replace_current_entry;
|
||||
load_url_params.is_renderer_initiated = params.is_renderer_initiated;
|
||||
load_url_params.transferred_global_request_id =
|
||||
params.transferred_global_request_id;
|
||||
load_url_params.should_clear_history_list = true;
|
||||
|
||||
source->GetController().LoadURLWithParams(load_url_params);
|
||||
return source;
|
||||
}
|
||||
|
||||
void CommonWebContentsDelegate::RequestToLockMouse(
|
||||
content::WebContents* web_contents,
|
||||
bool user_gesture,
|
||||
bool last_unlocked_by_target) {
|
||||
GetWebContents()->GotResponseToLockMouseRequest(true);
|
||||
}
|
||||
|
||||
bool CommonWebContentsDelegate::CanOverscrollContent() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CommonWebContentsDelegate::IsPopupOrPanel(
|
||||
const content::WebContents* source) const {
|
||||
return !is_guest_;
|
||||
}
|
||||
|
||||
content::JavaScriptDialogManager*
|
||||
CommonWebContentsDelegate::GetJavaScriptDialogManager(
|
||||
content::WebContents* source) {
|
||||
if (!dialog_manager_)
|
||||
dialog_manager_.reset(new AtomJavaScriptDialogManager);
|
||||
|
||||
return dialog_manager_.get();
|
||||
}
|
||||
|
||||
content::ColorChooser* CommonWebContentsDelegate::OpenColorChooser(
|
||||
content::WebContents* web_contents,
|
||||
SkColor color,
|
||||
const std::vector<content::ColorSuggestion>& suggestions) {
|
||||
return chrome::ShowColorChooser(web_contents, color);
|
||||
}
|
||||
|
||||
void CommonWebContentsDelegate::RunFileChooser(
|
||||
content::WebContents* guest,
|
||||
const content::FileChooserParams& params) {
|
||||
if (!web_dialog_helper_)
|
||||
web_dialog_helper_.reset(new WebDialogHelper(owner_window_));
|
||||
web_dialog_helper_->RunFileChooser(guest, params);
|
||||
}
|
||||
|
||||
void CommonWebContentsDelegate::EnumerateDirectory(content::WebContents* guest,
|
||||
int request_id,
|
||||
const base::FilePath& path) {
|
||||
if (!web_dialog_helper_)
|
||||
web_dialog_helper_.reset(new WebDialogHelper(owner_window_));
|
||||
web_dialog_helper_->EnumerateDirectory(guest, request_id, path);
|
||||
}
|
||||
|
||||
void CommonWebContentsDelegate::EnterFullscreenModeForTab(
|
||||
content::WebContents* source, const GURL& origin) {
|
||||
if (!owner_window_)
|
||||
return;
|
||||
SetHtmlApiFullscreen(true);
|
||||
owner_window_->NotifyWindowEnterHtmlFullScreen();
|
||||
source->GetRenderViewHost()->WasResized();
|
||||
}
|
||||
|
||||
void CommonWebContentsDelegate::ExitFullscreenModeForTab(
|
||||
content::WebContents* source) {
|
||||
if (!owner_window_)
|
||||
return;
|
||||
SetHtmlApiFullscreen(false);
|
||||
owner_window_->NotifyWindowLeaveHtmlFullScreen();
|
||||
source->GetRenderViewHost()->WasResized();
|
||||
}
|
||||
|
||||
bool CommonWebContentsDelegate::IsFullscreenForTabOrPending(
|
||||
const content::WebContents* source) const {
|
||||
return html_fullscreen_;
|
||||
}
|
||||
|
||||
void CommonWebContentsDelegate::DevToolsSaveToFile(
|
||||
const std::string& url, const std::string& content, bool save_as) {
|
||||
base::FilePath path;
|
||||
PathsMap::iterator it = saved_files_.find(url);
|
||||
if (it != saved_files_.end() && !save_as) {
|
||||
path = it->second;
|
||||
} else {
|
||||
file_dialog::Filters filters;
|
||||
base::FilePath default_path(base::FilePath::FromUTF8Unsafe(url));
|
||||
if (!file_dialog::ShowSaveDialog(owner_window_, url, default_path,
|
||||
filters, &path)) {
|
||||
base::StringValue url_value(url);
|
||||
web_contents_->CallClientFunction(
|
||||
"DevToolsAPI.canceledSaveURL", &url_value, nullptr, nullptr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
saved_files_[url] = path;
|
||||
base::WriteFile(path, content.data(), content.size());
|
||||
|
||||
// Notify devtools.
|
||||
base::StringValue url_value(url);
|
||||
web_contents_->CallClientFunction(
|
||||
"DevToolsAPI.savedURL", &url_value, nullptr, nullptr);
|
||||
}
|
||||
|
||||
void CommonWebContentsDelegate::DevToolsAppendToFile(
|
||||
const std::string& url, const std::string& content) {
|
||||
PathsMap::iterator it = saved_files_.find(url);
|
||||
if (it == saved_files_.end())
|
||||
return;
|
||||
base::AppendToFile(it->second, content.data(), content.size());
|
||||
|
||||
// Notify devtools.
|
||||
base::StringValue url_value(url);
|
||||
web_contents_->CallClientFunction(
|
||||
"DevToolsAPI.appendedToURL", &url_value, nullptr, nullptr);
|
||||
}
|
||||
|
||||
void CommonWebContentsDelegate::DevToolsAddFileSystem() {
|
||||
file_dialog::Filters filters;
|
||||
base::FilePath default_path;
|
||||
std::vector<base::FilePath> paths;
|
||||
int flag = file_dialog::FILE_DIALOG_OPEN_DIRECTORY;
|
||||
if (!file_dialog::ShowOpenDialog(owner_window_, "", default_path,
|
||||
filters, flag, &paths))
|
||||
return;
|
||||
|
||||
base::FilePath path = paths[0];
|
||||
std::string registered_name;
|
||||
std::string file_system_id = RegisterFileSystem(GetDevToolsWebContents(),
|
||||
path,
|
||||
®istered_name);
|
||||
|
||||
WorkspaceMap::iterator it = saved_paths_.find(file_system_id);
|
||||
if (it != saved_paths_.end())
|
||||
return;
|
||||
|
||||
saved_paths_[file_system_id] = path;
|
||||
|
||||
FileSystem file_system = CreateFileSystemStruct(GetDevToolsWebContents(),
|
||||
file_system_id,
|
||||
registered_name,
|
||||
path.AsUTF8Unsafe());
|
||||
|
||||
scoped_ptr<base::StringValue> error_string_value(
|
||||
new base::StringValue(std::string()));
|
||||
scoped_ptr<base::DictionaryValue> file_system_value;
|
||||
if (!file_system.file_system_path.empty())
|
||||
file_system_value.reset(CreateFileSystemValue(file_system));
|
||||
web_contents_->CallClientFunction(
|
||||
"DevToolsAPI.fileSystemAdded",
|
||||
error_string_value.get(),
|
||||
file_system_value.get(),
|
||||
nullptr);
|
||||
}
|
||||
|
||||
void CommonWebContentsDelegate::DevToolsRemoveFileSystem(
|
||||
const std::string& file_system_path) {
|
||||
if (!web_contents_)
|
||||
return;
|
||||
|
||||
base::FilePath path = base::FilePath::FromUTF8Unsafe(file_system_path);
|
||||
storage::IsolatedContext::GetInstance()->RevokeFileSystemByPath(path);
|
||||
|
||||
for (auto it = saved_paths_.begin(); it != saved_paths_.end(); ++it)
|
||||
if (it->second == path) {
|
||||
saved_paths_.erase(it);
|
||||
break;
|
||||
}
|
||||
|
||||
base::StringValue file_system_path_value(file_system_path);
|
||||
web_contents_->CallClientFunction(
|
||||
"DevToolsAPI.fileSystemRemoved",
|
||||
&file_system_path_value,
|
||||
nullptr,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
void CommonWebContentsDelegate::SetHtmlApiFullscreen(bool enter_fullscreen) {
|
||||
// Window is already in fullscreen mode, save the state.
|
||||
if (enter_fullscreen && owner_window_->IsFullscreen()) {
|
||||
native_fullscreen_ = true;
|
||||
html_fullscreen_ = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Exit html fullscreen state but not window's fullscreen mode.
|
||||
if (!enter_fullscreen && native_fullscreen_) {
|
||||
html_fullscreen_ = false;
|
||||
return;
|
||||
}
|
||||
|
||||
owner_window_->SetFullScreen(enter_fullscreen);
|
||||
html_fullscreen_ = enter_fullscreen;
|
||||
native_fullscreen_ = false;
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
124
atom/browser/common_web_contents_delegate.h
Normal file
124
atom/browser/common_web_contents_delegate.h
Normal file
@@ -0,0 +1,124 @@
|
||||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_COMMON_WEB_CONTENTS_DELEGATE_H_
|
||||
#define ATOM_BROWSER_COMMON_WEB_CONTENTS_DELEGATE_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "brightray/browser/default_web_contents_delegate.h"
|
||||
#include "brightray/browser/inspectable_web_contents_impl.h"
|
||||
#include "brightray/browser/inspectable_web_contents_delegate.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomJavaScriptDialogManager;
|
||||
class NativeWindow;
|
||||
class WebDialogHelper;
|
||||
|
||||
class CommonWebContentsDelegate
|
||||
: public brightray::DefaultWebContentsDelegate,
|
||||
public brightray::InspectableWebContentsDelegate {
|
||||
public:
|
||||
explicit CommonWebContentsDelegate(bool is_guest);
|
||||
virtual ~CommonWebContentsDelegate();
|
||||
|
||||
// Create a InspectableWebContents object and takes onwership of
|
||||
// |web_contents|.
|
||||
void InitWithWebContents(content::WebContents* web_contents,
|
||||
NativeWindow* owner_window);
|
||||
|
||||
// Destroy the managed InspectableWebContents object.
|
||||
void DestroyWebContents();
|
||||
|
||||
// Returns the WebContents managed by this delegate.
|
||||
content::WebContents* GetWebContents() const;
|
||||
|
||||
// Returns the WebContents of devtools.
|
||||
content::WebContents* GetDevToolsWebContents() const;
|
||||
|
||||
brightray::InspectableWebContents* managed_web_contents() const {
|
||||
return web_contents_.get();
|
||||
}
|
||||
|
||||
bool is_guest() const { return is_guest_; }
|
||||
|
||||
protected:
|
||||
// content::WebContentsDelegate:
|
||||
content::WebContents* OpenURLFromTab(
|
||||
content::WebContents* source,
|
||||
const content::OpenURLParams& params) override;
|
||||
void RequestToLockMouse(content::WebContents* web_contents,
|
||||
bool user_gesture,
|
||||
bool last_unlocked_by_target) override;
|
||||
bool CanOverscrollContent() const override;
|
||||
bool IsPopupOrPanel(const content::WebContents* source) const override;
|
||||
content::JavaScriptDialogManager* GetJavaScriptDialogManager(
|
||||
content::WebContents* source) override;
|
||||
content::ColorChooser* OpenColorChooser(
|
||||
content::WebContents* web_contents,
|
||||
SkColor color,
|
||||
const std::vector<content::ColorSuggestion>& suggestions) override;
|
||||
void RunFileChooser(content::WebContents* web_contents,
|
||||
const content::FileChooserParams& params) override;
|
||||
void EnumerateDirectory(content::WebContents* web_contents,
|
||||
int request_id,
|
||||
const base::FilePath& path) override;
|
||||
void EnterFullscreenModeForTab(content::WebContents* source,
|
||||
const GURL& origin) override;
|
||||
void ExitFullscreenModeForTab(content::WebContents* source) override;
|
||||
bool IsFullscreenForTabOrPending(
|
||||
const content::WebContents* source) const override;
|
||||
|
||||
// brightray::InspectableWebContentsDelegate:
|
||||
void DevToolsSaveToFile(const std::string& url,
|
||||
const std::string& content,
|
||||
bool save_as) override;
|
||||
void DevToolsAppendToFile(const std::string& url,
|
||||
const std::string& content) override;
|
||||
void DevToolsAddFileSystem() override;
|
||||
void DevToolsRemoveFileSystem(const std::string& file_system_path) override;
|
||||
|
||||
private:
|
||||
// Set fullscreen mode triggered by html api.
|
||||
void SetHtmlApiFullscreen(bool enter_fullscreen);
|
||||
|
||||
// Whether this is guest WebContents or NativeWindow.
|
||||
const bool is_guest_;
|
||||
|
||||
// The window that this WebContents belongs to.
|
||||
NativeWindow* owner_window_;
|
||||
|
||||
// Whether window is fullscreened by HTML5 api.
|
||||
bool html_fullscreen_;
|
||||
|
||||
// Whether window is fullscreened by window api.
|
||||
bool native_fullscreen_;
|
||||
|
||||
scoped_ptr<WebDialogHelper> web_dialog_helper_;
|
||||
scoped_ptr<AtomJavaScriptDialogManager> dialog_manager_;
|
||||
|
||||
// The stored InspectableWebContents object.
|
||||
// Notice that web_contents_ must be placed after dialog_manager_, so we can
|
||||
// make sure web_contents_ is destroyed before dialog_manager_, otherwise a
|
||||
// crash would happen.
|
||||
scoped_ptr<brightray::InspectableWebContents> web_contents_;
|
||||
|
||||
// Maps url to file path, used by the file requests sent from devtools.
|
||||
typedef std::map<std::string, base::FilePath> PathsMap;
|
||||
PathsMap saved_files_;
|
||||
|
||||
// Maps file system id to file path, used by the file system requests
|
||||
// sent from devtools.
|
||||
typedef std::map<std::string, base::FilePath> WorkspaceMap;
|
||||
WorkspaceMap saved_paths_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CommonWebContentsDelegate);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_COMMON_WEB_CONTENTS_DELEGATE_H_
|
||||
@@ -1,10 +1,7 @@
|
||||
var app = require('app');
|
||||
var Menu = require('menu');
|
||||
var MenuItem = require('menu-item');
|
||||
var BrowserWindow = require('browser-window');
|
||||
|
||||
var mainWindow = null;
|
||||
var menu = null;
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function() {
|
||||
@@ -15,221 +12,9 @@ app.on('ready', function() {
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
resizable: false,
|
||||
'auto-hide-menu-bar': true,
|
||||
'use-content-size': true,
|
||||
});
|
||||
mainWindow.loadUrl('file://' + __dirname + '/index.html');
|
||||
mainWindow.focus();
|
||||
|
||||
if (process.platform == 'darwin') {
|
||||
var template = [
|
||||
{
|
||||
label: 'Electron',
|
||||
submenu: [
|
||||
{
|
||||
label: 'About Electron',
|
||||
selector: 'orderFrontStandardAboutPanel:'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Services',
|
||||
submenu: []
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Hide Electron',
|
||||
accelerator: 'Command+H',
|
||||
selector: 'hide:'
|
||||
},
|
||||
{
|
||||
label: 'Hide Others',
|
||||
accelerator: 'Command+Shift+H',
|
||||
selector: 'hideOtherApplications:'
|
||||
},
|
||||
{
|
||||
label: 'Show All',
|
||||
selector: 'unhideAllApplications:'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Quit',
|
||||
accelerator: 'Command+Q',
|
||||
click: function() { app.quit(); }
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Edit',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Undo',
|
||||
accelerator: 'Command+Z',
|
||||
selector: 'undo:'
|
||||
},
|
||||
{
|
||||
label: 'Redo',
|
||||
accelerator: 'Shift+Command+Z',
|
||||
selector: 'redo:'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Cut',
|
||||
accelerator: 'Command+X',
|
||||
selector: 'cut:'
|
||||
},
|
||||
{
|
||||
label: 'Copy',
|
||||
accelerator: 'Command+C',
|
||||
selector: 'copy:'
|
||||
},
|
||||
{
|
||||
label: 'Paste',
|
||||
accelerator: 'Command+V',
|
||||
selector: 'paste:'
|
||||
},
|
||||
{
|
||||
label: 'Select All',
|
||||
accelerator: 'Command+A',
|
||||
selector: 'selectAll:'
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'View',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Reload',
|
||||
accelerator: 'Command+R',
|
||||
click: function() { mainWindow.restart(); }
|
||||
},
|
||||
{
|
||||
label: 'Toggle Full Screen',
|
||||
accelerator: 'Ctrl+Command+F',
|
||||
click: function() { mainWindow.setFullScreen(!mainWindow.isFullScreen()); }
|
||||
},
|
||||
{
|
||||
label: 'Toggle Developer Tools',
|
||||
accelerator: 'Alt+Command+I',
|
||||
click: function() { mainWindow.toggleDevTools(); }
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Window',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Minimize',
|
||||
accelerator: 'Command+M',
|
||||
selector: 'performMiniaturize:'
|
||||
},
|
||||
{
|
||||
label: 'Close',
|
||||
accelerator: 'Command+W',
|
||||
selector: 'performClose:'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Bring All to Front',
|
||||
selector: 'arrangeInFront:'
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Help',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Learn More',
|
||||
click: function() { require('shell').openExternal('http://electron.atom.io') }
|
||||
},
|
||||
{
|
||||
label: 'Documentation',
|
||||
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
|
||||
},
|
||||
{
|
||||
label: 'Community Discussions',
|
||||
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
|
||||
},
|
||||
{
|
||||
label: 'Search Issues',
|
||||
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
menu = Menu.buildFromTemplate(template);
|
||||
Menu.setApplicationMenu(menu);
|
||||
} else {
|
||||
var template = [
|
||||
{
|
||||
label: '&File',
|
||||
submenu: [
|
||||
{
|
||||
label: '&Open',
|
||||
accelerator: 'Ctrl+O',
|
||||
},
|
||||
{
|
||||
label: '&Close',
|
||||
accelerator: 'Ctrl+W',
|
||||
click: function() { mainWindow.close(); }
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '&View',
|
||||
submenu: [
|
||||
{
|
||||
label: '&Reload',
|
||||
accelerator: 'Ctrl+R',
|
||||
click: function() { mainWindow.restart(); }
|
||||
},
|
||||
{
|
||||
label: 'Toggle &Full Screen',
|
||||
accelerator: 'F11',
|
||||
click: function() { mainWindow.setFullScreen(!mainWindow.isFullScreen()); }
|
||||
},
|
||||
{
|
||||
label: 'Toggle &Developer Tools',
|
||||
accelerator: 'Alt+Ctrl+I',
|
||||
click: function() { mainWindow.toggleDevTools(); }
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Help',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Learn More',
|
||||
click: function() { require('shell').openExternal('http://electron.atom.io') }
|
||||
},
|
||||
{
|
||||
label: 'Documentation',
|
||||
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
|
||||
},
|
||||
{
|
||||
label: 'Community Discussions',
|
||||
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
|
||||
},
|
||||
{
|
||||
label: 'Search Issues',
|
||||
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
menu = Menu.buildFromTemplate(template);
|
||||
mainWindow.setMenu(menu);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2,6 +2,8 @@ var app = require('app');
|
||||
var dialog = require('dialog');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var Menu = require('menu');
|
||||
var BrowserWindow = require('browser-window');
|
||||
|
||||
// Quit when all windows are closed and no other one is listening to this.
|
||||
app.on('window-all-closed', function() {
|
||||
@@ -29,6 +31,246 @@ for (var i in argv) {
|
||||
}
|
||||
}
|
||||
|
||||
// Create default menu.
|
||||
app.once('ready', function() {
|
||||
var template;
|
||||
if (process.platform == 'darwin') {
|
||||
template = [
|
||||
{
|
||||
label: 'Electron',
|
||||
submenu: [
|
||||
{
|
||||
label: 'About Electron',
|
||||
selector: 'orderFrontStandardAboutPanel:'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Services',
|
||||
submenu: []
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Hide Electron',
|
||||
accelerator: 'Command+H',
|
||||
selector: 'hide:'
|
||||
},
|
||||
{
|
||||
label: 'Hide Others',
|
||||
accelerator: 'Command+Shift+H',
|
||||
selector: 'hideOtherApplications:'
|
||||
},
|
||||
{
|
||||
label: 'Show All',
|
||||
selector: 'unhideAllApplications:'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Quit',
|
||||
accelerator: 'Command+Q',
|
||||
click: function() { app.quit(); }
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Edit',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Undo',
|
||||
accelerator: 'Command+Z',
|
||||
selector: 'undo:'
|
||||
},
|
||||
{
|
||||
label: 'Redo',
|
||||
accelerator: 'Shift+Command+Z',
|
||||
selector: 'redo:'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Cut',
|
||||
accelerator: 'Command+X',
|
||||
selector: 'cut:'
|
||||
},
|
||||
{
|
||||
label: 'Copy',
|
||||
accelerator: 'Command+C',
|
||||
selector: 'copy:'
|
||||
},
|
||||
{
|
||||
label: 'Paste',
|
||||
accelerator: 'Command+V',
|
||||
selector: 'paste:'
|
||||
},
|
||||
{
|
||||
label: 'Select All',
|
||||
accelerator: 'Command+A',
|
||||
selector: 'selectAll:'
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'View',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Reload',
|
||||
accelerator: 'Command+R',
|
||||
click: function() {
|
||||
var focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
if (focusedWindow)
|
||||
focusedWindow.reload();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Toggle Full Screen',
|
||||
accelerator: 'Ctrl+Command+F',
|
||||
click: function() {
|
||||
var focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
if (focusedWindow)
|
||||
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Toggle Developer Tools',
|
||||
accelerator: 'Alt+Command+I',
|
||||
click: function() {
|
||||
var focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
if (focusedWindow)
|
||||
focusedWindow.toggleDevTools();
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Window',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Minimize',
|
||||
accelerator: 'Command+M',
|
||||
selector: 'performMiniaturize:'
|
||||
},
|
||||
{
|
||||
label: 'Close',
|
||||
accelerator: 'Command+W',
|
||||
selector: 'performClose:'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Bring All to Front',
|
||||
selector: 'arrangeInFront:'
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Help',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Learn More',
|
||||
click: function() { require('shell').openExternal('http://electron.atom.io') }
|
||||
},
|
||||
{
|
||||
label: 'Documentation',
|
||||
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
|
||||
},
|
||||
{
|
||||
label: 'Community Discussions',
|
||||
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
|
||||
},
|
||||
{
|
||||
label: 'Search Issues',
|
||||
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
} else {
|
||||
template = [
|
||||
{
|
||||
label: '&File',
|
||||
submenu: [
|
||||
{
|
||||
label: '&Open',
|
||||
accelerator: 'Ctrl+O',
|
||||
},
|
||||
{
|
||||
label: '&Close',
|
||||
accelerator: 'Ctrl+W',
|
||||
click: function() {
|
||||
var focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
if (focusedWindow)
|
||||
focusedWindow.close();
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '&View',
|
||||
submenu: [
|
||||
{
|
||||
label: '&Reload',
|
||||
accelerator: 'Ctrl+R',
|
||||
click: function() {
|
||||
var focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
if (focusedWindow)
|
||||
focusedWindow.reload();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Toggle &Full Screen',
|
||||
accelerator: 'F11',
|
||||
click: function() {
|
||||
var focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
if (focusedWindow)
|
||||
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Toggle &Developer Tools',
|
||||
accelerator: 'Alt+Ctrl+I',
|
||||
click: function() {
|
||||
var focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
if (focusedWindow)
|
||||
focusedWindow.toggleDevTools();
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Help',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Learn More',
|
||||
click: function() { require('shell').openExternal('http://electron.atom.io') }
|
||||
},
|
||||
{
|
||||
label: 'Documentation',
|
||||
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
|
||||
},
|
||||
{
|
||||
label: 'Community Discussions',
|
||||
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
|
||||
},
|
||||
{
|
||||
label: 'Search Issues',
|
||||
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
var menu = Menu.buildFromTemplate(template);
|
||||
Menu.setApplicationMenu(menu);
|
||||
});
|
||||
|
||||
// Start the specified app if there is one specified in command line, otherwise
|
||||
// start the default app.
|
||||
if (option.file && !option.webdriver) {
|
||||
@@ -53,7 +295,7 @@ if (option.file && !option.webdriver) {
|
||||
} catch(e) {
|
||||
if (e.code == 'MODULE_NOT_FOUND') {
|
||||
app.focus();
|
||||
dialog.showErrorBox('Error opening app', 'The app provided is not a valid electron app, please read the docs on how to write one:\nhttps://github.com/atom/electron/tree/master/docs');
|
||||
dialog.showErrorBox('Error opening app', 'The app provided is not a valid electron app, please read the docs on how to write one:\nhttps://github.com/atom/electron/tree/master/docs\n\n' + e.toString());
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.error('App threw an error when running', e);
|
||||
|
||||
@@ -38,10 +38,7 @@ createGuest = (embedder, params) ->
|
||||
webViewManager ?= process.atomBinding 'web_view_manager'
|
||||
|
||||
id = getNextInstanceId embedder
|
||||
guest = webContents.create
|
||||
isGuest: true
|
||||
guestInstanceId: id
|
||||
storagePartitionId: params.storagePartitionId
|
||||
guest = webContents.create {embedder}
|
||||
guestInstances[id] = {guest, embedder}
|
||||
|
||||
# Destroy guest when the embedder is gone or navigated.
|
||||
@@ -58,14 +55,19 @@ createGuest = (embedder, params) ->
|
||||
delete @attachParams
|
||||
|
||||
@viewInstanceId = params.instanceId
|
||||
min = width: params.minwidth, height: params.minheight
|
||||
max = width: params.maxwidth, height: params.maxheight
|
||||
@setAutoSize params.autosize, min, max
|
||||
@setSize
|
||||
normal:
|
||||
width: params.elementWidth, height: params.elementHeight
|
||||
enableAutoSize: params.autosize
|
||||
min:
|
||||
width: params.minwidth, height: params.minheight
|
||||
max:
|
||||
width: params.maxwidth, height: params.maxheight
|
||||
|
||||
if params.src
|
||||
opts = {}
|
||||
opts.httpreferrer = params.httpreferrer if params.httpreferrer
|
||||
opts.useragent = params.useragent if params.useragent
|
||||
opts.httpReferrer = params.httpreferrer if params.httpreferrer
|
||||
opts.userAgent = params.useragent if params.useragent
|
||||
@loadUrl params.src, opts
|
||||
|
||||
if params.allowtransparency?
|
||||
@@ -123,7 +125,7 @@ destroyGuest = (embedder, id) ->
|
||||
delete reverseEmbedderElementsMap[id]
|
||||
delete embedderElementsMap[key]
|
||||
|
||||
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', (event, type, params, requestId) ->
|
||||
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', (event, params, requestId) ->
|
||||
event.sender.send "ATOM_SHELL_RESPONSE_#{requestId}", createGuest(event.sender, params)
|
||||
|
||||
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', (event, elementInstanceId, guestInstanceId, params) ->
|
||||
@@ -132,8 +134,8 @@ ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', (event, elementInstanceId,
|
||||
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', (event, id) ->
|
||||
destroyGuest event.sender, id
|
||||
|
||||
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_AUTO_SIZE', (event, id, params) ->
|
||||
guestInstances[id]?.guest.setAutoSize params.enableAutoSize, params.min, params.max
|
||||
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_SIZE', (event, id, params) ->
|
||||
guestInstances[id]?.guest.setSize params
|
||||
|
||||
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_ALLOW_TRANSPARENCY', (event, id, allowtransparency) ->
|
||||
guestInstances[id]?.guest.setAllowTransparency allowtransparency
|
||||
|
||||
@@ -7,6 +7,7 @@ v8Util = process.atomBinding 'v8_util'
|
||||
valueToMeta = (sender, value) ->
|
||||
meta = type: typeof value
|
||||
|
||||
meta.type = 'buffer' if Buffer.isBuffer value
|
||||
meta.type = 'value' if value is null
|
||||
meta.type = 'array' if Array.isArray value
|
||||
|
||||
@@ -26,6 +27,8 @@ valueToMeta = (sender, value) ->
|
||||
|
||||
meta.members = []
|
||||
meta.members.push {name: prop, type: typeof field} for prop, field of value
|
||||
else if meta.type is 'buffer'
|
||||
meta.value = Array::slice.call value, 0
|
||||
else
|
||||
meta.type = 'value'
|
||||
meta.value = value
|
||||
@@ -43,6 +46,7 @@ unwrapArgs = (sender, args) ->
|
||||
when 'value' then meta.value
|
||||
when 'remote-object' then objectsRegistry.get meta.id
|
||||
when 'array' then unwrapArgs sender, meta.value
|
||||
when 'buffer' then new Buffer(meta.value)
|
||||
when 'object'
|
||||
ret = v8Util.createObjectWithName meta.name
|
||||
for member in meta.members
|
||||
|
||||
@@ -9,10 +9,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/atom_javascript_dialog_manager.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/ui/file_dialog.h"
|
||||
#include "atom/browser/web_dialog_helper.h"
|
||||
#include "atom/browser/window_list.h"
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "atom/common/atom_version.h"
|
||||
@@ -31,16 +28,12 @@
|
||||
#include "brightray/browser/inspectable_web_contents.h"
|
||||
#include "brightray/browser/inspectable_web_contents_view.h"
|
||||
#include "chrome/browser/printing/print_view_manager_basic.h"
|
||||
#include "chrome/browser/ui/browser_dialogs.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_impl.h"
|
||||
#include "content/public/browser/devtools_agent_host.h"
|
||||
#include "content/public/browser/invalidate_type.h"
|
||||
#include "content/public/browser/navigation_entry.h"
|
||||
#include "content/public/browser/notification_details.h"
|
||||
#include "content/public/browser/notification_source.h"
|
||||
#include "content/public/browser/notification_types.h"
|
||||
#include "content/public/browser/plugin_service.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "content/public/browser/render_widget_host_view.h"
|
||||
@@ -78,6 +71,7 @@ const char* kWebRuntimeFeatures[] = {
|
||||
switches::kOverlayScrollbars,
|
||||
switches::kOverlayFullscreenVideo,
|
||||
switches::kSharedWorker,
|
||||
switches::kPageVisibility,
|
||||
};
|
||||
|
||||
std::string RemoveWhitespace(const std::string& str) {
|
||||
@@ -92,21 +86,20 @@ std::string RemoveWhitespace(const std::string& str) {
|
||||
|
||||
NativeWindow::NativeWindow(content::WebContents* web_contents,
|
||||
const mate::Dictionary& options)
|
||||
: content::WebContentsObserver(web_contents),
|
||||
: CommonWebContentsDelegate(false),
|
||||
content::WebContentsObserver(web_contents),
|
||||
has_frame_(true),
|
||||
transparent_(false),
|
||||
enable_larger_than_screen_(false),
|
||||
is_closed_(false),
|
||||
node_integration_(true),
|
||||
has_dialog_attached_(false),
|
||||
html_fullscreen_(false),
|
||||
native_fullscreen_(false),
|
||||
zoom_factor_(1.0),
|
||||
weak_factory_(this),
|
||||
inspectable_web_contents_(
|
||||
brightray::InspectableWebContents::Create(web_contents)) {
|
||||
weak_factory_(this) {
|
||||
printing::PrintViewManagerBasic::CreateForWebContents(web_contents);
|
||||
|
||||
InitWithWebContents(web_contents, this);
|
||||
|
||||
options.Get(switches::kFrame, &has_frame_);
|
||||
options.Get(switches::kTransparent, &transparent_);
|
||||
options.Get(switches::kEnableLargerThanScreen, &enable_larger_than_screen_);
|
||||
@@ -138,9 +131,6 @@ NativeWindow::NativeWindow(content::WebContents* web_contents,
|
||||
// Read the zoom factor before any navigation.
|
||||
options.Get(switches::kZoomFactor, &zoom_factor_);
|
||||
|
||||
web_contents->SetDelegate(this);
|
||||
inspectable_web_contents()->SetDelegate(this);
|
||||
|
||||
WindowList::AddWindow(this);
|
||||
|
||||
// Override the user agent to contain application and atom-shell's version.
|
||||
@@ -294,37 +284,6 @@ bool NativeWindow::HasModalDialog() {
|
||||
return has_dialog_attached_;
|
||||
}
|
||||
|
||||
void NativeWindow::OpenDevTools(bool can_dock) {
|
||||
inspectable_web_contents()->SetCanDock(can_dock);
|
||||
inspectable_web_contents()->ShowDevTools();
|
||||
}
|
||||
|
||||
void NativeWindow::CloseDevTools() {
|
||||
inspectable_web_contents()->CloseDevTools();
|
||||
}
|
||||
|
||||
bool NativeWindow::IsDevToolsOpened() {
|
||||
return inspectable_web_contents()->IsDevToolsViewShowing();
|
||||
}
|
||||
|
||||
void NativeWindow::InspectElement(int x, int y) {
|
||||
OpenDevTools(true);
|
||||
scoped_refptr<content::DevToolsAgentHost> agent(
|
||||
content::DevToolsAgentHost::GetOrCreateFor(GetWebContents()));
|
||||
agent->InspectElement(x, y);
|
||||
}
|
||||
|
||||
void NativeWindow::InspectServiceWorker() {
|
||||
for (const auto& agent_host : content::DevToolsAgentHost::GetOrCreateAll()) {
|
||||
if (agent_host->GetType() ==
|
||||
content::DevToolsAgentHost::TYPE_SERVICE_WORKER) {
|
||||
OpenDevTools(true);
|
||||
inspectable_web_contents()->AttachTo(agent_host);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindow::FocusOnWebView() {
|
||||
GetWebContents()->GetRenderViewHost()->Focus();
|
||||
}
|
||||
@@ -373,13 +332,6 @@ void NativeWindow::CapturePage(const gfx::Rect& rect,
|
||||
kBGRA_8888_SkColorType);
|
||||
}
|
||||
|
||||
void NativeWindow::DestroyWebContents() {
|
||||
if (!inspectable_web_contents_)
|
||||
return;
|
||||
|
||||
inspectable_web_contents_.reset();
|
||||
}
|
||||
|
||||
void NativeWindow::CloseWebContents() {
|
||||
bool prevent_default = false;
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver,
|
||||
@@ -409,20 +361,8 @@ void NativeWindow::CloseWebContents() {
|
||||
web_contents->Close();
|
||||
}
|
||||
|
||||
content::WebContents* NativeWindow::GetWebContents() const {
|
||||
if (!inspectable_web_contents_)
|
||||
return nullptr;
|
||||
return inspectable_web_contents()->GetWebContents();
|
||||
}
|
||||
|
||||
content::WebContents* NativeWindow::GetDevToolsWebContents() const {
|
||||
if (!inspectable_web_contents_)
|
||||
return nullptr;
|
||||
return inspectable_web_contents()->devtools_web_contents();
|
||||
}
|
||||
|
||||
void NativeWindow::AppendExtraCommandLineSwitches(
|
||||
base::CommandLine* command_line, int child_process_id) {
|
||||
base::CommandLine* command_line) {
|
||||
// Append --node-integration to renderer process.
|
||||
command_line->AppendSwitchASCII(switches::kNodeIntegration,
|
||||
node_integration_ ? "true" : "false");
|
||||
@@ -489,25 +429,6 @@ void NativeWindow::OverrideWebkitPrefs(content::WebPreferences* prefs) {
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindow::SetHtmlApiFullscreen(bool enter_fullscreen) {
|
||||
// Window is already in fullscreen mode, save the state.
|
||||
if (enter_fullscreen && IsFullscreen()) {
|
||||
native_fullscreen_ = true;
|
||||
html_fullscreen_ = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Exit html fullscreen state but not window's fullscreen mode.
|
||||
if (!enter_fullscreen && native_fullscreen_) {
|
||||
html_fullscreen_ = false;
|
||||
return;
|
||||
}
|
||||
|
||||
SetFullScreen(enter_fullscreen);
|
||||
html_fullscreen_ = enter_fullscreen;
|
||||
native_fullscreen_ = false;
|
||||
}
|
||||
|
||||
void NativeWindow::NotifyWindowClosed() {
|
||||
if (is_closed_)
|
||||
return;
|
||||
@@ -621,27 +542,7 @@ content::WebContents* NativeWindow::OpenURLFromTab(
|
||||
if (prevent_default)
|
||||
return nullptr;
|
||||
|
||||
content::NavigationController::LoadURLParams load_url_params(params.url);
|
||||
load_url_params.referrer = params.referrer;
|
||||
load_url_params.transition_type = params.transition;
|
||||
load_url_params.extra_headers = params.extra_headers;
|
||||
load_url_params.should_replace_current_entry =
|
||||
params.should_replace_current_entry;
|
||||
load_url_params.is_renderer_initiated = params.is_renderer_initiated;
|
||||
load_url_params.transferred_global_request_id =
|
||||
params.transferred_global_request_id;
|
||||
load_url_params.should_clear_history_list = true;
|
||||
|
||||
source->GetController().LoadURLWithParams(load_url_params);
|
||||
return source;
|
||||
}
|
||||
|
||||
content::JavaScriptDialogManager* NativeWindow::GetJavaScriptDialogManager(
|
||||
content::WebContents* source) {
|
||||
if (!dialog_manager_)
|
||||
dialog_manager_.reset(new AtomJavaScriptDialogManager);
|
||||
|
||||
return dialog_manager_.get();
|
||||
return CommonWebContentsDelegate::OpenURLFromTab(source, params);
|
||||
}
|
||||
|
||||
void NativeWindow::RenderViewCreated(
|
||||
@@ -669,38 +570,6 @@ void NativeWindow::BeforeUnloadFired(content::WebContents* tab,
|
||||
}
|
||||
}
|
||||
|
||||
content::ColorChooser* NativeWindow::OpenColorChooser(
|
||||
content::WebContents* web_contents,
|
||||
SkColor color,
|
||||
const std::vector<content::ColorSuggestion>& suggestions) {
|
||||
return chrome::ShowColorChooser(web_contents, color);
|
||||
}
|
||||
|
||||
void NativeWindow::RunFileChooser(content::WebContents* web_contents,
|
||||
const content::FileChooserParams& params) {
|
||||
if (!web_dialog_helper_)
|
||||
web_dialog_helper_.reset(new WebDialogHelper(this));
|
||||
web_dialog_helper_->RunFileChooser(web_contents, params);
|
||||
}
|
||||
|
||||
void NativeWindow::EnumerateDirectory(content::WebContents* web_contents,
|
||||
int request_id,
|
||||
const base::FilePath& path) {
|
||||
if (!web_dialog_helper_)
|
||||
web_dialog_helper_.reset(new WebDialogHelper(this));
|
||||
web_dialog_helper_->EnumerateDirectory(web_contents, request_id, path);
|
||||
}
|
||||
|
||||
void NativeWindow::RequestToLockMouse(content::WebContents* web_contents,
|
||||
bool user_gesture,
|
||||
bool last_unlocked_by_target) {
|
||||
GetWebContents()->GotResponseToLockMouseRequest(true);
|
||||
}
|
||||
|
||||
bool NativeWindow::CanOverscrollContent() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void NativeWindow::ActivateContents(content::WebContents* contents) {
|
||||
FocusOnWebView();
|
||||
}
|
||||
@@ -729,11 +598,6 @@ void NativeWindow::CloseContents(content::WebContents* source) {
|
||||
window_unresposive_closure_.Cancel();
|
||||
}
|
||||
|
||||
bool NativeWindow::IsPopupOrPanel(const content::WebContents* source) const {
|
||||
// Only popup window can use things like window.moveTo.
|
||||
return true;
|
||||
}
|
||||
|
||||
void NativeWindow::RendererUnresponsive(content::WebContents* source) {
|
||||
// Schedule the unresponsive shortly later, since we may receive the
|
||||
// responsive event soon. This could happen after the whole application had
|
||||
@@ -750,20 +614,6 @@ void NativeWindow::RendererResponsive(content::WebContents* source) {
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnRendererResponsive());
|
||||
}
|
||||
|
||||
void NativeWindow::EnterFullscreenModeForTab(content::WebContents* source,
|
||||
const GURL& origin) {
|
||||
SetHtmlApiFullscreen(true);
|
||||
}
|
||||
|
||||
void NativeWindow::ExitFullscreenModeForTab(content::WebContents* source) {
|
||||
SetHtmlApiFullscreen(false);
|
||||
}
|
||||
|
||||
bool NativeWindow::IsFullscreenForTabOrPending(
|
||||
const content::WebContents* source) const {
|
||||
return is_html_api_fullscreen();
|
||||
}
|
||||
|
||||
void NativeWindow::BeforeUnloadFired(const base::TimeTicks& proceed_time) {
|
||||
// Do nothing, we override this method just to avoid compilation error since
|
||||
// there are two virtual functions named BeforeUnloadFired.
|
||||
@@ -800,47 +650,18 @@ void NativeWindow::Observe(int type,
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindow::DevToolsSaveToFile(const std::string& url,
|
||||
const std::string& content,
|
||||
bool save_as) {
|
||||
base::FilePath path;
|
||||
PathsMap::iterator it = saved_files_.find(url);
|
||||
if (it != saved_files_.end() && !save_as) {
|
||||
path = it->second;
|
||||
} else {
|
||||
file_dialog::Filters filters;
|
||||
base::FilePath default_path(base::FilePath::FromUTF8Unsafe(url));
|
||||
if (!file_dialog::ShowSaveDialog(this, url, default_path, filters, &path)) {
|
||||
base::StringValue url_value(url);
|
||||
CallDevToolsFunction("DevToolsAPI.canceledSaveURL", &url_value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
saved_files_[url] = path;
|
||||
base::WriteFile(path, content.data(), content.size());
|
||||
|
||||
// Notify devtools.
|
||||
base::StringValue url_value(url);
|
||||
CallDevToolsFunction("DevToolsAPI.savedURL", &url_value);
|
||||
}
|
||||
|
||||
void NativeWindow::DevToolsAppendToFile(const std::string& url,
|
||||
const std::string& content) {
|
||||
PathsMap::iterator it = saved_files_.find(url);
|
||||
if (it == saved_files_.end())
|
||||
return;
|
||||
base::AppendToFile(it->second, content.data(), content.size());
|
||||
|
||||
// Notify devtools.
|
||||
base::StringValue url_value(url);
|
||||
CallDevToolsFunction("DevToolsAPI.appendedToURL", &url_value);
|
||||
}
|
||||
|
||||
void NativeWindow::DevToolsFocused() {
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsFocus());
|
||||
}
|
||||
|
||||
void NativeWindow::DevToolsOpened() {
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsOpened());
|
||||
}
|
||||
|
||||
void NativeWindow::DevToolsClosed() {
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsClosed());
|
||||
}
|
||||
|
||||
void NativeWindow::ScheduleUnresponsiveEvent(int ms) {
|
||||
if (!window_unresposive_closure_.IsCancelled())
|
||||
return;
|
||||
@@ -869,27 +690,4 @@ void NativeWindow::OnCapturePageDone(const CapturePageCallback& callback,
|
||||
callback.Run(bitmap);
|
||||
}
|
||||
|
||||
void NativeWindow::CallDevToolsFunction(const std::string& function_name,
|
||||
const base::Value* arg1,
|
||||
const base::Value* arg2,
|
||||
const base::Value* arg3) {
|
||||
std::string params;
|
||||
if (arg1) {
|
||||
std::string json;
|
||||
base::JSONWriter::Write(arg1, &json);
|
||||
params.append(json);
|
||||
if (arg2) {
|
||||
base::JSONWriter::Write(arg2, &json);
|
||||
params.append(", " + json);
|
||||
if (arg3) {
|
||||
base::JSONWriter::Write(arg3, &json);
|
||||
params.append(", " + json);
|
||||
}
|
||||
}
|
||||
}
|
||||
base::string16 javascript =
|
||||
base::UTF8ToUTF16(function_name + "(" + params + ");");
|
||||
GetDevToolsWebContents()->GetMainFrame()->ExecuteJavaScript(javascript);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -9,15 +9,13 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/common_web_contents_delegate.h"
|
||||
#include "atom/browser/native_window_observer.h"
|
||||
#include "atom/browser/ui/accelerator_util.h"
|
||||
#include "base/cancelable_callback.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/observer_list.h"
|
||||
#include "brightray/browser/default_web_contents_delegate.h"
|
||||
#include "brightray/browser/inspectable_web_contents_delegate.h"
|
||||
#include "brightray/browser/inspectable_web_contents_impl.h"
|
||||
#include "content/public/browser/notification_registrar.h"
|
||||
#include "content/public/browser/notification_observer.h"
|
||||
#include "content/public/browser/readback_types.h"
|
||||
@@ -50,12 +48,9 @@ class MenuModel;
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomJavaScriptDialogManager;
|
||||
struct DraggableRegion;
|
||||
class WebDialogHelper;
|
||||
|
||||
class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
||||
public brightray::InspectableWebContentsDelegate,
|
||||
class NativeWindow : public CommonWebContentsDelegate,
|
||||
public content::WebContentsObserver,
|
||||
public content::NotificationObserver {
|
||||
public:
|
||||
@@ -149,11 +144,6 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
||||
virtual bool IsVisibleOnAllWorkspaces() = 0;
|
||||
|
||||
virtual bool IsClosed() const { return is_closed_; }
|
||||
virtual void OpenDevTools(bool can_dock);
|
||||
virtual void CloseDevTools();
|
||||
virtual bool IsDevToolsOpened();
|
||||
virtual void InspectElement(int x, int y);
|
||||
virtual void InspectServiceWorker();
|
||||
|
||||
virtual void FocusOnWebView();
|
||||
virtual void BlurWebView();
|
||||
@@ -181,24 +171,14 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
||||
// Should be called by platform code when user want to close the window.
|
||||
virtual void CloseWebContents();
|
||||
|
||||
// Destroy the WebContents immediately.
|
||||
virtual void DestroyWebContents();
|
||||
|
||||
base::WeakPtr<NativeWindow> GetWeakPtr() {
|
||||
return weak_factory_.GetWeakPtr();
|
||||
}
|
||||
|
||||
content::WebContents* GetWebContents() const;
|
||||
content::WebContents* GetDevToolsWebContents() const;
|
||||
|
||||
// Called when renderer process is going to be started.
|
||||
void AppendExtraCommandLineSwitches(base::CommandLine* command_line,
|
||||
int child_process_id);
|
||||
void AppendExtraCommandLineSwitches(base::CommandLine* command_line);
|
||||
void OverrideWebkitPrefs(content::WebPreferences* prefs);
|
||||
|
||||
// Set fullscreen mode triggered by html api.
|
||||
void SetHtmlApiFullscreen(bool enter_fullscreen);
|
||||
|
||||
// Public API used by platform-dependent delegates and observers to send UI
|
||||
// related notifications.
|
||||
void NotifyWindowClosed();
|
||||
@@ -224,9 +204,11 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
||||
observers_.RemoveObserver(obs);
|
||||
}
|
||||
|
||||
bool has_frame() const { return has_frame_; }
|
||||
brightray::InspectableWebContents* inspectable_web_contents() const {
|
||||
return managed_web_contents();
|
||||
}
|
||||
|
||||
bool is_html_api_fullscreen() const { return html_fullscreen_; }
|
||||
bool has_frame() const { return has_frame_; }
|
||||
|
||||
void set_has_dialog_attached(bool has_dialog_attached) {
|
||||
has_dialog_attached_ = has_dialog_attached;
|
||||
@@ -236,11 +218,6 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
||||
explicit NativeWindow(content::WebContents* web_contents,
|
||||
const mate::Dictionary& options);
|
||||
|
||||
brightray::InspectableWebContentsImpl* inspectable_web_contents() const {
|
||||
return static_cast<brightray::InspectableWebContentsImpl*>(
|
||||
inspectable_web_contents_.get());
|
||||
}
|
||||
|
||||
// Called when the window needs to update its draggable region.
|
||||
virtual void UpdateDraggableRegions(
|
||||
const std::vector<DraggableRegion>& regions) = 0;
|
||||
@@ -258,38 +235,16 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
||||
content::WebContents* OpenURLFromTab(
|
||||
content::WebContents* source,
|
||||
const content::OpenURLParams& params) override;
|
||||
content::JavaScriptDialogManager* GetJavaScriptDialogManager(
|
||||
content::WebContents* source) override;
|
||||
void BeforeUnloadFired(content::WebContents* tab,
|
||||
bool proceed,
|
||||
bool* proceed_to_fire_unload) override;
|
||||
content::ColorChooser* OpenColorChooser(
|
||||
content::WebContents* web_contents,
|
||||
SkColor color,
|
||||
const std::vector<content::ColorSuggestion>& suggestions) override;
|
||||
void RunFileChooser(content::WebContents* web_contents,
|
||||
const content::FileChooserParams& params) override;
|
||||
void EnumerateDirectory(content::WebContents* web_contents,
|
||||
int request_id,
|
||||
const base::FilePath& path) override;
|
||||
void RequestToLockMouse(content::WebContents* web_contents,
|
||||
bool user_gesture,
|
||||
bool last_unlocked_by_target) override;
|
||||
bool CanOverscrollContent() const override;
|
||||
void ActivateContents(content::WebContents* contents) override;
|
||||
void DeactivateContents(content::WebContents* contents) override;
|
||||
void MoveContents(content::WebContents* source,
|
||||
const gfx::Rect& pos) override;
|
||||
void CloseContents(content::WebContents* source) override;
|
||||
bool IsPopupOrPanel(
|
||||
const content::WebContents* source) const override;
|
||||
void RendererUnresponsive(content::WebContents* source) override;
|
||||
void RendererResponsive(content::WebContents* source) override;
|
||||
void EnterFullscreenModeForTab(content::WebContents* source,
|
||||
const GURL& origin) override;
|
||||
void ExitFullscreenModeForTab(content::WebContents* source) override;
|
||||
bool IsFullscreenForTabOrPending(
|
||||
const content::WebContents* source) const override;
|
||||
|
||||
// Implementations of content::WebContentsObserver.
|
||||
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
|
||||
@@ -302,12 +257,9 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
||||
const content::NotificationDetails& details) override;
|
||||
|
||||
// Implementations of brightray::InspectableWebContentsDelegate.
|
||||
void DevToolsSaveToFile(const std::string& url,
|
||||
const std::string& content,
|
||||
bool save_as) override;
|
||||
void DevToolsAppendToFile(const std::string& url,
|
||||
const std::string& content) override;
|
||||
void DevToolsFocused() override;
|
||||
void DevToolsOpened() override;
|
||||
void DevToolsClosed() override;
|
||||
|
||||
// Whether window has standard frame.
|
||||
bool has_frame_;
|
||||
@@ -328,12 +280,6 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
||||
// Dispatch unresponsive event to observers.
|
||||
void NotifyWindowUnresponsive();
|
||||
|
||||
// Call a function in devtools.
|
||||
void CallDevToolsFunction(const std::string& function_name,
|
||||
const base::Value* arg1 = NULL,
|
||||
const base::Value* arg2 = NULL,
|
||||
const base::Value* arg3 = NULL);
|
||||
|
||||
// Called when CapturePage has done.
|
||||
void OnCapturePageDone(const CapturePageCallback& callback,
|
||||
const SkBitmap& bitmap,
|
||||
@@ -354,12 +300,6 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
||||
// There is a dialog that has been attached to window.
|
||||
bool has_dialog_attached_;
|
||||
|
||||
// Whether window is fullscreened by HTML5 api.
|
||||
bool html_fullscreen_;
|
||||
|
||||
// Whether window is fullscreened by window api.
|
||||
bool native_fullscreen_;
|
||||
|
||||
// Closure that would be called when window is unresponsive when closing,
|
||||
// it should be cancelled when we can prove that the window is responsive.
|
||||
base::CancelableClosure window_unresposive_closure_;
|
||||
@@ -375,18 +315,6 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
||||
|
||||
base::WeakPtrFactory<NativeWindow> weak_factory_;
|
||||
|
||||
scoped_ptr<WebDialogHelper> web_dialog_helper_;
|
||||
scoped_ptr<AtomJavaScriptDialogManager> dialog_manager_;
|
||||
|
||||
// Notice that inspectable_web_contents_ must be placed after dialog_manager_,
|
||||
// so we can make sure inspectable_web_contents_ is destroyed before
|
||||
// dialog_manager_, otherwise a crash would happen.
|
||||
scoped_ptr<brightray::InspectableWebContents> inspectable_web_contents_;
|
||||
|
||||
// Maps url to file path, used by the file requests sent from devtools.
|
||||
typedef std::map<std::string, base::FilePath> PathsMap;
|
||||
PathsMap saved_files_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(NativeWindow);
|
||||
};
|
||||
|
||||
|
||||
@@ -55,8 +55,10 @@ class NativeWindowObserver {
|
||||
virtual void OnWindowEnterHtmlFullScreen() {}
|
||||
virtual void OnWindowLeaveHtmlFullScreen() {}
|
||||
|
||||
// Called when devtools window gets focused.
|
||||
// Redirect devtools events.
|
||||
virtual void OnDevToolsFocus() {}
|
||||
virtual void OnDevToolsOpened() {}
|
||||
virtual void OnDevToolsClosed() {}
|
||||
|
||||
// Called when renderer is hung.
|
||||
virtual void OnRendererUnresponsive() {}
|
||||
|
||||
@@ -541,6 +541,19 @@ bool NativeWindowViews::IsKiosk() {
|
||||
}
|
||||
|
||||
void NativeWindowViews::SetMenu(ui::MenuModel* menu_model) {
|
||||
if (menu_model == nullptr) {
|
||||
// Remove accelerators
|
||||
accelerator_table_.clear();
|
||||
GetFocusManager()->UnregisterAccelerators(this);
|
||||
// and menu bar.
|
||||
#if defined(USE_X11)
|
||||
global_menu_bar_.reset();
|
||||
#endif
|
||||
SetMenuBarVisibility(false);
|
||||
menu_bar_.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
RegisterAccelerators(menu_model);
|
||||
|
||||
#if defined(USE_X11)
|
||||
@@ -713,7 +726,8 @@ void NativeWindowViews::OnWidgetActivationChanged(
|
||||
else
|
||||
NotifyWindowBlur();
|
||||
|
||||
if (active && GetWebContents() && !IsDevToolsOpened())
|
||||
if (active && GetWebContents() &&
|
||||
!inspectable_web_contents()->IsDevToolsViewShowing())
|
||||
GetWebContents()->Focus();
|
||||
|
||||
// Hide menu bar when window is blured.
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>atom.icns</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.27.1</string>
|
||||
<string>0.28.0</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.8.0</string>
|
||||
<key>NSMainNibFile</key>
|
||||
|
||||
@@ -50,8 +50,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,27,1,0
|
||||
PRODUCTVERSION 0,27,1,0
|
||||
FILEVERSION 0,28,0,0
|
||||
PRODUCTVERSION 0,28,0,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -68,12 +68,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "GitHub, Inc."
|
||||
VALUE "FileDescription", "Electron"
|
||||
VALUE "FileVersion", "0.27.1"
|
||||
VALUE "FileVersion", "0.28.0"
|
||||
VALUE "InternalName", "electron.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
||||
VALUE "OriginalFilename", "electron.exe"
|
||||
VALUE "ProductName", "Electron"
|
||||
VALUE "ProductVersion", "0.27.1"
|
||||
VALUE "ProductVersion", "0.28.0"
|
||||
VALUE "SquirrelAwareVersion", "1"
|
||||
END
|
||||
END
|
||||
|
||||
@@ -93,12 +93,15 @@ class FileChooserDialog {
|
||||
gtk_window_set_modal(GTK_WINDOW(dialog_), TRUE);
|
||||
|
||||
if (!default_path.empty()) {
|
||||
if (base::DirectoryExists(default_path))
|
||||
if (base::DirectoryExists(default_path)) {
|
||||
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog_),
|
||||
default_path.value().c_str());
|
||||
else
|
||||
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog_),
|
||||
default_path.value().c_str());
|
||||
} else {
|
||||
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog_),
|
||||
default_path.DirName().value().c_str());
|
||||
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog_),
|
||||
default_path.BaseName().value().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (!filters.empty())
|
||||
|
||||
@@ -49,7 +49,16 @@ void NotifyIcon::HandleClickEvent(const gfx::Point& cursor_pos,
|
||||
bool left_mouse_click) {
|
||||
// Pass to the observer if appropriate.
|
||||
if (left_mouse_click) {
|
||||
NotifyClicked();
|
||||
NOTIFYICONIDENTIFIER icon_id;
|
||||
memset(&icon_id, 0, sizeof(NOTIFYICONIDENTIFIER));
|
||||
icon_id.uID = icon_id_;
|
||||
icon_id.hWnd = window_;
|
||||
icon_id.cbSize = sizeof(NOTIFYICONIDENTIFIER);
|
||||
|
||||
RECT rect = { 0 };
|
||||
Shell_NotifyIconGetRect(&icon_id, &rect);
|
||||
|
||||
NotifyClicked(gfx::Rect(rect));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,10 +12,9 @@ namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
WebViewManager* GetManagerFromProcess(content::RenderProcessHost* process) {
|
||||
if (!process)
|
||||
return nullptr;
|
||||
auto context = process->GetBrowserContext();
|
||||
WebViewManager* GetManagerFromWebContents(
|
||||
const content::WebContents* web_contents) {
|
||||
auto context = web_contents->GetBrowserContext();
|
||||
if (!context)
|
||||
return nullptr;
|
||||
return static_cast<WebViewManager*>(context->GetGuestManager());
|
||||
@@ -24,28 +23,17 @@ WebViewManager* GetManagerFromProcess(content::RenderProcessHost* process) {
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
bool WebViewManager::GetInfoForProcess(content::RenderProcessHost* process,
|
||||
WebViewInfo* info) {
|
||||
auto manager = GetManagerFromProcess(process);
|
||||
bool WebViewManager::GetInfoForWebContents(
|
||||
const content::WebContents* web_contents, WebViewInfo* info) {
|
||||
auto manager = GetManagerFromWebContents(web_contents);
|
||||
if (!manager)
|
||||
return false;
|
||||
return manager->GetInfo(process->GetID(), info);
|
||||
}
|
||||
|
||||
// static
|
||||
void WebViewManager::UpdateGuestProcessID(
|
||||
content::RenderProcessHost* old_process,
|
||||
content::RenderProcessHost* new_process) {
|
||||
auto manager = GetManagerFromProcess(old_process);
|
||||
if (manager) {
|
||||
base::AutoLock auto_lock(manager->lock_);
|
||||
int old_id = old_process->GetID();
|
||||
int new_id = new_process->GetID();
|
||||
if (!ContainsKey(manager->webview_info_map_, old_id))
|
||||
return;
|
||||
manager->webview_info_map_[new_id] = manager->webview_info_map_[old_id];
|
||||
manager->webview_info_map_.erase(old_id);
|
||||
}
|
||||
base::AutoLock auto_lock(manager->lock_);
|
||||
auto iter = manager->webview_info_map_.find(web_contents);
|
||||
if (iter == manager->webview_info_map_.end())
|
||||
return false;
|
||||
*info = iter->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
WebViewManager::WebViewManager(content::BrowserContext* context) {
|
||||
@@ -61,9 +49,7 @@ void WebViewManager::AddGuest(int guest_instance_id,
|
||||
const WebViewInfo& info) {
|
||||
base::AutoLock auto_lock(lock_);
|
||||
web_contents_embdder_map_[guest_instance_id] = { web_contents, embedder };
|
||||
|
||||
int guest_process_id = web_contents->GetRenderProcessHost()->GetID();
|
||||
webview_info_map_[guest_process_id] = info;
|
||||
webview_info_map_[web_contents] = info;
|
||||
|
||||
// Map the element in embedder to guest.
|
||||
int owner_process_id = embedder->GetRenderProcessHost()->GetID();
|
||||
@@ -78,9 +64,7 @@ void WebViewManager::RemoveGuest(int guest_instance_id) {
|
||||
|
||||
auto web_contents = web_contents_embdder_map_[guest_instance_id].web_contents;
|
||||
web_contents_embdder_map_.erase(guest_instance_id);
|
||||
|
||||
int guest_process_id = web_contents->GetRenderProcessHost()->GetID();
|
||||
webview_info_map_.erase(guest_process_id);
|
||||
webview_info_map_.erase(web_contents);
|
||||
|
||||
// Remove the record of element in embedder too.
|
||||
for (const auto& element : element_instance_id_to_guest_map_)
|
||||
@@ -90,16 +74,6 @@ void WebViewManager::RemoveGuest(int guest_instance_id) {
|
||||
}
|
||||
}
|
||||
|
||||
bool WebViewManager::GetInfo(int guest_process_id, WebViewInfo* webview_info) {
|
||||
base::AutoLock auto_lock(lock_);
|
||||
WebViewInfoMap::iterator iter = webview_info_map_.find(guest_process_id);
|
||||
if (iter != webview_info_map_.end()) {
|
||||
*webview_info = iter->second;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
content::WebContents* WebViewManager::GetGuestByInstanceID(
|
||||
int owner_process_id,
|
||||
int element_instance_id) {
|
||||
|
||||
@@ -29,14 +29,10 @@ class WebViewManager : public content::BrowserPluginGuestManager {
|
||||
base::FilePath preload_script;
|
||||
};
|
||||
|
||||
// Finds the WebViewManager attached with |process| and returns the
|
||||
// Finds the WebViewManager attached with |web_contents| and returns the
|
||||
// WebViewInfo of it.
|
||||
static bool GetInfoForProcess(content::RenderProcessHost* process,
|
||||
WebViewInfo* info);
|
||||
|
||||
// Updates the guest process ID.
|
||||
static void UpdateGuestProcessID(content::RenderProcessHost* old_process,
|
||||
content::RenderProcessHost* new_process);
|
||||
static bool GetInfoForWebContents(const content::WebContents* web_contents,
|
||||
WebViewInfo* info);
|
||||
|
||||
explicit WebViewManager(content::BrowserContext* context);
|
||||
virtual ~WebViewManager();
|
||||
@@ -48,10 +44,6 @@ class WebViewManager : public content::BrowserPluginGuestManager {
|
||||
const WebViewInfo& info);
|
||||
void RemoveGuest(int guest_instance_id);
|
||||
|
||||
// Looks up the information for the embedder <webview> for a given render
|
||||
// view, if one exists. Called on the IO thread.
|
||||
bool GetInfo(int guest_process_id, WebViewInfo* webview_info);
|
||||
|
||||
protected:
|
||||
// content::BrowserPluginGuestManager:
|
||||
content::WebContents* GetGuestByInstanceID(int owner_process_id,
|
||||
@@ -89,8 +81,8 @@ class WebViewManager : public content::BrowserPluginGuestManager {
|
||||
// (embedder_process_id, element_instance_id) => guest_instance_id
|
||||
std::map<ElementInstanceKey, int> element_instance_id_to_guest_map_;
|
||||
|
||||
typedef std::map<int, WebViewInfo> WebViewInfoMap;
|
||||
// guest_process_id => (guest_instance_id, embedder, ...)
|
||||
typedef std::map<const content::WebContents*, WebViewInfo> WebViewInfoMap;
|
||||
// web_contents => (guest_instance_id, embedder, ...)
|
||||
WebViewInfoMap webview_info_map_;
|
||||
|
||||
base::Lock lock_;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "atom/common/native_mate_converters/image_converter.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "native_mate/arguments.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "third_party/skia/include/core/SkBitmap.h"
|
||||
#include "ui/base/clipboard/clipboard.h"
|
||||
@@ -15,44 +16,32 @@
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<ui::ClipboardType> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
ui::ClipboardType* out) {
|
||||
std::string type;
|
||||
if (!Converter<std::string>::FromV8(isolate, val, &type))
|
||||
return false;
|
||||
|
||||
if (type == "selection")
|
||||
*out = ui::CLIPBOARD_TYPE_SELECTION;
|
||||
else
|
||||
*out = ui::CLIPBOARD_TYPE_COPY_PASTE;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace {
|
||||
|
||||
std::vector<base::string16> AvailableFormats(ui::ClipboardType type) {
|
||||
ui::ClipboardType GetClipboardType(mate::Arguments* args) {
|
||||
std::string type;
|
||||
if (args->GetNext(&type) && type == "selection")
|
||||
return ui::CLIPBOARD_TYPE_SELECTION;
|
||||
else
|
||||
return ui::CLIPBOARD_TYPE_COPY_PASTE;
|
||||
}
|
||||
|
||||
std::vector<base::string16> AvailableFormats(mate::Arguments* args) {
|
||||
std::vector<base::string16> format_types;
|
||||
bool ignore;
|
||||
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
|
||||
clipboard->ReadAvailableTypes(type, &format_types, &ignore);
|
||||
clipboard->ReadAvailableTypes(GetClipboardType(args), &format_types, &ignore);
|
||||
return format_types;
|
||||
}
|
||||
|
||||
bool Has(const std::string& format_string, ui::ClipboardType type) {
|
||||
bool Has(const std::string& format_string, mate::Arguments* args) {
|
||||
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
|
||||
ui::Clipboard::FormatType format(ui::Clipboard::GetFormatType(format_string));
|
||||
return clipboard->IsFormatAvailable(format, type);
|
||||
return clipboard->IsFormatAvailable(format, GetClipboardType(args));
|
||||
}
|
||||
|
||||
std::string Read(const std::string& format_string,
|
||||
ui::ClipboardType type) {
|
||||
mate::Arguments* args) {
|
||||
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
|
||||
ui::Clipboard::FormatType format(ui::Clipboard::GetFormatType(format_string));
|
||||
|
||||
@@ -61,62 +50,62 @@ std::string Read(const std::string& format_string,
|
||||
return data;
|
||||
}
|
||||
|
||||
base::string16 ReadText(ui::ClipboardType type) {
|
||||
base::string16 ReadText(mate::Arguments* args) {
|
||||
base::string16 data;
|
||||
ui::Clipboard::GetForCurrentThread()->ReadText(type, &data);
|
||||
ui::Clipboard::GetForCurrentThread()->ReadText(GetClipboardType(args), &data);
|
||||
return data;
|
||||
}
|
||||
|
||||
void WriteText(const base::string16& text, ui::ClipboardType type) {
|
||||
ui::ScopedClipboardWriter writer(type);
|
||||
void WriteText(const base::string16& text, mate::Arguments* args) {
|
||||
ui::ScopedClipboardWriter writer(GetClipboardType(args));
|
||||
writer.WriteText(text);
|
||||
}
|
||||
|
||||
base::string16 ReadHtml(ui::ClipboardType type) {
|
||||
base::string16 ReadHtml(mate::Arguments* args) {
|
||||
base::string16 data;
|
||||
base::string16 html;
|
||||
std::string url;
|
||||
uint32 start;
|
||||
uint32 end;
|
||||
ui::Clipboard::GetForCurrentThread()->ReadHTML(type, &html, &url,
|
||||
&start, &end);
|
||||
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
|
||||
clipboard->ReadHTML(GetClipboardType(args), &html, &url, &start, &end);
|
||||
data = html.substr(start, end - start);
|
||||
return data;
|
||||
}
|
||||
|
||||
void WriteHtml(const base::string16& html,
|
||||
ui::ClipboardType type) {
|
||||
ui::ScopedClipboardWriter writer(type);
|
||||
void WriteHtml(const base::string16& html, mate::Arguments* args) {
|
||||
ui::ScopedClipboardWriter writer(GetClipboardType(args));
|
||||
writer.WriteHTML(html, std::string());
|
||||
}
|
||||
|
||||
gfx::Image ReadImage(ui::ClipboardType type) {
|
||||
SkBitmap bitmap = ui::Clipboard::GetForCurrentThread()->ReadImage(type);
|
||||
gfx::Image ReadImage(mate::Arguments* args) {
|
||||
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
|
||||
SkBitmap bitmap = clipboard->ReadImage(GetClipboardType(args));
|
||||
return gfx::Image::CreateFrom1xBitmap(bitmap);
|
||||
}
|
||||
|
||||
void WriteImage(const gfx::Image& image, ui::ClipboardType type) {
|
||||
ui::ScopedClipboardWriter writer(type);
|
||||
void WriteImage(const gfx::Image& image, mate::Arguments* args) {
|
||||
ui::ScopedClipboardWriter writer(GetClipboardType(args));
|
||||
writer.WriteImage(image.AsBitmap());
|
||||
}
|
||||
|
||||
void Clear(ui::ClipboardType type) {
|
||||
ui::Clipboard::GetForCurrentThread()->Clear(type);
|
||||
void Clear(mate::Arguments* args) {
|
||||
ui::Clipboard::GetForCurrentThread()->Clear(GetClipboardType(args));
|
||||
}
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
mate::Dictionary dict(context->GetIsolate(), exports);
|
||||
dict.SetMethod("_availableFormats", &AvailableFormats);
|
||||
dict.SetMethod("_has", &Has);
|
||||
dict.SetMethod("_read", &Read);
|
||||
dict.SetMethod("_readText", &ReadText);
|
||||
dict.SetMethod("_writeText", &WriteText);
|
||||
dict.SetMethod("_readHtml", &ReadHtml);
|
||||
dict.SetMethod("_writeHtml", &WriteHtml);
|
||||
dict.SetMethod("_readImage", &ReadImage);
|
||||
dict.SetMethod("_writeImage", &WriteImage);
|
||||
dict.SetMethod("_clear", &Clear);
|
||||
dict.SetMethod("availableFormats", &AvailableFormats);
|
||||
dict.SetMethod("has", &Has);
|
||||
dict.SetMethod("read", &Read);
|
||||
dict.SetMethod("readText", &ReadText);
|
||||
dict.SetMethod("writeText", &WriteText);
|
||||
dict.SetMethod("readHtml", &ReadHtml);
|
||||
dict.SetMethod("writeHtml", &WriteHtml);
|
||||
dict.SetMethod("readImage", &ReadImage);
|
||||
dict.SetMethod("writeImage", &WriteImage);
|
||||
dict.SetMethod("clear", &Clear);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
using crash_reporter::CrashReporter;
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
@@ -31,17 +33,30 @@ struct Converter<std::map<std::string, std::string> > {
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<CrashReporter::UploadReportResult> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const CrashReporter::UploadReportResult& reports) {
|
||||
mate::Dictionary dict(isolate, v8::Object::New(isolate));
|
||||
dict.Set("date", v8::Date::New(isolate, reports.first*1000.0));
|
||||
dict.Set("id", reports.second);
|
||||
return dict.GetHandle();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
using crash_reporter::CrashReporter;
|
||||
mate::Dictionary dict(context->GetIsolate(), exports);
|
||||
auto report = base::Unretained(CrashReporter::GetInstance());
|
||||
dict.SetMethod("start",
|
||||
base::Bind(&CrashReporter::Start,
|
||||
base::Unretained(CrashReporter::GetInstance())));
|
||||
base::Bind(&CrashReporter::Start, report));
|
||||
dict.SetMethod("_getUploadedReports",
|
||||
base::Bind(&CrashReporter::GetUploadedReports, report));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -35,7 +35,7 @@ int32_t IDWeakMap::Add(v8::Isolate* isolate, v8::Local<v8::Object> object) {
|
||||
|
||||
v8::Local<v8::Value> IDWeakMap::Get(v8::Isolate* isolate, int32_t key) {
|
||||
if (!Has(key)) {
|
||||
node::ThrowError("Invalid key");
|
||||
node::ThrowError(isolate, "Invalid key");
|
||||
return v8::Undefined(isolate);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
binding = process.atomBinding 'clipboard'
|
||||
module.exports =
|
||||
availableFormats: (type='standard') -> binding._availableFormats type
|
||||
has: (format, type='standard') -> binding._has format, type
|
||||
read: (format, type='standard') -> binding._read format, type
|
||||
readText: (type='standard') -> binding._readText type
|
||||
writeText: (text, type='standard') -> binding._writeText text, type
|
||||
readHtml: (type='standard') -> binding._readHtml type
|
||||
writeHtml: (markup, type='standard') -> binding._writeHtml markup, type
|
||||
readImage: (type='standard') -> binding._readImage type
|
||||
writeImage: (image, type='standard') -> binding._writeImage image, type
|
||||
clear: (type='standard') -> binding._clear type
|
||||
if process.platform is 'linux' and process.type is 'renderer'
|
||||
# On Linux we could not access clipboard in renderer process.
|
||||
module.exports = require('remote').require 'clipboard'
|
||||
else
|
||||
module.exports = process.atomBinding 'clipboard'
|
||||
|
||||
@@ -41,19 +41,22 @@ class CrashReporter
|
||||
start()
|
||||
|
||||
getLastCrashReport: ->
|
||||
reports = this.getUploadedReports()
|
||||
if reports.length > 0 then reports[0] else null
|
||||
|
||||
getUploadedReports: ->
|
||||
tmpdir =
|
||||
if process.platform is 'win32'
|
||||
os.tmpdir()
|
||||
else
|
||||
'/tmp'
|
||||
log = path.join tmpdir, "#{@productName} Crashes", 'uploads.log'
|
||||
try
|
||||
reports = String(fs.readFileSync(log)).split('\n')
|
||||
return null unless reports.length > 1
|
||||
[time, id] = reports[reports.length - 2].split ','
|
||||
return {date: new Date(parseInt(time) * 1000), id}
|
||||
catch e
|
||||
return null
|
||||
log =
|
||||
if process.platform is 'darwin'
|
||||
path.join tmpdir, "#{@productName} Crashes"
|
||||
else
|
||||
path.join tmpdir, "#{@productName} Crashes", 'uploads.log'
|
||||
binding._getUploadedReports log
|
||||
|
||||
|
||||
crashRepoter = new CrashReporter
|
||||
module.exports = crashRepoter
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
#define ATOM_VERSION_H
|
||||
|
||||
#define ATOM_MAJOR_VERSION 0
|
||||
#define ATOM_MINOR_VERSION 27
|
||||
#define ATOM_PATCH_VERSION 1
|
||||
#define ATOM_MINOR_VERSION 28
|
||||
#define ATOM_PATCH_VERSION 0
|
||||
|
||||
#define ATOM_VERSION_IS_RELEASE 1
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#ifndef ATOM_COMMON_CHROME_VERSION_H_
|
||||
#define ATOM_COMMON_CHROME_VERSION_H_
|
||||
|
||||
#define CHROME_VERSION_STRING "42.0.2311.107"
|
||||
#define CHROME_VERSION_STRING "43.0.2357.65"
|
||||
#define CHROME_VERSION "v" CHROME_VERSION_STRING
|
||||
|
||||
#endif // ATOM_COMMON_CHROME_VERSION_H_
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/common/atom_version.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/strings/string_split.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "content/public/common/content_switches.h"
|
||||
|
||||
namespace crash_reporter {
|
||||
@@ -39,4 +42,26 @@ void CrashReporter::SetUploadParameters(const StringMap& parameters) {
|
||||
SetUploadParameters();
|
||||
}
|
||||
|
||||
std::vector<CrashReporter::UploadReportResult>
|
||||
CrashReporter::GetUploadedReports(const std::string& path) {
|
||||
std::string file_content;
|
||||
std::vector<CrashReporter::UploadReportResult> result;
|
||||
if (base::ReadFileToString(base::FilePath::FromUTF8Unsafe(path),
|
||||
&file_content)) {
|
||||
std::vector<std::string> reports;
|
||||
base::SplitString(file_content, '\n', &reports);
|
||||
for (const std::string& report : reports) {
|
||||
std::vector<std::string> report_item;
|
||||
base::SplitString(report, ',', &report_item);
|
||||
int report_time = 0;
|
||||
if (report_item.size() >= 2 && base::StringToInt(report_item[0],
|
||||
&report_time)) {
|
||||
result.push_back(CrashReporter::UploadReportResult(report_time,
|
||||
report_item[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace crash_reporter
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
@@ -15,6 +17,7 @@ namespace crash_reporter {
|
||||
class CrashReporter {
|
||||
public:
|
||||
typedef std::map<std::string, std::string> StringMap;
|
||||
typedef std::pair<int, std::string> UploadReportResult; // upload-date, id
|
||||
|
||||
static CrashReporter* GetInstance();
|
||||
|
||||
@@ -25,6 +28,9 @@ class CrashReporter {
|
||||
bool skip_system_crash_handler,
|
||||
const StringMap& extra_parameters);
|
||||
|
||||
virtual std::vector<CrashReporter::UploadReportResult> GetUploadedReports(
|
||||
const std::string& path);
|
||||
|
||||
protected:
|
||||
CrashReporter();
|
||||
virtual ~CrashReporter();
|
||||
|
||||
@@ -6,10 +6,13 @@
|
||||
#define ATOM_COMMON_CRASH_REPORTER_CRASH_REPORTER_MAC_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/common/crash_reporter/crash_reporter.h"
|
||||
#include "base/compiler_specific.h"
|
||||
#import "vendor/breakpad/src/client/mac/Framework/Breakpad.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/strings/string_piece.h"
|
||||
#include "vendor/crashpad/client/simple_string_dictionary.h"
|
||||
|
||||
template <typename T> struct DefaultSingletonTraits;
|
||||
|
||||
@@ -33,7 +36,14 @@ class CrashReporterMac : public CrashReporter {
|
||||
CrashReporterMac();
|
||||
virtual ~CrashReporterMac();
|
||||
|
||||
BreakpadRef breakpad_;
|
||||
void SetUploadsEnabled(bool enable_uploads);
|
||||
void SetCrashKeyValue(const base::StringPiece& key,
|
||||
const base::StringPiece& value);
|
||||
|
||||
std::vector<UploadReportResult> GetUploadedReports(
|
||||
const std::string& path) override;
|
||||
|
||||
scoped_ptr<crashpad::SimpleStringDictionary> simple_string_dictionary_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CrashReporterMac);
|
||||
};
|
||||
|
||||
@@ -4,20 +4,25 @@
|
||||
|
||||
#include "atom/common/crash_reporter/crash_reporter_mac.h"
|
||||
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/mac/bundle_locations.h"
|
||||
#include "base/mac/mac_util.h"
|
||||
#include "base/memory/singleton.h"
|
||||
#include "base/strings/string_piece.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#import "vendor/breakpad/src/client/apple/Framework/BreakpadDefines.h"
|
||||
#include "vendor/crashpad/client/crash_report_database.h"
|
||||
#include "vendor/crashpad/client/crashpad_client.h"
|
||||
#include "vendor/crashpad/client/crashpad_info.h"
|
||||
#include "vendor/crashpad/client/settings.h"
|
||||
|
||||
namespace crash_reporter {
|
||||
|
||||
CrashReporterMac::CrashReporterMac()
|
||||
: breakpad_(NULL) {
|
||||
CrashReporterMac::CrashReporterMac() {
|
||||
}
|
||||
|
||||
CrashReporterMac::~CrashReporterMac() {
|
||||
if (breakpad_ != NULL)
|
||||
BreakpadRelease(breakpad_);
|
||||
}
|
||||
|
||||
void CrashReporterMac::InitBreakpad(const std::string& product_name,
|
||||
@@ -26,54 +31,52 @@ void CrashReporterMac::InitBreakpad(const std::string& product_name,
|
||||
const std::string& submit_url,
|
||||
bool auto_submit,
|
||||
bool skip_system_crash_handler) {
|
||||
if (breakpad_ != NULL)
|
||||
BreakpadRelease(breakpad_);
|
||||
|
||||
NSMutableDictionary* parameters =
|
||||
[NSMutableDictionary dictionaryWithCapacity:4];
|
||||
|
||||
[parameters setValue:@ATOM_PRODUCT_NAME
|
||||
forKey:@BREAKPAD_PRODUCT];
|
||||
[parameters setValue:base::SysUTF8ToNSString(product_name)
|
||||
forKey:@BREAKPAD_PRODUCT_DISPLAY];
|
||||
[parameters setValue:base::SysUTF8ToNSString(version)
|
||||
forKey:@BREAKPAD_VERSION];
|
||||
[parameters setValue:base::SysUTF8ToNSString(company_name)
|
||||
forKey:@BREAKPAD_VENDOR];
|
||||
[parameters setValue:base::SysUTF8ToNSString(submit_url)
|
||||
forKey:@BREAKPAD_URL];
|
||||
[parameters setValue:(auto_submit ? @"YES" : @"NO")
|
||||
forKey:@BREAKPAD_SKIP_CONFIRM];
|
||||
[parameters setValue:(skip_system_crash_handler ? @"YES" : @"NO")
|
||||
forKey:@BREAKPAD_SEND_AND_EXIT];
|
||||
|
||||
// Report all crashes (important for testing the crash reporter).
|
||||
[parameters setValue:@"0" forKey:@BREAKPAD_REPORT_INTERVAL];
|
||||
|
||||
// Put dump files under "/tmp/ProductName Crashes".
|
||||
std::string dump_dir = "/tmp/" + product_name + " Crashes";
|
||||
[parameters setValue:base::SysUTF8ToNSString(dump_dir)
|
||||
forKey:@BREAKPAD_DUMP_DIRECTORY];
|
||||
|
||||
// Temporarily run Breakpad in-process on 10.10 and later because APIs that
|
||||
// it depends on got broken (http://crbug.com/386208).
|
||||
// This can catch crashes in the browser process only.
|
||||
if (base::mac::IsOSYosemiteOrLater()) {
|
||||
[parameters setObject:[NSNumber numberWithBool:YES]
|
||||
forKey:@BREAKPAD_IN_PROCESS];
|
||||
}
|
||||
|
||||
breakpad_ = BreakpadCreate(parameters);
|
||||
if (!breakpad_) {
|
||||
LOG(ERROR) << "Failed to initialize breakpad";
|
||||
// check whether crashpad has been initilized.
|
||||
// Only need to initilize once.
|
||||
if (simple_string_dictionary_)
|
||||
return;
|
||||
|
||||
std::string dump_dir = "/tmp/" + product_name + " Crashes";
|
||||
base::FilePath database_path(dump_dir);
|
||||
if (is_browser_) {
|
||||
@autoreleasepool {
|
||||
base::FilePath framework_bundle_path = base::mac::FrameworkBundlePath();
|
||||
base::FilePath handler_path =
|
||||
framework_bundle_path.Append("Resources").Append("crashpad_handler");
|
||||
|
||||
crashpad::CrashpadClient crashpad_client;
|
||||
if (crashpad_client.StartHandler(handler_path, database_path,
|
||||
submit_url,
|
||||
StringMap(),
|
||||
std::vector<std::string>())) {
|
||||
crashpad_client.UseHandler();
|
||||
}
|
||||
} // @autoreleasepool
|
||||
}
|
||||
|
||||
for (StringMap::const_iterator iter = upload_parameters_.begin();
|
||||
iter != upload_parameters_.end(); ++iter) {
|
||||
BreakpadAddUploadParameter(breakpad_,
|
||||
base::SysUTF8ToNSString(iter->first),
|
||||
base::SysUTF8ToNSString(iter->second));
|
||||
crashpad::CrashpadInfo* crashpad_info =
|
||||
crashpad::CrashpadInfo::GetCrashpadInfo();
|
||||
if (skip_system_crash_handler) {
|
||||
crashpad_info->set_system_crash_reporter_forwarding(
|
||||
crashpad::TriState::kDisabled);
|
||||
}
|
||||
|
||||
simple_string_dictionary_.reset(new crashpad::SimpleStringDictionary());
|
||||
crashpad_info->set_simple_annotations(simple_string_dictionary_.get());
|
||||
|
||||
SetCrashKeyValue("prod", ATOM_PRODUCT_NAME);
|
||||
SetCrashKeyValue("process_type", is_browser_ ? "browser" : "renderer");
|
||||
SetCrashKeyValue("ver", version);
|
||||
|
||||
for (const auto& upload_parameter: upload_parameters_) {
|
||||
SetCrashKeyValue(upload_parameter.first, upload_parameter.second);
|
||||
}
|
||||
if (is_browser_) {
|
||||
scoped_ptr<crashpad::CrashReportDatabase> database =
|
||||
crashpad::CrashReportDatabase::Initialize(database_path);
|
||||
if (database) {
|
||||
database->GetSettings()->SetUploadsEnabled(auto_submit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,6 +84,46 @@ void CrashReporterMac::SetUploadParameters() {
|
||||
upload_parameters_["platform"] = "darwin";
|
||||
}
|
||||
|
||||
void CrashReporterMac::SetCrashKeyValue(const base::StringPiece& key,
|
||||
const base::StringPiece& value) {
|
||||
simple_string_dictionary_->SetKeyValue(key.data(), value.data());
|
||||
}
|
||||
|
||||
std::vector<CrashReporter::UploadReportResult>
|
||||
CrashReporterMac::GetUploadedReports(const std::string& path) {
|
||||
std::vector<CrashReporter::UploadReportResult> uploaded_reports;
|
||||
|
||||
base::FilePath file_path(path);
|
||||
if (!base::PathExists(file_path)) {
|
||||
return uploaded_reports;
|
||||
}
|
||||
// Load crashpad database.
|
||||
scoped_ptr<crashpad::CrashReportDatabase> database =
|
||||
crashpad::CrashReportDatabase::Initialize(file_path);
|
||||
DCHECK(database);
|
||||
|
||||
std::vector<crashpad::CrashReportDatabase::Report> completed_reports;
|
||||
crashpad::CrashReportDatabase::OperationStatus status =
|
||||
database->GetCompletedReports(&completed_reports);
|
||||
if (status != crashpad::CrashReportDatabase::kNoError) {
|
||||
return uploaded_reports;
|
||||
}
|
||||
|
||||
for (const crashpad::CrashReportDatabase::Report& completed_report :
|
||||
completed_reports) {
|
||||
if (completed_report.uploaded) {
|
||||
uploaded_reports.push_back(
|
||||
UploadReportResult(static_cast<int>(completed_report.creation_time),
|
||||
completed_report.id));
|
||||
}
|
||||
}
|
||||
|
||||
auto sort_by_time = [](const UploadReportResult& a,
|
||||
const UploadReportResult& b) {return a.first >= b.first;};
|
||||
std::sort(uploaded_reports.begin(), uploaded_reports.end(), sort_by_time);
|
||||
return uploaded_reports;
|
||||
}
|
||||
|
||||
// static
|
||||
CrashReporterMac* CrashReporterMac::GetInstance() {
|
||||
return Singleton<CrashReporterMac>::get();
|
||||
|
||||
@@ -14,7 +14,7 @@ getOrCreateArchive = (p) ->
|
||||
|
||||
# Clean cache on quit.
|
||||
process.on 'exit', ->
|
||||
archive.destroy() for p, archive of cachedArchives
|
||||
archive.destroy() for own p, archive of cachedArchives
|
||||
|
||||
# Separate asar package's path from full path.
|
||||
splitPath = (p) ->
|
||||
@@ -310,6 +310,38 @@ exports.wrapFsWithAsar = (fs) ->
|
||||
|
||||
files
|
||||
|
||||
internalModuleReadFile = process.binding('fs').internalModuleReadFile
|
||||
process.binding('fs').internalModuleReadFile = (p) ->
|
||||
[isAsar, asarPath, filePath] = splitPath p
|
||||
return internalModuleReadFile p unless isAsar
|
||||
|
||||
archive = getOrCreateArchive asarPath
|
||||
return undefined unless archive
|
||||
|
||||
info = archive.getFileInfo filePath
|
||||
return undefined unless info
|
||||
return '' if info.size is 0
|
||||
|
||||
buffer = new Buffer(info.size)
|
||||
fd = archive.getFd()
|
||||
retrun undefined unless fd >= 0
|
||||
|
||||
fs.readSync fd, buffer, 0, info.size, info.offset
|
||||
buffer.toString 'utf8'
|
||||
|
||||
internalModuleStat = process.binding('fs').internalModuleStat
|
||||
process.binding('fs').internalModuleStat = (p) ->
|
||||
[isAsar, asarPath, filePath] = splitPath p
|
||||
return internalModuleStat p unless isAsar
|
||||
|
||||
archive = getOrCreateArchive asarPath
|
||||
return -34 unless archive # -ENOENT
|
||||
|
||||
stats = archive.stat filePath
|
||||
return -34 unless stats # -ENOENT
|
||||
|
||||
if stats.isDirectory then return 1 else return 0
|
||||
|
||||
overrideAPI fs, 'open'
|
||||
overrideAPI child_process, 'execFile'
|
||||
overrideAPISync process, 'dlopen', 1
|
||||
|
||||
@@ -23,6 +23,13 @@ bool Converter<base::DictionaryValue>::FromV8(v8::Isolate* isolate,
|
||||
}
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> Converter<base::DictionaryValue>::ToV8(
|
||||
v8::Isolate* isolate,
|
||||
const base::DictionaryValue& val) {
|
||||
scoped_ptr<atom::V8ValueConverter> converter(new atom::V8ValueConverter);
|
||||
return converter->ToV8Value(&val, isolate->GetCurrentContext());
|
||||
}
|
||||
|
||||
bool Converter<base::ListValue>::FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
base::ListValue* out) {
|
||||
|
||||
@@ -19,6 +19,8 @@ struct Converter<base::DictionaryValue> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
base::DictionaryValue* out);
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const base::DictionaryValue& val);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -27,7 +29,7 @@ struct Converter<base::ListValue> {
|
||||
v8::Local<v8::Value> val,
|
||||
base::ListValue* out);
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const base::ListValue& val);
|
||||
const base::ListValue& val);
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
@@ -178,6 +178,9 @@ void NodeBindings::LoadEnvironment(node::Environment* env) {
|
||||
|
||||
if (node::use_debug_agent)
|
||||
node::EnableDebug(env);
|
||||
|
||||
v8::Local<v8::Value> msg = mate::StringToV8(env->isolate(), "loaded");
|
||||
node::MakeCallback(env->isolate(), env->process_object(), "emit", 1, &msg);
|
||||
}
|
||||
|
||||
void NodeBindings::PrepareMessageLoop() {
|
||||
|
||||
@@ -87,6 +87,9 @@ const char kDisableAutoHideCursor[] = "disable-auto-hide-cursor";
|
||||
// Use the OS X's standard window instead of the textured window.
|
||||
const char kStandardWindow[] = "standard-window";
|
||||
|
||||
// Path to client certificate.
|
||||
const char kClientCertificate[] = "client-certificate";
|
||||
|
||||
// Web runtime features.
|
||||
const char kExperimentalFeatures[] = "experimental-features";
|
||||
const char kExperimentalCanvasFeatures[] = "experimental-canvas-features";
|
||||
@@ -95,6 +98,9 @@ const char kOverlayScrollbars[] = "overlay-scrollbars";
|
||||
const char kOverlayFullscreenVideo[] = "overlay-fullscreen-video";
|
||||
const char kSharedWorker[] = "shared-worker";
|
||||
|
||||
// Set page visiblity to always visible.
|
||||
const char kPageVisibility[] = "page-visibility";
|
||||
|
||||
// Disable HTTP cache.
|
||||
const char kDisableHttpCache[] = "disable-http-cache";
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ extern const char kTransparent[];
|
||||
extern const char kType[];
|
||||
extern const char kDisableAutoHideCursor[];
|
||||
extern const char kStandardWindow[];
|
||||
extern const char kClientCertificate[];
|
||||
|
||||
extern const char kExperimentalFeatures[];
|
||||
extern const char kExperimentalCanvasFeatures[];
|
||||
@@ -52,6 +53,7 @@ extern const char kSubpixelFontScaling[];
|
||||
extern const char kOverlayScrollbars[];
|
||||
extern const char kOverlayFullscreenVideo[];
|
||||
extern const char kSharedWorker[];
|
||||
extern const char kPageVisibility[];
|
||||
|
||||
extern const char kDisableHttpCache[];
|
||||
|
||||
|
||||
@@ -30,7 +30,9 @@ RenderView* GetCurrentRenderView() {
|
||||
return RenderView::FromWebView(view);
|
||||
}
|
||||
|
||||
void Send(const base::string16& channel, const base::ListValue& arguments) {
|
||||
void Send(v8::Isolate* isolate,
|
||||
const base::string16& channel,
|
||||
const base::ListValue& arguments) {
|
||||
RenderView* render_view = GetCurrentRenderView();
|
||||
if (render_view == NULL)
|
||||
return;
|
||||
@@ -39,10 +41,11 @@ void Send(const base::string16& channel, const base::ListValue& arguments) {
|
||||
render_view->GetRoutingID(), channel, arguments));
|
||||
|
||||
if (!success)
|
||||
node::ThrowError("Unable to send AtomViewHostMsg_Message");
|
||||
node::ThrowError(isolate, "Unable to send AtomViewHostMsg_Message");
|
||||
}
|
||||
|
||||
base::string16 SendSync(const base::string16& channel,
|
||||
base::string16 SendSync(v8::Isolate* isolate,
|
||||
const base::string16& channel,
|
||||
const base::ListValue& arguments) {
|
||||
base::string16 json;
|
||||
|
||||
@@ -57,7 +60,7 @@ base::string16 SendSync(const base::string16& channel,
|
||||
bool success = render_view->Send(message);
|
||||
|
||||
if (!success)
|
||||
node::ThrowError("Unable to send AtomViewHostMsg_Message_Sync");
|
||||
node::ThrowError(isolate, "Unable to send AtomViewHostMsg_Message_Sync");
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
@@ -10,9 +10,11 @@
|
||||
#define USE(WTF_FEATURE) (defined WTF_USE_##WTF_FEATURE && WTF_USE_##WTF_FEATURE) // NOLINT
|
||||
#define ENABLE(WTF_FEATURE) (defined ENABLE_##WTF_FEATURE && ENABLE_##WTF_FEATURE) // NOLINT
|
||||
|
||||
#include "atom/common/native_mate_converters/gfx_converter.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "atom/renderer/api/atom_api_spell_check_client.h"
|
||||
#include "content/public/renderer/render_frame.h"
|
||||
#include "native_mate/callback.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
#include "third_party/WebKit/public/web/WebDocument.h"
|
||||
@@ -78,6 +80,14 @@ v8::Local<v8::Value> WebFrame::RegisterEmbedderCustomElement(
|
||||
return web_frame_->document().registerEmbedderCustomElement(name, options, c);
|
||||
}
|
||||
|
||||
void WebFrame::RegisterElementResizeCallback(
|
||||
int element_instance_id,
|
||||
const GuestViewContainer::ResizeCallback& callback) {
|
||||
auto guest_view_container = GuestViewContainer::FromID(element_instance_id);
|
||||
if (guest_view_container)
|
||||
guest_view_container->RegisterElementResizeCallback(callback);
|
||||
}
|
||||
|
||||
void WebFrame::AttachGuest(int id) {
|
||||
content::RenderFrame::FromWebFrame(web_frame_)->AttachGuest(id);
|
||||
}
|
||||
@@ -106,6 +116,8 @@ mate::ObjectTemplateBuilder WebFrame::GetObjectTemplateBuilder(
|
||||
.SetMethod("getZoomFactor", &WebFrame::GetZoomFactor)
|
||||
.SetMethod("registerEmbedderCustomElement",
|
||||
&WebFrame::RegisterEmbedderCustomElement)
|
||||
.SetMethod("registerElementResizeCallback",
|
||||
&WebFrame::RegisterElementResizeCallback)
|
||||
.SetMethod("attachGuest", &WebFrame::AttachGuest)
|
||||
.SetMethod("setSpellCheckProvider", &WebFrame::SetSpellCheckProvider)
|
||||
.SetMethod("registerUrlSchemeAsSecure",
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/renderer/guest_view_container.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "native_mate/wrappable.h"
|
||||
@@ -42,6 +43,9 @@ class WebFrame : public mate::Wrappable {
|
||||
|
||||
v8::Local<v8::Value> RegisterEmbedderCustomElement(
|
||||
const base::string16& name, v8::Local<v8::Object> options);
|
||||
void RegisterElementResizeCallback(
|
||||
int element_instance_id,
|
||||
const GuestViewContainer::ResizeCallback& callback);
|
||||
void AttachGuest(int element_instance_id);
|
||||
|
||||
// Set the provider that will be used by SpellCheckClient for spell check.
|
||||
|
||||
@@ -10,6 +10,8 @@ wrapArgs = (args) ->
|
||||
valueToMeta = (value) ->
|
||||
if Array.isArray value
|
||||
type: 'array', value: wrapArgs(value)
|
||||
else if Buffer.isBuffer value
|
||||
type: 'buffer', value: Array::slice.call(value, 0)
|
||||
else if value? and typeof value is 'object' and v8Util.getHiddenValue value, 'atomId'
|
||||
type: 'remote-object', id: v8Util.getHiddenValue value, 'atomId'
|
||||
else if value? and typeof value is 'object'
|
||||
@@ -30,6 +32,7 @@ metaToValue = (meta) ->
|
||||
switch meta.type
|
||||
when 'value' then meta.value
|
||||
when 'array' then (metaToValue(el) for el in meta.members)
|
||||
when 'buffer' then new Buffer(meta.value)
|
||||
when 'error'
|
||||
throw new Error("#{meta.message}\n#{meta.stack}")
|
||||
else
|
||||
|
||||
@@ -191,6 +191,21 @@ content::BrowserPluginDelegate* AtomRendererClient::CreateBrowserPluginDelegate(
|
||||
}
|
||||
}
|
||||
|
||||
bool AtomRendererClient::ShouldOverridePageVisibilityState(
|
||||
const content::RenderFrame* render_frame,
|
||||
blink::WebPageVisibilityState* override_state) {
|
||||
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
||||
bool b;
|
||||
|
||||
if (IsSwitchEnabled(command_line, switches::kPageVisibility, &b)
|
||||
&& b) {
|
||||
*override_state = blink::WebPageVisibilityStateVisible;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void AtomRendererClient::EnableWebRuntimeFeatures() {
|
||||
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
||||
bool b;
|
||||
|
||||
@@ -55,6 +55,9 @@ class AtomRendererClient : public content::ContentRendererClient,
|
||||
content::RenderFrame* render_frame,
|
||||
const std::string& mime_type,
|
||||
const GURL& original_url) override;
|
||||
bool ShouldOverridePageVisibilityState(
|
||||
const content::RenderFrame* render_frame,
|
||||
blink::WebPageVisibilityState* override_state) override;
|
||||
|
||||
void EnableWebRuntimeFeatures();
|
||||
|
||||
|
||||
@@ -4,12 +4,54 @@
|
||||
|
||||
#include "atom/renderer/guest_view_container.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "base/lazy_instance.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
GuestViewContainer::GuestViewContainer(content::RenderFrame* render_frame) {
|
||||
namespace {
|
||||
|
||||
using GuestViewContainerMap = std::map<int, GuestViewContainer*>;
|
||||
static base::LazyInstance<GuestViewContainerMap> g_guest_view_container_map =
|
||||
LAZY_INSTANCE_INITIALIZER;
|
||||
|
||||
} // namespace
|
||||
|
||||
GuestViewContainer::GuestViewContainer(content::RenderFrame* render_frame)
|
||||
: render_frame_(render_frame) {
|
||||
}
|
||||
|
||||
GuestViewContainer::~GuestViewContainer() {
|
||||
if (element_instance_id_ > 0)
|
||||
g_guest_view_container_map.Get().erase(element_instance_id_);
|
||||
}
|
||||
|
||||
// static
|
||||
GuestViewContainer* GuestViewContainer::FromID(int element_instance_id) {
|
||||
GuestViewContainerMap* guest_view_containers =
|
||||
g_guest_view_container_map.Pointer();
|
||||
auto it = guest_view_containers->find(element_instance_id);
|
||||
return it == guest_view_containers->end() ? nullptr : it->second;
|
||||
}
|
||||
|
||||
void GuestViewContainer::RegisterElementResizeCallback(
|
||||
const ResizeCallback& callback) {
|
||||
element_resize_callback_ = callback;
|
||||
}
|
||||
|
||||
void GuestViewContainer::SetElementInstanceID(int element_instance_id) {
|
||||
element_instance_id_ = element_instance_id;
|
||||
g_guest_view_container_map.Get().insert(
|
||||
std::make_pair(element_instance_id, this));
|
||||
}
|
||||
|
||||
void GuestViewContainer::DidResizeElement(const gfx::Size& old_size,
|
||||
const gfx::Size& new_size) {
|
||||
if (element_resize_callback_.is_null())
|
||||
return;
|
||||
|
||||
element_resize_callback_.Run(old_size, new_size);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -5,17 +5,38 @@
|
||||
#ifndef ATOM_RENDERER_GUEST_VIEW_CONTAINER_H_
|
||||
#define ATOM_RENDERER_GUEST_VIEW_CONTAINER_H_
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "content/public/renderer/browser_plugin_delegate.h"
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
namespace gfx {
|
||||
class Size;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class GuestViewContainer : public content::BrowserPluginDelegate {
|
||||
public:
|
||||
typedef base::Callback<void(const gfx::Size&, const gfx::Size&)>
|
||||
ResizeCallback;
|
||||
|
||||
explicit GuestViewContainer(content::RenderFrame* render_frame);
|
||||
~GuestViewContainer() override;
|
||||
|
||||
static GuestViewContainer* FromID(int element_instance_id);
|
||||
|
||||
void RegisterElementResizeCallback(const ResizeCallback& callback);
|
||||
|
||||
// content::BrowserPluginDelegate:
|
||||
void SetElementInstanceID(int element_instance_id) final;
|
||||
void DidResizeElement(const gfx::Size& old_size,
|
||||
const gfx::Size& new_size) final;
|
||||
|
||||
private:
|
||||
int element_instance_id_;
|
||||
content::RenderFrame* render_frame_;
|
||||
|
||||
ResizeCallback element_resize_callback_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(GuestViewContainer);
|
||||
};
|
||||
|
||||
|
||||
@@ -88,12 +88,8 @@ if nodeIntegration in ['true', 'all', 'except-iframe', 'manual-enable-iframe']
|
||||
window.addEventListener 'unload', ->
|
||||
process.emit 'exit'
|
||||
else
|
||||
# The Module.runMain will run process._tickCallck() immediately, so we are
|
||||
# able to delete the symbols in this tick even though we used process.nextTick
|
||||
# to schedule it.
|
||||
# It is important that we put this in process.nextTick, if we delete them now
|
||||
# some code in node.js will complain about "process not defined".
|
||||
process.nextTick ->
|
||||
# Delete Node's symbols after the Environment has been loaded.
|
||||
process.once 'loaded', ->
|
||||
delete global.process
|
||||
delete global.setImmediate
|
||||
delete global.clearImmediate
|
||||
|
||||
@@ -62,6 +62,7 @@ window.open = (url, frameName='', features='') ->
|
||||
window.alert = (message, title='') ->
|
||||
dialog = remote.require 'dialog'
|
||||
buttons = ['OK']
|
||||
message = message.toString()
|
||||
dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons}
|
||||
|
||||
# And the confirm().
|
||||
|
||||
@@ -55,9 +55,9 @@ module.exports =
|
||||
ipc.removeAllListeners "ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-#{viewInstanceId}"
|
||||
ipc.removeAllListeners "ATOM_SHELL_GUEST_VIEW_INTERNAL_SIZE_CHANGED-#{viewInstanceId}"
|
||||
|
||||
createGuest: (type, params, callback) ->
|
||||
createGuest: (params, callback) ->
|
||||
requestId++
|
||||
ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', type, params, requestId
|
||||
ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', params, requestId
|
||||
ipc.once "ATOM_SHELL_RESPONSE_#{requestId}", callback
|
||||
|
||||
attachGuest: (elementInstanceId, guestInstanceId, params) ->
|
||||
@@ -67,8 +67,8 @@ module.exports =
|
||||
destroyGuest: (guestInstanceId) ->
|
||||
ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', guestInstanceId
|
||||
|
||||
setAutoSize: (guestInstanceId, params) ->
|
||||
ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_AUTO_SIZE', guestInstanceId, params
|
||||
setSize: (guestInstanceId, params) ->
|
||||
ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_SIZE', guestInstanceId, params
|
||||
|
||||
setAllowTransparency: (guestInstanceId, allowtransparency) ->
|
||||
ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_ALLOW_TRANSPARENCY', guestInstanceId, allowtransparency
|
||||
|
||||
@@ -28,7 +28,7 @@ class WebViewAttribute
|
||||
# Changes the attribute's value without triggering its mutation handler.
|
||||
setValueIgnoreMutation: (value) ->
|
||||
@ignoreMutation = true
|
||||
@webViewImpl.webviewNode.setAttribute(@name, value || '')
|
||||
@setValue value
|
||||
@ignoreMutation = false
|
||||
|
||||
# Defines this attribute as a property on the webview node.
|
||||
@@ -72,7 +72,7 @@ class AutosizeDimensionAttribute extends WebViewAttribute
|
||||
|
||||
handleMutation: (oldValue, newValue) ->
|
||||
return unless @webViewImpl.guestInstanceId
|
||||
guestViewInternal.setAutoSize @webViewImpl.guestInstanceId,
|
||||
guestViewInternal.setSize @webViewImpl.guestInstanceId,
|
||||
enableAutoSize: @webViewImpl.attributes[webViewConstants.ATTRIBUTE_AUTOSIZE].getValue()
|
||||
min:
|
||||
width: parseInt @webViewImpl.attributes[webViewConstants.ATTRIBUTE_MINWIDTH].getValue() || 0
|
||||
@@ -119,6 +119,14 @@ class SrcAttribute extends WebViewAttribute
|
||||
else
|
||||
''
|
||||
|
||||
setValueIgnoreMutation: (value) ->
|
||||
WebViewAttribute::setValueIgnoreMutation value
|
||||
# takeRecords() is needed to clear queued up src mutations. Without it, it
|
||||
# is possible for this change to get picked up asyncronously by src's
|
||||
# mutation observer |observer|, and then get handled even though we do not
|
||||
# want to handle this mutation.
|
||||
@observer.takeRecords()
|
||||
|
||||
handleMutation: (oldValue, newValue) ->
|
||||
# Once we have navigated, we don't allow clearing the src attribute.
|
||||
# Once <webview> enters a navigated state, it cannot return to a
|
||||
@@ -138,7 +146,10 @@ class SrcAttribute extends WebViewAttribute
|
||||
setupMutationObserver: ->
|
||||
@observer = new MutationObserver (mutations) =>
|
||||
for mutation in mutations
|
||||
@handleMutation mutation.oldValue, @getValue()
|
||||
oldValue = mutation.oldValue
|
||||
newValue = @getValue()
|
||||
return if oldValue isnt newValue
|
||||
@handleMutation oldValue, newValue
|
||||
params =
|
||||
attributes: true,
|
||||
attributeOldValue: true,
|
||||
@@ -160,10 +171,10 @@ class SrcAttribute extends WebViewAttribute
|
||||
# Navigate to |this.src|.
|
||||
opts = {}
|
||||
httpreferrer = @webViewImpl.attributes[webViewConstants.ATTRIBUTE_HTTPREFERRER].getValue()
|
||||
if httpreferrer then opts.httpreferrer = httpreferrer
|
||||
if httpreferrer then opts.httpReferrer = httpreferrer
|
||||
|
||||
useragent = @webViewImpl.attributes[webViewConstants.ATTRIBUTE_USERAGENT].getValue()
|
||||
if useragent then opts.useragent = useragent
|
||||
if useragent then opts.userAgent = useragent
|
||||
|
||||
guestContents = remote.getGuestWebContents(@webViewImpl.guestInstanceId)
|
||||
guestContents.loadUrl @getValue(), opts
|
||||
|
||||
@@ -13,7 +13,6 @@ class WebViewImpl
|
||||
constructor: (@webviewNode) ->
|
||||
v8Util.setHiddenValue @webviewNode, 'internal', this
|
||||
@attached = false
|
||||
@pendingGuestCreation = false
|
||||
@elementAttached = false
|
||||
|
||||
@beforeFirstNavigation = true
|
||||
@@ -87,9 +86,12 @@ class WebViewImpl
|
||||
@browserPluginNode.removeAttribute webViewConstants.ATTRIBUTE_INTERNALINSTANCEID
|
||||
@internalInstanceId = parseInt newValue
|
||||
|
||||
# Track when the element resizes using the element resize callback.
|
||||
webFrame.registerElementResizeCallback @internalInstanceId, @onElementResize.bind(this)
|
||||
|
||||
return unless @guestInstanceId
|
||||
|
||||
guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, @buildAttachParams()
|
||||
guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, @buildParams()
|
||||
|
||||
onSizeChanged: (webViewEvent) ->
|
||||
newWidth = webViewEvent.newWidth
|
||||
@@ -107,6 +109,9 @@ class WebViewImpl
|
||||
minWidth = @attributes[webViewConstants.ATTRIBUTE_MINWIDTH].getValue() | width
|
||||
minHeight = @attributes[webViewConstants.ATTRIBUTE_MINHEIGHT].getValue() | width
|
||||
|
||||
minWidth = Math.min minWidth, maxWidth
|
||||
minHeight = Math.min minHeight, maxHeight
|
||||
|
||||
if not @attributes[webViewConstants.ATTRIBUTE_AUTOSIZE].getValue() or
|
||||
(newWidth >= minWidth and
|
||||
newWidth <= maxWidth and
|
||||
@@ -118,17 +123,21 @@ class WebViewImpl
|
||||
# changed.
|
||||
@dispatchEvent webViewEvent
|
||||
|
||||
onElementResize: (oldSize, newSize) ->
|
||||
# Dispatch the 'resize' event.
|
||||
resizeEvent = new Event('resize', bubbles: true)
|
||||
resizeEvent.oldWidth = oldSize.width
|
||||
resizeEvent.oldHeight = oldSize.height
|
||||
resizeEvent.newWidth = newSize.width
|
||||
resizeEvent.newHeight = newSize.height
|
||||
@dispatchEvent resizeEvent
|
||||
|
||||
if @guestInstanceId
|
||||
guestViewInternal.setSize @guestInstanceId, normal: newSize
|
||||
|
||||
createGuest: ->
|
||||
return if @pendingGuestCreation
|
||||
params =
|
||||
storagePartitionId: @attributes[webViewConstants.ATTRIBUTE_PARTITION].getValue()
|
||||
guestViewInternal.createGuest 'webview', params, (guestInstanceId) =>
|
||||
@pendingGuestCreation = false
|
||||
unless @elementAttached
|
||||
guestViewInternal.destroyGuest guestInstanceId
|
||||
return
|
||||
guestViewInternal.createGuest @buildParams(), (guestInstanceId) =>
|
||||
@attachWindow guestInstanceId
|
||||
@pendingGuestCreation = true
|
||||
|
||||
dispatchEvent: (webViewEvent) ->
|
||||
@webviewNode.dispatchEvent webViewEvent
|
||||
@@ -160,21 +169,30 @@ class WebViewImpl
|
||||
onAttach: (storagePartitionId) ->
|
||||
@attributes[webViewConstants.ATTRIBUTE_PARTITION].setValue storagePartitionId
|
||||
|
||||
buildAttachParams: ->
|
||||
buildParams: ->
|
||||
params =
|
||||
instanceId: @viewInstanceId
|
||||
userAgentOverride: @userAgentOverride
|
||||
for attributeName, attribute of @attributes
|
||||
for own attributeName, attribute of @attributes
|
||||
params[attributeName] = attribute.getValue()
|
||||
# When the WebView is not participating in layout (display:none)
|
||||
# then getBoundingClientRect() would report a width and height of 0.
|
||||
# However, in the case where the WebView has a fixed size we can
|
||||
# use that value to initially size the guest so as to avoid a relayout of
|
||||
# the on display:block.
|
||||
css = window.getComputedStyle @webviewNode, null
|
||||
elementRect = @webviewNode.getBoundingClientRect()
|
||||
params.elementWidth = parseInt(elementRect.width) ||
|
||||
parseInt(css.getPropertyValue('width'))
|
||||
params.elementHeight = parseInt(elementRect.height) ||
|
||||
parseInt(css.getPropertyValue('height'))
|
||||
params
|
||||
|
||||
attachWindow: (guestInstanceId) ->
|
||||
@guestInstanceId = guestInstanceId
|
||||
params = @buildAttachParams()
|
||||
|
||||
return true unless @internalInstanceId
|
||||
|
||||
guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, params
|
||||
guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, @buildParams()
|
||||
|
||||
# Registers browser plugin <object> custom element.
|
||||
registerBrowserPluginElement = ->
|
||||
|
||||
@@ -31,8 +31,11 @@ class PdfFunctions {
|
||||
render_pdf_to_dc_func_(NULL) {}
|
||||
|
||||
bool Init() {
|
||||
base::FilePath pdf_module_path(FILE_PATH_LITERAL("pdf.dll"));
|
||||
pdf_lib_.Reset(base::LoadNativeLibrary(pdf_module_path, NULL));
|
||||
base::FilePath module_path;
|
||||
if (!PathService::Get(base::DIR_MODULE, &module_path))
|
||||
return false;
|
||||
base::FilePath::StringType name(FILE_PATH_LITERAL("pdf.dll"));
|
||||
pdf_lib_.Reset(base::LoadNativeLibrary(module_path.Append(name), NULL));
|
||||
if (!pdf_lib_.is_valid()) {
|
||||
LOG(WARNING) << "Couldn't load PDF plugin";
|
||||
return false;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
'component%': 'static_library',
|
||||
'python': 'python',
|
||||
'openssl_no_asm': 1,
|
||||
'node_target_type': 'shared_library',
|
||||
'node_install_npm': 'false',
|
||||
'node_prefix': '',
|
||||
'node_shared_cares': 'false',
|
||||
@@ -26,6 +27,7 @@
|
||||
'uv_library': 'static_library',
|
||||
'uv_parent_path': 'vendor/node/deps/uv',
|
||||
'uv_use_dtrace': 'false',
|
||||
'V8_BASE': '',
|
||||
'v8_postmortem_support': 'false',
|
||||
'v8_enable_i18n_support': 'false',
|
||||
# Required by Linux (empty for now, should support it in future).
|
||||
@@ -99,7 +101,10 @@
|
||||
],
|
||||
}],
|
||||
['_target_name=="node"', {
|
||||
'include_dirs': [ '<(libchromiumcontent_src_dir)/v8/include' ],
|
||||
'include_dirs': [
|
||||
'<(libchromiumcontent_src_dir)/v8',
|
||||
'<(libchromiumcontent_src_dir)/v8/include',
|
||||
],
|
||||
'conditions': [
|
||||
['OS=="mac" and libchromiumcontent_component==0', {
|
||||
# -all_load is the "whole-archive" on OS X.
|
||||
|
||||
@@ -43,7 +43,7 @@ You can also create a window without chrome by using
|
||||
other windows
|
||||
* `fullscreen` Boolean - Whether the window should show in fullscreen, when
|
||||
set to `false` the fullscreen button would also be hidden on OS X
|
||||
* `skip-taskbar` Boolean - Do not show window in Taskbar
|
||||
* `skip-taskbar` Boolean - Do not show window in taskbar
|
||||
* `zoom-factor` Number - The default zoom factor of the page, zoom factor is
|
||||
zoom percent / 100, so `3.0` represents `300%`
|
||||
* `kiosk` Boolean - The kiosk mode
|
||||
@@ -97,6 +97,10 @@ You can also create a window without chrome by using
|
||||
* `shared-worker` Boolean
|
||||
* `direct-write` Boolean - Whether the DirectWrite font rendering system on
|
||||
Windows is enabled
|
||||
* `page-visibility` Boolean - Page would be forced to be always in visible
|
||||
or hidden state once set, instead of reflecting current window's
|
||||
visibility. Users can set it to `true` to prevent throttling of DOM
|
||||
timers.
|
||||
|
||||
Creates a new `BrowserWindow` with native properties set by the `options`.
|
||||
Usually you only need to set the `width` and `height`, other properties will
|
||||
@@ -127,9 +131,9 @@ window.onbeforeunload = function(e) {
|
||||
console.log('I do not want to be closed');
|
||||
|
||||
// Unlike usual browsers, in which a string should be returned and the user is
|
||||
// prompted to confirm the page unload. Electron gives the power completely
|
||||
// to the developers, return empty string or false would prevent the unloading
|
||||
// now. You can also use the dialog API to let user confirm it.
|
||||
// prompted to confirm the page unload, Electron gives developers more options.
|
||||
// Returning empty string or false would prevent the unloading now.
|
||||
// You can also use the dialog API to let the user confirm closing the application.
|
||||
return false;
|
||||
};
|
||||
```
|
||||
@@ -460,7 +464,7 @@ Starts or stops flashing the window to attract user's attention.
|
||||
|
||||
* `skip` Boolean
|
||||
|
||||
Makes the window do not show in Taskbar.
|
||||
Makes the window not show in the taskbar.
|
||||
|
||||
### BrowserWindow.setKiosk(flag)
|
||||
|
||||
@@ -479,13 +483,13 @@ Returns whether the window is in kiosk mode.
|
||||
Sets the pathname of the file the window represents, and the icon of the file
|
||||
will show in window's title bar.
|
||||
|
||||
__Note__: This API is available only on OS X.
|
||||
__Note__: This API is only available on OS X.
|
||||
|
||||
### BrowserWindow.getRepresentedFilename()
|
||||
|
||||
Returns the pathname of the file the window represents.
|
||||
|
||||
__Note__: This API is available only on OS X.
|
||||
__Note__: This API is only available on OS X.
|
||||
|
||||
### BrowserWindow.setDocumentEdited(edited)
|
||||
|
||||
@@ -494,13 +498,13 @@ __Note__: This API is available only on OS X.
|
||||
Specifies whether the window’s document has been edited, and the icon in title
|
||||
bar will become grey when set to `true`.
|
||||
|
||||
__Note__: This API is available only on OS X.
|
||||
__Note__: This API is only available on OS X.
|
||||
|
||||
### BrowserWindow.IsDocumentEdited()
|
||||
|
||||
Whether the window's document has been edited.
|
||||
|
||||
__Note__: This API is available only on OS X.
|
||||
__Note__: This API is only available on OS X.
|
||||
|
||||
### BrowserWindow.openDevTools([options])
|
||||
|
||||
@@ -567,9 +571,9 @@ Calling `window.print()` in web page is equivalent to call
|
||||
doesn't need print feature, you can safely remove `pdf.dll` in saving binary
|
||||
size.
|
||||
|
||||
### BrowserWindow.loadUrl(url)
|
||||
### BrowserWindow.loadUrl(url, [options])
|
||||
|
||||
Same with `webContents.loadUrl(url)`.
|
||||
Same with `webContents.loadUrl(url, [options])`.
|
||||
|
||||
### BrowserWindow.reload()
|
||||
|
||||
@@ -579,7 +583,8 @@ Same with `webContents.reload`.
|
||||
|
||||
* `menu` Menu
|
||||
|
||||
Sets the `menu` as the window top menu.
|
||||
Sets the `menu` as the window's menu bar, setting it to `null` will remove the
|
||||
menu bar.
|
||||
|
||||
__Note:__ This API is not available on OS X.
|
||||
|
||||
@@ -599,20 +604,20 @@ it will assume `app.getName().desktop`.
|
||||
### BrowserWindow.setOverlayIcon(overlay, description)
|
||||
|
||||
* `overlay` [NativeImage](native-image.md) - the icon to display on the bottom
|
||||
right corner of the Taskbar icon. If this parameter is `null`, the overlay is
|
||||
right corner of the taskbar icon. If this parameter is `null`, the overlay is
|
||||
cleared
|
||||
* `description` String - a description that will be provided to Accessibility
|
||||
screen readers
|
||||
|
||||
Sets a 16px overlay onto the current Taskbar icon, usually used to convey some sort of application status or to passively notify the user.
|
||||
Sets a 16px overlay onto the current taskbar icon, usually used to convey some sort of application status or to passively notify the user.
|
||||
|
||||
__Note:__ This API is only available on Windows, Win7 or above
|
||||
__Note:__ This API is only available on Windows (Windows 7 and above)
|
||||
|
||||
### BrowserWindow.showDefinitionForSelection()
|
||||
|
||||
Shows pop-up dictionary that searches the selected word on the page.
|
||||
|
||||
__Note__: This API is available only on OS X.
|
||||
__Note__: This API is only available on OS X.
|
||||
|
||||
### BrowserWindow.setAutoHideMenuBar(hide)
|
||||
|
||||
@@ -748,7 +753,7 @@ Calling `event.preventDefault()` can prevent creating new windows.
|
||||
Emitted when user or the page wants to start an navigation, it can happen when
|
||||
`window.location` object is changed or user clicks a link in the page.
|
||||
|
||||
This event will not emit when the navigation is started programmely with APIs
|
||||
This event will not emit when the navigation is started programmatically with APIs
|
||||
like `WebContents.loadUrl` and `WebContents.back`.
|
||||
|
||||
Calling `event.preventDefault()` can prevent the navigation.
|
||||
@@ -773,9 +778,12 @@ Emitted when a plugin process is crashed.
|
||||
|
||||
Emitted when the WebContents is destroyed.
|
||||
|
||||
### WebContents.loadUrl(url)
|
||||
### WebContents.loadUrl(url, [options])
|
||||
|
||||
* `url` URL
|
||||
* `options` URL
|
||||
* `httpReferrer` String - A HTTP Referer url
|
||||
* `userAgent` String - A user agent originating the request
|
||||
|
||||
Loads the `url` in the window, the `url` must contains the protocol prefix,
|
||||
e.g. the `http://` or `file://`.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Supported Chrome command line switches
|
||||
|
||||
Following command lines switches in Chrome browser are also Supported in
|
||||
The following command lines switches in Chrome browser are also supported in
|
||||
Electron, you can use [app.commandLine.appendSwitch][append-switch] to append
|
||||
them in your app's main script before the [ready][ready] event of [app][app]
|
||||
module is emitted:
|
||||
@@ -11,9 +11,14 @@ app.commandLine.appendSwitch('remote-debugging-port', '8315');
|
||||
app.commandLine.appendSwitch('host-rules', 'MAP * 127.0.0.1');
|
||||
|
||||
app.on('ready', function() {
|
||||
// Your code here
|
||||
});
|
||||
```
|
||||
|
||||
## --client-certificate=`path`
|
||||
|
||||
Sets `path` of client certificate file.
|
||||
|
||||
## --disable-http-cache
|
||||
|
||||
Disables the disk cache for HTTP requests.
|
||||
@@ -60,15 +65,19 @@ Like `--host-rules` but these `rules` only apply to the host resolver.
|
||||
|
||||
## --ignore-certificate-errors
|
||||
|
||||
Ignore certificate related errors.
|
||||
Ignores certificate related errors.
|
||||
|
||||
## --ppapi-flash-path
|
||||
## --ppapi-flash-path=`path`
|
||||
|
||||
Set path to pepper flash plugin for use.
|
||||
Sets `path` of pepper flash plugin.
|
||||
|
||||
## --ppapi-flash-version
|
||||
## --ppapi-flash-version=`version`
|
||||
|
||||
Set the pepper flash version.
|
||||
Sets `version` of pepper flash plugin.
|
||||
|
||||
## --log-net-log=`path`
|
||||
|
||||
Enables saving net log events and writes them to `path`.
|
||||
|
||||
## --v=`log_level`
|
||||
|
||||
|
||||
@@ -27,11 +27,23 @@ crashReporter.start({
|
||||
* Only string properties are send correctly.
|
||||
* Nested objects are not supported.
|
||||
|
||||
Developers are required to call the API before using other crashReporter APIs.
|
||||
|
||||
|
||||
**Note:** On OS X, electron uses a new `crashpad` client, which is different
|
||||
with the `breakpad` on Windows and Linux. To enable crash collection feature,
|
||||
you are required to call `crashReporter.start` API to initiliaze `crashpad` in
|
||||
main process, even you only collect crash report in renderer process.
|
||||
|
||||
## crashReporter.getLastCrashReport()
|
||||
|
||||
Returns the date and ID of last crash report, when there was no crash report
|
||||
sent or the crash reporter is not started, `null` will be returned.
|
||||
|
||||
## crashReporter.getUploadedReports()
|
||||
|
||||
Returns all uploaded crash reports, each report contains date and uploaded ID.
|
||||
|
||||
# crash-reporter payload
|
||||
|
||||
The crash reporter will send the following data to the `submitUrl` as `POST`:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# dialog
|
||||
|
||||
The `dialog` module provides APIs to show native system dialogs, so web
|
||||
applications can get the same user experience with native applications.
|
||||
applications can deliver the same user experience as native applications.
|
||||
|
||||
An example of showing a dialog to select multiple files and directories:
|
||||
|
||||
@@ -11,7 +11,7 @@ var dialog = require('dialog');
|
||||
console.log(dialog.showOpenDialog({ properties: [ 'openFile', 'openDirectory', 'multiSelections' ]}));
|
||||
```
|
||||
|
||||
**Note for OS X**: If you want to present dialogs as sheets, the only thing you have to do is to provide a `BrowserWindow` reference in the `browserWindow` parameter.
|
||||
**Note for OS X**: If you want to present dialogs as sheets, the only thing you have to do is provide a `BrowserWindow` reference in the `browserWindow` parameter.
|
||||
|
||||
## dialog.showOpenDialog([browserWindow], [options], [callback])
|
||||
|
||||
@@ -36,18 +36,17 @@ selected, an example is:
|
||||
filters: [
|
||||
{ name: 'Images', extensions: ['jpg', 'png', 'gif'] },
|
||||
{ name: 'Movies', extensions: ['mkv', 'avi', 'mp4'] },
|
||||
{ name: 'Custom File Type', extensions: ['as'] },
|
||||
],
|
||||
{ name: 'Custom File Type', extensions: ['as'] }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
If a `callback` is passed, the API call would be asynchronous and the result
|
||||
would be passed via `callback(filenames)`
|
||||
|
||||
**Note:** On Windows and Linux, an open dialog could not be both file selector
|
||||
and directory selector at the same time, so if you set `properties` to
|
||||
`['openFile', 'openDirectory']` on these platforms, a directory selector would
|
||||
be showed.
|
||||
**Note:** On Windows and Linux, an open dialog can not be both a file selector
|
||||
and a directory selector, so if you set `properties` to
|
||||
`['openFile', 'openDirectory']` on these platforms, a directory selector will be shown.
|
||||
|
||||
## dialog.showSaveDialog([browserWindow], [options], [callback])
|
||||
|
||||
@@ -58,14 +57,14 @@ be showed.
|
||||
* `filters` Array
|
||||
* `callback` Function
|
||||
|
||||
On success, returns the path of file chosen by the user, otherwise returns
|
||||
On success, returns the path of the file chosen by the user, otherwise returns
|
||||
`undefined`.
|
||||
|
||||
The `filters` specifies an array of file types that can be displayed, see
|
||||
`dialog.showOpenDialog` for an example.
|
||||
|
||||
If a `callback` is passed, the API call would be asynchronous and the result
|
||||
would be passed via `callback(filename)`
|
||||
If a `callback` is passed, the API call will be asynchronous and the result
|
||||
will be passed via `callback(filename)`
|
||||
|
||||
## dialog.showMessageBox([browserWindow], options, [callback])
|
||||
|
||||
@@ -82,8 +81,8 @@ would be passed via `callback(filename)`
|
||||
Shows a message box, it will block until the message box is closed. It returns
|
||||
the index of the clicked button.
|
||||
|
||||
If a `callback` is passed, the API call would be asynchronous and the result
|
||||
would be passed via `callback(response)`
|
||||
If a `callback` is passed, the API call will be asynchronous and the result
|
||||
will be passed via `callback(response)`
|
||||
|
||||
## dialog.showErrorBox(title, content)
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ var win = new BrowserWindow({ transparent: true, frame: false });
|
||||
API to set window shape to solve this, but currently blocked at an
|
||||
[upstream bug](https://code.google.com/p/chromium/issues/detail?id=387234).
|
||||
* Transparent window is not resizable, setting `resizable` to `true` may make
|
||||
transprent window stop working on some platforms.
|
||||
transparent window stop working on some platforms.
|
||||
* The `blur` filter only applies to the web page, so there is no way to apply
|
||||
blur effect to the content below the window.
|
||||
* On Windows transparent window will not work when DWM is disabled.
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
# global-shortcut
|
||||
|
||||
The `global-shortcut` module can register/unregister a global keyboard shortcut
|
||||
in operating system, so that you can custom the operations for various shortcuts.
|
||||
Note that it is global, even the app does not get focused, it still works.
|
||||
in operating system, so that you can customize the operations for various shortcuts.
|
||||
Note that the shortcut is global, even if the app does not get focused, it will still work.
|
||||
|
||||
```javascript
|
||||
var globalShortcut = require('global-shortcut');
|
||||
|
||||
// Register a 'ctrl+x' shortcut listener.
|
||||
var ret = globalShortcut.register('ctrl+x', function() { console.log('ctrl+x is pressed'); })
|
||||
if (!ret)
|
||||
console.log('registerion fails');
|
||||
|
||||
if (!ret) {
|
||||
console.log('registration failed');
|
||||
}
|
||||
|
||||
// Check whether a shortcut is registered.
|
||||
console.log(globalShortcut.isRegistered('ctrl+x'));
|
||||
@@ -34,7 +36,7 @@ the registered shortcut is pressed by user.
|
||||
|
||||
* `accelerator` [Accelerator](accelerator.md)
|
||||
|
||||
Returns whether shortcut of `accelerator` is registered.
|
||||
Returns `true` or `false` depending on if the shortcut `accelerator` is registered.
|
||||
|
||||
## globalShortcut.unregister(accelerator)
|
||||
|
||||
|
||||
@@ -29,8 +29,11 @@ window.addEventListener('contextmenu', function (e) {
|
||||
|
||||
Another example of creating the application menu with the simple template API:
|
||||
|
||||
```javascript
|
||||
// main.js
|
||||
```html
|
||||
<!-- index.html -->
|
||||
<script>
|
||||
var remote = require('remote');
|
||||
var Menu = remote.require('menu');
|
||||
var template = [
|
||||
{
|
||||
label: 'Electron',
|
||||
@@ -69,7 +72,7 @@ var template = [
|
||||
{
|
||||
label: 'Quit',
|
||||
accelerator: 'Command+Q',
|
||||
click: function() { app.quit(); }
|
||||
selector: 'terminate:'
|
||||
},
|
||||
]
|
||||
},
|
||||
@@ -108,7 +111,7 @@ var template = [
|
||||
label: 'Select All',
|
||||
accelerator: 'Command+A',
|
||||
selector: 'selectAll:'
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -117,12 +120,12 @@ var template = [
|
||||
{
|
||||
label: 'Reload',
|
||||
accelerator: 'Command+R',
|
||||
click: function() { BrowserWindow.getFocusedWindow().reloadIgnoringCache(); }
|
||||
click: function() { remote.getCurrentWindow().reload(); }
|
||||
},
|
||||
{
|
||||
label: 'Toggle DevTools',
|
||||
accelerator: 'Alt+Command+I',
|
||||
click: function() { BrowserWindow.getFocusedWindow().toggleDevTools(); }
|
||||
click: function() { remote.getCurrentWindow().toggleDevTools(); }
|
||||
},
|
||||
]
|
||||
},
|
||||
@@ -145,18 +148,19 @@ var template = [
|
||||
{
|
||||
label: 'Bring All to Front',
|
||||
selector: 'arrangeInFront:'
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Help',
|
||||
submenu: []
|
||||
},
|
||||
}
|
||||
];
|
||||
|
||||
menu = Menu.buildFromTemplate(template);
|
||||
|
||||
Menu.setApplicationMenu(menu); // Must be called within app.on('ready', function(){ ... });
|
||||
Menu.setApplicationMenu(menu);
|
||||
</script>
|
||||
```
|
||||
|
||||
## Class: Menu
|
||||
@@ -281,10 +285,10 @@ Template:
|
||||
|
||||
```javascript
|
||||
[
|
||||
{label: '4', id: '4'}
|
||||
{label: '5', id: '5'}
|
||||
{label: '1', id: '1', position: 'before=4'}
|
||||
{label: '2', id: '2'}
|
||||
{label: '4', id: '4'},
|
||||
{label: '5', id: '5'},
|
||||
{label: '1', id: '1', position: 'before=4'},
|
||||
{label: '2', id: '2'},
|
||||
{label: '3', id: '3'}
|
||||
]
|
||||
```
|
||||
@@ -303,11 +307,11 @@ Template:
|
||||
|
||||
```javascript
|
||||
[
|
||||
{label: 'a', position: 'endof=letters'}
|
||||
{label: '1', position: 'endof=numbers'}
|
||||
{label: 'b', position: 'endof=letters'}
|
||||
{label: '2', position: 'endof=numbers'}
|
||||
{label: 'c', position: 'endof=letters'}
|
||||
{label: 'a', position: 'endof=letters'},
|
||||
{label: '1', position: 'endof=numbers'},
|
||||
{label: 'b', position: 'endof=letters'},
|
||||
{label: '2', position: 'endof=numbers'},
|
||||
{label: 'c', position: 'endof=letters'},
|
||||
{label: '3', position: 'endof=numbers'}
|
||||
]
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Process object
|
||||
|
||||
The `process` object in Electron has following differences between the one in
|
||||
The `process` object in Electron has the following differences from the one in
|
||||
upstream node:
|
||||
|
||||
* `process.type` String - Process's type, can be `browser` (i.e. main process) or `renderer`.
|
||||
|
||||
@@ -7,8 +7,8 @@ An example of implementing a protocol that has the same effect with the
|
||||
`file://` protocol:
|
||||
|
||||
```javascript
|
||||
var app = require('app'),
|
||||
path = require('path');
|
||||
var app = require('app');
|
||||
var path = require('path');
|
||||
|
||||
app.on('ready', function() {
|
||||
var protocol = require('protocol');
|
||||
|
||||
@@ -20,6 +20,8 @@ var win = new BrowserWindow({ width: 800, height: 600 });
|
||||
win.loadUrl('https://github.com');
|
||||
```
|
||||
|
||||
Note: for the reverse (access renderer process from main process), you can use [webContents.executeJavascript](https://github.com/atom/electron/blob/master/docs/api/browser-window.md#browserwindowwebcontents).
|
||||
|
||||
## Remote objects
|
||||
|
||||
Each object (including functions) returned by the `remote` module represents an
|
||||
@@ -97,7 +99,8 @@ returns a `Buffer` by calling the passed callback:
|
||||
```javascript
|
||||
var remote = require('remote');
|
||||
var fs = require('fs');
|
||||
remote.getCurrentWindow().capturePage(function(buf) {
|
||||
remote.getCurrentWindow().capturePage(function(image) {
|
||||
var buf = image.toPng();
|
||||
fs.writeFile('/tmp/screenshot.png', buf, function(err) {
|
||||
console.log(err);
|
||||
});
|
||||
@@ -115,7 +118,8 @@ The work-around is to write the `buf` in the main process, where it is a real
|
||||
|
||||
```javascript
|
||||
var remote = require('remote');
|
||||
remote.getCurrentWindow().capturePage(function(buf) {
|
||||
remote.getCurrentWindow().capturePage(function(image) {
|
||||
var buf = image.toPng();
|
||||
remote.require('fs').writeFile('/tmp/screenshot.png', buf, function(err) {
|
||||
console.log(err);
|
||||
});
|
||||
|
||||
@@ -15,7 +15,7 @@ app.on('ready', function(){
|
||||
{ label: 'Item1', type: 'radio' },
|
||||
{ label: 'Item2', type: 'radio' },
|
||||
{ label: 'Item3', type: 'radio', checked: true },
|
||||
{ label: 'Item4', type: 'radio' },
|
||||
{ label: 'Item4', type: 'radio' }
|
||||
]);
|
||||
appIcon.setToolTip('This is my application.');
|
||||
appIcon.setContextMenu(contextMenu);
|
||||
@@ -55,7 +55,7 @@ Creates a new tray icon associated with the `image`.
|
||||
|
||||
Emitted when the tray icon is clicked.
|
||||
|
||||
__Note:__ The `bounds` payload is only implemented on OS X.
|
||||
__Note:__ The `bounds` payload is only implemented on OS X and Windows 7 or newer.
|
||||
|
||||
### Event: 'double-clicked'
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ form, the `webview` tag includes the `src` of the web page and css styles that
|
||||
control the appearance of the `webview` container:
|
||||
|
||||
```html
|
||||
<webview id="foo" src="https://www.github.com/" style="width:640px; height:480px"></webview>
|
||||
<webview id="foo" src="https://www.github.com/" style="display:inline-block; width:640px; height:480px"></webview>
|
||||
```
|
||||
|
||||
If you want to control the guest content in any way, you can write JavaScript
|
||||
@@ -390,7 +390,7 @@ without regard for log level or other properties.
|
||||
|
||||
```javascript
|
||||
webview.addEventListener('console-message', function(e) {
|
||||
console.log('Guest page logged a message: ', e.message);
|
||||
console.log('Guest page logged a message:', e.message);
|
||||
});
|
||||
```
|
||||
|
||||
@@ -448,7 +448,7 @@ webview.send('ping');
|
||||
var ipc = require('ipc');
|
||||
ipc.on('ping', function() {
|
||||
ipc.sendToHost('pong');
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
### crashed
|
||||
|
||||
@@ -2,30 +2,33 @@
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* [Node.js](http://nodejs.org)
|
||||
* Python 2.7.x. Some distributions like CentOS still use Python 2.6.x
|
||||
so you may need to check your Python version with `python -V`.
|
||||
* Node.js v0.12.x. There are various ways to install Node. One can download
|
||||
source code from [Node.js] (http://nodejs.org) and compile from source.
|
||||
Doing so permits installing Node to 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)
|
||||
* Clang 3.4 or later
|
||||
* Development headers of GTK+ and libnotify
|
||||
|
||||
On Ubuntu you could install the libraries via:
|
||||
On Ubuntu, install the following libraries:
|
||||
|
||||
```bash
|
||||
$ sudo apt-get install build-essential clang libdbus-1-dev libgtk2.0-dev \
|
||||
libnotify-dev libgnome-keyring-dev libgconf2-dev \
|
||||
libasound2-dev libcap-dev libcups2-dev libxtst-dev \
|
||||
gcc-multilib g++-multilib
|
||||
libxss1 gcc-multilib g++-multilib
|
||||
```
|
||||
|
||||
Latest Node.js could be installed via ppa:
|
||||
Other distributions may offer similar packages for installation via package
|
||||
managers such as yum. Or one can compile from source code.
|
||||
|
||||
```bash
|
||||
$ sudo apt-get install python-software-properties software-properties-common
|
||||
$ sudo add-apt-repository ppa:chris-lea/node.js
|
||||
$ sudo apt-get update
|
||||
$ sudo apt-get install nodejs
|
||||
|
||||
# Update to latest npm
|
||||
$ sudo npm install npm -g
|
||||
```
|
||||
## If You Use Virtual Machines For Building
|
||||
|
||||
If you plan to build electron on a virtual machine, you will need a fixed-size
|
||||
device container of at least 25 gigabytes in size.
|
||||
|
||||
|
||||
## Getting the code
|
||||
|
||||
@@ -36,8 +39,9 @@ $ git clone https://github.com/atom/electron.git
|
||||
## Bootstrapping
|
||||
|
||||
The bootstrap script will download all necessary build dependencies and create
|
||||
build project files. Notice that we're using `ninja` to build Electron so
|
||||
there is no `Makefile` generated.
|
||||
build project files. You must have Python 2.7.x for the script to succeed.
|
||||
Downloading certain files could take a long time. Notice that we are using
|
||||
`ninja` to build Electron so there is no `Makefile` generated.
|
||||
|
||||
```bash
|
||||
$ cd electron
|
||||
@@ -46,76 +50,48 @@ $ ./script/bootstrap.py -v
|
||||
|
||||
## Building
|
||||
|
||||
Build both `Release` and `Debug` targets:
|
||||
If you would like to build both `Release` and `Debug` targets:
|
||||
|
||||
```bash
|
||||
$ ./script/build.py
|
||||
```
|
||||
|
||||
You can also only build the `Debug` target:
|
||||
This script will cause a very large Electron executable to be placed in
|
||||
the directory `out/R`. The file size is in excess of 1.3 gigabytes. This
|
||||
happens because the Release target binary contains debugging symbols.
|
||||
To reduce the file size, run the `create-dist.py` script:
|
||||
|
||||
```bash
|
||||
$ ./script/create-dist.py
|
||||
```
|
||||
|
||||
This will put a working distribution with much smaller file sizes in
|
||||
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.
|
||||
|
||||
You can also build the `Debug` target only:
|
||||
|
||||
```bash
|
||||
$ ./script/build.py -c D
|
||||
```
|
||||
|
||||
After building is done, you can find `atom` under `out/D`.
|
||||
After building is done, you can find the `electron` debug binary
|
||||
under `out/D`.
|
||||
|
||||
|
||||
## Cleaning
|
||||
|
||||
|
||||
To clean the build files:
|
||||
|
||||
```bash
|
||||
$ ./script/clean.py
|
||||
```
|
||||
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### fatal error: bits/predefs.h: No such file or directory
|
||||
|
||||
If you got an error like this:
|
||||
|
||||
````
|
||||
In file included from /usr/include/stdio.h:28:0,
|
||||
from ../../../svnsrc/libgcc/../gcc/tsystem.h:88,
|
||||
from ../../../svnsrc/libgcc/libgcc2.c:29:
|
||||
/usr/include/features.h:324:26: fatal error: bits/predefs.h: No such file or directory
|
||||
#include <bits/predefs.h>
|
||||
````
|
||||
|
||||
Then you need to install `gcc-multilib` and `g++-multilib`, on Ubuntu you can do
|
||||
this:
|
||||
|
||||
```bash
|
||||
$ sudo apt-get install gcc-multilib g++-multilib
|
||||
```
|
||||
|
||||
### error adding symbols: DSO missing from command line
|
||||
|
||||
If you got an error like this:
|
||||
|
||||
````
|
||||
/usr/bin/ld: vendor/download/libchromiumcontent/Release/libchromiumcontent.so: undefined reference to symbol 'gconf_client_get'
|
||||
//usr/lib/x86_64-linux-gnu/libgconf-2.so.4: error adding symbols: DSO missing from command line
|
||||
````
|
||||
|
||||
libchromiumcontent.so is build with clang 3.0 which is incompatible with newer
|
||||
versions of clang. Try using clang 3.0, default version in Ubuntu 12.04.
|
||||
|
||||
### libudev.so.0 missing
|
||||
|
||||
If you get an error like:
|
||||
|
||||
````
|
||||
/usr/bin/ld: warning: libudev.so.0, needed by .../vendor/brightray/vendor/download/libchromiumcontent/Release/libchromiumcontent.so, not found (try using -rpath or -rpath-link)
|
||||
````
|
||||
|
||||
and you are on Ubuntu 13.04+, 64 bit system, try doing
|
||||
|
||||
```bash
|
||||
sudo ln -s /lib/x86_64-linux-gnu/libudev.so.1.3.5 /usr/lib/libudev.so.0
|
||||
```
|
||||
|
||||
for ubuntu 13.04+ 32 bit systems, try doing
|
||||
|
||||
```bash
|
||||
sudo ln -s /lib/i386-linux-gnu/libudev.so.1.3.5 /usr/lib/libudev.so.0
|
||||
```
|
||||
|
||||
also see
|
||||
|
||||
https://github.com/nwjs/nw.js/wiki/The-solution-of-lacking-libudev.so.0
|
||||
Make sure you have installed all the build dependencies.
|
||||
|
||||
## Tests
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ exposing your app's source code to users.
|
||||
|
||||
To use an `asar` archive to replace the `app` folder, you need to rename the
|
||||
archive to `app.asar`, and put it under Electron's resources directory like
|
||||
bellow, and Electron will then try read the archive and start from it.
|
||||
below, and Electron will then try read the archive and start from it.
|
||||
|
||||
On OS X:
|
||||
|
||||
|
||||
@@ -70,9 +70,9 @@ var dockMenu = Menu.buildFromTemplate([
|
||||
{ label: 'New Window', click: function() { console.log('New Window'); } },
|
||||
{ label: 'New Window with Settings', submenu: [
|
||||
{ label: 'Basic' },
|
||||
{ label: 'Pro'},
|
||||
{ label: 'Pro'}
|
||||
]},
|
||||
{ label: 'New Command...'},
|
||||
{ label: 'New Command...'}
|
||||
]);
|
||||
app.dock.setMenu(dockMenu);
|
||||
```
|
||||
@@ -119,7 +119,7 @@ app.setUserTasks([
|
||||
iconPath: process.execPath,
|
||||
iconIndex: 0,
|
||||
title: 'New Window',
|
||||
description: 'Create a new window',
|
||||
description: 'Create a new window'
|
||||
}
|
||||
]);
|
||||
```
|
||||
@@ -149,8 +149,8 @@ On Windows, a taskbar button can be used to display a progress bar. This enables
|
||||
a window to provide progress information to the user without that user having to
|
||||
switch to the window itself.
|
||||
|
||||
The Unity DE also has a simililar feature that allows you to specify progress
|
||||
bar in the lancher.
|
||||
The Unity DE also has a similar feature that allows you to specify the progress
|
||||
bar in the launcher.
|
||||
|
||||
__Progress bar in taskbar button:__
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# DevTools extension
|
||||
|
||||
To make debugging more easy, Electron has added basic support for
|
||||
To make debugging easier, Electron has basic support for
|
||||
[Chrome DevTools Extension][devtools-extension].
|
||||
|
||||
For most devtools extensions, you can simply download their source codes and use
|
||||
For most devtools extensions, you can simply download the source code and use
|
||||
the `BrowserWindow.addDevToolsExtension` API to load them, the loaded extensions
|
||||
will be remembered so you don't need to call the API every time when creating
|
||||
a window.
|
||||
|
||||
For example to use the React DevTools Extension, first you need to download its
|
||||
For example to use the [React DevTools Extension](https://github.com/facebook/react-devtools), first you need to download its
|
||||
source code:
|
||||
|
||||
```bash
|
||||
@@ -16,41 +16,37 @@ $ cd /some-directory
|
||||
$ git clone --recursive https://github.com/facebook/react-devtools.git
|
||||
```
|
||||
|
||||
Then you can load it in Electron by opening the devtools in arbitray window,
|
||||
and run this code in the console of devtools:
|
||||
Then you can load the extension in Electron by opening devtools in any window,
|
||||
and then running the following code in the devtools console:
|
||||
|
||||
```javascript
|
||||
require('remote').require('browser-window').addDevToolsExtension('/some-directory/react-devtools')
|
||||
require('remote').require('browser-window').addDevToolsExtension('/some-directory/react-devtools');
|
||||
```
|
||||
|
||||
To unload the extension, you can call `BrowserWindow.removeDevToolsExtension`
|
||||
API with its name and it will disappear the next time you open the devtools:
|
||||
API with its name and it will not load the next time you open the devtools:
|
||||
|
||||
```javascript
|
||||
require('remote').require('browser-window').removeDevToolsExtension('React Developer Tools')
|
||||
require('remote').require('browser-window').removeDevToolsExtension('React Developer Tools');
|
||||
```
|
||||
|
||||
## Format of devtools extension
|
||||
|
||||
Ideally all devtools extension written for Chrome browser can be loaded by
|
||||
Electron, but they have to be in a plain directory, for those packaged `crx`
|
||||
extensions, there is no way in Electron to load them unless you find a way to
|
||||
extensions, there is no way for Electron to load them unless you find a way to
|
||||
extract them into a directory.
|
||||
|
||||
## Background pages
|
||||
|
||||
Currently Electron doesn't support the background pages of chrome extensions,
|
||||
so for some devtools extensions that rely on this feature, they may not work
|
||||
well in Electron
|
||||
Currently Electron doesn't support the background pages feature in chrome extensions,
|
||||
so for some devtools extensions that rely on this feature, they may not work in Electron.
|
||||
|
||||
## `chrome.*` APIs
|
||||
|
||||
Some chrome extensions use `chrome.*` APIs for some features, there is some
|
||||
effort to implement those APIs in Electron to make them work, but we have
|
||||
only implemented few for now.
|
||||
Some chrome extensions use `chrome.*` APIs for some features, there has been some
|
||||
effort to implement those APIs in Electron, however not all are implemented.
|
||||
|
||||
So if the devtools extension is using APIs other than `chrome.devtools.*`, it is
|
||||
very likely to fail, but you can report those extensions in the issues tracker
|
||||
so we can add support for those APIs.
|
||||
Given that not all `chrome.*` APIs are implemented if the devtools extension is using APIs other than `chrome.devtools.*`, the extension is very likely not to work. You can report failing extensions in the issue tracker so that we can add support for those APIs.
|
||||
|
||||
[devtools-extension]: https://developer.chrome.com/extensions/devtools
|
||||
|
||||
@@ -82,8 +82,9 @@ var mainWindow = null;
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function() {
|
||||
if (process.platform != 'darwin')
|
||||
if (process.platform != 'darwin') {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
|
||||
// This method will be called when Electron has done everything
|
||||
|
||||
@@ -23,8 +23,9 @@ var mainWindow = null;
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function() {
|
||||
if (process.platform != 'darwin')
|
||||
if (process.platform != 'darwin') {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
|
||||
// Specify flash path.
|
||||
|
||||
@@ -49,14 +49,14 @@ and where to find Electron's binary:
|
||||
```javascript
|
||||
var webdriver = require('selenium-webdriver');
|
||||
|
||||
var driver = new webdriver.Builder().
|
||||
// The "9515" is the port opened by chrome driver.
|
||||
usingServer('http://localhost:9515').
|
||||
withCapabilities({chromeOptions: {
|
||||
// Here is the path to your Electron binary.
|
||||
binary: '/Path-to-Your-App.app/Contents/MacOS/Atom'}}).
|
||||
forBrowser('electron').
|
||||
build();
|
||||
var driver = new webdriver.Builder()
|
||||
// The "9515" is the port opened by chrome driver.
|
||||
.usingServer('http://localhost:9515')
|
||||
.withCapabilities({chromeOptions: {
|
||||
// Here is the path to your Electron binary.
|
||||
binary: '/Path-to-Your-App.app/Contents/MacOS/Atom'}})
|
||||
.forBrowser('electron')
|
||||
.build();
|
||||
|
||||
driver.get('http://www.google.com');
|
||||
driver.findElement(webdriver.By.name('q')).sendKeys('webdriver');
|
||||
@@ -70,4 +70,10 @@ driver.wait(function() {
|
||||
driver.quit();
|
||||
```
|
||||
|
||||
## Workflow
|
||||
|
||||
To test your application without rebuilding Electron, simply [place](https://github.com/atom/electron/blob/master/docs/tutorial/application-distribution.md) your app source into Electron's resource directory.
|
||||
|
||||
[chrome-driver]: https://sites.google.com/a/chromium.org/chromedriver/
|
||||
|
||||
|
||||
|
||||
@@ -115,8 +115,6 @@
|
||||
'atom/browser/atom_javascript_dialog_manager.h',
|
||||
'atom/browser/atom_quota_permission_context.cc',
|
||||
'atom/browser/atom_quota_permission_context.h',
|
||||
'atom/browser/atom_resource_dispatcher_host_delegate.cc',
|
||||
'atom/browser/atom_resource_dispatcher_host_delegate.h',
|
||||
'atom/browser/atom_speech_recognition_manager_delegate.cc',
|
||||
'atom/browser/atom_speech_recognition_manager_delegate.h',
|
||||
'atom/browser/browser.cc',
|
||||
@@ -125,6 +123,8 @@
|
||||
'atom/browser/browser_mac.mm',
|
||||
'atom/browser/browser_win.cc',
|
||||
'atom/browser/browser_observer.h',
|
||||
'atom/browser/common_web_contents_delegate.cc',
|
||||
'atom/browser/common_web_contents_delegate.h',
|
||||
'atom/browser/javascript_environment.cc',
|
||||
'atom/browser/javascript_environment.h',
|
||||
'atom/browser/mac/atom_application.h',
|
||||
|
||||
@@ -38,6 +38,7 @@ TARGET_BINARIES = {
|
||||
'msvcp120.dll',
|
||||
'msvcr120.dll',
|
||||
'node.dll',
|
||||
'pdf.dll',
|
||||
'content_resources_200_percent.pak',
|
||||
'ui_resources_200_percent.pak',
|
||||
'xinput1_3.dll',
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import platform
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
@@ -43,10 +44,19 @@ def run_gyp(target_arch, component):
|
||||
defines = [
|
||||
'-Dlibchromiumcontent_component={0}'.format(component),
|
||||
'-Dtarget_arch={0}'.format(target_arch),
|
||||
'-Dhost_arch={0}'.format(target_arch),
|
||||
'-Dlibrary=static_library',
|
||||
]
|
||||
return subprocess.call([python, gyp, '-f', 'ninja', '--depth', '.',
|
||||
'atom.gyp', '-Icommon.gypi'] + defines)
|
||||
|
||||
|
||||
def get_host_arch():
|
||||
if platform.architecture()[0] == '32bit':
|
||||
return 'ia32'
|
||||
else:
|
||||
return 'x64'
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
|
||||
@@ -188,6 +188,7 @@ describe 'browser-window module', ->
|
||||
w.loadUrl 'file://' + path.join(fixtures, 'api', 'close-beforeunload-empty-string.html')
|
||||
|
||||
describe 'new-window event', ->
|
||||
return if isCI and process.platform is 'darwin'
|
||||
it 'emits when window.open is called', (done) ->
|
||||
w.webContents.once 'new-window', (e, url, frameName) ->
|
||||
e.preventDefault()
|
||||
@@ -230,6 +231,7 @@ describe 'browser-window module', ->
|
||||
w.minimize()
|
||||
|
||||
describe 'will-navigate event', ->
|
||||
return if isCI and process.platform is 'darwin'
|
||||
it 'emits when user starts a navigation', (done) ->
|
||||
@timeout 10000
|
||||
w.webContents.on 'will-navigate', (event, url) ->
|
||||
@@ -239,6 +241,7 @@ describe 'browser-window module', ->
|
||||
w.loadUrl "file://#{fixtures}/pages/will-navigate.html"
|
||||
|
||||
describe 'dom-ready event', ->
|
||||
return if isCI and process.platform is 'darwin'
|
||||
it 'emits when document is loaded', (done) ->
|
||||
ipc = remote.require 'ipc'
|
||||
server = http.createServer (req, res) ->
|
||||
|
||||
@@ -25,8 +25,10 @@ describe 'clipboard module', ->
|
||||
markup =
|
||||
if process.platform is 'darwin'
|
||||
'<meta charset=\'utf-8\'><string>Hi</string>'
|
||||
else
|
||||
else if process.platform is 'linux'
|
||||
'<meta http-equiv="content-type" ' +
|
||||
'content="text/html; charset=utf-8"><string>Hi</string>'
|
||||
else
|
||||
'<string>Hi</string>'
|
||||
clipboard.writeHtml text
|
||||
assert.equal clipboard.readHtml(), markup
|
||||
|
||||
@@ -5,12 +5,10 @@ url = require 'url'
|
||||
remote = require 'remote'
|
||||
formidable = require 'formidable'
|
||||
|
||||
crashReporter = remote.require 'crash-reporter'
|
||||
BrowserWindow = remote.require 'browser-window'
|
||||
|
||||
describe 'crash-reporter module', ->
|
||||
# We have trouble makeing crash reporter work on Yosemite.
|
||||
return if process.platform is 'darwin'
|
||||
|
||||
fixtures = path.resolve __dirname, 'fixtures'
|
||||
|
||||
w = null
|
||||
@@ -41,10 +39,15 @@ describe 'crash-reporter module', ->
|
||||
res.end('abc-123-def')
|
||||
server.close()
|
||||
done()
|
||||
server.listen 0, '127.0.0.1', ->
|
||||
# Server port is generated randomly for the first run, it will be reused
|
||||
# when page is refreshed.
|
||||
port = remote.process.port
|
||||
server.listen port, '127.0.0.1', ->
|
||||
{port} = server.address()
|
||||
remote.process.port = port
|
||||
url = url.format
|
||||
protocol: 'file'
|
||||
pathname: path.join fixtures, 'api', 'crash.html'
|
||||
search: "?port=#{port}"
|
||||
crashReporter.start {'submitUrl': 'http://127.0.0.1:' + port}
|
||||
w.loadUrl url
|
||||
|
||||
@@ -5,6 +5,7 @@ var BrowserWindow = require('browser-window');
|
||||
var Menu = require('menu');
|
||||
|
||||
var window = null;
|
||||
process.port = 0; // will be used by crash-reporter spec.
|
||||
|
||||
app.commandLine.appendSwitch('js-flags', '--expose_gc');
|
||||
app.commandLine.appendSwitch('ignore-certificate-errors');
|
||||
|
||||
@@ -54,7 +54,7 @@ describe '<webview> tag', ->
|
||||
assert.equal e.message, 'function'
|
||||
done()
|
||||
webview.addEventListener 'console-message', listener2
|
||||
webview.src = "file://#{fixtures}/pages/native-module.html"
|
||||
webview.reload()
|
||||
webview.addEventListener 'did-finish-load', listener
|
||||
webview.setAttribute 'nodeintegration', 'on'
|
||||
webview.src = "file://#{fixtures}/pages/native-module.html"
|
||||
|
||||
2
vendor/brightray
vendored
2
vendor/brightray
vendored
Submodule vendor/brightray updated: 8fba2a8835...7c6c530608
1
vendor/crashpad
vendored
Submodule
1
vendor/crashpad
vendored
Submodule
Submodule vendor/crashpad added at e6a0d433b0
2
vendor/native_mate
vendored
2
vendor/native_mate
vendored
Submodule vendor/native_mate updated: 1696237a3f...ad207eeabb
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user