Compare commits

...

94 Commits

Author SHA1 Message Date
Cheng Zhao
4608f5e9cd Bump v0.25.2 2015-05-01 14:57:25 +08:00
Cheng Zhao
9300859983 Merge pull request #1535 from deepak1556/contents_patch
webContents: adding serviceworker helper utilities
2015-05-01 14:56:35 +08:00
Cheng Zhao
52240750a1 Merge pull request #1540 from atom/webview-beforeunload
Make beforeunload handler work in webview
2015-05-01 14:55:52 +08:00
deepak1556
d76bd4a103 webContents: adding serviceworker helper utilities 2015-05-01 12:02:57 +05:30
Cheng Zhao
bfac7f7a17 Make beforeunload work in webview 2015-05-01 13:48:39 +08:00
Cheng Zhao
36d2512ff8 spec: Test beforeunload handler in webview 2015-05-01 13:48:23 +08:00
Cheng Zhao
ca7e2c4d96 Merge pull request #1538 from leemac/patch-1
Typo and missing comma in Desktop Integration doc page
2015-05-01 12:48:55 +08:00
Cheng Zhao
817dfbdc27 Merge pull request #1525 from deepak1556/dom_event_patch
webContents: providing dom-ready event
2015-05-01 12:08:03 +08:00
Lee McKinnon
5fa7ae7d72 Fixing typo in desktop-environment-integration.md
Missing comma in the 'setUserTasks' as well as a typo in the description under "User tasks (Windows)"
2015-04-30 15:40:30 -04:00
Cheng Zhao
c54eca8dff Update node to fix #1472 2015-04-30 17:07:20 +08:00
Cheng Zhao
72f5381c31 Merge pull request #1521 from deepak1556/title_patch
webContents: check for navigation entry before using
2015-04-30 16:54:14 +08:00
Cheng Zhao
7ca2363d78 Merge pull request #1533 from atom/iojs-headers
Upload io.js headers
2015-04-30 16:17:26 +08:00
Cheng Zhao
dec7c40fd8 Also upload iojs-*-.tar.gz 2015-04-30 16:01:54 +08:00
Cheng Zhao
a8846e0432 Also upload headers to iojs's locations 2015-04-30 15:36:54 +08:00
deepak1556
8c5f171a93 webContents: providing dom-ready event 2015-04-30 09:58:29 +05:30
Daniel Hengeveld
ea74e825c9 Merge pull request #1527 from frewsxcv/patch-1
Enable syntax highlighting in README
2015-04-29 12:28:52 -07:00
Corey Farwell
2b3ef714bd Enable syntax highlighting in README
Primarily to fade the comments in the code block
2015-04-29 13:56:31 -04:00
Cheng Zhao
23afffa46d Chaning src of webview should always do a load
Previously changing src to the same value won't have any effect, which
does not follow the behavior of browsers.
2015-04-29 17:57:16 +08:00
Cheng Zhao
129cdb7680 spec,win: Fix page-favicon-updated event spec 2015-04-29 17:31:56 +08:00
Cheng Zhao
8d3404d26c win: Fix compilation error 2015-04-29 15:13:46 +08:00
Cheng Zhao
05e0564426 Merge pull request #1477 from atom/dont-rig-app-name
Provide an optional way to explicitly set the AppUserModelID
2015-04-29 14:10:12 +08:00
deepak1556
d8be645d5a webContents: check for navigation entry before using 2015-04-29 08:57:49 +05:30
Cheng Zhao
3f499f69ff Merge pull request #1520 from atom/disable-auto-hide-cursor
Add option to disable hiding cursor when typing
2015-04-29 10:39:44 +08:00
Cheng Zhao
75b24c7d76 docs: disable-auto-hide-cursor option 2015-04-29 10:28:42 +08:00
Cheng Zhao
c6cf91d11f Add 'disable-auto-hide-cursor' option 2015-04-29 10:26:31 +08:00
Cheng Zhao
3a50c9e48c Update to the new patch for acceptsFirstMouse 2015-04-29 10:26:31 +08:00
Paul Betts
7c2b1468c8 Fix typo 2015-04-28 15:49:16 -07:00
Paul Betts
fb6c80d12e Create an explicit API for setting the App User Model ID 2015-04-28 12:23:58 -07:00
Kevin Sawicki
d826e1e5fb Merge pull request #1514 from mnquintana/patch-1
Logo png -> svg
2015-04-28 08:57:35 -07:00
Machiste N. Quintana
04a0aaa35f Logo png -> svg
Fixes broken image in Readme
2015-04-28 10:48:54 -04:00
Cheng Zhao
f5fbd52dbd Merge pull request #1505 from atom/default-help-menu
Add help menu to default app
2015-04-28 17:55:06 +08:00
Daniel Hengeveld
5575d17d0e Merge pull request #1495 from bendrucker/grammar
Fix grammar in NW.js comparison
2015-04-27 13:30:26 -07:00
Ben Drucker
0e7970fec5 Fix grammar in NW.js comparison 2015-04-27 15:55:25 -04:00
Kevin Sawicki
fdfd8807a0 Tweak path docs 2015-04-27 10:17:15 -07:00
Kevin Sawicki
da07e72f20 Add -h/--help usage message 2015-04-27 10:17:14 -07:00
Kevin Sawicki
f4a27f699a Add help menu to electron site 2015-04-27 10:17:14 -07:00
Kevin Sawicki
e3c21424de Add default help menu 2015-04-27 10:17:14 -07:00
Kevin Sawicki
b5aa2a31a1 Make full screen menu a toggler 2015-04-27 10:17:14 -07:00
Cheng Zhao
05ae1960d1 Merge pull request #1502 from atom/renderer-restart
Manage navigation history with JavaScript on user side
2015-04-27 22:00:23 +08:00
Cheng Zhao
dde791d475 Allow calling goBack for multiple times 2015-04-27 15:11:59 +08:00
Cheng Zhao
16b2f08cd3 Don't use Chromium's history list 2015-04-27 15:11:59 +08:00
Cheng Zhao
0143a45488 Implement our own NavigationController 2015-04-27 15:11:59 +08:00
Cheng Zhao
2f1683445b Only append command line params for renderer process 2015-04-27 15:11:59 +08:00
Cheng Zhao
4c78f98da6 Check if it is guest process before updating process ID 2015-04-27 15:11:59 +08:00
Cheng Zhao
3ff2959f0c spec: Native modules should work after navigation in webview 2015-04-27 15:11:59 +08:00
Cheng Zhao
36c4b1705d Update guest process id when navigating 2015-04-27 15:11:58 +08:00
Cheng Zhao
d8adbc0875 NULL => nullptr 2015-04-27 15:11:58 +08:00
Cheng Zhao
b527846ee4 Use our new way to restart renderer process
As a side effect, it will also restart the renderer process of webview
tag guests.
2015-04-27 15:11:58 +08:00
Cheng Zhao
ee45f0e8bc Upgrade libchromiumcontent 2015-04-27 15:11:58 +08:00
Cheng Zhao
ca5ee0fc81 Merge pull request #1491 from atom/minimal-mac-menu
Remove native actions in Mac default menu
2015-04-25 21:00:26 +08:00
Cheng Zhao
ecf29f72bc mac: Remove unused action handler 2015-04-25 20:41:12 +08:00
Cheng Zhao
c811beb1e2 mac: Remove all unnecessary default menu items 2015-04-25 20:36:09 +08:00
Cheng Zhao
0c091428d3 Merge pull request #1455 from deepak1556/fullscreen_patch
window: supports HTML5 fullscreen api
2015-04-25 16:16:57 +08:00
Cheng Zhao
858198a2bd Merge pull request #1461 from deepak1556/webview_devtools_patch
webview: add inspectElement method
2015-04-25 16:14:13 +08:00
Cheng Zhao
1649d8f900 Merge pull request #1438 from deepak1556/api_web_view_patch
webview: page-favicon-updated navigation event and getFavicon api
2015-04-25 13:04:43 +08:00
Cheng Zhao
eb42fdbbc6 Merge pull request #1453 from deepak1556/asar_patch
asar: make fs async methods create errors asynchronously
2015-04-25 13:04:35 +08:00
deepak1556
6cc571bdfe include headers only in places used 2015-04-25 10:13:52 +05:30
deepak1556
da648511b3 asar: make fs async methods create errors asynchronously 2015-04-25 10:08:02 +05:30
deepak1556
18b3dfa350 removed will-navigate and did-navigate events 2015-04-25 09:50:28 +05:30
deepak1556
05be71e9bc fix getFavcion api in webview to return dataUrl 2015-04-25 09:50:28 +05:30
deepak1556
36819e2638 added did-navigate event, getFavicon api and workaround webview spec 2015-04-25 09:50:28 +05:30
deepak1556
9b585458c1 webview: will-navigate and page-favicon-set navigation events 2015-04-25 09:50:28 +05:30
Cheng Zhao
c424d0e9f3 Upgrade CoffeeScript to 1.9.2 2015-04-25 10:45:28 +08:00
Cheng Zhao
81783b255e Increase timeout for some tests 2015-04-25 10:45:16 +08:00
Cheng Zhao
80c8ab4c39 Style fix 2015-04-25 10:35:28 +08:00
Cheng Zhao
826a4e0e48 Merge branch 'master' of https://github.com/MaxGraey/electron into MaxGraey-master 2015-04-25 10:29:34 +08:00
Cheng Zhao
7917748b21 ⬆️ asar@0.5.0 2015-04-24 13:06:49 +08:00
Daniel Hengeveld
b7f974f469 Merge pull request #1481 from bhargavrpatel/patch-1
Minor grammatical fixes
2015-04-23 17:18:26 -07:00
Bhargav Patel
5c5fd377f7 Minor grammatical fixes
Fixed some run-on sentances and changed structor of some.
2015-04-23 20:12:04 -04:00
Kevin Sawicki
0a995c3731 Mention new twitter account 2015-04-23 17:03:05 -07:00
Kevin Sawicki
47b754e914 Merge pull request #1480 from lazaruslarue/patch-1
fix minor text error
2015-04-23 16:50:05 -07:00
lazarus
00ef99826d fix minor text error 2015-04-23 16:32:41 -07:00
Kevin Sawicki
45943302ee Merge pull request #1476 from mnquintana/patch-2
Add david-dm dependency status badge to Readme
2015-04-23 14:02:47 -07:00
Machiste N. Quintana
2157f898bb Add david-dm dependency status badge to Readme 2015-04-23 17:00:40 -04:00
Kevin Sawicki
132c7aba2d Merge pull request #1475 from mnquintana/patch-1
Add Electron logo to Readme
2015-04-23 13:52:14 -07:00
Machiste N. Quintana
1ae88f0f0f 🎨 2015-04-23 16:50:43 -04:00
Machiste N. Quintana
c0f0fcba7b Add Electron logo to Readme 2015-04-23 16:46:48 -04:00
deepak1556
cdb1711fe1 webview: add inspectElement method 2015-04-23 15:18:13 +05:30
deepak1556
20b4cae980 window: supports HTML5 fullscreen api 2015-04-23 12:14:29 +05:30
Cheng Zhao
67bc4afe88 Bump v0.25.1 2015-04-23 13:29:34 +08:00
Cheng Zhao
fb78169396 Don't add tag in bump-version.py
It will be done by GitHub Releases.
2015-04-23 13:28:29 +08:00
Cheng Zhao
ba7e26539f Upgrade brightray for #1462 2015-04-23 13:27:11 +08:00
Cheng Zhao
500d15f53a Also remove user-defined search paths in renderer 2015-04-23 13:17:18 +08:00
Cheng Zhao
fad977e27d Simplify how we remove user-defined search paths 2015-04-23 13:13:58 +08:00
deepak1556
4983ef77bd module: remove system paths from search 2015-04-23 12:55:34 +08:00
Cheng Zhao
4a6066c69e Update native_mate 2015-04-23 10:22:09 +08:00
Cheng Zhao
1690df9bcf Merge branch 'api_content_tracing_patch' of https://github.com/deepak1556/atom-shell into deepak1556-api_content_tracing_patch 2015-04-23 10:21:15 +08:00
Kevin Sawicki
5c94f7ccd4 Merge pull request #1464 from bnvk/patch-1
updated bash path to ./Electron.app/Contents/MacOS/Electron
2015-04-22 14:08:09 -07:00
Kevin Sawicki
494c3f3255 Merge pull request #1466 from gappsby/master
node.js --> io.js
2015-04-22 14:04:29 -07:00
Florian Hämmerle
ec4d596189 Update quick-start.md 2015-04-22 22:14:50 +02:00
Brennan Novak
bc04e951cf updated bash path to ./Electron.app/Contents/MacOS/Electron
it had the trailing /Atom which no longer exists
2015-04-22 16:22:08 +02:00
Max Graey
916fa4b9a8 Merge pull request #1 from atom/master
Merge with forked
2015-04-21 04:39:54 +07:00
Max Graey
0d3cc8aaa7 Fix some draw issues in native mac os window
Fix some non-transparent corners and lacking redraw while resizing non-frame window
2015-04-18 19:08:22 +07:00
deepak1556
51cadc6e90 nativemate: moved std::set converter 2015-04-18 01:29:57 +05:30
60 changed files with 731 additions and 3309 deletions

