Compare commits

..

114 Commits

Author SHA1 Message Date
Cheng Zhao
de151cef8e Bump v0.20.8 2015-01-27 11:38:30 -08:00
Cheng Zhao
5bfe644c3e Merge pull request #1059 from atom/ipc-preload
Don't rely on global "process" object for message dispatching
2015-01-27 10:58:20 -08:00
Cheng Zhao
20431f4f2f No need to route via ATOM_INTERNAL_MESSAGE 2015-01-27 10:47:11 -08:00
Cheng Zhao
ad16e9ea49 Check for the existence of "ipc" object 2015-01-26 18:47:23 -08:00
Cheng Zhao
a10782cdea Don't rely on the global process object for message dispatching 2015-01-26 18:42:43 -08:00
Cheng Zhao
c14c6a3521 spec: The preload script should be able to receive ipc messages 2015-01-26 18:06:27 -08:00
Cheng Zhao
6c62895898 Merge pull request #1044 from atom/load-environment-later
Fix race condition when initializing node integration
2015-01-25 13:04:33 -08:00
Cheng Zhao
134aa32612 Merge pull request #1052 from gappsby/patch-1
Correct spelling mistake.
2015-01-25 13:04:22 -08:00
Florian Hämmerle
0a59384003 Correct spelling mistake. 2015-01-24 13:39:36 +01:00
Cheng Zhao
c2b109f7fc Fix process.crash() 2015-01-23 21:55:42 -08:00
Cheng Zhao
a755edebfa Simplify atom_bindings 2015-01-23 21:33:40 -08:00
Cheng Zhao
76fc62808c Use FILE_PATH_LITERAL instead of AppendASCII 2015-01-23 21:12:45 -08:00
Cheng Zhao
54ab6744f1 Remove some unused virtual functions 2015-01-23 21:05:32 -08:00
Cheng Zhao
2d262d2dbd Use node::CreateEnvironment to create environment 2015-01-23 21:02:31 -08:00
Cheng Zhao
de99c38fb6 Get rid of AtomRenderFrameObserver 2015-01-23 20:51:19 -08:00
Cheng Zhao
91320a9e55 Remove AtomRendererBindings
After the simplification of code this class is no longer needed.
2015-01-23 20:43:38 -08:00
Cheng Zhao
0bcc9b7713 Don't handle browser messages before document object is created
When we recevied messages from browser, we will try to transfer the
message to web page, and when we do that blink will create an empty
document when there is no document object yet, which will make our init
script run when window.location is still about:blank.
2015-01-23 18:33:01 -08:00
Cheng Zhao
33b6876cc1 Add support for Plus as accelerator key, fixes #1050 2015-01-23 15:26:54 -08:00
Cheng Zhao
81b370ee9f Implement CheckMediaAccessPermission, fixes #1017 2015-01-23 15:13:49 -08:00
Cheng Zhao
fe81e5b32d Use https://atom.io/download/atom-shell as headers download URL 2015-01-23 12:16:49 -08:00
Cheng Zhao
4ba3e101f6 Clean the init.coffee 2015-01-21 17:38:26 -08:00
Cheng Zhao
7210f6e64d spec: No node integration in iframe 2015-01-21 17:05:19 -08:00
Cheng Zhao
ef15b670a9 Initialize node integration after window object is cleared 2015-01-21 16:40:19 -08:00
Cheng Zhao
706f547287 Don't insert node symbols in frames
This greatly simplified our code, and it is not useful to enable node
integrations in frames.
2015-01-21 15:42:57 -08:00
Cheng Zhao
f142f572c3 Add DidClearWindowObject for renderer client 2015-01-21 15:35:43 -08:00
Cheng Zhao
7e33e26465 Add atom-shell bindings before loading environment 2015-01-21 15:02:09 -08:00
Cheng Zhao
5e58915bdd Separate LoadEnvironment from CreateEnvironment 2015-01-21 14:00:19 -08:00
Cheng Zhao
854c59df5c docs: Make getCurrentWindow more clear, fixes #1035 2015-01-21 13:47:28 -08:00
Cheng Zhao
f6db9bc84c Merge pull request #1034 from atom/index-js
Update index.json when publishing
2015-01-21 13:38:56 -08:00
Cheng Zhao
b8d0c5b3fe Include node's version 2015-01-21 13:37:52 -08:00
Cheng Zhao
23760058e9 Fix target url 2015-01-20 22:16:27 -08:00
Cheng Zhao
7b621262ea Upload the index.json to S3 2015-01-20 22:09:30 -08:00
Cheng Zhao
62756a79df Include apm version in index.json 2015-01-20 22:01:51 -08:00
Cheng Zhao
87cd762eb3 ⬆️ apm@0.122.0 2015-01-20 21:58:46 -08:00
Cheng Zhao
74566375b5 Download the index.json from server 2015-01-20 21:53:53 -08:00
Cheng Zhao
5d9b538513 Add script to dump information for atom-shell 2015-01-20 14:39:14 -08:00
Cheng Zhao
7c0f414881 Bump v0.20.7 2015-01-20 11:30:41 -08:00
Cheng Zhao
62d2b90e18 Merge pull request #1027 from fengmk2/mirror
Add China download mirrors
2015-01-19 19:44:19 -08:00
Cheng Zhao
69092eee15 No need to preheat original-fs module 2015-01-19 15:47:21 -08:00
Cheng Zhao
96f24b88ea Update asar specs 2015-01-19 15:36:56 -08:00
Cheng Zhao
3d858bee95 Guard against bad events in screen module
It can happen that the DisplayObserver methods are called without a
valid Display object passed.
2015-01-19 14:46:29 -08:00
Cheng Zhao
0933a7d1b2 Evaluate the "fs.js" in original-fs
Some high-level APIs in fs are using low-level APIs via "fs.xxx", which
will be overriden by our asar wrappers, so just shadow-copy those
methods is not enough.

By evaluating the whole "fs.js" we can make sure original-fs is not
polluted by the asar wrappers.

Fixes #782.
2015-01-19 14:22:32 -08:00
Cheng Zhao
fe78c17ea6 Don't popup error if the user has a custom uncaught exception handler
Fix #1012.
2015-01-19 12:50:44 -08:00
Cheng Zhao
79a233436b Merge pull request #1029 from atom/editing-commands
Add editing commands for <webview> and WebContents
2015-01-19 12:40:30 -08:00
Cheng Zhao
3da347a783 docs: The editing commands 2015-01-19 12:30:28 -08:00
Cheng Zhao
ff856e679d Make editing commands available in <webview> 2015-01-19 12:15:07 -08:00
Cheng Zhao
7fbf4246ac Add editing commands for WebContents 2015-01-19 12:09:47 -08:00
fengmk2
42077999e9 Add China download mirrors 2015-01-19 22:30:33 +08:00
Cheng Zhao
e75950cb89 Merge pull request #1026 from atom/set-data-path
Add API to set/get path to special directory or file
2015-01-18 21:53:29 -08:00
Cheng Zhao
4604c9bb0e Add a few more paths for app.getPath 2015-01-18 21:43:23 -08:00
Cheng Zhao
8aa5b97c61 docs: Say more about Linux's behavior 2015-01-18 21:43:22 -08:00
Cheng Zhao
ce52a87477 Add "cache" and "userCache" directories 2015-01-18 21:43:22 -08:00
Cheng Zhao
9a04f67c0a docs: Mention when to override userData path 2015-01-18 21:43:21 -08:00
Cheng Zhao
3d398458a8 Throw error when PathService call failed 2015-01-18 21:43:21 -08:00
Cheng Zhao
dec3e37683 docs: Document app.getPath/app.setPath 2015-01-18 21:43:20 -08:00
Cheng Zhao
a988b48016 Implement app.getHomeDir with app.getPath 2015-01-18 21:43:20 -08:00
Cheng Zhao
d31df439c3 Override default userData according to app's name 2015-01-18 21:43:19 -08:00
Cheng Zhao
06da5f254a Add app.setPath and app.getPath APIs
They can be used to set/get any path defined in PathService
2015-01-18 21:43:19 -08:00
Cheng Zhao
2d1afbf51b Call app.getDataPath after app is ready
It is possible for users to override the data path.
2015-01-18 21:43:18 -08:00
Cheng Zhao
45c26e0e5a Add app.setDataPath API 2015-01-18 21:43:18 -08:00
Cheng Zhao
c6fb645f6b Warning of app not ready in screen module 2015-01-18 21:42:46 -08:00
Cheng Zhao
e8f1f6819c Merge pull request #1016 from atom/screen-improve
Add API to enumerate external displays in screen module
2015-01-18 10:23:18 -08:00
Cheng Zhao
c59bd82f6f Merge pull request #1019 from atom/locale-in-node
Initialize ICU in Node mode
2015-01-16 17:08:30 -08:00
Cheng Zhao
b2be9373b0 linux,win: Initalize ICU for node mode 2015-01-16 16:12:12 -08:00
Cheng Zhao
f81df9a5d3 spec: Test localeCompare in child process 2015-01-16 16:11:02 -08:00
Cheng Zhao
51c03c3a71 mac: Initialize ICU in Node mode 2015-01-16 15:55:50 -08:00
Cheng Zhao
4f6ee31a28 docs: Fix typo 2015-01-16 14:01:52 -08:00
Cheng Zhao
1746518cdf docs: Update docs and examples for screen module 2015-01-16 13:57:16 -08:00
Cheng Zhao
b3c3556286 Update the displays when there is metrics change 2015-01-16 12:04:35 -08:00
Cheng Zhao
50b96ca7ef Pass the display in screen events 2015-01-16 12:02:32 -08:00
Cheng Zhao
7749484628 Make getAllDisplays return current displays. 2015-01-16 11:39:25 -08:00
Cheng Zhao
b5898d3355 Add events on display add/remove. 2015-01-16 11:01:38 -08:00
Cheng Zhao
809c995c0b Make "screen" module a browser module 2015-01-16 11:01:38 -08:00
Cheng Zhao
551c39e241 Add some more attributes for Display 2015-01-16 11:01:38 -08:00
Cheng Zhao
97070246b7 Don't put gfx_converter's implementaion in header file 2015-01-16 11:01:38 -08:00
Cheng Zhao
029ee9aa1e Add a few more API bindings 2015-01-16 11:01:38 -08:00
Cheng Zhao
509294b228 Don't hard-code API names 2015-01-16 11:01:38 -08:00
Cheng Zhao
ab9e1dd650 Upgrade brightray for #863 2015-01-15 17:52:14 -08:00
Cheng Zhao
0ac2443eb0 Merge pull request #1009 from atom/better-emit
Convert arguments to V8 directly in EventEmitter::Emit
2015-01-15 17:40:20 -08:00
Cheng Zhao
136b3da458 Add -stdlib=libc++ for linking 2015-01-15 17:17:43 -08:00
Cheng Zhao
9f5ed14f24 mac: Upgrade libchromiumcontent to fix linking error 2015-01-14 20:15:39 -08:00
Cheng Zhao
482c740e61 Also unpack arguments in ipc-message-host message 2015-01-14 19:43:01 -08:00
Cheng Zhao
1a1cf57097 Unpack the arguments in ipc message 2015-01-14 19:33:24 -08:00
Cheng Zhao
f6f5ff4330 Fix converting ListValue to V8 2015-01-14 19:09:25 -08:00
Cheng Zhao
6a11eccc3e Update native_mate to fix linking error 2015-01-14 18:55:54 -08:00
Cheng Zhao
2d6dc9c527 Convert arguments to V8 directly in EventEmitter::Emmit
This gets rid of the extra conversion between ListValue.
2015-01-14 17:51:54 -08:00
Cheng Zhao
65d2540807 Use C++11 stdlib 2015-01-14 17:40:24 -08:00
Cheng Zhao
834d28f528 win: Fix building 2015-01-14 14:05:22 -08:00
Cheng Zhao
b4ba4a908e Bump v0.20.6 2015-01-13 11:47:10 -08:00
Cheng Zhao
bda3711815 docs: Transparent window 2015-01-12 15:27:33 -08:00
Cheng Zhao
b4cdb546fe Don't set contentWindow property for <webview>
This property is only available in Chrome and we don't need it in
atom-shell, so remove it to avoid confusions.

Fixes #997.
2015-01-12 14:17:49 -08:00
Cheng Zhao
7ab5db1adb Use http in framework download url, fixes #998 2015-01-12 14:10:22 -08:00
Cheng Zhao
1926c2cd01 Merge pull request #949 from atom/window-transparency
Add support for window transparency
2015-01-12 14:05:20 -08:00
Cheng Zhao
21ba5b867d Merge branch 'master' into window-transparency
Conflicts:
	script/lib/config.py
2015-01-12 13:39:32 -08:00
Kevin Sawicki
1a80bc786d Merge pull request #1000 from yibuyisheng/master
remove `will`
2015-01-12 09:10:22 -08:00
yibuyisheng
6a532292c4 remove 2015-01-12 23:23:10 +08:00
Cheng Zhao
c8ed581e5c Merge pull request #990 from deepak1556/chrome_extension_patch
ensuring single instance for loading and unloading extension
2015-01-09 15:11:21 -08:00
deepak1556
c0f0f4cdc6 ensuring single instance for loading and unloading extension 2015-01-10 04:12:13 +05:30
Cheng Zhao
b83f042363 Merge pull request #985 from atom/set-safe-schema
Add webFrame.registerUrlSchemeAsSecure API
2015-01-08 13:12:14 -08:00
Cheng Zhao
bce8a3f835 Fix cpplint warning 2015-01-08 12:51:15 -08:00
Cheng Zhao
2d5b17552a Add webFrame.registerUrlSchemeAsSecure API 2015-01-08 12:39:58 -08:00
Cheng Zhao
19d6d171b1 Don't show insecure content by default
This follows the behavior of Chrome.
2015-01-08 11:50:55 -08:00
Cheng Zhao
09acb9032a Allow using blink's private headers 2015-01-08 11:50:55 -08:00
Cheng Zhao
3dfc496243 Add support for --ignore-certificate-errors
This makes it possible to test HTTPS related APIs.
2015-01-08 11:50:55 -08:00
Cheng Zhao
6939567cb4 win: Make transparent window resizable 2014-12-23 17:24:04 -08:00
Cheng Zhao
1a34e09a45 views: Make transparent window work 2014-12-23 16:55:57 -08:00
Cheng Zhao
85685feff4 mac: Simplify frameless window dragging code 2014-12-23 15:55:56 -08:00
Cheng Zhao
4ca0458b37 OVERRIDE => override in native_window_mac.h 2014-12-23 15:31:39 -08:00
Cheng Zhao
effcf18d56 Upgrade libchromiumcontent to make transparent window work on Mac 2014-12-23 13:32:18 -08:00
Cheng Zhao
5b312e8f64 mac: Fix a crash when closing window 2014-12-23 12:31:27 -08:00
Cheng Zhao
8506725b54 mac: Don't show title text in transparent window 2014-12-23 11:48:20 -08:00
Cheng Zhao
45c41fe880 mac: Use transparent window 2014-12-23 11:17:56 -08:00
Cheng Zhao
4fc73117c4 Tell the render widget to use transparent background. 2014-12-23 11:17:32 -08:00
Cheng Zhao
9593c71f52 Add "transparent" option 2014-12-22 17:48:54 -08:00
91 changed files with 1483 additions and 939 deletions

View File