View File

@@ -1,4 +1,7 @@
# Electron [![Build Status](https://travis-ci.org/atom/electron.svg?branch=master)](https://travis-ci.org/atom/electron)
[![Electron Logo](http://electron.atom.io/images/electron-logo.svg)](http://electron.atom.io/)
[![Build Status](https://travis-ci.org/atom/electron.svg?branch=master)](https://travis-ci.org/atom/electron)
[![devDependency Status](https://david-dm.org/atom/electron/dev-status.svg)](https://david-dm.org/atom/electron#info=devDependencies)
:zap: *formerly known as Atom Shell* :zap:
@@ -7,6 +10,9 @@ using JavaScript, HTML and CSS. It is based on [io.js](http://iojs.org) and
[Chromium](http://www.chromium.org) and is used in the [Atom
editor](https://github.com/atom/atom).
Follow [@ElectronJS](https://twitter.com/electronjs) on Twitter for important
announcements.
## Downloads
Prebuilt binaries and debug symbols of Electron for Linux, Windows and Mac can
@@ -15,7 +21,7 @@ be found on the [releases](https://github.com/atom/electron/releases) page.
You can also use [`npm`](https://docs.npmjs.com/) to install prebuilt electron
binaries:
```
```sh
# Install the `electron` command globally in your $PATH
npm install electron-prebuilt -g

View File

@@ -4,7 +4,7 @@
'product_name%': 'Electron',
'company_name%': 'GitHub, Inc',
'company_abbr%': 'github',
'version%': '0.25.0',
'version%': '0.25.2',
'atom_source_root': '<!(["python", "tools/atom_source_root.py"])',
},

View File

@@ -7,6 +7,10 @@
#include <string>
#include <vector>
#if defined(OS_WIN)
#include <shlobj.h>
#endif
#include "atom/browser/api/atom_api_menu.h"
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/browser.h"
@@ -25,6 +29,10 @@
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#if defined(OS_WIN)
#include "base/strings/utf_string_conversions.h"
#endif
#include "atom/common/node_includes.h"
using atom::Browser;
@@ -200,6 +208,13 @@ void App::SetDesktopName(const std::string& desktop_name) {
#endif
}
void App::SetAppUserModelId(const std::string& app_id) {
#if defined(OS_WIN)
base::string16 app_id_utf16 = base::UTF8ToUTF16(app_id);
SetCurrentProcessExplicitAppUserModelID(app_id_utf16.c_str());
#endif
}
mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
auto browser = base::Unretained(Browser::Get());
@@ -222,7 +237,8 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder(
.SetMethod("setPath", &App::SetPath)
.SetMethod("getPath", &App::GetPath)
.SetMethod("resolveProxy", &App::ResolveProxy)
.SetMethod("setDesktopName", &App::SetDesktopName);
.SetMethod("setDesktopName", &App::SetDesktopName)
.SetMethod("setAppUserModelId", &App::SetAppUserModelId);
}
// static

View File

@@ -61,6 +61,7 @@ class App : public mate::EventEmitter,
void ResolveProxy(const GURL& url, ResolveProxyCallback callback);
void SetDesktopName(const std::string& desktop_name);
void SetAppUserModelId(const std::string& app_id);
DISALLOW_COPY_AND_ASSIGN(App);
};

View File

@@ -17,20 +17,6 @@ using content::TracingController;
namespace mate {
template<typename T>
struct Converter<std::set<T> > {
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
const std::set<T>& val) {
v8::Handle<v8::Array> result = v8::Array::New(
isolate, static_cast<int>(val.size()));
typename std::set<T>::const_iterator it;
int i;
for (i = 0, it = val.begin(); it != val.end(); ++it, ++i)
result->Set(i, Converter<T>::ToV8(isolate, *it));
return result;
}
};
template<>
struct Converter<base::trace_event::CategoryFilter> {
static bool FromV8(v8::Isolate* isolate,

View File

@@ -4,17 +4,23 @@
#include "atom/browser/api/atom_api_web_contents.h"
#include <set>
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_javascript_dialog_manager.h"
#include "atom/browser/native_window.h"
#include "atom/browser/web_dialog_helper.h"
#include "atom/browser/web_view_manager.h"
#include "atom/common/api/api_messages.h"
#include "atom/common/native_mate_converters/gfx_converter.h"
#include "atom/common/native_mate_converters/gurl_converter.h"
#include "atom/common/native_mate_converters/image_converter.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "base/strings/utf_string_conversions.h"
#include "brightray/browser/inspectable_web_contents.h"
#include "brightray/browser/media/media_stream_devices_controller.h"
#include "content/public/browser/favicon_status.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/render_frame_host.h"
@@ -22,11 +28,13 @@
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/resource_request_details.h"
#include "content/public/browser/service_worker_context.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/web_contents.h"
#include "native_mate/callback.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "vendor/brightray/browser/media/media_stream_devices_controller.h"
#include "atom/common/node_includes.h"
@@ -49,6 +57,22 @@ NativeWindow* GetWindowFromGuest(const content::WebContents* guest) {
return nullptr;
}
content::ServiceWorkerContext* GetServiceWorkerContext(
const content::WebContents* web_contents) {
auto context = web_contents->GetBrowserContext();
auto site_instance = web_contents->GetSiteInstance();
if (!context || !site_instance)
return nullptr;
content::StoragePartition* storage_partition =
content::BrowserContext::GetStoragePartition(
context, site_instance);
DCHECK(storage_partition);
return storage_partition->GetServiceWorkerContext();
}
} // namespace
WebContents::WebContents(content::WebContents* web_contents)
@@ -136,11 +160,20 @@ content::WebContents* WebContents::OpenURLFromTab(
load_url_params.is_renderer_initiated = params.is_renderer_initiated;
load_url_params.transferred_global_request_id =
params.transferred_global_request_id;
load_url_params.should_clear_history_list = true;
web_contents()->GetController().LoadURLWithParams(load_url_params);
return web_contents();
}
content::JavaScriptDialogManager* WebContents::GetJavaScriptDialogManager(
content::WebContents* source) {
if (!dialog_manager_)
dialog_manager_.reset(new AtomJavaScriptDialogManager);
return dialog_manager_.get();
}
void WebContents::RunFileChooser(content::WebContents* guest,
const content::FileChooserParams& params) {
if (!web_dialog_helper_)
@@ -191,6 +224,12 @@ void WebContents::RenderProcessGone(base::TerminationStatus status) {
Emit("crashed");
}
void WebContents::DocumentLoadedInFrame(
content::RenderFrameHost* render_frame_host) {
if (!render_frame_host->GetParent())
Emit("dom-ready");
}
void WebContents::DidFinishLoad(content::RenderFrameHost* render_frame_host,
const GURL& validated_url) {
bool is_main_frame = !render_frame_host->GetParent();
@@ -253,7 +292,22 @@ void WebContents::DidNavigateMainFrame(
void WebContents::TitleWasSet(content::NavigationEntry* entry,
bool explicit_set) {
Emit("page-title-set", entry->GetTitle(), explicit_set);
// Back/Forward navigation may have pruned entries.
if (entry)
Emit("page-title-set", entry->GetTitle(), explicit_set);
}
void WebContents::DidUpdateFaviconURL(
const std::vector<content::FaviconURL>& urls) {
std::set<GURL> unique_urls;
for (auto iter = urls.begin(); iter != urls.end(); ++iter) {
if (iter->icon_type != content::FaviconURL::FAVICON)
continue;
const GURL& url = iter->icon_url;
if (url.is_valid())
unique_urls.insert(url);
}
Emit("page-favicon-updated", unique_urls);
}
bool WebContents::OnMessageReceived(const IPC::Message& message) {
@@ -295,8 +349,7 @@ void WebContents::WebContentsDestroyed() {
void WebContents::NavigationEntryCommitted(
const content::LoadCommittedDetails& load_details) {
auto entry = web_contents()->GetController().GetLastCommittedEntry();
entry->SetVirtualURL(load_details.entry->GetOriginalRequestURL());
Emit("navigation-entry-commited", load_details.entry->GetURL());
}
void WebContents::DidAttach(int guest_proxy_routing_id) {
@@ -364,21 +417,22 @@ void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) {
blink::WebReferrerPolicyDefault);
params.transition_type = ui::PAGE_TRANSITION_TYPED;
params.should_clear_history_list = true;
params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE;
web_contents()->GetController().LoadURLWithParams(params);
}
GURL WebContents::GetURL() const {
auto entry = web_contents()->GetController().GetLastCommittedEntry();
if (!entry)
return GURL::EmptyGURL();
return entry->GetVirtualURL();
}
base::string16 WebContents::GetTitle() const {
return web_contents()->GetTitle();
}
gfx::Image WebContents::GetFavicon() const {
auto entry = web_contents()->GetController().GetLastCommittedEntry();
if (!entry)
return gfx::Image();
return entry->GetFavicon().image;
}
bool WebContents::IsLoading() const {
return web_contents()->IsLoading();
}
@@ -391,46 +445,8 @@ void WebContents::Stop() {
web_contents()->Stop();
}
void WebContents::Reload(const mate::Dictionary& options) {
// Navigating to a URL would always restart the renderer process, we want this
// because normal reloading will break our node integration.
// This is done by AtomBrowserClient::ShouldSwapProcessesForNavigation.
LoadURL(GetURL(), options);
}
void WebContents::ReloadIgnoringCache(const mate::Dictionary& options) {
// Hack to remove pending entries that ignores cache and treated as a fresh
// load.
void WebContents::ReloadIgnoringCache() {
web_contents()->GetController().ReloadIgnoringCache(false);
Reload(options);
}
bool WebContents::CanGoBack() const {
return web_contents()->GetController().CanGoBack();
}
bool WebContents::CanGoForward() const {
return web_contents()->GetController().CanGoForward();
}
bool WebContents::CanGoToOffset(int offset) const {
return web_contents()->GetController().CanGoToOffset(offset);
}
void WebContents::GoBack() {
web_contents()->GetController().GoBack();
}
void WebContents::GoForward() {
web_contents()->GetController().GoForward();
}
void WebContents::GoToIndex(int index) {
web_contents()->GetController().GoToIndex(index);
}
void WebContents::GoToOffset(int offset) {
web_contents()->GetController().GoToOffset(offset);
}
int WebContents::GetRoutingID() const {
@@ -470,6 +486,13 @@ bool WebContents::IsDevToolsOpened() {
return storage_->IsDevToolsViewShowing();
}
void WebContents::InspectElement(int x, int y) {
OpenDevTools();
scoped_refptr<content::DevToolsAgentHost> agent(
content::DevToolsAgentHost::GetOrCreateFor(storage_->GetWebContents()));
agent->InspectElement(x, y);
}
void WebContents::Undo() {
web_contents()->Undo();
}
@@ -561,6 +584,27 @@ void WebContents::SetAllowTransparency(bool allow) {
}
}
void WebContents::HasServiceWorker(
const base::Callback<void(bool)>& callback) {
auto context = GetServiceWorkerContext(web_contents());
if (!context)
return;
context->CheckHasServiceWorker(web_contents()->GetLastCommittedURL(),
GURL::EmptyGURL(),
callback);
}
void WebContents::UnregisterServiceWorker(
const base::Callback<void(bool)>& callback) {
auto context = GetServiceWorkerContext(web_contents());
if (!context)
return;
context->UnregisterServiceWorker(web_contents()->GetLastCommittedURL(),
callback);
}
mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
if (template_.IsEmpty())
@@ -568,20 +612,12 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
.SetMethod("destroy", &WebContents::Destroy)
.SetMethod("isAlive", &WebContents::IsAlive)
.SetMethod("_loadUrl", &WebContents::LoadURL)
.SetMethod("getUrl", &WebContents::GetURL)
.SetMethod("getTitle", &WebContents::GetTitle)
.SetMethod("getFavicon", &WebContents::GetFavicon)
.SetMethod("isLoading", &WebContents::IsLoading)
.SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse)
.SetMethod("stop", &WebContents::Stop)
.SetMethod("_reload", &WebContents::Reload)
.SetMethod("_stop", &WebContents::Stop)
.SetMethod("_reloadIgnoringCache", &WebContents::ReloadIgnoringCache)
.SetMethod("canGoBack", &WebContents::CanGoBack)
.SetMethod("canGoForward", &WebContents::CanGoForward)
.SetMethod("canGoToOffset", &WebContents::CanGoToOffset)
.SetMethod("goBack", &WebContents::GoBack)
.SetMethod("goForward", &WebContents::GoForward)
.SetMethod("goToIndex", &WebContents::GoToIndex)
.SetMethod("goToOffset", &WebContents::GoToOffset)
.SetMethod("getRoutingId", &WebContents::GetRoutingID)
.SetMethod("getProcessId", &WebContents::GetProcessID)
.SetMethod("isCrashed", &WebContents::IsCrashed)
@@ -591,6 +627,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
.SetMethod("openDevTools", &WebContents::OpenDevTools)
.SetMethod("closeDevTools", &WebContents::CloseDevTools)
.SetMethod("isDevToolsOpened", &WebContents::IsDevToolsOpened)
.SetMethod("inspectElement", &WebContents::InspectElement)
.SetMethod("undo", &WebContents::Undo)
.SetMethod("redo", &WebContents::Redo)
.SetMethod("cut", &WebContents::Cut)
@@ -605,6 +642,9 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
.SetMethod("setAutoSize", &WebContents::SetAutoSize)
.SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency)
.SetMethod("isGuest", &WebContents::is_guest)
.SetMethod("hasServiceWorker", &WebContents::HasServiceWorker)
.SetMethod("unregisterServiceWorker",
&WebContents::UnregisterServiceWorker)
.Build());
return mate::ObjectTemplateBuilder(

View File

@@ -6,13 +6,16 @@
#define ATOM_BROWSER_API_ATOM_API_WEB_CONTENTS_H_
#include <string>
#include <vector>
#include "atom/browser/api/event_emitter.h"
#include "brightray/browser/default_web_contents_delegate.h"
#include "content/public/browser/browser_plugin_guest_delegate.h"
#include "content/public/common/favicon_url.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "native_mate/handle.h"
#include "ui/gfx/image/image.h"
namespace brightray {
class InspectableWebContents;
@@ -24,6 +27,7 @@ class Dictionary;
namespace atom {
class AtomJavaScriptDialogManager;
class WebDialogHelper;
namespace api {
@@ -44,20 +48,12 @@ class WebContents : public mate::EventEmitter,
void Destroy();
bool IsAlive() const;
void LoadURL(const GURL& url, const mate::Dictionary& options);
GURL GetURL() const;
base::string16 GetTitle() const;
gfx::Image GetFavicon() const;
bool IsLoading() const;
bool IsWaitingForResponse() const;
void Stop();
void Reload(const mate::Dictionary& options);
void ReloadIgnoringCache(const mate::Dictionary& options);
bool CanGoBack() const;
bool CanGoForward() const;
bool CanGoToOffset(int offset) const;
void GoBack();
void GoForward();
void GoToIndex(int index);
void GoToOffset(int offset);
void ReloadIgnoringCache();
int GetRoutingID() const;
int GetProcessID() const;
bool IsCrashed() const;
@@ -67,6 +63,9 @@ class WebContents : public mate::EventEmitter,
void OpenDevTools();
void CloseDevTools();
bool IsDevToolsOpened();
void InspectElement(int x, int y);
void HasServiceWorker(const base::Callback<void(bool)>&);
void UnregisterServiceWorker(const base::Callback<void(bool)>&);
// Editing commands.
void Undo();
@@ -130,6 +129,8 @@ class WebContents : public mate::EventEmitter,
content::WebContents* OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) override;
content::JavaScriptDialogManager* GetJavaScriptDialogManager(
content::WebContents* source) override;
void RunFileChooser(content::WebContents* web_contents,
const content::FileChooserParams& params) override;
void EnumerateDirectory(content::WebContents* web_contents,
@@ -149,6 +150,8 @@ class WebContents : public mate::EventEmitter,
// content::WebContentsObserver:
void RenderViewDeleted(content::RenderViewHost*) override;
void RenderProcessGone(base::TerminationStatus status) override;
void DocumentLoadedInFrame(
content::RenderFrameHost* render_frame_host) override;
void DidFinishLoad(content::RenderFrameHost* render_frame_host,
const GURL& validated_url) override;
void DidFailLoad(content::RenderFrameHost* render_frame_host,
@@ -175,6 +178,8 @@ class WebContents : public mate::EventEmitter,
void NavigationEntryCommitted(
const content::LoadCommittedDetails& load_details) override;
void TitleWasSet(content::NavigationEntry* entry, bool explicit_set) override;
void DidUpdateFaviconURL(
const std::vector<content::FaviconURL>& urls) override;
// content::BrowserPluginGuestDelegate:
void DidAttach(int guest_proxy_routing_id) final;
@@ -201,6 +206,7 @@ class WebContents : public mate::EventEmitter,
const gfx::Size& new_size);
scoped_ptr<WebDialogHelper> web_dialog_helper_;
scoped_ptr<AtomJavaScriptDialogManager> dialog_manager_;
// Unique ID for a guest WebContents.
int guest_instance_id_;

View File

@@ -0,0 +1,79 @@
# JavaScript implementation of Chromium's NavigationController.
# Instead of relying on Chromium for history control, we compeletely do history
# control on user land, and only rely on WebContents.loadUrl for navigation.
# This helps us avoid Chromium's various optimizations so we can ensure renderer
# process is restarted everytime.
class NavigationController
constructor: (@webContents) ->
@history = []
@currentIndex = -1
@pendingIndex = -1
@webContents.on 'navigation-entry-commited', (event, url) =>
if @pendingIndex is -1 # Normal navigation.
@history = @history.slice 0, @currentIndex + 1 # Clear history.
if @history[@currentIndex] isnt url
@currentIndex++
@history.push url
else # Go to index.
@currentIndex = @pendingIndex
@pendingIndex = -1
@history[@currentIndex] = url
loadUrl: (url, options={}) ->
@pendingIndex = -1
@webContents._loadUrl url, options
getUrl: ->
if @currentIndex is -1
''
else
@history[@currentIndex]
stop: ->
@pendingIndex = -1
@webContents._stop()
reload: ->
@pendingIndex = @currentIndex
@webContents._loadUrl @getUrl(), {}
reloadIgnoringCache: ->
@webContents._reloadIgnoringCache() # Rely on WebContents to clear cache.
@reload()
canGoBack: ->
@getActiveIndex() > 0
canGoForward: ->
@getActiveIndex() < @history.length - 1
canGoToIndex: (index) ->
index >=0 and index < @history.length
canGoToOffset: (offset) ->
@canGoToIndex @currentIndex + offset
goBack: ->
return unless @canGoBack()
@pendingIndex = @getActiveIndex() - 1
@webContents._loadUrl @history[@pendingIndex], {}
goForward: ->
return unless @canGoForward()
@pendingIndex = @getActiveIndex() + 1
@webContents._loadUrl @history[@pendingIndex], {}
goToIndex: (index) ->
return unless @canGoToIndex index
@pendingIndex = index
@webContents._loadUrl @history[@pendingIndex], {}
goToOffset: (offset) ->
return unless @canGoToOffset offset
@goToIndex @currentIndex + offset
getActiveIndex: ->
if @pendingIndex is -1 then @currentIndex else @pendingIndex
module.exports = NavigationController

View File

@@ -1,4 +1,5 @@
EventEmitter = require('events').EventEmitter
NavigationController = require './navigation-controller'
binding = process.atomBinding 'web_contents'
ipc = require 'ipc'
@@ -26,10 +27,12 @@ module.exports.wrap = (webContents) ->
webContents.getId = -> "#{@getProcessId()}-#{@getRoutingId()}"
webContents.equal = (other) -> @getId() is other.getId()
# Provide a default parameter for |urlOptions|.
webContents.loadUrl = (url, urlOptions={}) -> @_loadUrl url, urlOptions
webContents.reload = (urlOptions={}) -> @_reload urlOptions
webContents.reloadIgnoringCache = (urlOptions={}) -> @_reloadIgnoringCache urlOptions
# The navigation controller.
controller = new NavigationController(webContents)
webContents.controller = controller
for name, method of NavigationController.prototype when method instanceof Function
do (name, method) ->
webContents[name] = -> method.apply controller, arguments
# Translate |disposition| to string for 'new-window' event.
webContents.on '-new-window', (args..., disposition) ->

View File

@@ -49,7 +49,7 @@ struct FindByProcessId {
} // namespace
AtomBrowserClient::AtomBrowserClient()
: dying_render_process_(NULL) {
: dying_render_process_(nullptr) {
}
AtomBrowserClient::~AtomBrowserClient() {
@@ -119,27 +119,31 @@ void AtomBrowserClient::OverrideWebkitPrefs(
window->OverrideWebkitPrefs(prefs);
}
bool AtomBrowserClient::ShouldSwapBrowsingInstancesForNavigation(
content::SiteInstance* site_instance,
const GURL& current_url,
const GURL& new_url) {
if (site_instance->HasProcess())
dying_render_process_ = site_instance->GetProcess();
// Restart renderer process for all navigations, this relies on a patch to
// Chromium: http://git.io/_PaNyg.
return true;
}
std::string AtomBrowserClient::GetApplicationLocale() {
return l10n_util::GetApplicationLocale("");
}
void AtomBrowserClient::OverrideSiteInstanceForNavigation(
content::BrowserContext* browser_context,
content::SiteInstance* current_instance,
const GURL& url,
content::SiteInstance** new_instance) {
if (current_instance->HasProcess())
dying_render_process_ = current_instance->GetProcess();
// Restart renderer process for all navigations.
*new_instance = content::SiteInstance::CreateForURL(browser_context, url);
}
void AtomBrowserClient::AppendExtraCommandLineSwitches(
base::CommandLine* command_line,
int child_process_id) {
std::string process_type = command_line->GetSwitchValueASCII("type");
if (process_type != "renderer")
return;
WindowList* list = WindowList::GetInstance();
NativeWindow* window = NULL;
NativeWindow* window = nullptr;
// Find the owner of this child process.
WindowList::const_iterator iter = std::find_if(
@@ -150,15 +154,25 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches(
// If the render process is a newly started one, which means the window still
// uses the old going-to-be-swapped render process, then we try to find the
// window from the swapped render process.
if (window == NULL && dying_render_process_ != NULL) {
child_process_id = dying_render_process_->GetID();
if (!window && dying_render_process_) {
int dying_process_id = dying_render_process_->GetID();
WindowList::const_iterator iter = std::find_if(
list->begin(), list->end(), FindByProcessId(child_process_id));
if (iter != list->end())
list->begin(), list->end(), FindByProcessId(dying_process_id));
if (iter != list->end()) {
window = *iter;
child_process_id = dying_process_id;
} else {
// It appears that the dying process doesn't belong to a BrowserWindow,
// then it might be a guest process, if it is we should update its
// process ID in the WebViewManager.
auto child_process = content::RenderProcessHost::FromID(child_process_id);
// Update the process ID in webview guests.
WebViewManager::UpdateGuestProcessID(dying_render_process_,
child_process);
}
}
if (window != NULL) {
if (window) {
window->AppendExtraCommandLineSwitches(command_line, child_process_id);
} else {
// Append commnad line arguments for guest web view.
@@ -180,7 +194,7 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches(
}
}
dying_render_process_ = NULL;
dying_render_process_ = nullptr;
}
brightray::BrowserMainParts* AtomBrowserClient::OverrideCreateBrowserMainParts(

View File

@@ -27,11 +27,12 @@ class AtomBrowserClient : public brightray::BrowserClient {
void ResourceDispatcherHostCreated() override;
void OverrideWebkitPrefs(content::RenderViewHost* render_view_host,
content::WebPreferences* prefs) override;
bool ShouldSwapBrowsingInstancesForNavigation(
content::SiteInstance* site_instance,
const GURL& current_url,
const GURL& new_url) override;
std::string GetApplicationLocale() override;
void OverrideSiteInstanceForNavigation(
content::BrowserContext* browser_context,
content::SiteInstance* current_instance,
const GURL& dest_url,
content::SiteInstance** new_instance);
void AppendExtraCommandLineSwitches(base::CommandLine* command_line,
int child_process_id) override;

View File

@@ -27,7 +27,6 @@ void AtomJavaScriptDialogManager::RunBeforeUnloadDialog(
const base::string16& message_text,
bool is_reload,
const DialogClosedCallback& callback) {
bool prevent_reload = message_text.empty() ||
message_text == base::ASCIIToUTF16("false");
callback.Run(!prevent_reload, message_text);

View File

@@ -112,11 +112,12 @@ app.on('ready', function() {
click: function() { mainWindow.restart(); }
},
{
label: 'Enter Fullscreen',
click: function() { mainWindow.setFullScreen(true); }
label: 'Toggle Full Screen',
accelerator: 'Ctrl+Command+F',
click: function() { mainWindow.setFullScreen(!mainWindow.isFullScreen()); }
},
{
label: 'Toggle DevTools',
label: 'Toggle Developer Tools',
accelerator: 'Alt+Command+I',
click: function() { mainWindow.toggleDevTools(); }
},
@@ -144,6 +145,27 @@ app.on('ready', function() {
},
]
},
{
label: 'Help',
submenu: [
{
label: 'Learn More',
click: function() { require('shell').openExternal('http://electron.atom.io') }
},
{
label: 'Documentation',
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
},
{
label: 'Community Discussions',
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
},
{
label: 'Search Issues',
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
}
]
}
];
menu = Menu.buildFromTemplate(template);
@@ -173,16 +195,38 @@ app.on('ready', function() {
click: function() { mainWindow.restart(); }
},
{
label: '&Enter Fullscreen',
click: function() { mainWindow.setFullScreen(true); }
label: 'Toggle &Full Screen',
accelerator: 'F11',
click: function() { mainWindow.setFullScreen(!mainWindow.isFullScreen()); }
},
{
label: '&Toggle DevTools',
label: 'Toggle &Developer Tools',
accelerator: 'Alt+Ctrl+I',
click: function() { mainWindow.toggleDevTools(); }
},
]
},
{
label: 'Help',
submenu: [
{
label: 'Learn More',
click: function() { require('shell').openExternal('http://electron.atom.io') }
},
{
label: 'Documentation',
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
},
{
label: 'Community Discussions',
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
},
{
label: 'Search Issues',
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
}
]
}
];
menu = Menu.buildFromTemplate(template);

View File

@@ -11,11 +11,14 @@ app.on('window-all-closed', function() {
// Parse command line options.
var argv = process.argv.slice(1);
var option = { file: null, version: null, webdriver: null };
var option = { file: null, help: null, version: null, webdriver: null };
for (var i in argv) {
if (argv[i] == '--version' || argv[i] == '-v') {
option.version = true;
break;
} else if (argv[i] == '--help' || argv[i] == '-h') {
option.help = true;
break;
} else if (argv[i] == '--test-type=webdriver') {
option.webdriver = true;
} else if (argv[i][0] == '-') {
@@ -58,7 +61,17 @@ if (option.file && !option.webdriver) {
}
}
} else if (option.version) {
console.log('v' + process.versions['electron']);
console.log('v' + process.versions.electron);
process.exit(0);
} else if (option.help) {
var helpMessage = "Electron v" + process.versions.electron + " - Cross Platform Desktop Application Shell\n\n";
helpMessage += "Usage: electron [options] [path]\n\n";
helpMessage += "A path to an Electron application may be specified. The path must be to \n";
helpMessage += "an index.js file or to a folder containing a package.json or index.js file.\n\n";
helpMessage += "Options:\n";
helpMessage += " -h, --help Print this usage message.\n";
helpMessage += " -v, --version Print the version.";
console.log(helpMessage);
process.exit(0);
} else {
require('./default_app.js');

View File

@@ -10,12 +10,14 @@ supportedWebViewEvents = [
'did-stop-loading'
'did-get-response-details'
'did-get-redirect-request'
'dom-ready'
'console-message'
'new-window'
'close'
'crashed'
'destroyed'
'page-title-set'
'page-favicon-updated'
]
nextInstanceId = 0

View File

@@ -1,15 +1,15 @@
fs = require 'fs'
path = require 'path'
module = require 'module'
util = require 'util'
Module = require 'module'
# We modified the original process.argv to let node.js load the atom.js,
# we need to restore it here.
process.argv.splice 1, 1
# Add browser/api/lib to require's search paths,
# which contains javascript part of Atom's built-in libraries.
globalPaths = module.globalPaths
# Add browser/api/lib to module search paths, which contains javascript part of
# Electron's built-in libraries.
globalPaths = Module.globalPaths
globalPaths.push path.resolve(__dirname, '..', 'api', 'lib')
# Import common settings.
@@ -89,4 +89,4 @@ app.setPath 'userCache', path.join(app.getPath('cache'), app.getName())
require './chrome-extension'
# Finally load app's main.js and transfer control to C++.
module._load path.join(packagePath, packageJson.main), module, true
Module._load path.join(packagePath, packageJson.main), Module, true

View File

@@ -18,6 +18,4 @@
// CrAppControlProtocol:
- (void)setHandlingSendEvent:(BOOL)handlingSendEvent;
- (IBAction)closeAllWindows:(id)sender;
@end

View File

@@ -36,10 +36,6 @@
andEventID:kAEGetURL];
}
- (IBAction)closeAllWindows:(id)sender {
atom::Browser::Get()->Quit();
}
- (void)handleURLEvent:(NSAppleEventDescriptor*)event
withReplyEvent:(NSAppleEventDescriptor*)replyEvent {
NSString* url = [

View File

@@ -565,6 +565,7 @@ content::WebContents* NativeWindow::OpenURLFromTab(
load_url_params.is_renderer_initiated = params.is_renderer_initiated;
load_url_params.transferred_global_request_id =
params.transferred_global_request_id;
load_url_params.should_clear_history_list = true;
source->GetController().LoadURLWithParams(load_url_params);
return source;
@@ -685,6 +686,20 @@ void NativeWindow::RendererResponsive(content::WebContents* source) {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnRendererResponsive());
}
void NativeWindow::EnterFullscreenModeForTab(content::WebContents* source,
const GURL& origin) {
SetFullScreen(true);
}
void NativeWindow::ExitFullscreenModeForTab(content::WebContents* source) {
SetFullScreen(false);
}
bool NativeWindow::IsFullscreenForTabOrPending(
const content::WebContents* source) const {
return IsFullscreen();
}
void NativeWindow::BeforeUnloadFired(const base::TimeTicks& proceed_time) {
// Do nothing, we override this method just to avoid compilation error since
// there are two virtual functions named BeforeUnloadFired.

View File

@@ -112,7 +112,7 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
virtual void Restore() = 0;
virtual bool IsMinimized() = 0;
virtual void SetFullScreen(bool fullscreen) = 0;
virtual bool IsFullscreen() = 0;
virtual bool IsFullscreen() const = 0;
virtual void SetSize(const gfx::Size& size) = 0;
virtual gfx::Size GetSize() = 0;
virtual void SetContentSize(const gfx::Size& size) = 0;
@@ -273,6 +273,11 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
const content::WebContents* source) const override;
void RendererUnresponsive(content::WebContents* source) override;
void RendererResponsive(content::WebContents* source) override;
void EnterFullscreenModeForTab(content::WebContents* source,
const GURL& origin) override;
void ExitFullscreenModeForTab(content::WebContents* source) override;
bool IsFullscreenForTabOrPending(
const content::WebContents* source) const override;
// Implementations of content::WebContentsObserver.
void RenderViewCreated(content::RenderViewHost* render_view_host) override;

View File

@@ -44,7 +44,7 @@ class NativeWindowMac : public NativeWindow {
void Restore() override;
bool IsMinimized() override;
void SetFullScreen(bool fullscreen) override;
bool IsFullscreen() override;
bool IsFullscreen() const override;
void SetSize(const gfx::Size& size) override;
gfx::Size GetSize() override;
void SetContentSize(const gfx::Size& size) override;

View File

@@ -54,10 +54,8 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
@interface AtomNSWindowDelegate : NSObject<NSWindowDelegate> {
@private
atom::NativeWindowMac* shell_;
BOOL acceptsFirstMouse_;
}
- (id)initWithShell:(atom::NativeWindowMac*)shell;
- (void)setAcceptsFirstMouse:(BOOL)accept;
@end
@implementation AtomNSWindowDelegate
@@ -65,15 +63,10 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
- (id)initWithShell:(atom::NativeWindowMac*)shell {
if ((self = [super init])) {
shell_ = shell;
acceptsFirstMouse_ = NO;
}
return self;
}
- (void)setAcceptsFirstMouse:(BOOL)accept {
acceptsFirstMouse_ = accept;
}
- (void)windowDidBecomeMain:(NSNotification*)notification {
content::WebContents* web_contents = shell_->GetWebContents();
if (!web_contents)
@@ -151,10 +144,6 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
return NO;
}
- (BOOL)acceptsFirstMouse:(NSEvent*)event {
return acceptsFirstMouse_;
}
@end
@interface AtomNSWindow : EventProcessingWindow {
@@ -162,6 +151,8 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
atom::NativeWindowMac* shell_;
bool enable_larger_than_screen_;
}
@property BOOL acceptsFirstMouse;
@property BOOL disableAutoHideCursor;
- (void)setShell:(atom::NativeWindowMac*)shell;
- (void)setEnableLargerThanScreen:(bool)enable;
@end
@@ -184,16 +175,6 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
return [super constrainFrameRect:frameRect toScreen:screen];
}
- (IBAction)reload:(id)sender {
content::WebContents* web_contents = shell_->GetWebContents();
content::NavigationController::LoadURLParams params(web_contents->GetURL());
web_contents->GetController().LoadURLWithParams(params);
}
- (IBAction)showDevTools:(id)sender {
shell_->OpenDevTools(true);
}
- (id)accessibilityAttributeValue:(NSString*)attribute {
if (![attribute isEqualToString:@"AXChildren"])
return [super accessibilityAttributeValue:attribute];
@@ -349,6 +330,10 @@ NativeWindowMac::NativeWindowMac(content::WebContents* web_contents,
[window_ setBackgroundColor:[NSColor clearColor]];
}
// Remove non-transparent corners, see http://git.io/vfonD.
if (!has_frame_)
[window_ setOpaque:NO];
// We will manage window's lifetime ourselves.
[window_ setReleasedWhenClosed:NO];
@@ -361,7 +346,12 @@ NativeWindowMac::NativeWindowMac(content::WebContents* web_contents,
// Enable the NSView to accept first mouse event.
bool acceptsFirstMouse = false;
options.Get(switches::kAcceptFirstMouse, &acceptsFirstMouse);
[window_delegate_ setAcceptsFirstMouse:acceptsFirstMouse];
[window_ setAcceptsFirstMouse:acceptsFirstMouse];
// Disable auto-hiding cursor.
bool disableAutoHideCursor = false;
options.Get(switches::kDisableAutoHideCursor, &disableAutoHideCursor);
[window_ setDisableAutoHideCursor:disableAutoHideCursor];
// Disable fullscreen button when 'fullscreen' is specified to false.
bool fullscreen;
@@ -476,7 +466,7 @@ void NativeWindowMac::SetFullScreen(bool fullscreen) {
[window_ toggleFullScreen:nil];
}
bool NativeWindowMac::IsFullscreen() {
bool NativeWindowMac::IsFullscreen() const {
return [window_ styleMask] & NSFullScreenWindowMask;
}

View File

@@ -369,7 +369,7 @@ void NativeWindowViews::SetFullScreen(bool fullscreen) {
#endif
}
bool NativeWindowViews::IsFullscreen() {
bool NativeWindowViews::IsFullscreen() const {
return window_->IsFullscreen();
}

View File

@@ -49,7 +49,7 @@ class NativeWindowViews : public NativeWindow,
void Restore() override;
bool IsMinimized() override;
void SetFullScreen(bool fullscreen) override;
bool IsFullscreen() override;
bool IsFullscreen() const override;
void SetSize(const gfx::Size& size) override;
gfx::Size GetSize() override;
void SetContentSize(const gfx::Size& size) override;

View File

@@ -17,7 +17,7 @@
<key>CFBundleIconFile</key>
<string>atom.icns</string>
<key>CFBundleVersion</key>
<string>0.25.0</string>
<string>0.25.2</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,25,0,0
PRODUCTVERSION 0,25,0,0
FILEVERSION 0,25,2,0
PRODUCTVERSION 0,25,2,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -68,12 +68,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "GitHub, Inc."
VALUE "FileDescription", "Electron"
VALUE "FileVersion", "0.25.0"
VALUE "FileVersion", "0.25.2"
VALUE "InternalName", "electron.exe"
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
VALUE "OriginalFilename", "electron.exe"
VALUE "ProductName", "Electron"
VALUE "ProductVersion", "0.25.0"
VALUE "ProductVersion", "0.25.2"
VALUE "SquirrelAwareVersion", "1"
END
END

View File

@@ -10,18 +10,42 @@
namespace atom {
namespace {
WebViewManager* GetManagerFromProcess(content::RenderProcessHost* process) {
if (!process)
return nullptr;
auto context = process->GetBrowserContext();
if (!context)
return nullptr;
return static_cast<WebViewManager*>(context->GetGuestManager());
}
} // namespace
// static
bool WebViewManager::GetInfoForProcess(content::RenderProcessHost* process,
WebViewInfo* info) {
if (!process)
return false;
auto context = process->GetBrowserContext();
if (!context)
return false;
auto manager = context->GetGuestManager();
auto manager = GetManagerFromProcess(process);
if (!manager)
return false;
return static_cast<WebViewManager*>(manager)->GetInfo(process->GetID(), info);
return manager->GetInfo(process->GetID(), info);
}
// static
void WebViewManager::UpdateGuestProcessID(
content::RenderProcessHost* old_process,
content::RenderProcessHost* new_process) {
auto manager = GetManagerFromProcess(old_process);
if (manager) {
base::AutoLock auto_lock(manager->lock_);
int old_id = old_process->GetID();
int new_id = new_process->GetID();
if (!ContainsKey(manager->webview_info_map_, old_id))
return;
manager->webview_info_map_[new_id] = manager->webview_info_map_[old_id];
manager->webview_info_map_.erase(old_id);
}
}
WebViewManager::WebViewManager(content::BrowserContext* context) {

View File

@@ -34,6 +34,10 @@ class WebViewManager : public content::BrowserPluginGuestManager {
static bool GetInfoForProcess(content::RenderProcessHost* process,
WebViewInfo* info);
// Updates the guest process ID.
static void UpdateGuestProcessID(content::RenderProcessHost* old_process,
content::RenderProcessHost* new_process);
explicit WebViewManager(content::BrowserContext* context);
virtual ~WebViewManager();

View File

@@ -7,7 +7,7 @@
#define ATOM_MAJOR_VERSION 0
#define ATOM_MINOR_VERSION 25
#define ATOM_PATCH_VERSION 0
#define ATOM_PATCH_VERSION 2
#define ATOM_VERSION_IS_RELEASE 1

View File

@@ -53,11 +53,20 @@ asarStatsToFsStats = (stats) ->
}
# Create a ENOENT error.
createNotFoundError = (asarPath, filePath) ->
notFoundError = (asarPath, filePath, callback) ->
error = new Error("ENOENT, #{filePath} not found in #{asarPath}")
error.code = "ENOENT"
error.errno = -2
error
unless typeof callback is 'function'
throw error
process.nextTick -> callback error
# Create invalid archive error.
invalidArchiveError = (asarPath, callback) ->
error = new Error("Invalid package #{asarPath}")
unless typeof callback is 'function'
throw error
process.nextTick -> callback error
# Override APIs that rely on passing file path instead of content to C++.
overrideAPISync = (module, name, arg = 0) ->
@@ -68,10 +77,10 @@ overrideAPISync = (module, name, arg = 0) ->
return old.apply this, arguments unless isAsar
archive = getOrCreateArchive asarPath
throw new Error("Invalid package #{asarPath}") unless archive
invalidArchiveError asarPath unless archive
newPath = archive.copyFileOut filePath
throw createNotFoundError(asarPath, filePath) unless newPath
notFoundError asarPath, filePath unless newPath
arguments[arg] = newPath
old.apply this, arguments
@@ -87,10 +96,10 @@ overrideAPI = (module, name, arg = 0) ->
return overrideAPISync module, name, arg unless typeof callback is 'function'
archive = getOrCreateArchive asarPath
return callback new Error("Invalid package #{asarPath}") unless archive
return invalidArchiveError asarPath, callback unless archive
newPath = archive.copyFileOut filePath
return callback createNotFoundError(asarPath, filePath) unless newPath
return notFoundError asarPath, filePath, callback unless newPath
arguments[arg] = newPath
old.apply this, arguments
@@ -103,10 +112,10 @@ exports.wrapFsWithAsar = (fs) ->
return lstatSync p unless isAsar
archive = getOrCreateArchive asarPath
throw new Error("Invalid package #{asarPath}") unless archive
invalidArchiveError asarPath unless archive
stats = archive.stat filePath
throw createNotFoundError(asarPath, filePath) unless stats
notFoundError asarPath, filePath unless stats
asarStatsToFsStats stats
@@ -116,10 +125,10 @@ exports.wrapFsWithAsar = (fs) ->
return lstat p, callback unless isAsar
archive = getOrCreateArchive asarPath
return callback new Error("Invalid package #{asarPath}") unless archive
return invalidArchiveError asarPath, callback unless archive
stats = getOrCreateArchive(asarPath).stat filePath
return callback createNotFoundError(asarPath, filePath) unless stats
return notFoundError asarPath, filePath, callback unless stats
process.nextTick -> callback null, asarStatsToFsStats stats
@@ -156,10 +165,10 @@ exports.wrapFsWithAsar = (fs) ->
return realpathSync.apply this, arguments unless isAsar
archive = getOrCreateArchive asarPath
throw new Error("Invalid package #{asarPath}") unless archive
invalidArchiveError asarPath unless archive
real = archive.realpath filePath
throw createNotFoundError(asarPath, filePath) if real is false
notFoundError asarPath, filePath if real is false
path.join realpathSync(asarPath), real
@@ -173,10 +182,11 @@ exports.wrapFsWithAsar = (fs) ->
cache = undefined
archive = getOrCreateArchive asarPath
return callback new Error("Invalid package #{asarPath}") unless archive
return invalidArchiveError asarPath, callback unless archive
real = archive.realpath filePath
return callback createNotFoundError(asarPath, filePath) if real is false
if real is false
return notFoundError asarPath, filePath, callback
realpath asarPath, (err, p) ->
return callback err if err
@@ -188,7 +198,7 @@ exports.wrapFsWithAsar = (fs) ->
return exists p, callback unless isAsar
archive = getOrCreateArchive asarPath
return callback new Error("Invalid package #{asarPath}") unless archive
return invalidArchiveError asarPath, callback unless archive
process.nextTick -> callback archive.stat(filePath) isnt false
@@ -213,11 +223,13 @@ exports.wrapFsWithAsar = (fs) ->
options = undefined
archive = getOrCreateArchive asarPath
return callback new Error("Invalid package #{asarPath}") unless archive
return invalidArchiveError asarPath, callback unless archive
info = archive.getFileInfo filePath
return callback createNotFoundError(asarPath, filePath) unless info
return callback null, new Buffer(0) if info.size is 0
return notFoundError asarPath, filePath, callback unless info
if info.size is 0
return process.nextTick -> callback null, new Buffer(0)
if info.unpacked
realPath = archive.copyFileOut filePath
@@ -247,10 +259,10 @@ exports.wrapFsWithAsar = (fs) ->
return readFileSync.apply this, arguments unless isAsar
archive = getOrCreateArchive asarPath
throw new Error("Invalid package #{asarPath}") unless archive
invalidArchiveError asarPath unless archive
info = archive.getFileInfo filePath
throw createNotFoundError(asarPath, filePath) unless info
notFoundError asarPath, filePath unless info
return new Buffer(0) if info.size is 0
if info.unpacked
@@ -283,10 +295,10 @@ exports.wrapFsWithAsar = (fs) ->
return readdir.apply this, arguments unless isAsar
archive = getOrCreateArchive asarPath
return callback new Error("Invalid package #{asarPath}") unless archive
return invalidArchiveError asarPath, callback unless archive
files = archive.readdir filePath
return callback createNotFoundError(asarPath, filePath) unless files
return notFoundError asarPath, filePath, callback unless files
process.nextTick -> callback null, files
@@ -296,10 +308,10 @@ exports.wrapFsWithAsar = (fs) ->
return readdirSync.apply this, arguments unless isAsar
archive = getOrCreateArchive asarPath
throw new Error("Invalid package #{asarPath}") unless archive
invalidArchiveError asarPath unless archive
files = archive.readdir filePath
throw createNotFoundError(asarPath, filePath) unless files
notFoundError asarPath, filePath unless files
files

View File

@@ -10,8 +10,20 @@ process.atomBinding = (name) ->
catch e
process.binding "atom_common_#{name}" if /No such module/.test e.message
# Add common/api/lib to module search paths.
# Global module search paths.
globalPaths = Module.globalPaths
# Don't lookup modules in user-defined search paths, see http://git.io/vf8sF.
homeDir =
if process.platform is 'win32'
process.env.USERPROFILE
else
process.env.HOME
if homeDir # Node only add user-defined search paths when $HOME is defined.
userModulePath = path.resolve homeDir, '.node_modules'
globalPaths.splice globalPaths.indexOf(userModulePath), 2
# Add common/api/lib to module search paths.
globalPaths.push path.resolve(__dirname, '..', 'api', 'lib')
# setImmediate and process.nextTick makes use of uv_check and uv_prepare to

View File

@@ -75,6 +75,9 @@ const char kTransparent[] = "transparent";
// Window type hint.
const char kType[] = "type";
// Disable auto-hiding cursor.
const char kDisableAutoHideCursor[] = "disable-auto-hide-cursor";
// Web runtime features.
const char kExperimentalFeatures[] = "experimental-features";
const char kExperimentalCanvasFeatures[] = "experimental-canvas-features";

View File

@@ -41,6 +41,7 @@ extern const char kGuestInstanceID[];
extern const char kPreloadScript[];
extern const char kTransparent[];
extern const char kType[];
extern const char kDisableAutoHideCursor[];
extern const char kExperimentalFeatures[];
extern const char kExperimentalCanvasFeatures[];

File diff suppressed because it is too large Load Diff

View File

@@ -12,12 +12,14 @@ WEB_VIEW_EVENTS =
'did-get-response-details': ['status', 'newUrl', 'originalUrl',
'httpResponseCode', 'requestMethod', 'referrer']
'did-get-redirect-request': ['oldUrl', 'newUrl', 'isMainFrame']
'dom-ready': []
'console-message': ['level', 'message', 'line', 'sourceId']
'new-window': ['url', 'frameName', 'disposition']
'close': []
'crashed': []
'destroyed': []
'page-title-set': ['title', 'explicitSet']
'page-favicon-updated': ['favicons']
dispatchEvent = (webView, event, args...) ->
throw new Error("Unkown event #{event}") unless WEB_VIEW_EVENTS[event]?

View File

@@ -138,10 +138,7 @@ class SrcAttribute extends WebViewAttribute
setupMutationObserver: ->
@observer = new MutationObserver (mutations) =>
for mutation in mutations
oldValue = mutation.oldValue
newValue = @getValue()
return if oldValue isnt newValue
@handleMutation oldValue, newValue
@handleMutation mutation.oldValue, @getValue()
params =
attributes: true,
attributeOldValue: true,

View File

@@ -255,6 +255,7 @@ registerWebViewElement = ->
"openDevTools"
"closeDevTools"
"isDevToolsOpened"
"inspectElement"
"undo"
"redo"
"cut"
@@ -276,6 +277,13 @@ registerWebViewElement = ->
remote.getGuestWebContents(internal.guestInstanceId)[m] args...
proto[m] = createHandler m for m in methods
# Return dataUrl instead of nativeImage.
proto.getFavicon = (args...) ->
internal = v8Util.getHiddenValue this, 'internal'
return unless internal
favicon = remote.getGuestWebContents(internal.guestInstanceId)['getFavicon'] args...
favicon.toDataUrl()
window.WebView = webFrame.registerEmbedderCustomElement 'webview',
prototype: proto

View File

@@ -54,9 +54,10 @@ You can also create a window without chrome by using
* `frame` Boolean - Specify `false` to create a
[Frameless Window](frameless-window.md)
* `node-integration` Boolean - Whether node integration is enabled, default
is `true`
is `true`
* `accept-first-mouse` Boolean - Whether the web view accepts a single
mouse-down event that simultaneously activates the window
mouse-down event that simultaneously activates the window
* `disable-auto-hide-cursor` Boolean - Do not hide cursor when typing
* `auto-hide-menu-bar` Boolean - Auto hide the menu bar unless the `Alt`
key is pressed.
* `enable-larger-than-screen` Boolean - Enable the window to be resized larger
@@ -662,6 +663,19 @@ Emitted when details regarding a requested resource is available.
Emitted when a redirect was received while requesting a resource.
### Event: 'dom-ready'
* `event` Event
Emitted when document in the given frame is loaded.
### Event: 'page-favicon-updated'
* `event` Event
* `favicons` Array - Array of Urls
Emitted when page receives favicon urls.
### Event: 'new-window'
* `event` Event
@@ -713,6 +727,10 @@ Returns URL of current web page.
Returns the title of web page.
### WebContents.getFavicon()
Returns the favicon of web page as [NativeImage](native-image.md).
### WebContents.isLoading()
Returns whether web page is still loading resources.
@@ -834,6 +852,21 @@ Executes editing command `replace` in page.
Executes editing command `replaceMisspelling` in page.
### WebContents.hasServiceWorker(callback)
* `callback` Function
Checks if any serviceworker is registered and returns boolean as
response to `callback`.
### WebContents.unregisterServiceWorker(callback)
* `callback` Function
Unregisters any serviceworker if present and returns boolean as
response to `callback` when the JS promise is fullfilled or false
when the JS promise is rejected.
### WebContents.send(channel[, args...])
* `channel` String

View File

@@ -130,6 +130,10 @@ Returns URL of guest page.
Returns the title of guest page.
### `<webview>`.getFavicon()
Returns the favicon of guest page as dataUrl.
### `<webview>`.isLoading()
Returns whether guest page is still loading resources.
@@ -219,6 +223,13 @@ Closes the devtools window of guest page.
Returns whether guest page has a devtools window attached.
### `<webview>`.inspectElement(x, y)
* `x` Integer
* `y` Integer
Starts inspecting element at position (`x`, `y`) of guest page.
### `<webview>`.undo()
Executes editing command `undo` in page.
@@ -322,6 +333,10 @@ Fired when details regarding a requested resource is available.
Fired when a redirect was received while requesting a resource.
### dom-ready
Fired when document in the given frame is loaded.
### page-title-set
* `title` String
@@ -330,6 +345,12 @@ Fired when a redirect was received while requesting a resource.
Fired when page title is set during navigation. `explicitSet` is false when title is synthesised from file
url.
### page-favicon-updated
* `favicons` Array - Array of Urls
Fired when page receives favicon urls.
### console-message
* `level` Integer

View File

@@ -3,7 +3,7 @@
__Note: Electron was previously named Atom Shell.__
Like NW.js, Electron provides a platform to write desktop applications
with JavaScript and HTML, and has Node integration to grant access to low level
with JavaScript and HTML and has Node integration to grant access to low level
system in web pages.
But there are also fundamental differences between the two projects that make
@@ -11,39 +11,38 @@ Electron a completely separate product from NW.js:
__1. Entry of application__
In NW.js, the main entry of an application is a web page, you specify a
main page in the `package.json` and it would be opened in a browser window as
In NW.js, the main entry of an application is a web page. You specify a
main page in the `package.json` and it is opened in a browser window as
the application's main window.
While in Electron, the entry point is a JavaScript script, instead of
providing a URL directly, you need to manually create a browser window and load
html file in it with corresponding API. You also need to listen to window events
In Electron, the entry point is a JavaScript script. Instead of
providing a URL directly, you manually create a browser window and load
an HTML file using the API. You also need to listen to window events
to decide when to quit the application.
So Electron works more like the Node.js runtime, and APIs are more low level,
you can also use Electron for web testing purpose like
[phantomjs](http://phantomjs.org/).
Electron works more like the Node.js runtime. Electron's APIs are lower level
so you can use it for browser testing in place of [PhantomJS](http://phantomjs.org/).
__2. Build system__
In order to avoid the complexity of building the whole Chromium, Electron uses
[libchromiumcontent](https://github.com/brightray/libchromiumcontent) to access
Chromium's Content API, libchromiumcontent is a single, shared library that
includes the Chromium Content module and all its dependencies. So users don't
Chromium's Content API. libchromiumcontent is a single, shared library that
includes the Chromium Content module and all its dependencies. Users don't
need a powerful machine to build Electron.
__3. Node integration__
In NW.js, the Node integration in web pages requires patching Chromium to
work, while in Electron we chose a different way to integrate libuv loop to
each platform's message loop to avoid hacking Chromium, see the
work, while in Electron we chose a different way to integrate libuv loop with
each platform's message loop to avoid hacking Chromium. See the
[`node_bindings`](../../atom/common/) code for how that was done.
__4. Multi-context__
If you are an experienced NW.js user, you should be familiar with the
concept of Node context and web context, these concepts were invented because
of how the NW.js was implemented.
concept of Node context and web context. These concepts were invented because
of how NW.js was implemented.
By using the [multi-context](http://strongloop.com/strongblog/whats-new-node-js-v0-12-multiple-context-execution/)
feature of Node, Electron doesn't introduce a new JavaScript context in web

View File

@@ -18,7 +18,7 @@ Guide](https://github.com/styleguide/javascript), and also following rules:
* File names should be concatenated with `-` instead of `_`, e.g.
`file-name.coffee` rather than `file_name.coffee`, because in
[github/atom](https://github.com/github/atom) module names are usually in
the `module-name` form, this rule only apply to `.coffee` files.
the `module-name` form, this rule only applies to `.coffee` files.
## API Names

View File

@@ -118,8 +118,8 @@ app.setUserTasks([
arguments: '--new-window',
iconPath: process.execPath,
iconIndex: 0,
title: 'New Window'
description: 'Create a new winodw',
title: 'New Window',
description: 'Create a new window',
}
]);
```

View File

@@ -2,41 +2,35 @@
## Introduction
Generally, Electron enables you to create desktop applications with pure
JavaScript by providing a runtime with rich native APIs. You could see it as
a variant of the io.js runtime which is focused on desktop applications
instead of web servers.
Electron enables you to create desktop applications with pure JavaScript by providing a runtime with rich native APIs. You could see it as a variant of the io.js runtime which is focused on desktop applications instead of web servers.
It doesn't mean Electron is a JavaScript binding to GUI libraries. Instead,
Electron uses web pages as its GUI, so you could also see it as a minimal
Chromium browser, controlled by JavaScript.
### The main process
### Main process
In Electron the process that runs `package.json`'s `main` script is called
__the main process__. The script runs in the main process can display GUI by
In Electron, the process that runs `package.json`'s `main` script is called
__the main process__. The script that runs in the main process, can display GUI by
creating web pages.
### The renderer process
### Renderer process
Since Electron uses Chromium for displaying web pages, Chromium's
multi-processes architecture is also used. Each web page in Electron runs in
its own process, which is called __the renderer process__.
In normal browsers web pages usually run in a sandboxed environment and are not
allowed access to native resources. In Electron users have the power to use
io.js APIs in web pages and it is therefore possible to interact with low level
operating system features.
allowed access to native resources. Electron users however, have the power to use
io.js APIs in web pages allowing lower level operating system interactions.
### Differences between main process and renderer process
The main process creates web pages by creating `BrowserWindow` instances, and
each `BrowserWindow` instance runs the web page in its own renderer process,
when a `BrowserWindow` instance is destroyed, the corresponding renderer process
The main process creates web pages by creating `BrowserWindow` instances. Each `BrowserWindow` instance runs the web page in its own renderer process. When a `BrowserWindow` instance is destroyed, the corresponding renderer process
would also be terminated.
So the main process manages all web pages and their corresponding renderer
processes, and each renderer process is separated from each other and only care
The main process manages all web pages and their corresponding renderer
processes, each renderer process is isolated and only cares
about the web page running in it.
In web pages, it is not allowed to call native GUI related APIs because managing
@@ -121,7 +115,7 @@ Finally the `index.html` is the web page you want to show:
</head>
<body>
<h1>Hello World!</h1>
We are using node.js <script>document.write(process.version)</script>
We are using io.js <script>document.write(process.version)</script>
and Electron <script>document.write(process.versions['electron'])</script>.
</body>
</html>
@@ -149,7 +143,7 @@ $ ./electron/electron your-app/
On OS X:
```bash
$ ./Electron.app/Contents/MacOS/Atom your-app/
$ ./Electron.app/Contents/MacOS/Electron your-app/
```
`Electron.app` here is part of the Electron's release package, you can download

View File

@@ -18,6 +18,7 @@
'atom/browser/api/lib/ipc.coffee',
'atom/browser/api/lib/menu.coffee',
'atom/browser/api/lib/menu-item.coffee',
'atom/browser/api/lib/navigation-controller.coffee',
'atom/browser/api/lib/power-monitor.coffee',
'atom/browser/api/lib/protocol.coffee',
'atom/browser/api/lib/screen.coffee',

View File

@@ -1,9 +1,9 @@
{
"name": "electron",
"devDependencies": {
"asar": "0.2.2",
"coffee-script": "~1.7.1",
"coffeelint": "~1.3.0",
"asar": "0.5.0",
"coffee-script": "^1.9.2",
"coffeelint": "^1.9.4",
"request": "*",
"runas": "^2.0.0"
},

View File

@@ -114,7 +114,6 @@ def update_info_plist(version):
def tag_version(version):
execute(['git', 'commit', '-a', '-m', 'Bump v{0}'.format(version)])
execute(['git', 'tag', 'v{0}'.format(version)])
if __name__ == '__main__':

View File

@@ -7,7 +7,7 @@ import sys
BASE_URL = 'http://gh-contractor-zcbenz.s3.amazonaws.com/libchromiumcontent'
LIBCHROMIUMCONTENT_COMMIT = '0529dc17ca2f950b671cf12f82260cc397b4cebb'
LIBCHROMIUMCONTENT_COMMIT = '0fb4fbe55f5a967b960644f0fdc2013668d5a46a'
PLATFORM = {
'cygwin': 'win32',

View File

@@ -39,8 +39,11 @@ def parse_args():
def get_files_list(version):
return [
'node-{0}.tar.gz'.format(version),
'iojs-{0}.tar.gz'.format(version),
'node.lib',
'x64/node.lib',
'win-x86/iojs.lib',
'win-x64/iojs.lib',
]

View File

@@ -38,10 +38,13 @@ def main():
safe_mkdir(DIST_DIR)
args = parse_args()
dist_headers_dir = os.path.join(DIST_DIR, 'node-{0}'.format(args.version))
node_headers_dir = os.path.join(DIST_DIR, 'node-{0}'.format(args.version))
iojs_headers_dir = os.path.join(DIST_DIR, 'iojs-{0}'.format(args.version))
copy_headers(dist_headers_dir)
create_header_tarball(dist_headers_dir)
copy_headers(node_headers_dir)
create_header_tarball(node_headers_dir)
copy_headers(iojs_headers_dir)
create_header_tarball(iojs_headers_dir)
# Upload node's headers to S3.
bucket, access_key, secret_key = s3_config()
@@ -103,22 +106,32 @@ def upload_node(bucket, access_key, secret_key, version):
with scoped_cwd(DIST_DIR):
s3put(bucket, access_key, secret_key, DIST_DIR,
'atom-shell/dist/{0}'.format(version), glob.glob('node-*.tar.gz'))
s3put(bucket, access_key, secret_key, DIST_DIR,
'atom-shell/dist/{0}'.format(version), glob.glob('iojs-*.tar.gz'))
if PLATFORM == 'win32':
if get_target_arch() == 'ia32':
node_lib = os.path.join(DIST_DIR, 'node.lib')
iojs_lib = os.path.join(DIST_DIR, 'win-x86', 'iojs.lib')
else:
node_lib = os.path.join(DIST_DIR, 'x64', 'node.lib')
safe_mkdir(os.path.dirname(node_lib))
iojs_lib = os.path.join(DIST_DIR, 'win-x64', 'iojs.lib')
safe_mkdir(os.path.dirname(node_lib))
safe_mkdir(os.path.dirname(iojs_lib))
# Copy atom.lib to node.lib
# Copy atom.lib to node.lib and iojs.lib.
atom_lib = os.path.join(OUT_DIR, 'node.dll.lib')
shutil.copy2(atom_lib, node_lib)
shutil.copy2(atom_lib, iojs_lib)
# Upload the node.lib.
s3put(bucket, access_key, secret_key, DIST_DIR,
'atom-shell/dist/{0}'.format(version), [node_lib])
# Upload the iojs.lib.
s3put(bucket, access_key, secret_key, DIST_DIR,
'atom-shell/dist/{0}'.format(version), [iojs_lib])
if __name__ == '__main__':
sys.exit(main())

View File

@@ -2,6 +2,8 @@ assert = require 'assert'
fs = require 'fs'
path = require 'path'
remote = require 'remote'
http = require 'http'
url = require 'url'
BrowserWindow = remote.require 'browser-window'
@@ -216,8 +218,28 @@ describe 'browser-window module', ->
describe 'will-navigate event', ->
it 'emits when user starts a navigation', (done) ->
@timeout 10000
w.webContents.on 'will-navigate', (event, url) ->
event.preventDefault()
assert.equal url, 'https://www.github.com/'
done()
w.loadUrl "file://#{fixtures}/pages/will-navigate.html"
describe 'dom-ready event', ->
it 'emits when document is loaded', (done) ->
server = http.createServer (req, res) ->
action = url.parse(req.url, true).pathname
if action == '/logo.png'
img = fs.readFileSync(path.join(fixtures, 'assets', 'logo.png'))
res.writeHead(200, {'Content-Type': 'image/png'})
setTimeout ->
res.end(img, 'binary')
, 2000
server.close()
server.listen 62542, '127.0.0.1'
remote.require('ipc').on 'dom-ready', (e, state) ->
assert.equal state, 'interactive'
done()
w.webContents.on 'did-finish-load', ->
w.close()
w.loadUrl "file://#{fixtures}/pages/f.html"

View File

@@ -66,6 +66,7 @@ describe 'ipc module', ->
assert.equal msg, 'test'
it 'does not crash when reply is not sent and browser is destroyed', (done) ->
@timeout 10000
w = new BrowserWindow(show: false)
remote.require('ipc').once 'send-sync-message', (event) ->
event.returnValue = null

View File

@@ -36,6 +36,14 @@ describe 'asar package', ->
throws = -> fs.readFileSync p
assert.throws throws, /ENOENT/
it 'passes ENOENT error to callback when can not find file', ->
p = path.join fixtures, 'asar', 'a.asar', 'not-exist'
async = false
fs.readFile p, (e) ->
assert async
assert /ENOENT/.test e
async = true
describe 'fs.readFile', ->
it 'reads a normal file', (done) ->
p = path.join fixtures, 'asar', 'a.asar', 'file1'

View File

@@ -1,4 +1,6 @@
<html>
<link rel="icon" type="image/png" href="/favicon.png"/>
<link rel="icon" type="image/png" href="http://test.com/favicon.png"/>
<body>
<script type="text/javascript" charset="utf-8">
console.log('a');

View File

@@ -0,0 +1,13 @@
<html>
<body>
<script type="text/javascript" charset="utf-8">
window.onbeforeunload = function() {
setTimeout(function() {
var ipc = require('ipc');
ipc.sendToHost('onbeforeunload');
}, 0);
return false;
}
</script>
</body>
</html>

11
spec/fixtures/pages/f.html vendored Normal file
View File

@@ -0,0 +1,11 @@
<html>
<body>
<img src='http://127.0.0.1:62542/logo.png' />
<script type="text/javascript" charset="utf-8">
var remote = require('remote')
remote.getCurrentWindow().webContents.on('dom-ready', function() {
require('ipc').send('dom-ready', document.readyState);
})
</script>
</body>
</html>

View File

@@ -0,0 +1,9 @@
<html>
<body>
<script type="text/javascript" charset="utf-8">
var path = require('path');
console.log(typeof require(path.join(__dirname, '..', '..', 'node_modules', 'runas')));
</script>
</body>
</html>

View File

@@ -47,6 +47,19 @@ describe '<webview> tag', ->
webview.src = "file://#{fixtures}/pages/d.html"
document.body.appendChild webview
it 'loads native modules when navigation happens', (done) ->
listener = (e) ->
webview.removeEventListener 'did-finish-load', listener
listener2 = (e) ->
assert.equal e.message, 'function'
done()
webview.addEventListener 'console-message', listener2
webview.src = "file://#{fixtures}/pages/native-module.html"
webview.addEventListener 'did-finish-load', listener
webview.setAttribute 'nodeintegration', 'on'
webview.src = "file://#{fixtures}/pages/native-module.html"
document.body.appendChild webview
describe 'preload attribute', ->
it 'loads the script before other scripts in window', (done) ->
listener = (e) ->
@@ -151,3 +164,32 @@ describe '<webview> tag', ->
done()
webview.src = "file://#{fixtures}/pages/a.html"
document.body.appendChild webview
describe 'page-favicon-updated event', ->
it 'emits when favicon urls are received', (done) ->
webview.addEventListener 'page-favicon-updated', (e) ->
assert.equal e.favicons.length, 2
url =
if process.platform is 'win32'
'file:///C:/favicon.png'
else
'file:///favicon.png'
assert.equal e.favicons[0], url
done()
webview.src = "file://#{fixtures}/pages/a.html"
document.body.appendChild webview
describe '<webview>.reload()', ->
it 'should emit beforeunload handler', (done) ->
webview.addEventListener 'did-finish-load', (e) ->
webview.reload()
listener = (e) ->
assert.equal e.channel, 'onbeforeunload'
webview.removeEventListener 'ipc-message', listener
done()
webview.addEventListener 'console-message', (e) ->
console.log(e)
webview.addEventListener 'ipc-message', listener
webview.setAttribute 'nodeintegration', 'on'
webview.src = "file://#{fixtures}/pages/beforeunload-false.html"
document.body.appendChild webview

2
vendor/node vendored