@@ -10,6 +10,10 @@ editor](https://github.com/atom/atom).
Prebuilt binaries of atom-shell for Linux, Windows and Mac can be found on the
[releases](https://github.com/atom/atom-shell/releases) page.
### Mirrors
- [China Mirror](https://npm.taobao.org/mirrors/atom-shell): Improve download speeds for Chinese user.
## Documentation
Guides and the API reference are located in the

View File

@@ -25,6 +25,7 @@
'atom/browser/api/lib/menu-item.coffee',
'atom/browser/api/lib/power-monitor.coffee',
'atom/browser/api/lib/protocol.coffee',
'atom/browser/api/lib/screen.coffee',
'atom/browser/api/lib/tray.coffee',
'atom/browser/api/lib/web-contents.coffee',
'atom/browser/lib/chrome-extension.coffee',
@@ -38,7 +39,6 @@
'atom/common/api/lib/crash-reporter.coffee',
'atom/common/api/lib/id-weak-map.coffee',
'atom/common/api/lib/original-fs.coffee',
'atom/common/api/lib/screen.coffee',
'atom/common/api/lib/shell.coffee',
'atom/common/lib/init.coffee',
'atom/common/lib/asar.coffee',
@@ -52,6 +52,7 @@
'atom/renderer/lib/web-view/web-view-constants.coffee',
'atom/renderer/api/lib/ipc.coffee',
'atom/renderer/api/lib/remote.coffee',
'atom/renderer/api/lib/screen.coffee',
'atom/renderer/api/lib/web-frame.coffee',
],
'lib_sources': [
@@ -78,6 +79,8 @@
'atom/browser/api/atom_api_power_monitor.h',
'atom/browser/api/atom_api_protocol.cc',
'atom/browser/api/atom_api_protocol.h',
'atom/browser/api/atom_api_screen.cc',
'atom/browser/api/atom_api_screen.h',
'atom/browser/api/atom_api_tray.cc',
'atom/browser/api/atom_api_tray.h',
'atom/browser/api/atom_api_web_contents.cc',
@@ -199,8 +202,6 @@
'atom/common/api/atom_api_crash_reporter.cc',
'atom/common/api/atom_api_id_weak_map.cc',
'atom/common/api/atom_api_id_weak_map.h',
'atom/common/api/atom_api_screen.cc',
'atom/common/api/atom_api_screen.h',
'atom/common/api/atom_api_shell.cc',
'atom/common/api/atom_api_v8_util.cc',
'atom/common/api/atom_bindings.cc',
@@ -234,6 +235,7 @@
'atom/common/native_mate_converters/accelerator_converter.cc',
'atom/common/native_mate_converters/accelerator_converter.h',
'atom/common/native_mate_converters/file_path_converter.h',
'atom/common/native_mate_converters/gfx_converter.cc',
'atom/common/native_mate_converters/gfx_converter.h',
'atom/common/native_mate_converters/gurl_converter.h',
'atom/common/native_mate_converters/image_converter.cc',
@@ -264,8 +266,6 @@
'atom/renderer/api/atom_api_spell_check_client.h',
'atom/renderer/api/atom_api_web_frame.cc',
'atom/renderer/api/atom_api_web_frame.h',
'atom/renderer/api/atom_renderer_bindings.cc',
'atom/renderer/api/atom_renderer_bindings.h',
'atom/renderer/atom_render_view_observer.cc',
'atom/renderer/atom_render_view_observer.h',
'atom/renderer/atom_renderer_client.cc',
@@ -340,8 +340,8 @@
'chromium_src/chrome/browser/ui/views/color_chooser_win.cc',
],
'framework_sources': [
'atom/app/atom_library_main.cc',
'atom/app/atom_library_main.h',
'atom/app/atom_library_main.mm',
],
'locales': [
'am', 'ar', 'bg', 'bn', 'ca', 'cs', 'da', 'de', 'el', 'en-GB',
@@ -550,6 +550,8 @@
'vendor/brightray/vendor/download/libchromiumcontent/src/v8/include',
# The `node.h` is using `#include"ares.h"`.
'vendor/node/deps/cares/include',
# The `third_party/WebKit/Source/platform/weborigin/SchemeRegistry.h` is using `platform/PlatformExport.h`.
'vendor/brightray/vendor/download/libchromiumcontent/src/third_party/WebKit/Source',
],
'direct_dependent_settings': {
'include_dirs': [
@@ -799,6 +801,9 @@
'vendor',
'<(libchromiumcontent_include_dir)',
],
'defines': [
'PRODUCT_NAME="<(product_name)"',
],
'export_dependent_settings': [
'<(project_name)_lib',
],

View File

@@ -11,6 +11,9 @@
extern "C" {
__attribute__((visibility("default")))
int AtomMain(int argc, const char* argv[]);
__attribute__((visibility("default")))
void AtomInitializeICU();
}
#endif // OS_MACOSX

View File

@@ -5,6 +5,9 @@
#include "atom/app/atom_library_main.h"
#include "atom/app/atom_main_delegate.h"
#include "base/i18n/icu_util.h"
#include "base/mac/bundle_locations.h"
#include "brightray/common/mac/main_application_bundle.h"
#include "content/public/app/content_main.h"
#if defined(OS_MACOSX)
@@ -15,4 +18,13 @@ int AtomMain(int argc, const char* argv[]) {
params.argv = argv;
return content::ContentMain(params);
}
void AtomInitializeICU() {
base::mac::SetOverrideFrameworkBundlePath(
brightray::MainApplicationBundlePath()
.Append("Contents")
.Append("Frameworks")
.Append(PRODUCT_NAME " Framework.framework"));
base::i18n::InitializeICU();
}
#endif // OS_MACOSX

View File

@@ -28,6 +28,8 @@
#include "atom/app/atom_library_main.h"
#endif // defined(OS_MACOSX)
#include "base/i18n/icu_util.h"
// Declaration of node::Start.
namespace node {
int Start(int argc, char *argv[]);
@@ -89,6 +91,7 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
}
}
// Now that conversion is done, we can finally start.
base::i18n::InitializeICU();
return node::Start(argc, argv);
} else if (env->GetVar("ATOM_SHELL_INTERNAL_CRASH_SERVICE",
&crash_service_indicator) &&
@@ -113,8 +116,10 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
int main(int argc, const char* argv[]) {
char* node_indicator = getenv("ATOM_SHELL_INTERNAL_RUN_AS_NODE");
if (node_indicator != NULL && strcmp(node_indicator, "1") == 0)
if (node_indicator != NULL && strcmp(node_indicator, "1") == 0) {
base::i18n::InitializeICU();
return node::Start(argc, const_cast<char**>(argv));
}
atom::AtomMainDelegate delegate;
content::ContentMainParams params(&delegate);
@@ -127,8 +132,10 @@ int main(int argc, const char* argv[]) {
int main(int argc, const char* argv[]) {
char* node_indicator = getenv("ATOM_SHELL_INTERNAL_RUN_AS_NODE");
if (node_indicator != NULL && strcmp(node_indicator, "1") == 0)
if (node_indicator != NULL && strcmp(node_indicator, "1") == 0) {
AtomInitializeICU();
return node::Start(argc, const_cast<char**>(argv));
}
return AtomMain(argc, argv);
}

View File

@@ -12,11 +12,11 @@
#include "atom/browser/browser.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "atom/common/native_mate_converters/gurl_converter.h"
#include "base/values.h"
#include "base/command_line.h"
#include "base/environment.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "brightray/browser/brightray_paths.h"
#include "native_mate/callback.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
@@ -27,10 +27,6 @@
#include "atom/common/node_includes.h"
#if defined(OS_LINUX)
#include "base/nix/xdg_util.h"
#endif
using atom::Browser;
namespace mate {
@@ -65,6 +61,30 @@ namespace api {
namespace {
// Return the path constant from string.
int GetPathConstant(const std::string& name) {
if (name == "appData")
return brightray::DIR_APP_DATA;
else if (name == "userData")
return brightray::DIR_USER_DATA;
else if (name == "cache")
return brightray::DIR_CACHE;
else if (name == "userCache")
return brightray::DIR_USER_CACHE;
else if (name == "home")
return base::DIR_HOME;
else if (name == "temp")
return base::DIR_TEMP;
else if (name == "userDesktop")
return base::DIR_USER_DESKTOP;
else if (name == "exe")
return base::FILE_EXE;
else if (name == "module")
return base::FILE_MODULE;
else
return -1;
}
class ResolveProxyHelper {
public:
ResolveProxyHelper(const GURL& url, App::ResolveProxyCallback callback)
@@ -124,15 +144,11 @@ void App::OnQuit() {
}
void App::OnOpenFile(bool* prevent_default, const std::string& file_path) {
base::ListValue args;
args.AppendString(file_path);
*prevent_default = Emit("open-file", args);
*prevent_default = Emit("open-file", file_path);
}
void App::OnOpenURL(const std::string& url) {
base::ListValue args;
args.AppendString(url);
Emit("open-url", args);
Emit("open-url", url);
}
void App::OnActivateWithNoOpenWindows() {
@@ -147,19 +163,26 @@ void App::OnFinishLaunching() {
Emit("ready");
}
base::FilePath App::GetDataPath() {
base::FilePath App::GetPath(mate::Arguments* args, const std::string& name) {
bool succeed = false;
base::FilePath path;
#if defined(OS_LINUX)
scoped_ptr<base::Environment> env(base::Environment::Create());
path = base::nix::GetXDGDirectory(env.get(),
base::nix::kXdgConfigHomeEnvVar,
base::nix::kDotConfigDir);
#else
PathService::Get(base::DIR_APP_DATA, &path);
#endif
int key = GetPathConstant(name);
if (key >= 0)
succeed = PathService::Get(key, &path);
if (!succeed)
args->ThrowError("Failed to get path");
return path;
}
return path.Append(base::FilePath::FromUTF8Unsafe(
Browser::Get()->GetName()));
void App::SetPath(mate::Arguments* args,
const std::string& name,
const base::FilePath& path) {
bool succeed = false;
int key = GetPathConstant(name);
if (key >= 0)
succeed = PathService::Override(key, path);
if (!succeed)
args->ThrowError("Failed to set path");
}
void App::ResolveProxy(const GURL& url, ResolveProxyCallback callback) {
@@ -192,7 +215,8 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder(
.SetMethod("setUserTasks",
base::Bind(&Browser::SetUserTasks, browser))
#endif
.SetMethod("getDataPath", &App::GetDataPath)
.SetMethod("setPath", &App::SetPath)
.SetMethod("getPath", &App::GetPath)
.SetMethod("resolveProxy", &App::ResolveProxy)
.SetMethod("setDesktopName", &App::SetDesktopName);
}

View File

@@ -18,6 +18,10 @@ namespace base {
class FilePath;
}
namespace mate {
class Arguments;
}
namespace atom {
namespace api {
@@ -48,7 +52,12 @@ class App : public mate::EventEmitter,
v8::Isolate* isolate) override;
private:
base::FilePath GetDataPath();
// Get/Set the pre-defined path in PathService.
base::FilePath GetPath(mate::Arguments* args, const std::string& name);
void SetPath(mate::Arguments* args,
const std::string& name,
const base::FilePath& path);
void ResolveProxy(const GURL& url, ResolveProxyCallback callback);
void SetDesktopName(const std::string& desktop_name);

View File

@@ -5,7 +5,6 @@
#include "atom/browser/api/atom_api_auto_updater.h"
#include "base/time/time.h"
#include "base/values.h"
#include "atom/browser/auto_updater.h"
#include "atom/browser/browser.h"
#include "native_mate/dictionary.h"
@@ -26,9 +25,7 @@ AutoUpdater::~AutoUpdater() {
}
void AutoUpdater::OnError(const std::string& error) {
base::ListValue args;
args.AppendString(error);
Emit("error", args);
Emit("error", error);
}
void AutoUpdater::OnCheckingForUpdate() {
@@ -49,13 +46,8 @@ void AutoUpdater::OnUpdateDownloaded(const std::string& release_notes,
const std::string& update_url,
const base::Closure& quit_and_install) {
quit_and_install_ = quit_and_install;
base::ListValue args;
args.AppendString(release_notes);
args.AppendString(release_name);
args.AppendDouble(release_date.ToJsTime());
args.AppendString(update_url);
Emit("update-downloaded-raw", args);
Emit("update-downloaded-raw", release_notes, release_name,
release_date.ToJsTime(), update_url);
}
mate::ObjectTemplateBuilder AutoUpdater::GetObjectTemplateBuilder(

View File

@@ -305,9 +305,7 @@ void Protocol::UninterceptProtocolInIO(const std::string& scheme) {
void Protocol::EmitEventInUI(const std::string& event,
const std::string& parameter) {
base::ListValue args;
args.AppendString(parameter);
Emit(event, args);
Emit(event, parameter);
}
// static

View File

@@ -0,0 +1,149 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_screen.h"
#include <algorithm>
#include <string>
#include "atom/browser/browser.h"
#include "atom/common/native_mate_converters/gfx_converter.h"
#include "base/bind.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "ui/gfx/screen.h"
#include "atom/common/node_includes.h"
namespace atom {
namespace api {
namespace {
// Find an item in container according to its ID.
template<class T>
typename T::iterator FindById(T* container, int id) {
auto predicate = [id] (const typename T::value_type& item) -> bool {
return item.id() == id;
};
return std::find_if(container->begin(), container->end(), predicate);
}
// Convert the changed_metrics bitmask to string array.
std::vector<std::string> MetricsToArray(uint32_t metrics) {
std::vector<std::string> array;
if (metrics & gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS)
array.push_back("bounds");
if (metrics & gfx::DisplayObserver::DISPLAY_METRIC_WORK_AREA)
array.push_back("workArea");
if (metrics & gfx::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR)
array.push_back("scaleFactor");
if (metrics & gfx::DisplayObserver::DISPLAY_METRIC_ROTATION)
array.push_back("rotaion");
return array;
}
} // namespace
Screen::Screen(gfx::Screen* screen) : screen_(screen) {
screen_->AddObserver(this);
}
Screen::~Screen() {
screen_->RemoveObserver(this);
}
gfx::Point Screen::GetCursorScreenPoint() {
return screen_->GetCursorScreenPoint();
}
gfx::Display Screen::GetPrimaryDisplay() {
return screen_->GetPrimaryDisplay();
}
std::vector<gfx::Display> Screen::GetAllDisplays() {
// The Screen::GetAllDisplays doesn't update when there is display added or
// removed, so we have to manually maintain the displays_ to make it up to
// date.
if (displays_.size() == 0)
displays_ = screen_->GetAllDisplays();
return displays_;
}
gfx::Display Screen::GetDisplayNearestPoint(const gfx::Point& point) {
return screen_->GetDisplayNearestPoint(point);
}
gfx::Display Screen::GetDisplayMatching(const gfx::Rect& match_rect) {
return screen_->GetDisplayMatching(match_rect);
}
void Screen::OnDisplayAdded(const gfx::Display& new_display) {
displays_.push_back(new_display);
Emit("display-added", new_display);
}
void Screen::OnDisplayRemoved(const gfx::Display& old_display) {
auto iter = FindById(&displays_, old_display.id());
if (iter == displays_.end())
return;
displays_.erase(iter);
Emit("display-removed", old_display);
}
void Screen::OnDisplayMetricsChanged(const gfx::Display& display,
uint32_t changed_metrics) {
auto iter = FindById(&displays_, display.id());
if (iter == displays_.end())
return;
*iter = display;
Emit("display-metrics-changed", display, MetricsToArray(changed_metrics));
}
mate::ObjectTemplateBuilder Screen::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
return mate::ObjectTemplateBuilder(isolate)
.SetMethod("getCursorScreenPoint", &Screen::GetCursorScreenPoint)
.SetMethod("getPrimaryDisplay", &Screen::GetPrimaryDisplay)
.SetMethod("getAllDisplays", &Screen::GetAllDisplays)
.SetMethod("getDisplayNearestPoint", &Screen::GetDisplayNearestPoint)
.SetMethod("getDisplayMatching", &Screen::GetDisplayMatching);
}
// static
v8::Handle<v8::Value> Screen::Create(v8::Isolate* isolate) {
if (!Browser::Get()->is_ready()) {
isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
isolate, "Can not initialize \"screen\" module before app is ready")));
return v8::Undefined(isolate);
}
gfx::Screen* screen = gfx::Screen::GetNativeScreen();
if (!screen) {
isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
isolate, "Failed to get screen information")));
return v8::Undefined(isolate);
}
return mate::CreateHandle(isolate, new Screen(screen)).ToV8();
}
} // namespace api
} // namespace atom
namespace {
void Initialize(v8::Handle<v8::Object> exports, v8::Handle<v8::Value> unused,
v8::Handle<v8::Context> context, void* priv) {
mate::Dictionary dict(context->GetIsolate(), exports);
dict.Set("screen", atom::api::Screen::Create(context->GetIsolate()));
}
} // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_common_screen, Initialize)

View File

@@ -0,0 +1,60 @@
// 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_API_ATOM_API_SCREEN_H_
#define ATOM_BROWSER_API_ATOM_API_SCREEN_H_
#include <vector>
#include "atom/browser/api/event_emitter.h"
#include "native_mate/handle.h"
#include "ui/gfx/display_observer.h"
namespace gfx {
class Point;
class Rect;
class Screen;
}
namespace atom {
namespace api {
class Screen : public mate::EventEmitter,
public gfx::DisplayObserver {
public:
static v8::Handle<v8::Value> Create(v8::Isolate* isolate);
protected:
explicit Screen(gfx::Screen* screen);
virtual ~Screen();
gfx::Point GetCursorScreenPoint();
gfx::Display GetPrimaryDisplay();
std::vector<gfx::Display> GetAllDisplays();
gfx::Display GetDisplayNearestPoint(const gfx::Point& point);
gfx::Display GetDisplayMatching(const gfx::Rect& match_rect);
// gfx::DisplayObserver:
void OnDisplayAdded(const gfx::Display& new_display) override;
void OnDisplayRemoved(const gfx::Display& old_display) override;
void OnDisplayMetricsChanged(const gfx::Display& display,
uint32_t changed_metrics) override;
// mate::Wrappable:
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override;
private:
gfx::Screen* screen_;
std::vector<gfx::Display> displays_;
DISALLOW_COPY_AND_ASSIGN(Screen);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_SCREEN_H_

View File

@@ -88,12 +88,7 @@ bool WebContents::AddMessageToConsole(content::WebContents* source,
const base::string16& message,
int32 line_no,
const base::string16& source_id) {
base::ListValue args;
args.AppendInteger(level);
args.AppendString(message);
args.AppendInteger(line_no);
args.AppendString(source_id);
Emit("console-message", args);
Emit("console-message", level, message, line_no, source_id);
return true;
}
@@ -105,11 +100,10 @@ bool WebContents::ShouldCreateWebContents(
const GURL& target_url,
const std::string& partition_id,
content::SessionStorageNamespace* session_storage_namespace) {
base::ListValue args;
args.AppendString(target_url.spec());
args.AppendString(frame_name);
args.AppendInteger(NEW_FOREGROUND_TAB);
Emit("-new-window", args);
Emit("-new-window",
target_url,
frame_name,
static_cast<int>(NEW_FOREGROUND_TAB));
return false;
}
@@ -121,18 +115,12 @@ content::WebContents* WebContents::OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) {
if (params.disposition != CURRENT_TAB) {
base::ListValue args;
args.AppendString(params.url.spec());
args.AppendString("");
args.AppendInteger(params.disposition);
Emit("-new-window", args);
Emit("-new-window", params.url, "", static_cast<int>(params.disposition));
return nullptr;
}
// Give user a chance to cancel navigation.
base::ListValue args;
args.AppendString(params.url.spec());
if (Emit("will-navigate", args))
if (Emit("will-navigate", params.url))
return nullptr;
content::NavigationController::LoadURLParams load_url_params(params.url);
@@ -164,6 +152,12 @@ void WebContents::EnumerateDirectory(content::WebContents* 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,
@@ -184,10 +178,9 @@ void WebContents::HandleKeyboardEvent(
}
void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) {
base::ListValue args;
args.AppendInteger(render_view_host->GetProcess()->GetID());
args.AppendInteger(render_view_host->GetRoutingID());
Emit("render-view-deleted", args);
Emit("render-view-deleted",
render_view_host->GetProcess()->GetID(),
render_view_host->GetRoutingID());
}
void WebContents::RenderProcessGone(base::TerminationStatus status) {
@@ -197,10 +190,7 @@ void WebContents::RenderProcessGone(base::TerminationStatus status) {
void WebContents::DidFinishLoad(content::RenderFrameHost* render_frame_host,
const GURL& validated_url) {
bool is_main_frame = !render_frame_host->GetParent();
base::ListValue args;
args.AppendBoolean(is_main_frame);
Emit("did-frame-finish-load", args);
Emit("did-frame-finish-load", is_main_frame);
if (is_main_frame)
Emit("did-finish-load");
@@ -210,10 +200,7 @@ void WebContents::DidFailLoad(content::RenderFrameHost* render_frame_host,
const GURL& validated_url,
int error_code,
const base::string16& error_description) {
base::ListValue args;
args.AppendInteger(error_code);
args.AppendString(error_description);
Emit("did-fail-load", args);
Emit("did-fail-load", error_code, error_description);
}
void WebContents::DidStartLoading(content::RenderViewHost* render_view_host) {
@@ -227,12 +214,10 @@ void WebContents::DidStopLoading(content::RenderViewHost* render_view_host) {
void WebContents::DidGetRedirectForResourceRequest(
content::RenderViewHost* render_view_host,
const content::ResourceRedirectDetails& details) {
base::ListValue args;
args.AppendString(details.url.spec());
args.AppendString(details.new_url.spec());
args.AppendBoolean(
details.resource_type == content::RESOURCE_TYPE_MAIN_FRAME);
Emit("did-get-redirect-request", args);
Emit("did-get-redirect-request",
details.url,
details.new_url,
(details.resource_type == content::RESOURCE_TYPE_MAIN_FRAME));
}
void WebContents::DidNavigateMainFrame(
@@ -433,6 +418,46 @@ bool WebContents::IsDevToolsOpened() {
return storage_->IsDevToolsViewShowing();
}
void WebContents::Undo() {
web_contents()->Undo();
}
void WebContents::Redo() {
web_contents()->Redo();
}
void WebContents::Cut() {
web_contents()->Cut();
}
void WebContents::Copy() {
web_contents()->Copy();
}
void WebContents::Paste() {
web_contents()->Paste();
}
void WebContents::Delete() {
web_contents()->Delete();
}
void WebContents::SelectAll() {
web_contents()->SelectAll();
}
void WebContents::Unselect() {
web_contents()->Unselect();
}
void WebContents::Replace(const base::string16& word) {
web_contents()->Replace(word);
}
void WebContents::ReplaceMisspelling(const base::string16& word) {
web_contents()->ReplaceMisspelling(word);
}
bool WebContents::SendIPCMessage(const base::string16& channel,
const base::ListValue& args) {
return Send(new AtomViewMsg_Message(routing_id(), channel, args));
@@ -503,13 +528,23 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
.SetMethod("setUserAgent", &WebContents::SetUserAgent)
.SetMethod("insertCSS", &WebContents::InsertCSS)
.SetMethod("_executeJavaScript", &WebContents::ExecuteJavaScript)
.SetMethod("openDevTools", &WebContents::OpenDevTools)
.SetMethod("closeDevTools", &WebContents::CloseDevTools)
.SetMethod("isDevToolsOpened", &WebContents::IsDevToolsOpened)
.SetMethod("undo", &WebContents::Undo)
.SetMethod("redo", &WebContents::Redo)
.SetMethod("cut", &WebContents::Cut)
.SetMethod("copy", &WebContents::Copy)
.SetMethod("paste", &WebContents::Paste)
.SetMethod("delete", &WebContents::Delete)
.SetMethod("selectAll", &WebContents::SelectAll)
.SetMethod("unselect", &WebContents::Unselect)
.SetMethod("replace", &WebContents::Replace)
.SetMethod("replaceMisspelling", &WebContents::ReplaceMisspelling)
.SetMethod("_send", &WebContents::SendIPCMessage)
.SetMethod("setAutoSize", &WebContents::SetAutoSize)
.SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency)
.SetMethod("isGuest", &WebContents::is_guest)
.SetMethod("openDevTools", &WebContents::OpenDevTools)
.SetMethod("closeDevTools", &WebContents::CloseDevTools)
.SetMethod("isDevToolsOpened", &WebContents::IsDevToolsOpened)
.Build());
return mate::ObjectTemplateBuilder(
@@ -526,17 +561,14 @@ void WebContents::OnRendererMessageSync(const base::string16& channel,
const base::ListValue& args,
IPC::Message* message) {
// webContents.emit(channel, new Event(sender, message), args...);
Emit(base::UTF16ToUTF8(channel), args, web_contents(), message);
EmitWithSender(base::UTF16ToUTF8(channel), web_contents(), message, args);
}
void WebContents::GuestSizeChangedDueToAutoSize(const gfx::Size& old_size,
const gfx::Size& new_size) {
base::ListValue args;
args.AppendInteger(old_size.width());
args.AppendInteger(old_size.height());
args.AppendInteger(new_size.width());
args.AppendInteger(new_size.height());
Emit("size-changed", args);
Emit("size-changed",
old_size.width(), old_size.height(),
new_size.width(), new_size.height());
}
// static

View File

@@ -67,6 +67,20 @@ class WebContents : public mate::EventEmitter,
void OpenDevTools();
void CloseDevTools();
bool IsDevToolsOpened();
// Editing commands.
void Undo();
void Redo();
void Cut();
void Copy();
void Paste();
void Delete();
void SelectAll();
void Unselect();
void Replace(const base::string16& word);
void ReplaceMisspelling(const base::string16& word);
// Sending messages to browser.
bool SendIPCMessage(const base::string16& channel,
const base::ListValue& args);
@@ -120,6 +134,9 @@ class WebContents : public mate::EventEmitter,
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&,

View File

@@ -8,6 +8,8 @@
#include "atom/browser/browser.h"
#include "atom/browser/native_window.h"
#include "atom/common/native_mate_converters/gfx_converter.h"
#include "atom/common/native_mate_converters/gurl_converter.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "content/public/browser/render_process_host.h"
#include "native_mate/callback.h"
#include "native_mate/constructor.h"
@@ -76,26 +78,18 @@ Window::~Window() {
void Window::OnPageTitleUpdated(bool* prevent_default,
const std::string& title) {
base::ListValue args;
args.AppendString(title);
*prevent_default = Emit("page-title-updated", args);
*prevent_default = Emit("page-title-updated", title);
}
void Window::WillCreatePopupWindow(const base::string16& frame_name,
const GURL& target_url,
const std::string& partition_id,
WindowOpenDisposition disposition) {
base::ListValue args;
args.AppendString(target_url.spec());
args.AppendString(frame_name);
args.AppendInteger(disposition);
Emit("-new-window", args);
Emit("-new-window", target_url, frame_name, static_cast<int>(disposition));
}
void Window::WillNavigate(bool* prevent_default, const GURL& url) {
base::ListValue args;
args.AppendString(url.spec());
*prevent_default = Emit("-will-navigate", args);
*prevent_default = Emit("-will-navigate", url);
}
void Window::WillCloseWindow(bool* prevent_default) {

View File

@@ -5,9 +5,6 @@
#include "atom/browser/api/event_emitter.h"
#include "atom/browser/api/event.h"
#include "atom/common/native_mate_converters/v8_value_converter.h"
#include "base/memory/scoped_ptr.h"
#include "base/values.h"
#include "native_mate/arguments.h"
#include "native_mate/object_template_builder.h"
@@ -41,43 +38,11 @@ v8::Local<v8::Object> CreateEventObject(v8::Isolate* isolate) {
EventEmitter::EventEmitter() {
}
bool EventEmitter::Emit(const base::StringPiece& name) {
return Emit(name, base::ListValue());
}
bool EventEmitter::Emit(const base::StringPiece& name,
const base::ListValue& args) {
return Emit(name, args, NULL, NULL);
}
bool EventEmitter::Emit(const base::StringPiece& name,
const base::ListValue& args,
content::WebContents* sender,
IPC::Message* message) {
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::Context> context = isolate->GetCurrentContext();
scoped_ptr<atom::V8ValueConverter> converter(new atom::V8ValueConverter);
// v8_args = [args...];
Arguments v8_args;
v8_args.reserve(args.GetSize());
for (size_t i = 0; i < args.GetSize(); i++) {
const base::Value* value(NULL);
if (args.Get(i, &value))
v8_args.push_back(converter->ToV8Value(value, context));
}
return Emit(isolate, name, v8_args, sender, message);
}
bool EventEmitter::Emit(v8::Isolate* isolate,
const base::StringPiece& name,
Arguments args,
content::WebContents* sender,
IPC::Message* message) {
bool EventEmitter::CallEmit(v8::Isolate* isolate,
const base::StringPiece& name,
content::WebContents* sender,
IPC::Message* message,
ValueArray args) {
v8::Handle<v8::Object> event;
bool use_native_event = sender && message;

View File

@@ -9,10 +9,6 @@
#include "native_mate/wrappable.h"
namespace base {
class ListValue;
}
namespace content {
class WebContents;
}
@@ -26,29 +22,39 @@ namespace mate {
// Provide helperers to emit event in JavaScript.
class EventEmitter : public Wrappable {
public:
typedef std::vector<v8::Handle<v8::Value>> Arguments;
typedef std::vector<v8::Handle<v8::Value>> ValueArray;
protected:
EventEmitter();
// this.emit(name, new Event());
bool Emit(const base::StringPiece& name);
// this.emit(name, new Event(), args...);
bool Emit(const base::StringPiece& name, const base::ListValue& args);
template<typename... Args>
bool Emit(const base::StringPiece& name, const Args&... args) {
return EmitWithSender(name, nullptr, nullptr, args...);
}
// this.emit(name, new Event(sender, message), args...);
bool Emit(const base::StringPiece& name, const base::ListValue& args,
content::WebContents* sender, IPC::Message* message);
template<typename... Args>
bool EmitWithSender(const base::StringPiece& name,
content::WebContents* sender,
IPC::Message* message,
const Args&... args) {
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
// Lower level implementations.
bool Emit(v8::Isolate* isolate,
const base::StringPiece& name,
Arguments args,
content::WebContents* sender = nullptr,
IPC::Message* message = nullptr);
ValueArray converted = { ConvertToV8(isolate, args)... };
return CallEmit(isolate, name, sender, message, converted);
}
private:
// Lower level implementations.
bool CallEmit(v8::Isolate* isolate,
const base::StringPiece& name,
content::WebContents* sender,
IPC::Message* message,
ValueArray args);
DISALLOW_COPY_AND_ASSIGN(EventEmitter);
};

View File

@@ -5,9 +5,6 @@ bindings = process.atomBinding 'app'
app = bindings.app
app.__proto__ = EventEmitter.prototype
app.getHomeDir = ->
process.env[if process.platform is 'win32' then 'USERPROFILE' else 'HOME']
app.setApplicationMenu = (menu) ->
require('menu').setApplicationMenu menu
@@ -32,6 +29,9 @@ if process.platform is 'darwin'
app.once 'ready', -> app.emit 'finish-launching'
app.terminate = app.quit
app.exit = process.exit
app.getHomeDir = -> app.getPath 'home'
app.getDataPath = -> app.getPath 'userData'
app.setDataPath = (path) -> app.setPath 'userData', path
# Only one App object pemitted.
module.exports = app

View File

@@ -0,0 +1,6 @@
EventEmitter = require('events').EventEmitter
screen = process.atomBinding('screen').screen
screen.__proto__ = EventEmitter.prototype
module.exports = screen

View File

@@ -9,8 +9,8 @@ module.exports.wrap = (webContents) ->
webContents.__proto__ = EventEmitter.prototype
# WebContents::send(channel, args..)
webContents.send = (args...) ->
@_send 'ATOM_INTERNAL_MESSAGE', [args...]
webContents.send = (channel, args...) ->
@_send channel, [args...]
# Make sure webContents.executeJavaScript would run the code only when the
# web contents has been loaded.
@@ -48,10 +48,12 @@ module.exports.wrap = (webContents) ->
process.emit 'ATOM_BROWSER_RELEASE_RENDER_VIEW', "#{processId}-#{routingId}"
# Dispatch IPC messages to the ipc module.
webContents.on 'ipc-message', (event, channel, args...) ->
webContents.on 'ipc-message', (event, packed) ->
[channel, args...] = packed
Object.defineProperty event, 'sender', value: webContents
ipc.emit channel, event, args...
webContents.on 'ipc-message-sync', (event, channel, args...) ->
webContents.on 'ipc-message-sync', (event, packed) ->
[channel, args...] = packed
Object.defineProperty event, 'returnValue', set: (value) -> event.sendReply JSON.stringify(value)
Object.defineProperty event, 'sender', value: webContents
ipc.emit channel, event, args...

View File

@@ -87,8 +87,8 @@ void AtomBrowserClient::OverrideWebkitPrefs(
prefs->allow_universal_access_from_file_urls = true;
prefs->allow_file_access_from_file_urls = true;
prefs->experimental_webgl_enabled = true;
prefs->allow_displaying_insecure_content = true;
prefs->allow_running_insecure_content = true;
prefs->allow_displaying_insecure_content = false;
prefs->allow_running_insecure_content = false;
// Turn off web security for devtools.
if (url.SchemeIs("chrome-devtools")) {

View File

@@ -72,6 +72,9 @@ void AtomBrowserMainParts::PostEarlyInitialization() {
// Add atom-shell extended APIs.
atom_bindings_->BindTo(js_env_->isolate(), global_env->process_object());
// Load everything.
node_bindings_->LoadEnvironment(global_env);
}
void AtomBrowserMainParts::PreMainMessageLoopRun() {

View File

@@ -41,6 +41,8 @@ if (option.file && !option.webdriver) {
app.setName(packageJson.productName);
else if (packageJson.name)
app.setName(packageJson.name);
app.setPath('userData', path.join(app.getPath('appData'), app.getName()));
app.setPath('userCache', path.join(app.getPath('cache'), app.getName()));
}
// Run the app.

View File

@@ -32,17 +32,11 @@ getExtensionInfoFromPath = (srcDirectory) ->
startPage: page
name: manifest.name
srcDirectory: srcDirectory
extensionInfoMap[manifest.name]
extensionInfoMap[manifest.name]
# Load persistented extensions.
loadedExtensionsPath = path.join app.getDataPath(), 'DevTools Extensions'
try
loadedExtensions = JSON.parse fs.readFileSync(loadedExtensionsPath)
loadedExtensions = [] unless Array.isArray loadedExtensions
# Preheat the extensionInfo cache.
getExtensionInfoFromPath srcDirectory for srcDirectory in loadedExtensions
catch e
# The loaded extensions cache and its persistent path.
loadedExtensions = null
loadedExtensionsPath = null
# Persistent loaded extensions.
app.on 'will-quit', ->
@@ -59,6 +53,16 @@ app.once 'ready', ->
protocol = require 'protocol'
BrowserWindow = require 'browser-window'
# Load persistented extensions.
loadedExtensionsPath = path.join app.getDataPath(), 'DevTools Extensions'
try
loadedExtensions = JSON.parse fs.readFileSync(loadedExtensionsPath)
loadedExtensions = [] unless Array.isArray loadedExtensions
# Preheat the extensionInfo cache.
getExtensionInfoFromPath srcDirectory for srcDirectory in loadedExtensions
catch e
# The chrome-extension: can map a extension URL request to real file path.
protocol.registerProtocol 'chrome-extension', (request) ->
parsed = url.parse request.url
@@ -74,8 +78,9 @@ app.once 'ready', ->
BrowserWindow.addDevToolsExtension = (srcDirectory) ->
extensionInfo = getExtensionInfoFromPath srcDirectory
window._loadDevToolsExtensions [extensionInfo] for window in BrowserWindow.getAllWindows()
extensionInfo.name
if extensionInfo
window._loadDevToolsExtensions [extensionInfo] for window in BrowserWindow.getAllWindows()
extensionInfo.name
BrowserWindow.removeDevToolsExtension = (name) ->
delete extensionInfoMap[name]

View File

@@ -68,7 +68,8 @@ createGuest = (embedder, params) ->
embedder.send "ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-#{guest.viewInstanceId}", event, args...
# Dispatch guest's IPC messages to embedder.
guest.on 'ipc-message-host', (_, channel, args...) ->
guest.on 'ipc-message-host', (_, packed) ->
[channel, args...] = packed
embedder.send "ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-#{guest.viewInstanceId}", channel, args...
# Autosize.
@@ -115,9 +116,8 @@ destroyGuest = (id) ->
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', (event, type, 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, requestId) ->
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', (event, elementInstanceId, guestInstanceId, params) ->
attachGuest event.sender, elementInstanceId, guestInstanceId, params
event.sender.send "ATOM_SHELL_RESPONSE_#{requestId}"
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', (event, id) ->
destroyGuest id

View File

@@ -23,75 +23,81 @@ process.argv.splice startMark, endMark - startMark + 1
globalPaths = module.globalPaths
globalPaths.push path.join process.resourcesPath, 'atom', 'browser', 'api', 'lib'
# Following operations need extra bindings by AtomBindings.
process.once 'BIND_DONE', ->
# Import common settings.
require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init.js')
# Import common settings.
require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init')
if process.platform is 'win32'
# Redirect node's console to use our own implementations, since node can not
# handle console output when running as GUI program.
print = (args...) ->
process.log util.format(args...)
console.log = console.error = console.warn = print
process.stdout.write = process.stderr.write = print
if process.platform is 'win32'
# Redirect node's console to use our own implementations, since node can not
# handle console output when running as GUI program.
print = (args...) ->
process.log util.format(args...)
console.log = console.error = console.warn = print
process.stdout.write = process.stderr.write = print
# Always returns EOF for stdin stream.
Readable = require('stream').Readable
stdin = new Readable
stdin.push null
process.__defineGetter__ 'stdin', -> stdin
# Always returns EOF for stdin stream.
Readable = require('stream').Readable
stdin = new Readable
stdin.push null
process.__defineGetter__ 'stdin', -> stdin
# Don't quit on fatal error.
process.on 'uncaughtException', (error) ->
# Show error in GUI.
stack = error.stack ? "#{error.name}: #{error.message}"
message = "Uncaught Exception:\n#{stack}"
require('dialog').showErrorBox 'A JavaScript error occured in the browser process', message
# Don't quit on fatal error.
process.on 'uncaughtException', (error) ->
# Do nothing if the user has a custom uncaught exception handler.
if process.listeners('uncaughtException').length > 1
return
# Emit 'exit' event on quit.
require('app').on 'quit', ->
process.emit 'exit'
# Show error in GUI.
stack = error.stack ? "#{error.name}: #{error.message}"
message = "Uncaught Exception:\n#{stack}"
require('dialog').showErrorBox 'A JavaScript error occured in the browser process', message
# Load the RPC server.
require './rpc-server'
# Emit 'exit' event on quit.
app = require 'app'
app.on 'quit', ->
process.emit 'exit'
# Load the guest view manager.
require './guest-view-manager'
require './guest-window-manager'
# Load the RPC server.
require './rpc-server'
# Now we try to load app's package.json.
packageJson = null
# Load the guest view manager.
require './guest-view-manager'
require './guest-window-manager'
searchPaths = [ 'app', 'app.asar', 'default_app' ]
for packagePath in searchPaths
try
packagePath = path.join process.resourcesPath, packagePath
packageJson = JSON.parse(fs.readFileSync(path.join(packagePath, 'package.json')))
break
catch e
continue
# Now we try to load app's package.json.
packageJson = null
throw new Error("Unable to find a valid app") unless packageJson?
searchPaths = [ 'app', 'app.asar', 'default_app' ]
for packagePath in searchPaths
try
packagePath = path.join process.resourcesPath, packagePath
packageJson = JSON.parse(fs.readFileSync(path.join(packagePath, 'package.json')))
break
catch e
continue
# Set application's version.
app = require 'app'
app.setVersion packageJson.version if packageJson.version?
throw new Error("Unable to find a valid app") unless packageJson?
# Set application's name.
if packageJson.productName?
app.setName packageJson.productName
else if packageJson.name?
app.setName packageJson.name
# Set application's version.
app.setVersion packageJson.version if packageJson.version?
# Set application's desktop name.
if packageJson.desktopName?
app.setDesktopName packageJson.desktopName
else
app.setDesktopName '#{app.getName()}.desktop'
# Set application's name.
if packageJson.productName?
app.setName packageJson.productName
else if packageJson.name?
app.setName packageJson.name
# Load the chrome extension support.
require './chrome-extension.js'
# Set application's desktop name.
if packageJson.desktopName?
app.setDesktopName packageJson.desktopName
else
app.setDesktopName "#{app.getName()}.desktop"
# Finally load app's main.js and transfer control to C++.
module._load path.join(packagePath, packageJson.main), module, true
# Set the user path according to application's name.
app.setPath 'userData', path.join(app.getPath('appData'), app.getName())
app.setPath 'userCache', path.join(app.getPath('cache'), app.getName())
# Load the chrome extension support.
require './chrome-extension'
# Finally load app's main.js and transfer control to C++.
module._load path.join(packagePath, packageJson.main), module, true

View File

@@ -32,6 +32,7 @@
#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"
@@ -60,6 +61,10 @@ using content::NavigationEntry;
using content::RenderWidgetHostView;
using content::RenderWidgetHost;
namespace content {
CONTENT_EXPORT extern bool g_use_transparent_window;
}
namespace atom {
namespace {
@@ -88,6 +93,7 @@ NativeWindow::NativeWindow(content::WebContents* web_contents,
const mate::Dictionary& options)
: content::WebContentsObserver(web_contents),
has_frame_(true),
transparent_(false),
enable_larger_than_screen_(false),
is_closed_(false),
node_integration_(true),
@@ -99,9 +105,14 @@ NativeWindow::NativeWindow(content::WebContents* web_contents,
printing::PrintViewManagerBasic::CreateForWebContents(web_contents);
options.Get(switches::kFrame, &has_frame_);
options.Get(switches::kTransparent, &transparent_);
options.Get(switches::kEnableLargerThanScreen, &enable_larger_than_screen_);
options.Get(switches::kNodeIntegration, &node_integration_);
// Tell the content module to initialize renderer widget with transparent
// mode.
content::g_use_transparent_window = transparent_;
// Read icon before window is created.
options.Get(switches::kIcon, &icon_);
@@ -560,6 +571,18 @@ content::JavaScriptDialogManager* NativeWindow::GetJavaScriptDialogManager() {
return dialog_manager_.get();
}
void NativeWindow::RenderViewCreated(
content::RenderViewHost* render_view_host) {
if (!transparent_)
return;
content::RenderWidgetHostImpl* impl = content::RenderWidgetHostImpl::FromID(
render_view_host->GetProcess()->GetID(),
render_view_host->GetRoutingID());
if (impl)
impl->SetBackgroundOpaque(false);
}
void NativeWindow::BeforeUnloadFired(content::WebContents* tab,
bool proceed,
bool* proceed_to_fire_unload) {

View File

@@ -269,6 +269,7 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
void RendererResponsive(content::WebContents* source) override;
// Implementations of content::WebContentsObserver.
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
void BeforeUnloadFired(const base::TimeTicks& proceed_time) override;
bool OnMessageReceived(const IPC::Message& message) override;
@@ -287,6 +288,9 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
// Whether window has standard frame.
bool has_frame_;
// Whether window is transparent.
bool transparent_;
// Whether window can be resized larger than screen.
bool enable_larger_than_screen_;

View File

@@ -26,52 +26,52 @@ class NativeWindowMac : public NativeWindow {
virtual ~NativeWindowMac();
// NativeWindow implementation.
virtual void Close() OVERRIDE;
virtual void CloseImmediately() OVERRIDE;
virtual void Move(const gfx::Rect& pos) OVERRIDE;
virtual void Focus(bool focus) OVERRIDE;
virtual bool IsFocused() OVERRIDE;
virtual void Show() OVERRIDE;
virtual void ShowInactive() OVERRIDE;
virtual void Hide() OVERRIDE;
virtual bool IsVisible() OVERRIDE;
virtual void Maximize() OVERRIDE;
virtual void Unmaximize() OVERRIDE;
virtual bool IsMaximized() OVERRIDE;
virtual void Minimize() OVERRIDE;
virtual void Restore() OVERRIDE;
virtual bool IsMinimized() OVERRIDE;
virtual void SetFullScreen(bool fullscreen) OVERRIDE;
virtual bool IsFullscreen() OVERRIDE;
virtual void SetSize(const gfx::Size& size) OVERRIDE;
virtual gfx::Size GetSize() OVERRIDE;
virtual void SetContentSize(const gfx::Size& size) OVERRIDE;
virtual gfx::Size GetContentSize() OVERRIDE;
virtual void SetMinimumSize(const gfx::Size& size) OVERRIDE;
virtual gfx::Size GetMinimumSize() OVERRIDE;
virtual void SetMaximumSize(const gfx::Size& size) OVERRIDE;
virtual gfx::Size GetMaximumSize() OVERRIDE;
virtual void SetResizable(bool resizable) OVERRIDE;
virtual bool IsResizable() OVERRIDE;
virtual void SetAlwaysOnTop(bool top) OVERRIDE;
virtual bool IsAlwaysOnTop() OVERRIDE;
virtual void Center() OVERRIDE;
virtual void SetPosition(const gfx::Point& position) OVERRIDE;
virtual gfx::Point GetPosition() OVERRIDE;
virtual void SetTitle(const std::string& title) OVERRIDE;
virtual std::string GetTitle() OVERRIDE;
virtual void FlashFrame(bool flash) OVERRIDE;
virtual void SetSkipTaskbar(bool skip) OVERRIDE;
virtual void SetKiosk(bool kiosk) OVERRIDE;
virtual bool IsKiosk() OVERRIDE;
virtual void SetRepresentedFilename(const std::string& filename) OVERRIDE;
virtual std::string GetRepresentedFilename() OVERRIDE;
virtual void SetDocumentEdited(bool edited) OVERRIDE;
virtual bool IsDocumentEdited() OVERRIDE;
virtual bool HasModalDialog() OVERRIDE;
virtual gfx::NativeWindow GetNativeWindow() OVERRIDE;
virtual void SetProgressBar(double progress) OVERRIDE;
virtual void ShowDefinitionForSelection() OVERRIDE;
void Close() override;
void CloseImmediately() override;
void Move(const gfx::Rect& pos) override;
void Focus(bool focus) override;
bool IsFocused() override;
void Show() override;
void ShowInactive() override;
void Hide() override;
bool IsVisible() override;
void Maximize() override;
void Unmaximize() override;
bool IsMaximized() override;
void Minimize() override;
void Restore() override;
bool IsMinimized() override;
void SetFullScreen(bool fullscreen) override;
bool IsFullscreen() override;
void SetSize(const gfx::Size& size) override;
gfx::Size GetSize() override;
void SetContentSize(const gfx::Size& size) override;
gfx::Size GetContentSize() override;
void SetMinimumSize(const gfx::Size& size) override;
gfx::Size GetMinimumSize() override;
void SetMaximumSize(const gfx::Size& size) override;
gfx::Size GetMaximumSize() override;
void SetResizable(bool resizable) override;
bool IsResizable() override;
void SetAlwaysOnTop(bool top) override;
bool IsAlwaysOnTop() override;
void Center() override;
void SetPosition(const gfx::Point& position) override;
gfx::Point GetPosition() override;
void SetTitle(const std::string& title) override;
std::string GetTitle() override;
void FlashFrame(bool flash) override;
void SetSkipTaskbar(bool skip) override;
void SetKiosk(bool kiosk) override;
bool IsKiosk() override;
void SetRepresentedFilename(const std::string& filename) override;
std::string GetRepresentedFilename() override;
void SetDocumentEdited(bool edited) override;
bool IsDocumentEdited() override;
bool HasModalDialog() override;
gfx::NativeWindow GetNativeWindow() override;
void SetProgressBar(double progress) override;
void ShowDefinitionForSelection() override;
// Returns true if |point| in local Cocoa coordinate system falls within
// the draggable region.
@@ -83,23 +83,22 @@ class NativeWindowMac : public NativeWindow {
// Clip web view to rounded corner.
void ClipWebView();
SkRegion* draggable_region() const { return draggable_region_.get(); }
protected:
virtual void UpdateDraggableRegions(
const std::vector<DraggableRegion>& regions) OVERRIDE;
void UpdateDraggableRegions(
const std::vector<DraggableRegion>& regions) override;
// Implementations of content::WebContentsDelegate.
virtual void HandleKeyboardEvent(
void HandleKeyboardEvent(
content::WebContents*,
const content::NativeWebKeyboardEvent&) OVERRIDE;
const content::NativeWebKeyboardEvent&) override;
private:
void InstallView();
void UninstallView();
void InstallDraggableRegionViews();
void UpdateDraggableRegionsForCustomDrag(
const std::vector<DraggableRegion>& regions);
// Install the drag view, which will cover the whole window and decides
// whehter we can drag.
void InstallDraggableRegionView();
base::scoped_nsobject<NSWindow> window_;
@@ -113,10 +112,6 @@ class NativeWindowMac : public NativeWindow {
// The presentation options before entering kiosk mode.
NSApplicationPresentationOptions kiosk_options_;
// For system drag, the whole window is draggable and the non-draggable areas
// have to been explicitly excluded.
std::vector<gfx::Rect> system_drag_exclude_areas_;
// For custom drag, the whole window is non-draggable and the draggable region
// has to been explicitly provided.
scoped_ptr<SkRegion> draggable_region_; // used in custom drag.

View File

@@ -101,7 +101,7 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
shell_->NotifyWindowBlur();
}
- (void)windowDidResize:(NSNotification*)otification {
- (void)windowDidResize:(NSNotification*)notification {
if (!shell_->has_frame())
shell_->ClipWebView();
}
@@ -280,6 +280,29 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
namespace atom {
namespace {
// Convert draggable regions in raw format to SkRegion format. Caller is
// responsible for deleting the returned SkRegion instance.
SkRegion* DraggableRegionsToSkRegion(
const std::vector<DraggableRegion>& regions) {
SkRegion* sk_region = new SkRegion;
for (std::vector<DraggableRegion>::const_iterator iter = regions.begin();
iter != regions.end();
++iter) {
const DraggableRegion& region = *iter;
sk_region->op(
region.bounds.x(),
region.bounds.y(),
region.bounds.right(),
region.bounds.bottom(),
region.draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op);
}
return sk_region;
}
} // namespace
NativeWindowMac::NativeWindowMac(content::WebContents* web_contents,
const mate::Dictionary& options)
: NativeWindow(web_contents, options),
@@ -296,9 +319,7 @@ NativeWindowMac::NativeWindowMac(content::WebContents* web_contents,
width,
height);
AtomNSWindow* atomWindow;
atomWindow = [[AtomNSWindow alloc]
AtomNSWindow* atomWindow = [[AtomNSWindow alloc]
initWithContentRect:cocoa_bounds
styleMask:NSTitledWindowMask | NSClosableWindowMask |
NSMiniaturizableWindowMask | NSResizableWindowMask |
@@ -314,6 +335,13 @@ NativeWindowMac::NativeWindowMac(content::WebContents* web_contents,
[[AtomNSWindowDelegate alloc] initWithShell:this];
[window_ setDelegate:delegate];
if (transparent_) {
// Make window has transparent background.
[window_ setOpaque:NO];
[window_ setHasShadow:NO];
[window_ setBackgroundColor:[NSColor clearColor]];
}
// We will manage window's lifetime ourselves.
[window_ setReleasedWhenClosed:NO];
@@ -542,6 +570,10 @@ gfx::Point NativeWindowMac::GetPosition() {
}
void NativeWindowMac::SetTitle(const std::string& title) {
// We don't want the title to show in transparent window.
if (transparent_)
return;
[window_ setTitle:base::SysUTF8ToNSString(title)];
}
@@ -659,7 +691,10 @@ void NativeWindowMac::ShowDefinitionForSelection() {
bool NativeWindowMac::IsWithinDraggableRegion(NSPoint point) const {
if (!draggable_region_)
return false;
NSView* webView = GetWebContents()->GetNativeView();
content::WebContents* web_contents = GetWebContents();
if (!web_contents)
return false;
NSView* webView = web_contents->GetNativeView();
NSInteger webViewHeight = NSHeight([webView bounds]);
// |draggable_region_| is stored in local platform-indepdent coordiate system
// while |point| is in local Cocoa coordinate system. Do the conversion
@@ -672,7 +707,6 @@ void NativeWindowMac::HandleMouseEvent(NSEvent* event) {
NSRect mouseRect = [window_ convertRectToScreen:NSMakeRect(eventLoc.x, eventLoc.y, 0, 0)];
NSPoint current_mouse_location = mouseRect.origin;
if ([event type] == NSLeftMouseDown) {
NSPoint frame_origin = [window_ frame].origin;
last_mouse_offset_ = NSMakePoint(
@@ -691,8 +725,7 @@ void NativeWindowMac::UpdateDraggableRegions(
if (has_frame_)
return;
UpdateDraggableRegionsForCustomDrag(regions);
InstallDraggableRegionViews();
draggable_region_.reset(DraggableRegionsToSkRegion(regions));
}
void NativeWindowMac::HandleKeyboardEvent(
@@ -749,11 +782,16 @@ void NativeWindowMac::InstallView() {
}
ClipWebView();
InstallDraggableRegionView();
[[window_ standardWindowButton:NSWindowZoomButton] setHidden:YES];
[[window_ standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
[[window_ standardWindowButton:NSWindowCloseButton] setHidden:YES];
[[window_ standardWindowButton:NSWindowFullScreenButton] setHidden:YES];
// Some third-party OS X utilities check the zoom button's enabled state to
// determine whether to show custom UI on hover, so we disable it here to
// prevent them from doing so in a frameless app window.
[[window_ standardWindowButton:NSWindowZoomButton] setEnabled:NO];
}
}
@@ -763,70 +801,19 @@ void NativeWindowMac::UninstallView() {
}
void NativeWindowMac::ClipWebView() {
NSView* view = GetWebContents()->GetNativeView();
view.layer.masksToBounds = YES;
view.layer.cornerRadius = kAtomWindowCornerRadius;
}
void NativeWindowMac::InstallDraggableRegionViews() {
DCHECK(!has_frame_);
// All ControlRegionViews should be added as children of the WebContentsView,
// because WebContentsView will be removed and re-added when entering and
// leaving fullscreen mode.
NSView* webView = GetWebContents()->GetNativeView();
NSInteger webViewHeight = NSHeight([webView bounds]);
// Remove all ControlRegionViews that are added last time.
// Note that [webView subviews] returns the view's mutable internal array and
// it should be copied to avoid mutating the original array while enumerating
// it.
base::scoped_nsobject<NSArray> subviews([[webView subviews] copy]);
for (NSView* subview in subviews.get())
if ([subview isKindOfClass:[ControlRegionView class]])
[subview removeFromSuperview];
// Create and add ControlRegionView for each region that needs to be excluded
// from the dragging.
for (std::vector<gfx::Rect>::const_iterator iter =
system_drag_exclude_areas_.begin();
iter != system_drag_exclude_areas_.end();
++iter) {
base::scoped_nsobject<NSView> controlRegion(
[[ControlRegionView alloc] initWithShellWindow:this]);
[controlRegion setFrame:NSMakeRect(iter->x(),
webViewHeight - iter->bottom(),
iter->width(),
iter->height())];
[webView addSubview:controlRegion];
}
webView.layer.masksToBounds = YES;
webView.layer.cornerRadius = kAtomWindowCornerRadius;
}
void NativeWindowMac::UpdateDraggableRegionsForCustomDrag(
const std::vector<DraggableRegion>& regions) {
// We still need one ControlRegionView to cover the whole window such that
// mouse events could be captured.
NSView* web_view = GetWebContents()->GetNativeView();
gfx::Rect window_bounds(
0, 0, NSWidth([web_view bounds]), NSHeight([web_view bounds]));
system_drag_exclude_areas_.clear();
system_drag_exclude_areas_.push_back(window_bounds);
// Aggregate the draggable areas and non-draggable areas such that hit test
// could be performed easily.
SkRegion* draggable_region = new SkRegion;
for (std::vector<DraggableRegion>::const_iterator iter = regions.begin();
iter != regions.end();
++iter) {
const DraggableRegion& region = *iter;
draggable_region->op(
region.bounds.x(),
region.bounds.y(),
region.bounds.right(),
region.bounds.bottom(),
region.draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op);
}
draggable_region_.reset(draggable_region);
void NativeWindowMac::InstallDraggableRegionView() {
NSView* webView = GetWebContents()->GetNativeView();
base::scoped_nsobject<NSView> controlRegion(
[[ControlRegionView alloc] initWithShellWindow:this]);
[controlRegion setFrame:NSMakeRect(0, 0,
NSWidth([webView bounds]),
NSHeight([webView bounds]))];
[webView addSubview:controlRegion];
}
// static

View File

@@ -28,6 +28,7 @@
#include "ui/views/window/client_view.h"
#include "ui/views/widget/native_widget_private.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/shadow_types.h"
#if defined(USE_X11)
#include "atom/browser/browser.h"
@@ -183,6 +184,9 @@ NativeWindowViews::NativeWindowViews(content::WebContents* web_contents,
params.type = views::Widget::InitParams::TYPE_WINDOW;
params.remove_standard_frame = !has_frame_;
if (transparent_)
params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
#if defined(USE_X11)
std::string name = Browser::Get()->GetName();
// Set WM_WINDOW_ROLE.
@@ -237,8 +241,18 @@ NativeWindowViews::NativeWindowViews(content::WebContents* web_contents,
// frameless.
DWORD frame_style = WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX |
WS_CAPTION;
// We should not show a frame for transparent window.
if (transparent_)
frame_style &= ~(WS_THICKFRAME | WS_CAPTION);
::SetWindowLong(GetAcceleratedWidget(), GWL_STYLE, frame_style);
}
if (transparent_) {
// Transparent window on Windows has to have WS_EX_COMPOSITED style.
LONG ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);
ex_style |= WS_EX_COMPOSITED;
::SetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE, ex_style);
}
#endif
// TODO(zcbenz): This was used to force using native frame on Windows 2003, we
@@ -248,6 +262,11 @@ NativeWindowViews::NativeWindowViews(content::WebContents* web_contents,
window_->FrameTypeChanged();
}
// The given window is most likely not rectangular since it uses
// transparency and has no standard frame, don't show a shadow for it.
if (transparent_ && !has_frame_)
wm::SetShadowType(GetNativeWindow(), wm::SHADOW_TYPE_NONE);
window_->UpdateWindowIcon();
window_->CenterWindow(bounds.size());
Layout();

View File

@@ -17,7 +17,7 @@
<key>CFBundleIconFile</key>
<string>atom.icns</string>
<key>CFBundleVersion</key>
<string>0.20.5</string>
<string>0.20.8</string>
<key>LSMinimumSystemVersion</key>
<string>10.8.0</string>
<key>NSMainNibFile</key>

View File

@@ -50,8 +50,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,20,5,0
PRODUCTVERSION 0,20,5,0
FILEVERSION 0,20,8,0
PRODUCTVERSION 0,20,8,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -68,12 +68,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "GitHub, Inc."
VALUE "FileDescription", "Atom-Shell"
VALUE "FileVersion", "0.20.5"
VALUE "FileVersion", "0.20.8"
VALUE "InternalName", "atom.exe"
VALUE "LegalCopyright", "Copyright (C) 2013 GitHub, Inc. All rights reserved."
VALUE "OriginalFilename", "atom.exe"
VALUE "ProductName", "Atom-Shell"
VALUE "ProductVersion", "0.20.5"
VALUE "ProductVersion", "0.20.8"
VALUE "SquirrelAwareVersion", "1"
END
END

View File

@@ -121,6 +121,9 @@ bool StringToAccelerator(const std::string& description,
modifiers |= ui::EF_ALT_DOWN;
} else if (tokens[i] == "shift") {
modifiers |= ui::EF_SHIFT_DOWN;
} else if (tokens[i] == "plus") {
modifiers |= ui::EF_SHIFT_DOWN;
key = ui::VKEY_OEM_PLUS;
} else if (tokens[i] == "tab") {
key = ui::VKEY_TAB;
} else if (tokens[i] == "space") {

View File

@@ -1,24 +0,0 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/common/native_mate_converters/gfx_converter.h"
#include "atom/common/node_includes.h"
namespace {
void Initialize(v8::Handle<v8::Object> exports, v8::Handle<v8::Value> unused,
v8::Handle<v8::Context> context, void* priv) {
gfx::Screen* screen = gfx::Screen::GetNativeScreen();
mate::Dictionary dict(context->GetIsolate(), exports);
dict.SetMethod("getCursorScreenPoint",
base::Bind(&gfx::Screen::GetCursorScreenPoint,
base::Unretained(screen)));
dict.SetMethod("getPrimaryDisplay",
base::Bind(&gfx::Screen::GetPrimaryDisplay,
base::Unretained(screen)));
}
} // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_common_screen, Initialize)

View File

@@ -11,7 +11,6 @@
#include "atom/common/chrome_version.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "base/logging.h"
#include "native_mate/callback.h"
#include "native_mate/dictionary.h"
#include "atom/common/node_includes.h"
@@ -20,20 +19,9 @@ namespace atom {
namespace {
// Async handle to execute the stored v8 callback.
uv_async_t g_callback_uv_handle;
// Stored v8 callback, to be called by the async handler.
base::Closure g_v8_callback;
// Dummy class type that used for crashing the program.
struct DummyClass { bool crash; };
// Async handler to execute the stored v8 callback.
void UvOnCallback(uv_async_t* handle) {
g_v8_callback.Run();
}
void Crash() {
static_cast<DummyClass*>(NULL)->crash = true;
}
@@ -49,19 +37,12 @@ void Log(const base::string16& message) {
logging::LogMessage("CONSOLE", 0, 0).stream() << message;
}
void ScheduleCallback(const base::Closure& callback) {
g_v8_callback = callback;
uv_async_send(&g_callback_uv_handle);
}
} // namespace
AtomBindings::AtomBindings() {
uv_async_init(uv_default_loop(), &call_next_tick_async_, OnCallNextTick);
call_next_tick_async_.data = this;
uv_async_init(uv_default_loop(), &g_callback_uv_handle, UvOnCallback);
}
AtomBindings::~AtomBindings() {
@@ -74,20 +55,14 @@ void AtomBindings::BindTo(v8::Isolate* isolate,
mate::Dictionary dict(isolate, process);
dict.SetMethod("crash", &Crash);
dict.SetMethod("log", &Log);
dict.SetMethod("scheduleCallback", &ScheduleCallback);
dict.SetMethod("activateUvLoop",
base::Bind(&AtomBindings::ActivateUVLoop, base::Unretained(this)));
v8::Handle<v8::Object> versions;
mate::Dictionary versions;
if (dict.Get("versions", &versions)) {
versions->Set(mate::StringToV8(isolate, "atom-shell"),
mate::StringToV8(isolate, ATOM_VERSION_STRING));
versions->Set(mate::StringToV8(isolate, "chrome"),
mate::StringToV8(isolate, CHROME_VERSION_STRING));
versions.Set("atom-shell", ATOM_VERSION_STRING);
versions.Set("chrome", CHROME_VERSION_STRING);
}
v8::Handle<v8::Value> event = mate::StringToV8(isolate, "BIND_DONE");
node::MakeCallback(isolate, process, "emit", 1, &event);
}
void AtomBindings::ActivateUVLoop(v8::Isolate* isolate) {

View File

@@ -24,7 +24,7 @@ class AtomBindings {
// Add process.atomBinding function, which behaves like process.binding but
// load native code from atom-shell instead.
virtual void BindTo(v8::Isolate* isolate, v8::Handle<v8::Object> process);
void BindTo(v8::Isolate* isolate, v8::Handle<v8::Object> process);
private:
void ActivateUVLoop(v8::Isolate* isolate);

View File

@@ -1,6 +1,8 @@
fs = require 'fs'
vm = require 'vm'
copied = {}
copied[k] = v for k, v of fs
module.exports = copied
# Execute the 'fs.js' and pass the 'exports' to it.
source = '(function (exports, require, module, __filename, __dirname) { ' +
process.binding('natives').fs +
'\n});'
fn = vm.runInThisContext source, { filename: 'fs.js' }
fn exports, require, module

View File

@@ -1,17 +0,0 @@
binding = process.atomBinding 'screen'
checkAppIsReady = ->
unless process.type is 'renderer' or require('app').isReady()
throw new Error('Can not use screen module before the "ready" event of app module gets emitted')
module.exports =
if process.platform in ['linux', 'win32'] and process.type is 'renderer'
# On Linux we could not access screen in renderer process.
require('remote').require 'screen'
else
getCursorScreenPoint: ->
checkAppIsReady()
binding.getCursorScreenPoint()
getPrimaryDisplay: ->
checkAppIsReady()
binding.getPrimaryDisplay()

View File

@@ -7,7 +7,7 @@
#define ATOM_MAJOR_VERSION 0
#define ATOM_MINOR_VERSION 20
#define ATOM_PATCH_VERSION 5
#define ATOM_PATCH_VERSION 8
#define ATOM_VERSION_IS_RELEASE 1

View File

@@ -35,8 +35,5 @@ if process.type is 'browser'
global.setTimeout = wrapWithActivateUvLoop timers.setTimeout
global.setInterval = wrapWithActivateUvLoop timers.setInterval
# Initialize the "original-fs" module before asar support is loaded.
require 'original-fs'
# Add support for asar packages.
require './asar'

View File

@@ -0,0 +1,110 @@
// 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/common/native_mate_converters/gfx_converter.h"
#include "native_mate/dictionary.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/size.h"
namespace mate {
v8::Handle<v8::Value> Converter<gfx::Point>::ToV8(v8::Isolate* isolate,
const gfx::Point& val) {
mate::Dictionary dict(isolate, v8::Object::New(isolate));
dict.Set("x", val.x());
dict.Set("y", val.y());
return dict.GetHandle();
}
bool Converter<gfx::Point>::FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
gfx::Point* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
int x, y;
if (!dict.Get("x", &x) || !dict.Get("y", &y))
return false;
*out = gfx::Point(x, y);
return true;
}
v8::Handle<v8::Value> Converter<gfx::Size>::ToV8(v8::Isolate* isolate,
const gfx::Size& val) {
mate::Dictionary dict(isolate, v8::Object::New(isolate));
dict.Set("width", val.width());
dict.Set("height", val.height());
return dict.GetHandle();
}
bool Converter<gfx::Size>::FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
gfx::Size* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
int width, height;
if (!dict.Get("width", &width) || !dict.Get("height", &height))
return false;
*out = gfx::Size(width, height);
return true;
}
v8::Handle<v8::Value> Converter<gfx::Rect>::ToV8(v8::Isolate* isolate,
const gfx::Rect& val) {
mate::Dictionary dict(isolate, v8::Object::New(isolate));
dict.Set("x", val.x());
dict.Set("y", val.y());
dict.Set("width", val.width());
dict.Set("height", val.height());
return dict.GetHandle();
}
bool Converter<gfx::Rect>::FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
gfx::Rect* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
int x, y, width, height;
if (!dict.Get("x", &x) || !dict.Get("y", &y) ||
!dict.Get("width", &width) || !dict.Get("height", &height))
return false;
*out = gfx::Rect(x, y, width, height);
return true;
}
template<>
struct Converter<gfx::Display::TouchSupport> {
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
const gfx::Display::TouchSupport& val) {
switch (val) {
case gfx::Display::TOUCH_SUPPORT_AVAILABLE:
return StringToV8(isolate, "available");
case gfx::Display::TOUCH_SUPPORT_UNAVAILABLE:
return StringToV8(isolate, "unavailable");
default:
return StringToV8(isolate, "unknown");
}
}
};
v8::Handle<v8::Value> Converter<gfx::Display>::ToV8(v8::Isolate* isolate,
const gfx::Display& val) {
mate::Dictionary dict(isolate, v8::Object::New(isolate));
dict.Set("id", val.id());
dict.Set("bounds", val.bounds());
dict.Set("workArea", val.work_area());
dict.Set("size", val.size());
dict.Set("workAreaSize", val.work_area_size());
dict.Set("scaleFactor", val.device_scale_factor());
dict.Set("rotation", val.RotationAsDegree());
dict.Set("touchSupport", val.touch_support());
return dict.GetHandle();
}
} // namespace mate

View File

@@ -5,95 +5,51 @@
#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_GFX_CONVERTER_H_
#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_GFX_CONVERTER_H_
#include "native_mate/dictionary.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/size.h"
#include "native_mate/converter.h"
namespace gfx {
class Point;
class Size;
class Rect;
class Display;
}
namespace mate {
template<>
struct Converter<gfx::Point> {
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
const gfx::Point& val) {
mate::Dictionary dict(isolate, v8::Object::New(isolate));
dict.Set("x", val.x());
dict.Set("y", val.y());
return dict.GetHandle();
}
static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
gfx::Point* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
int x, y;
if (!dict.Get("x", &x) || !dict.Get("y", &y))
return false;
*out = gfx::Point(x, y);
return true;
}
const gfx::Point& val);
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
gfx::Point* out);
};
template<>
struct Converter<gfx::Size> {
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
const gfx::Size& val) {
mate::Dictionary dict(isolate, v8::Object::New(isolate));
dict.Set("width", val.width());
dict.Set("height", val.height());
return dict.GetHandle();
}
static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
gfx::Size* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
int width, height;
if (!dict.Get("width", &width) || !dict.Get("height", &height))
return false;
*out = gfx::Size(width, height);
return true;
}
const gfx::Size& val);
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
gfx::Size* out);
};
template<>
struct Converter<gfx::Rect> {
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
const gfx::Rect& val) {
mate::Dictionary dict(isolate, v8::Object::New(isolate));
dict.Set("x", val.x());
dict.Set("y", val.y());
dict.Set("width", val.width());
dict.Set("height", val.height());
return dict.GetHandle();
}
static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
gfx::Rect* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
int x, y, width, height;
if (!dict.Get("x", &x) || !dict.Get("y", &y) ||
!dict.Get("width", &width) || !dict.Get("height", &height))
return false;
*out = gfx::Rect(x, y, width, height);
return true;
}
const gfx::Rect& val);
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
gfx::Rect* out);
};
template<>
struct Converter<gfx::Display> {
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
const gfx::Display& display) {
mate::Dictionary dict(isolate, v8::Object::New(isolate));
dict.Set("bounds", display.bounds());
dict.Set("workArea", display.work_area());
dict.Set("size", display.size());
dict.Set("workAreaSize", display.work_area_size());
dict.Set("scaleFactor", display.device_scale_factor());
return dict.GetHandle();
}
const gfx::Display& val);
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
gfx::Display* out);
};
} // namespace mate

View File

@@ -37,4 +37,11 @@ bool Converter<base::ListValue>::FromV8(v8::Isolate* isolate,
}
}
v8::Handle<v8::Value> Converter<base::ListValue>::ToV8(
v8::Isolate* isolate,
const base::ListValue& val) {
scoped_ptr<atom::V8ValueConverter> converter(new atom::V8ValueConverter);
return converter->ToV8Value(&val, isolate->GetCurrentContext());
}
} // namespace mate

View File

@@ -26,6 +26,8 @@ struct Converter<base::ListValue> {
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
base::ListValue* out);
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
const base::ListValue& val);
};
} // namespace mate

View File

@@ -26,9 +26,6 @@ using content::BrowserThread;
// Forward declaration of internal node functions.
namespace node {
void Init(int*, const char**, int*, const char***);
void Load(Environment* env);
void SetupProcessObject(Environment*, int, const char* const*, int,
const char* const*);
}
// Force all builtin modules to be referenced so they can actually run their
@@ -89,19 +86,6 @@ namespace {
void UvNoOp(uv_async_t* handle) {
}
// Moved from node.cc.
void HandleCloseCb(uv_handle_t* handle) {
node::Environment* env = reinterpret_cast<node::Environment*>(handle->data);
env->FinishHandleCleanup(handle);
}
void HandleCleanup(node::Environment* env,
uv_handle_t* handle,
void* arg) {
handle->data = env;
uv_close(handle, HandleCloseCb);
}
// Convert the given vector to an array of C-strings. The strings in the
// returned vector are only guaranteed valid so long as the vector of strings
// is not modified.
@@ -126,14 +110,14 @@ std::vector<std::string> String16VectorToStringVector(
} // namespace
node::Environment* global_env = NULL;
node::Environment* global_env = nullptr;
NodeBindings::NodeBindings(bool is_browser)
: is_browser_(is_browser),
message_loop_(NULL),
message_loop_(nullptr),
uv_loop_(uv_default_loop()),
embed_closed_(false),
uv_env_(NULL),
uv_env_(nullptr),
weak_factory_(this) {
}
@@ -158,20 +142,21 @@ void NodeBindings::Initialize() {
// Init node.
// (we assume it would not node::Init would not modify the parameters under
// embedded mode).
node::Init(NULL, NULL, NULL, NULL);
node::Init(nullptr, nullptr, nullptr, nullptr);
}
node::Environment* NodeBindings::CreateEnvironment(
v8::Handle<v8::Context> context) {
CommandLine* command_line = CommandLine::ForCurrentProcess();
std::vector<std::string> args =
#if defined(OS_WIN)
String16VectorToStringVector(CommandLine::ForCurrentProcess()->argv());
String16VectorToStringVector(command_line->argv());
#else
CommandLine::ForCurrentProcess()->argv();
command_line->argv();
#endif
// Feed node the path to initialization script.
base::FilePath exec_path(CommandLine::ForCurrentProcess()->argv()[0]);
base::FilePath exec_path(command_line->argv()[0]);
PathService::Get(base::FILE_EXE, &exec_path);
base::FilePath resources_path =
#if defined(OS_MACOSX)
@@ -179,77 +164,27 @@ node::Environment* NodeBindings::CreateEnvironment(
exec_path.DirName().DirName().DirName().DirName().DirName()
.Append("Resources");
#else
exec_path.DirName().AppendASCII("resources");
exec_path.DirName().Append(FILE_PATH_LITERAL("resources"));
#endif
base::FilePath script_path =
resources_path.AppendASCII("atom")
.AppendASCII(is_browser_ ? "browser" : "renderer")
.AppendASCII("lib")
.AppendASCII("init.js");
resources_path.Append(FILE_PATH_LITERAL("atom"))
.Append(is_browser_ ? FILE_PATH_LITERAL("browser") :
FILE_PATH_LITERAL("renderer"))
.Append(FILE_PATH_LITERAL("lib"))
.Append(FILE_PATH_LITERAL("init.js"));
std::string script_path_str = script_path.AsUTF8Unsafe();
args.insert(args.begin() + 1, script_path_str.c_str());
// Convert string vector to const char* array.
scoped_ptr<const char*[]> c_argv = StringVectorToArgArray(args);
return node::CreateEnvironment(context->GetIsolate(),
uv_default_loop(),
context,
args.size(), c_argv.get(),
0, nullptr);
}
// Construct the parameters that passed to node::CreateEnvironment:
v8::Isolate* isolate = context->GetIsolate();
uv_loop_t* loop = uv_default_loop();
int argc = args.size();
const char** argv = c_argv.get();
int exec_argc = 0;
const char** exec_argv = NULL;
using namespace v8; // NOLINT
using namespace node; // NOLINT
// Following code are stripped from node::CreateEnvironment in node.cc:
HandleScope handle_scope(isolate);
Context::Scope context_scope(context);
Environment* env = Environment::New(context, loop);
isolate->SetAutorunMicrotasks(false);
uv_check_init(env->event_loop(), env->immediate_check_handle());
uv_unref(
reinterpret_cast<uv_handle_t*>(env->immediate_check_handle()));
uv_idle_init(env->event_loop(), env->immediate_idle_handle());
uv_prepare_init(env->event_loop(), env->idle_prepare_handle());
uv_check_init(env->event_loop(), env->idle_check_handle());
uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_prepare_handle()));
uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_check_handle()));
// Register handle cleanups
env->RegisterHandleCleanup(
reinterpret_cast<uv_handle_t*>(env->immediate_check_handle()),
HandleCleanup,
nullptr);
env->RegisterHandleCleanup(
reinterpret_cast<uv_handle_t*>(env->immediate_idle_handle()),
HandleCleanup,
nullptr);
env->RegisterHandleCleanup(
reinterpret_cast<uv_handle_t*>(env->idle_prepare_handle()),
HandleCleanup,
nullptr);
env->RegisterHandleCleanup(
reinterpret_cast<uv_handle_t*>(env->idle_check_handle()),
HandleCleanup,
nullptr);
Local<FunctionTemplate> process_template = FunctionTemplate::New(isolate);
process_template->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "process"));
Local<Object> process_object = process_template->GetFunction()->NewInstance();
env->set_process_object(process_object);
SetupProcessObject(env, argc, argv, exec_argc, exec_argv);
LoadEnvironment(env);
return env;
void NodeBindings::LoadEnvironment(node::Environment* env) {
node::LoadEnvironment(env);
}
void NodeBindings::PrepareMessageLoop() {

View File

@@ -27,13 +27,16 @@ class NodeBindings {
virtual ~NodeBindings();
// Setup V8, libuv.
virtual void Initialize();
void Initialize();
// Create the environment and load node.js.
virtual node::Environment* CreateEnvironment(v8::Handle<v8::Context> context);
node::Environment* CreateEnvironment(v8::Handle<v8::Context> context);
// Load node.js in the environment.
void LoadEnvironment(node::Environment* env);
// Prepare for message loop integration.
virtual void PrepareMessageLoop();
void PrepareMessageLoop();
// Do message loop integration.
virtual void RunMessageLoop();

View File

@@ -15,13 +15,13 @@ class NodeBindingsLinux : public NodeBindings {
explicit NodeBindingsLinux(bool is_browser);
virtual ~NodeBindingsLinux();
virtual void RunMessageLoop() OVERRIDE;
void RunMessageLoop() override;
private:
// Called when uv's watcher queue changes.
static void OnWatcherQueueChanged(uv_loop_t* loop);
virtual void PollEvents() OVERRIDE;
void PollEvents() override;
// Epoll to poll for uv's backend fd.
int epoll_;

View File

@@ -15,13 +15,13 @@ class NodeBindingsMac : public NodeBindings {
explicit NodeBindingsMac(bool is_browser);
virtual ~NodeBindingsMac();
virtual void RunMessageLoop() OVERRIDE;
void RunMessageLoop() override;
private:
// Called when uv's watcher queue changes.
static void OnWatcherQueueChanged(uv_loop_t* loop);
virtual void PollEvents() OVERRIDE;
void PollEvents() override;
// Kqueue to poll for uv's backend fd.
int kqueue_;

View File

@@ -16,7 +16,7 @@ class NodeBindingsWin : public NodeBindings {
virtual ~NodeBindingsWin();
private:
virtual void PollEvents() OVERRIDE;
void PollEvents() override;
DISALLOW_COPY_AND_ASSIGN(NodeBindingsWin);
};

View File

@@ -7,6 +7,7 @@
// Include common headers for using node APIs.
#undef ASSERT
#undef CHECK
#undef CHECK_EQ
#undef CHECK_NE
@@ -15,6 +16,7 @@
#undef CHECK_LE
#undef CHECK_LT
#undef DISALLOW_COPY_AND_ASSIGN
#undef NO_RETURN
#undef debug_string // This is defined in OS X 10.9 SDK in AssertMacros.h.
#include "vendor/node/src/env.h"
#include "vendor/node/src/env-inl.h"

View File

@@ -69,6 +69,9 @@ const char kGuestInstanceID[] = "guest-instance-id";
// Script that will be loaded by guest WebContents before other scripts.
const char kPreloadScript[] = "preload";
// Whether the window should be transparent.
const char kTransparent[] = "transparent";
// Web runtime features.
const char kExperimentalFeatures[] = "experimental-features";
const char kExperimentalCanvasFeatures[] = "experimental-canvas-features";

View File

@@ -39,6 +39,7 @@ extern const char kDirectWrite[];
extern const char kEnablePlugins[];
extern const char kGuestInstanceID[];
extern const char kPreloadScript[];
extern const char kTransparent[];
extern const char kExperimentalFeatures[];
extern const char kExperimentalCanvasFeatures[];

View File

@@ -4,6 +4,12 @@
#include "atom/renderer/api/atom_api_web_frame.h"
// This defines are required by SchemeRegistry.h.
#define ALWAYS_INLINE inline
#define OS(WTF_FEATURE) (defined WTF_OS_##WTF_FEATURE && WTF_OS_##WTF_FEATURE) // NOLINT
#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/string16_converter.h"
#include "atom/renderer/api/atom_api_spell_check_client.h"
#include "content/public/renderer/render_frame.h"
@@ -12,9 +18,28 @@
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "third_party/WebKit/Source/platform/weborigin/SchemeRegistry.h"
#include "atom/common/node_includes.h"
namespace mate {
template<>
struct Converter<WTF::String> {
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
WTF::String* out) {
if (!val->IsString())
return false;
v8::String::Value s(val);
*out = WTF::String(reinterpret_cast<const base::char16*>(*s), s.length());
return true;
}
};
} // namespace mate
namespace atom {
namespace api {
@@ -82,7 +107,9 @@ mate::ObjectTemplateBuilder WebFrame::GetObjectTemplateBuilder(
.SetMethod("registerEmbedderCustomElement",
&WebFrame::RegisterEmbedderCustomElement)
.SetMethod("attachGuest", &WebFrame::AttachGuest)
.SetMethod("setSpellCheckProvider", &WebFrame::SetSpellCheckProvider);
.SetMethod("setSpellCheckProvider", &WebFrame::SetSpellCheckProvider)
.SetMethod("registerUrlSchemeAsSecure",
&blink::SchemeRegistry::registerURLSchemeAsSecure);
}
// static

View File

@@ -1,84 +0,0 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/renderer/api/atom_renderer_bindings.h"
#include <vector>
#include "atom/common/native_mate_converters/string16_converter.h"
#include "atom/common/native_mate_converters/v8_value_converter.h"
#include "base/memory/scoped_ptr.h"
#include "base/values.h"
#include "content/public/renderer/render_view.h"
#include "native_mate/converter.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "atom/common/node_includes.h"
namespace atom {
namespace {
v8::Handle<v8::Object> GetProcessObject(v8::Handle<v8::Context> context) {
v8::Handle<v8::Object> process = context->Global()->Get(
mate::StringToV8(context->GetIsolate(), "process"))->ToObject();
DCHECK(!process.IsEmpty());
return process;
}
} // namespace
AtomRendererBindings::AtomRendererBindings() {
}
AtomRendererBindings::~AtomRendererBindings() {
}
void AtomRendererBindings::BindToFrame(blink::WebFrame* frame) {
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
if (context.IsEmpty())
return;
v8::Context::Scope scope(context);
AtomBindings::BindTo(isolate, GetProcessObject(context));
}
void AtomRendererBindings::OnBrowserMessage(content::RenderView* render_view,
const base::string16& channel,
const base::ListValue& args) {
if (!render_view->GetWebView())
return;
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context =
render_view->GetWebView()->mainFrame()->mainWorldScriptContext();
if (context.IsEmpty())
return;
v8::Context::Scope context_scope(context);
v8::Handle<v8::Object> process = GetProcessObject(context);
scoped_ptr<V8ValueConverter> converter(new V8ValueConverter);
std::vector<v8::Handle<v8::Value>> arguments;
arguments.reserve(1 + args.GetSize());
arguments.push_back(mate::ConvertToV8(isolate, channel));
for (size_t i = 0; i < args.GetSize(); i++) {
const base::Value* value;
if (args.Get(i, &value))
arguments.push_back(converter->ToV8Value(value, context));
}
node::MakeCallback(isolate, process, "emit", arguments.size(), &arguments[0]);
}
} // namespace atom

View File

@@ -1,45 +0,0 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_RENDERER_API_ATOM_RENDERER_BINDINGS_H_
#define ATOM_RENDERER_API_ATOM_RENDERER_BINDINGS_H_
#include "atom/common/api/atom_bindings.h"
#include "base/strings/string16.h"
namespace base {
class ListValue;
}
namespace content {
class RenderView;
}
namespace blink {
class WebFrame;
}
namespace atom {
class AtomRendererBindings : public AtomBindings {
public:
AtomRendererBindings();
virtual ~AtomRendererBindings();
// Call BindTo for process object of the frame.
void BindToFrame(blink::WebFrame* frame);
// Dispatch messages from browser.
void OnBrowserMessage(content::RenderView* render_view,
const base::string16& channel,
const base::ListValue& args);
private:
DISALLOW_COPY_AND_ASSIGN(AtomRendererBindings);
};
} // namespace atom
#endif // ATOM_RENDERER_API_ATOM_RENDERER_BINDINGS_H_

View File

@@ -1,26 +1,20 @@
EventEmitter = require('events').EventEmitter
process = global.process
ipc = process.atomBinding('ipc')
binding = process.atomBinding 'ipc'
v8Util = process.atomBinding 'v8_util'
class Ipc extends EventEmitter
constructor: ->
process.on 'ATOM_INTERNAL_MESSAGE', (args...) =>
@emit args...
# Created by init.coffee.
ipc = v8Util.getHiddenValue global, 'ipc'
window.addEventListener 'unload', (event) ->
process.removeAllListeners 'ATOM_INTERNAL_MESSAGE'
ipc.send = (args...) ->
binding.send 'ipc-message', [args...]
send: (args...) ->
ipc.send 'ipc-message', [args...]
ipc.sendSync = (args...) ->
JSON.parse binding.sendSync('ipc-message-sync', [args...])
sendSync: (args...) ->
JSON.parse ipc.sendSync('ipc-message-sync', [args...])
ipc.sendToHost = (args...) ->
binding.send 'ipc-message-host', [args...]
sendToHost: (args...) ->
ipc.send 'ipc-message-host', [args...]
# Deprecated.
ipc.sendChannel = ipc.send
ipc.sendChannelSync = ipc.sendSync
# Discarded
sendChannel: -> @send.apply this, arguments
sendChannelSync: -> @sendSync.apply this, arguments
module.exports = new Ipc
module.exports = ipc

View File

@@ -0,0 +1 @@
module.exports = require('remote').require('screen')

View File

@@ -8,8 +8,9 @@
#include <vector>
#include "atom/common/api/api_messages.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "atom/common/options_switches.h"
#include "atom/renderer/api/atom_renderer_bindings.h"
#include "atom/renderer/atom_renderer_client.h"
#include "base/command_line.h"
#include "base/strings/string_number_conversions.h"
@@ -19,19 +20,43 @@
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebKit.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "atom/common/node_includes.h"
using blink::WebFrame;
namespace atom {
namespace {
bool GetIPCObject(v8::Isolate* isolate,
v8::Handle<v8::Context> context,
v8::Handle<v8::Object>* ipc) {
v8::Handle<v8::String> key = mate::StringToV8(isolate, "ipc");
v8::Handle<v8::Value> value = context->Global()->GetHiddenValue(key);
if (value.IsEmpty() || !value->IsObject())
return false;
*ipc = value->ToObject();
return true;
}
std::vector<v8::Handle<v8::Value>> ListValueToVector(
v8::Isolate* isolate,
const base::ListValue& list) {
v8::Handle<v8::Value> array = mate::ConvertToV8(isolate, list);
std::vector<v8::Handle<v8::Value>> result;
mate::ConvertFromV8(isolate, array, &result);
return result;
}
} // namespace
AtomRenderViewObserver::AtomRenderViewObserver(
content::RenderView* render_view,
AtomRendererClient* renderer_client)
: content::RenderViewObserver(render_view),
renderer_client_(renderer_client) {
renderer_client_(renderer_client),
document_created_(false) {
}
AtomRenderViewObserver::~AtomRenderViewObserver() {
@@ -39,6 +64,8 @@ AtomRenderViewObserver::~AtomRenderViewObserver() {
void AtomRenderViewObserver::DidCreateDocumentElement(
blink::WebLocalFrame* frame) {
document_created_ = true;
// Read --zoom-factor from command line.
std::string zoom_factor_str = CommandLine::ForCurrentProcess()->
GetSwitchValueASCII(switches::kZoomFactor);;
@@ -76,8 +103,29 @@ bool AtomRenderViewObserver::OnMessageReceived(const IPC::Message& message) {
void AtomRenderViewObserver::OnBrowserMessage(const base::string16& channel,
const base::ListValue& args) {
renderer_client_->atom_bindings()->OnBrowserMessage(
render_view(), channel, args);
if (!document_created_)
return;
if (!render_view()->GetWebView())
return;
blink::WebFrame* frame = render_view()->GetWebView()->mainFrame();
if (!frame || frame->isWebRemoteFrame())
return;
v8::Isolate* isolate = blink::mainThreadIsolate();
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = frame->mainWorldScriptContext();
v8::Context::Scope context_scope(context);
std::vector<v8::Handle<v8::Value>> arguments = ListValueToVector(
isolate, args);
arguments.insert(arguments.begin(), mate::ConvertToV8(isolate, channel));
v8::Handle<v8::Object> ipc;
if (GetIPCObject(isolate, context, &ipc))
node::MakeCallback(isolate, ipc, "emit", arguments.size(), &arguments[0]);
}
} // namespace atom

View File

@@ -36,6 +36,9 @@ class AtomRenderViewObserver : public content::RenderViewObserver {
// Weak reference to renderer client.
AtomRendererClient* renderer_client_;
// Whether the document object has been created.
bool document_created_;
DISALLOW_COPY_AND_ASSIGN(AtomRenderViewObserver);
};

View File

@@ -4,21 +4,17 @@
#include "atom/renderer/atom_renderer_client.h"
#include <algorithm>
#include <string>
#include "atom/common/api/atom_bindings.h"
#include "atom/common/node_bindings.h"
#include "atom/common/options_switches.h"
#include "atom/renderer/api/atom_renderer_bindings.h"
#include "atom/renderer/atom_render_view_observer.h"
#include "chrome/renderer/printing/print_web_view_helper.h"
#include "chrome/renderer/tts_dispatcher.h"
#include "content/public/common/content_constants.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_frame_observer.h"
#include "content/public/renderer/render_thread.h"
#include "base/command_line.h"
#include "native_mate/converter.h"
#include "third_party/WebKit/public/web/WebCustomElement.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebPluginParams.h"
@@ -44,33 +40,12 @@ bool IsSwitchEnabled(base::CommandLine* command_line,
return true;
}
// Helper class to forward the WillReleaseScriptContext message to the client.
class AtomRenderFrameObserver : public content::RenderFrameObserver {
public:
AtomRenderFrameObserver(content::RenderFrame* frame,
AtomRendererClient* renderer_client)
: content::RenderFrameObserver(frame),
renderer_client_(renderer_client) {}
// content::RenderFrameObserver:
virtual void WillReleaseScriptContext(v8::Handle<v8::Context> context,
int world_id) OVERRIDE {
renderer_client_->WillReleaseScriptContext(
render_frame()->GetWebFrame(), context, world_id);
}
private:
AtomRendererClient* renderer_client_;
DISALLOW_COPY_AND_ASSIGN(AtomRenderFrameObserver);
};
} // namespace
AtomRendererClient::AtomRendererClient()
: node_bindings_(NodeBindings::Create(false)),
atom_bindings_(new AtomRendererBindings),
main_frame_(NULL) {
atom_bindings_(new AtomBindings),
main_frame_(nullptr) {
}
AtomRendererClient::~AtomRendererClient() {
@@ -99,11 +74,6 @@ void AtomRendererClient::RenderThreadStarted() {
content::RenderThread::Get()->AddObserver(this);
}
void AtomRendererClient::RenderFrameCreated(
content::RenderFrame* render_frame) {
new AtomRenderFrameObserver(render_frame, this);
}
void AtomRendererClient::RenderViewCreated(content::RenderView* render_view) {
new printing::PrintWebViewHelper(render_view);
new AtomRenderViewObserver(render_view, this);
@@ -132,17 +102,13 @@ void AtomRendererClient::DidCreateScriptContext(blink::WebFrame* frame,
v8::Handle<v8::Context> context,
int extension_group,
int world_id) {
// The first web frame is the main frame.
if (main_frame_ == NULL)
main_frame_ = frame;
v8::Context::Scope scope(context);
// Check the existance of process object to prevent duplicate initialization.
if (context->Global()->Has(
mate::StringToV8(context->GetIsolate(), "process")))
// Only attach node bindings in main frame.
if (main_frame_)
return;
// The first web frame is the main frame.
main_frame_ = frame;
// Give the node loop a run to make sure everything is ready.
node_bindings_->RunMessageLoop();
@@ -150,46 +116,14 @@ void AtomRendererClient::DidCreateScriptContext(blink::WebFrame* frame,
node::Environment* env = node_bindings_->CreateEnvironment(context);
// Add atom-shell extended APIs.
atom_bindings_->BindToFrame(frame);
// Store the created environment.
web_page_envs_.push_back(env);
atom_bindings_->BindTo(env->isolate(), env->process_object());
// Make uv loop being wrapped by window context.
if (node_bindings_->uv_env() == NULL)
if (node_bindings_->uv_env() == nullptr)
node_bindings_->set_uv_env(env);
}
void AtomRendererClient::WillReleaseScriptContext(
blink::WebLocalFrame* frame,
v8::Handle<v8::Context> context,
int world_id) {
node::Environment* env = node::Environment::GetCurrent(context);
if (env == NULL) {
LOG(ERROR) << "Encounter a non-node context when releasing script context";
return;
}
// Clear the environment.
web_page_envs_.erase(
std::remove(web_page_envs_.begin(), web_page_envs_.end(), env),
web_page_envs_.end());
// Notice that we are not disposing the environment object here, because there
// may still be pending uv operations in the uv loop, and when they got done
// they would be needing the original environment.
// So we are leaking the environment object here, just like Chrome leaking the
// memory :) . Since it's only leaked when refreshing or unloading, so as long
// as we make sure renderer process is restared then the memory would not be
// leaked.
// env->Dispose();
// Wrap the uv loop with another environment.
if (env == node_bindings_->uv_env()) {
node::Environment* env = web_page_envs_.size() > 0 ? web_page_envs_[0] :
NULL;
node_bindings_->set_uv_env(env);
}
// Load everything.
node_bindings_->LoadEnvironment(env);
}
bool AtomRendererClient::ShouldFork(blink::WebFrame* frame,

View File

@@ -6,18 +6,13 @@
#define ATOM_RENDERER_ATOM_RENDERER_CLIENT_H_
#include <string>
#include <vector>
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/renderer/render_process_observer.h"
namespace node {
class Environment;
}
namespace atom {
class AtomRendererBindings;
class AtomBindings;
class NodeBindings;
class AtomRendererClient : public content::ContentRendererClient,
@@ -26,13 +21,6 @@ class AtomRendererClient : public content::ContentRendererClient,
AtomRendererClient();
virtual ~AtomRendererClient();
// Forwarded by RenderFrameObserver.
void WillReleaseScriptContext(blink::WebLocalFrame* frame,
v8::Handle<v8::Context> context,
int world_id);
AtomRendererBindings* atom_bindings() const { return atom_bindings_.get(); }
private:
enum NodeIntegration {
ALL,
@@ -42,11 +30,10 @@ class AtomRendererClient : public content::ContentRendererClient,
};
// content::RenderProcessObserver:
virtual void WebKitInitialized() OVERRIDE;
void WebKitInitialized() override;
// content::ContentRendererClient:
void RenderThreadStarted() override;
void RenderFrameCreated(content::RenderFrame* render_frame) override;
void RenderViewCreated(content::RenderView*) override;
blink::WebSpeechSynthesizer* OverrideSpeechSynthesizer(
blink::WebSpeechSynthesizerClient* client) override;
@@ -67,10 +54,8 @@ class AtomRendererClient : public content::ContentRendererClient,
void EnableWebRuntimeFeatures();
std::vector<node::Environment*> web_page_envs_;
scoped_ptr<NodeBindings> node_bindings_;
scoped_ptr<AtomRendererBindings> atom_bindings_;
scoped_ptr<AtomBindings> atom_bindings_;
// The main frame.
blink::WebFrame* main_frame_;

View File

@@ -1,4 +1,5 @@
process = global.process
events = require 'events'
path = require 'path'
url = require 'url'
Module = require 'module'
@@ -19,7 +20,11 @@ globalPaths.push path.join(process.resourcesPath, 'atom', 'renderer', 'api', 'li
globalPaths.push path.join(process.resourcesPath, 'app')
# Import common settings.
require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init.js')
require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init')
# The global variable will be used by ipc for event dispatching
v8Util = process.atomBinding 'v8_util'
v8Util.setHiddenValue global, 'ipc', new events.EventEmitter
# Process command line arguments.
nodeIntegration = 'false'
@@ -86,9 +91,12 @@ if nodeIntegration in ['true', 'all', 'except-iframe', 'manual-enable-iframe']
window.addEventListener 'unload', ->
process.emit 'exit'
else
# There still some native initialization codes needs "process", delete the
# global reference after they are done.
process.once 'BIND_DONE', ->
# 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 global.process
delete global.setImmediate
delete global.clearImmediate

View File

@@ -45,10 +45,8 @@ module.exports =
ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', type, params, requestId
ipc.once "ATOM_SHELL_RESPONSE_#{requestId}", callback
attachGuest: (elementInstanceId, guestInstanceId, params, callback) ->
requestId++
ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', elementInstanceId, guestInstanceId, params, requestId
ipc.once "ATOM_SHELL_RESPONSE_#{requestId}", callback
attachGuest: (elementInstanceId, guestInstanceId, params) ->
ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', elementInstanceId, guestInstanceId, params
webFrame.attachGuest elementInstanceId
destroyGuest: (guestInstanceId) ->

View File

@@ -22,8 +22,5 @@ module.exports =
ERROR_MSG_ALREADY_NAVIGATED: 'The object has already navigated, so its partition cannot be changed.'
ERROR_MSG_CANNOT_INJECT_SCRIPT: '<webview>: ' +
'Script cannot be injected into content until the page has loaded.'
ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE: '<webview>: ' +
'contentWindow is not available at this time. It will become available ' +
'when the page has finished loading.'
ERROR_MSG_INVALID_PARTITION_ATTRIBUTE: 'Invalid partition attribute.'
ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE: 'Only "file:" or "asar:" protocol is supported in "preload" attribute.'

View File

@@ -17,7 +17,6 @@ class WebViewImpl
@elementAttached = false
@beforeFirstNavigation = true
@contentWindow = null
# on* Event handlers.
@on = {}
@@ -26,7 +25,6 @@ class WebViewImpl
shadowRoot = @webviewNode.createShadowRoot()
@setupWebViewAttributes()
@setupFocusPropagation()
@setupWebviewNodeProperties()
@viewInstanceId = getNextId()
@@ -54,7 +52,6 @@ class WebViewImpl
@guestInstanceId = undefined
@beforeFirstNavigation = true
@attributes[webViewConstants.ATTRIBUTE_PARTITION].validPartitionId = true
@contentWindow = null
@internalInstanceId = 0
# Sets the <webview>.request property.
@@ -75,16 +72,6 @@ class WebViewImpl
# Blur the BrowserPlugin when the <webview> loses focus.
@browserPluginNode.blur()
setupWebviewNodeProperties: ->
# We cannot use {writable: true} property descriptor because we want a
# dynamic getter value.
Object.defineProperty @webviewNode, 'contentWindow',
get: =>
return @contentWindow if @contentWindow?
window.console.error webViewConstants.ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE
# No setter.
enumerable: true
# This observer monitors mutations to attributes of the <webview> and
# updates the BrowserPlugin properties accordingly. In turn, updating
# a BrowserPlugin property will update the corresponding BrowserPlugin
@@ -104,7 +91,7 @@ class WebViewImpl
return unless @guestInstanceId
guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, @buildAttachParams(), (w) => @contentWindow = w
guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, @buildAttachParams()
onSizeChanged: (webViewEvent) ->
newWidth = webViewEvent.newWidth
@@ -189,7 +176,7 @@ class WebViewImpl
return true unless @internalInstanceId
guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, params, (w) => @contentWindow = w
guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, params
# Registers browser plugin <object> custom element.
registerBrowserPluginElement = ->
@@ -267,6 +254,16 @@ registerWebViewElement = ->
"openDevTools"
"closeDevTools"
"isDevToolsOpened"
"undo"
"redo"
"cut"
"copy"
"paste"
"delete"
"selectAll"
"unselect"
"replace"
"replaceMisspelling"
"send"
"getId"
]

View File

@@ -130,6 +130,14 @@
}], # OS=="linux"
],
}],
['_type in ["executable", "shared_library"]', {
# On some machines setting CLANG_CXX_LIBRARY doesn't work for linker.
'xcode_settings': {
'OTHER_LDFLAGS': [
'-stdlib=libc++'
],
},
}],
],
'msvs_cygwin_shell': 0, # Strangely setting it to 1 would make building under cygwin fail.
'msvs_disabled_warnings': [
@@ -184,21 +192,18 @@
],
'target_defaults': {
'cflags_cc': [
# Use gnu++11 instead of c++11 here, see:
# https://code.google.com/p/chromium/issues/detail?id=224515
'-std=gnu++11',
'-std=c++11',
],
'xcode_settings': {
'CC': '/usr/bin/clang',
'LDPLUSPLUS': '/usr/bin/clang++',
'OTHER_CPLUSPLUSFLAGS': [
'$(inherited)', '-std=gnu++11'
],
'OTHER_CFLAGS': [
'-fcolor-diagnostics',
],
'GCC_C_LANGUAGE_STANDARD': 'c99', # -std=c99
'CLANG_CXX_LIBRARY': 'libc++', # -stdlib=libc++
'CLANG_CXX_LANGUAGE_STANDARD': 'c++11', # -std=c++11
},
},
}], # clang==1

View File

@@ -28,6 +28,7 @@ Linux and Windows to define some accelerators.
* `A` to `Z`
* `F1` to `F24`
* Punctuations like `~`, `!`, `@`, `#`, `$`, etc.
* `Plus`
* `Space`
* `Backspace`
* `Delete`

View File

@@ -91,13 +91,47 @@ executed. It is possible that a window cancels the quitting by returning
Quit the application directly, it will not try to close all windows so cleanup
code will not run.
## app.getDataPath()
## app.getPath(name)
Returns the path for storing configuration files, with app name appended.
* `name` String
* `%APPDATA%\MyAppName` on Windows
* `~/.config/MyAppName` on Linux
* `~/Library/Application Support/MyAppName` on OS X
Retrieves a path to a special directory or file associated with `name`. On
failure an `Error` would throw.
You can request following paths by the names:
* `home`: User's home directory
* `appData`: Per-user application data directory, by default it is pointed to:
* `%APPDATA%` on Windows
* `$XDG_CONFIG_HOME` or `~/.config` on Linux
* `~/Library/Application Support` on OS X
* `userData`: The directory for storing your app's configuration files, by
default it is the `appData` directory appended with your app's name
* `cache`: Per-user application cache directory, by default it is pointed to:
* `%APPDATA%` on Window, which doesn't has a universal place for cache
* `$XDG_CACHE_HOME` or `~/.cache` on Linux
* `~/Library/Caches` on OS X
* `userCache`: The directory for placing your app's caches, by default it is the
`cache` directory appended with your app's name
* `temp`: Temporary directory
* `userDesktop`: The current user's Desktop directory
* `exe`: The current executable file
* `module`: The `libchromiumcontent` library
## app.setPath(name, path)
* `name` String
* `path` String
Overrides the `path` to a special directory or file associated with `name`. if
the path specifies a directory that does not exist, the directory will be
created by this method. On failure an `Error` would throw.
You can only override paths of `name`s defined in `app.getPath`.
By default web pages' cookies and caches will be stored under `userData`
directory, if you want to change this location, you have to override the
`userData` path before the `ready` event of `app` module gets emitted.
## app.getVersion()

View File

@@ -48,7 +48,8 @@ You can also create a window without chrome by using
zoom percent / 100, so `3.0` represents `300%`
* `kiosk` Boolean - The kiosk mode
* `title` String - Default window title
* `icon` [Image](image.md) - The window icon
* `icon` [Image](image.md) - The window icon, when omitted on Windows the
executable's icon would be used as window icon
* `show` Boolean - Whether window should be shown when created
* `frame` Boolean - Specify `false` to create a
[Frameless Window](frameless-window.md)
@@ -66,6 +67,7 @@ You can also create a window without chrome by using
scripts run in the window. This script will always have access to node APIs
no matter whether node integration is turned on for the window, and the path
of `preload` script has to be absolute path.
* `transparent` Boolean - Makes the window [transparent](frameless-window.md)
* `web-preferences` Object - Settings of web page's features
* `javascript` Boolean
* `web-security` Boolean
@@ -741,7 +743,51 @@ Injects CSS into this page.
* `code` String
Evaluate `code` in page.
Evaluates `code` in page.
### WebContents.undo()
Executes editing command `undo` in page.
### WebContents.redo()
Executes editing command `redo` in page.
### WebContents.cut()
Executes editing command `cut` in page.
### WebContents.copy()
Executes editing command `copy` in page.
### WebContents.paste()
Executes editing command `paste` in page.
### WebContents.delete()
Executes editing command `delete` in page.
### WebContents.selectAll()
Executes editing command `selectAll` in page.
### WebContents.unselect()
Executes editing command `unselect` in page.
### WebContents.replace(text)
* `text` String
Executes editing command `replace` in page.
### WebContents.replaceMisspelling(text)
* `text` String
Executes editing command `replaceMisspelling` in page.
### WebContents.send(channel[, args...])

View File

@@ -57,3 +57,7 @@ Like `--host-rules` but these `rules` only apply to the host resolver.
[app]: app.md
[append-switch]: app.md#appcommandlineappendswitchswitch-value
[ready]: app.md#event-ready
## --ignore-certificate-errors
Ignore certificate related errors.

View File

@@ -13,6 +13,31 @@ var BrowserWindow = require('browser-window');
var win = new BrowserWindow({ width: 800, height: 600, frame: false });
```
## Transparent window
By setting the `transparent` option to `true`, you can also make the frameless
window transparent:
```javascript
var win = new BrowserWindow({ transparent: true, frame: false });
```
### Limitations
* You can not click through the transparent area, we are going to introduce an
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.
* 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.
* On Linux users have to put `--enable-transparent-visuals --disable-gpu` in
command line to disable GPU and allow ARGB to make transparent window, this is
caused by an upstream bug that [alpha channel doesn't work on some NVidia
drivers](https://code.google.com/p/chromium/issues/detail?id=369209) on Linux.
* On Mac the native window shadow will not show for transparent window.
## Draggable region
By default, the frameless window is non-draggable. Apps need to specify

View File

@@ -135,8 +135,8 @@ Returns the object returned by `require(module)` in the browser process.
## remote.getCurrentWindow()
Returns the [BrowserWindow](browser-window.md) object which
represents the current window.
Returns the [BrowserWindow](browser-window.md) object which this web page
belongs to.
## remote.getGlobal(name)

View File

@@ -1,13 +1,77 @@
# screen
Gets various info about screen size, displays, cursor position, etc.
```js
var Screen = require('screen');
Gets various info about screen size, displays, cursor position, etc. You should
not use this module until the `ready` event of `app` module gets emitted.
`screen` is an [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter).
An example of creating a window that fills the whole screen:
```javascript
var app = require('app');
var BrowserWindow = require('browser-window');
var size = Screen.getPrimaryDisplay().workAreaSize;
mainWindow = new BrowserWindow({ width: size.width, height: size.height });
var mainWindow;
app.on('ready', function() {
var screen = require('screen');
var size = screen.getPrimaryDisplay().workAreaSize;
mainWindow = new BrowserWindow({ width: size.width, height: size.height });
});
```
Another example of creating a window in the external display:
```javascript
var app = require('app');
var BrowserWindow = require('browser-window');
var mainWindow;
app.on('ready', function() {
var screen = require('screen');
var displays = screen.getAllDisplays();
var externalDisplay = null;
for (var i in displays) {
if (displays[i].bounds.x > 0 || displays[i].bounds.y > 0) {
externalDisplay = displays[i];
break;
}
}
if (externalDisplay) {
mainWindow = new BrowserWindow({
x: externalDisplay.bounds.x + 50,
y: externalDisplay.bounds.y + 50,
});
}
});
```
## Event: display-added
* `event` Event
* `newDisplay` Object
Emitted when `newDisplay` has been added.
## Event: display-removed
* `event` Event
* `oldDisplay` Object
Emitted when `oldDisplay` has been removed.
## Event: display-metrics-changed
* `event` Event
* `display` Object
* `changedMetricts` Array
Emitted when a `display` has one or more metrics changed, `changedMetricts` is
an array of strings that describe the changes. Possible changes are `bounds`,
`workArea`, `scaleFactor` and `rotation`.
## screen.getCursorScreenPoint()
Returns the current absolute position of the mouse pointer.
@@ -15,3 +79,25 @@ Returns the current absolute position of the mouse pointer.
## screen.getPrimaryDisplay()
Returns the primary display.
## screen.getAllDisplays()
Returns an array of displays that are currently available.
## screen.getDisplayNearestPoint(point)
* `point` Object
* `x` Integer
* `y` Integer
Returns the display nearest the specified point.
## screen.getDisplayMatching(rect)
* `rect` Object
* `x` Integer
* `y` Integer
* `width` Integer
* `height` Integer
Returns the display that most closely intersects the provided bounds.

View File

@@ -53,4 +53,14 @@ require('web-frame').setSpellCheckProvider("en-US", true, {
});
```
## webFrame.registerUrlSchemeAsSecure(scheme)
* `scheme` String
Sets the `scheme` as secure scheme.
Secure schemes do not trigger mixed content warnings. For example, `https` and
`data` are secure schemes because they cannot be corrupted by active network
attackers.
[spellchecker]: https://github.com/atom/node-spellchecker

View File

@@ -67,7 +67,7 @@ The `src` attribute can also accept data URLs, such as
<webview src="https://www.github.com/" autosize="on" minwidth="576" minheight="432"></webview>
```
If "on", the `webview` will container will automatically resize within the
If "on", the `webview` container will automatically resize within the
bounds specified by the attributes `minwidth`, `minheight`, `maxwidth`, and
`maxheight`. These contraints do not impact the `webview` UNLESS `autosize` is
enabled. When `autosize` is enabled, the `webview` container size cannot be less
@@ -219,6 +219,50 @@ Closes the devtools window of guest page.
Returns whether guest page has a devtools window attached.
### `<webview>`.undo()
Executes editing command `undo` in page.
### `<webview>`.redo()
Executes editing command `redo` in page.
### `<webview>`.cut()
Executes editing command `cut` in page.
### `<webview>`.copy()
Executes editing command `copy` in page.
### `<webview>`.paste()
Executes editing command `paste` in page.
### `<webview>`.delete()
Executes editing command `delete` in page.
### `<webview>`.selectAll()
Executes editing command `selectAll` in page.
### `<webview>`.unselect()
Executes editing command `unselect` in page.
### `<webview>`.replace(text)
* `text` String
Executes editing command `replace` in page.
### `<webview>`.replaceMisspelling(text)
* `text` String
Executes editing command `replaceMisspelling` in page.
### `<webview>`.send(channel[, args...])
* `channel` String

View File

@@ -53,7 +53,7 @@ where to download headers and which version to use:
```bash
$ cd /path-to-module/
$ HOME=~/.atom-shell-gyp node-gyp rebuild --target=0.16.0 --arch=ia32 --dist-url=https://gh-contractor-zcbenz.s3.amazonaws.com/atom-shell/dist
$ HOME=~/.atom-shell-gyp node-gyp rebuild --target=0.16.0 --arch=ia32 --dist-url=https://atom.io/download/atom-shell
```
The `HOME=~/.atom-shell-gyp` changes where to find development headers. The
@@ -64,7 +64,7 @@ where to download the headers. The `--arch=ia32` says the module is built for
### The npm way
```bash
export npm_config_disturl=https://gh-contractor-zcbenz.s3.amazonaws.com/atom-shell/dist
export npm_config_disturl=https://atom.io/download/atom-shell
export npm_config_target=0.6.0
export npm_config_arch=ia32
HOME=~/.atom-shell-gyp npm install module-name

View File

@@ -1,6 +1,6 @@
{
"name": "atom-shell",
"version": "0.20.5",
"version": "0.20.8",
"licenses": [
{
@@ -10,9 +10,10 @@
],
"devDependencies": {
"atom-package-manager": "0.112.0",
"atom-package-manager": "0.122.0",
"coffee-script": "~1.7.1",
"coffeelint": "~1.3.0"
"coffeelint": "~1.3.0",
"request": "*"
},
"private": true,

View File

@@ -0,0 +1,86 @@
var app = require('app');
var fs = require('fs');
var path = require('path');
var request = require('request');
var TARGET_URL = 'https://atom.io/download/atom-shell/index.json';
function getDate() {
var today = new Date();
var year = today.getFullYear();
var month = today.getMonth() + 1;
if (month <= 9)
month = '0' + month;
var day= today.getDate();
if (day <= 9)
day = '0' + day;
return year + '-' + month + '-' + day;
}
function getApmVersion() {
var package = require(path.resolve(__dirname, '..', 'package.json'));
return package.devDependencies['atom-package-manager'];
}
function getInfoForCurrentVersion() {
var json = {};
json.version = process.versions['atom-shell'];
json.date = getDate();
json.apm = getApmVersion();
var names = ['node', 'v8', 'uv', 'zlib', 'openssl', 'modules', 'chrome']
for (var i in names) {
var name = names[i];
json[name] = process.versions[name];
}
json.files = [
'darwin-x64',
'darwin-x64-symbols',
'linux-ia32',
'linux-ia32-symbols',
'linux-x64',
'linux-x64-symbols',
'win32-ia32',
'win32-ia32-symbols',
];
return json;
}
function getIndexJsInServer(callback) {
request(TARGET_URL, function(e, res, body) {
if (e)
callback(e);
else if (res.statusCode != 200)
callback(new Error('Server returned ' + res.statusCode));
else
callback(null, JSON.parse(body));
});
}
function findObjectByVersion(all, version) {
for (var i in all)
if (all[i].version == version)
return i;
return -1;
}
app.on('ready', function() {
getIndexJsInServer(function(e, all) {
if (e) {
console.error(e);
process.exit(1);
}
var current = getInfoForCurrentVersion();
var found = findObjectByVersion(all, current.version);
if (found == -1)
all.unshift(current);
else
all[found] = current;
fs.writeFileSync(process.argv[2], JSON.stringify(all));
process.exit(0);
});
});

View File

@@ -4,7 +4,7 @@ import platform
import sys
BASE_URL = 'http://gh-contractor-zcbenz.s3.amazonaws.com/libchromiumcontent'
LIBCHROMIUMCONTENT_COMMIT = '55efd338101e08691560192b2be0f9c3b1b0eb72'
LIBCHROMIUMCONTENT_COMMIT = '6300862b4b16bd171f00ae566b697098c29743f7'
ARCH = {
'cygwin': '32bit',

View File

@@ -9,7 +9,7 @@ from lib.util import safe_mkdir, rm_rf, extract_zip, tempdir, download
VERSION = 'v0.3.0'
SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
FRAMEWORKS_URL = 'https://github.com/atom/atom-shell-frameworks/releases' \
FRAMEWORKS_URL = 'http://github.com/atom/atom-shell-frameworks/releases' \
'/download/' + VERSION

View File

@@ -8,7 +8,7 @@ import tempfile
from lib.util import download, rm_rf, s3_config, s3put
DIST_URL = 'https://gh-contractor-zcbenz.s3.amazonaws.com/atom-shell/dist/'
DIST_URL = 'https://atom.io/download/atom-shell/'
def main():

View File

@@ -190,6 +190,15 @@ def upload_node(bucket, access_key, secret_key, version):
s3put(bucket, access_key, secret_key, OUT_DIR,
'atom-shell/dist/{0}'.format(version), [node_lib])
# Upload the index.json
atom_shell = os.path.join(OUT_DIR, 'atom.exe')
index_json = os.path.join(OUT_DIR, 'index.json')
execute([atom_shell,
os.path.join(SOURCE_ROOT, 'script', 'dump-version-info.js'),
index_json])
s3put(bucket, access_key, secret_key, OUT_DIR, 'atom-shell/dist',
[index_json])
def auth_token():
token = os.environ.get('ATOM_SHELL_GITHUB_TOKEN')

View File

@@ -395,12 +395,6 @@ describe 'asar package', ->
describe 'original-fs module', ->
originalFs = require 'original-fs'
it 'uses the original fs api', ->
changedApis = ['readFile', 'stat', 'lstat', 'realpath', 'exists']
unchangedApis = ['read', 'write', 'writeFile', 'close']
assert.notStrictEqual fs[api], originalFs[api] for api in changedApis
assert.strictEqual fs[api], originalFs[api] for api in unchangedApis
it 'treats .asar as file', ->
file = path.join fixtures, 'asar', 'a.asar'
stats = originalFs.statSync file

View File

@@ -65,3 +65,19 @@ describe 'chromium feature', ->
assert.equal event.data, message
done()
worker.port.postMessage message
describe 'iframe', ->
iframe = null
beforeEach ->
iframe = document.createElement 'iframe'
afterEach ->
document.body.removeChild iframe
it 'does not have node integration', (done) ->
iframe.src = "file://#{fixtures}/pages/set-global.html"
document.body.appendChild iframe
iframe.onload = ->
assert.equal iframe.contentWindow.test, 'undefined undefined undefined'
done()

View File

@@ -0,0 +1,7 @@
process.on('message', function (msg) {
process.send([
'a'.localeCompare('a'),
'ä'.localeCompare('z', 'de'),
'ä'.localeCompare('a', 'sv', { sensitivity: 'base' }),
]);
});

4
spec/fixtures/module/preload-ipc.js vendored Normal file
View File

@@ -0,0 +1,4 @@
var ipc = require('ipc');
ipc.on('ping', function(message) {
ipc.sendToHost('pong', message);
});

7
spec/fixtures/pages/set-global.html vendored Normal file
View File

@@ -0,0 +1,7 @@
<html>
<body>
<script type="text/javascript" charset="utf-8">
window.test = [typeof require, typeof module, typeof process].join(' ')
</script>
</body>
</html>

View File

@@ -41,17 +41,19 @@ describe 'node feature', ->
done()
child.send 'message'
it 'has String::localeCompare working in script', (done) ->
child = child_process.fork path.join(fixtures, 'module', 'locale-compare.js')
child.on 'message', (msg) ->
assert.deepEqual msg, [0, -1, 1]
done()
child.send 'message'
describe 'contexts', ->
describe 'setTimeout in fs callback', ->
it 'does not crash', (done) ->
fs.readFile __filename, ->
setTimeout done, 0
describe 'setTimeout in pure uv callback', ->
it 'does not crash', (done) ->
process.scheduleCallback ->
setTimeout done, 0
describe 'throw error in node context', ->
it 'gets caught', (done) ->
error = new Error('boo!')

View File

@@ -58,6 +58,22 @@ describe '<webview> tag', ->
webview.src = "file://#{fixtures}/pages/e.html"
document.body.appendChild webview
it 'receives ipc message in preload script', (done) ->
message = 'boom!'
listener = (e) ->
assert.equal e.channel, 'pong'
assert.deepEqual e.args, [message]
webview.removeEventListener 'ipc-message', listener
done()
listener2 = (e) ->
webview.send 'ping', message
webview.removeEventListener 'did-finish-load', listener2
webview.addEventListener 'ipc-message', listener
webview.addEventListener 'did-finish-load', listener2
webview.setAttribute 'preload', "#{fixtures}/module/preload-ipc.js"
webview.src = "file://#{fixtures}/pages/e.html"
document.body.appendChild webview
describe 'httpreferrer attribute', ->
it 'sets the referrer url', (done) ->
referrer = 'http://github.com/'