diff --git a/README.md b/README.md index 94d4c09982..dd03f7099e 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,11 @@ contains documents describing how to build and contribute to Electron. - [Simplified Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-CN) - [Traditional Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-TW) +## Quick Start + +Clone and run the [`atom/electron-quick-start`](https://github.com/atom/electron-quick-start) +repository to see a minimal Electron app in action. + ## Community You can ask questions and interact with the community in the following diff --git a/atom/app/atom_main_delegate.cc b/atom/app/atom_main_delegate.cc index 44f2048c09..e4ac7cfc0a 100644 --- a/atom/app/atom_main_delegate.cc +++ b/atom/app/atom_main_delegate.cc @@ -59,7 +59,9 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) { #endif // !defined(OS_WIN) // Only enable logging when --enable-logging is specified. - if (!command_line->HasSwitch(switches::kEnableLogging)) { + scoped_ptr env(base::Environment::Create()); + if (!command_line->HasSwitch(switches::kEnableLogging) && + !env->HasVar("ELECTRON_ENABLE_LOGGING")) { settings.logging_dest = logging::LOG_NONE; logging::SetMinLogLevel(logging::LOG_NUM_SEVERITIES); } @@ -69,10 +71,13 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) { // Logging with pid and timestamp. logging::SetLogItems(true, false, true, false); -#if defined(DEBUG) && defined(OS_LINUX) // Enable convient stack printing. - base::debug::EnableInProcessStackDumping(); + bool enable_stack_dumping = env->HasVar("ELECTRON_ENABLE_STACK_DUMPING"); +#if defined(DEBUG) && defined(OS_LINUX) + enable_stack_dumping = true; #endif + if (enable_stack_dumping) + base::debug::EnableInProcessStackDumping(); return brightray::MainDelegate::BasicStartupComplete(exit_code); } diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 70595856c4..f124b00e80 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -251,6 +251,12 @@ void App::SetAppUserModelId(const std::string& app_id) { #endif } +void App::AllowNTLMCredentialsForAllDomains(bool should_allow) { + auto browser_context = static_cast( + AtomBrowserMainParts::Get()->browser_context()); + browser_context->AllowNTLMCredentialsForAllDomains(should_allow); +} + std::string App::GetLocale() { return l10n_util::GetApplicationLocale(""); } @@ -285,6 +291,8 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder( .SetMethod("getPath", &App::GetPath) .SetMethod("setDesktopName", &App::SetDesktopName) .SetMethod("setAppUserModelId", &App::SetAppUserModelId) + .SetMethod("allowNTLMCredentialsForAllDomains", + &App::AllowNTLMCredentialsForAllDomains) .SetMethod("getLocale", &App::GetLocale) .SetProperty("defaultSession", &App::DefaultSession); } diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index 4896a5f066..75889d2454 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -65,6 +65,8 @@ class App : public mate::EventEmitter, void SetDesktopName(const std::string& desktop_name); void SetAppUserModelId(const std::string& app_id); + void AllowNTLMCredentialsForAllDomains(bool should_allow); + std::string GetLocale(); v8::Local DefaultSession(v8::Isolate* isolate); diff --git a/atom/browser/api/save_page_handler.cc b/atom/browser/api/save_page_handler.cc index 42b93befdd..1e5bc094cf 100644 --- a/atom/browser/api/save_page_handler.cc +++ b/atom/browser/api/save_page_handler.cc @@ -36,8 +36,13 @@ bool SavePageHandler::Handle(const base::FilePath& full_path, auto download_manager = content::BrowserContext::GetDownloadManager( web_contents_->GetBrowserContext()); download_manager->AddObserver(this); + // Chromium will create a 'foo_files' directory under the directory of saving + // page 'foo.html' for holding other resource files of 'foo.html'. + base::FilePath saved_main_directory_path = full_path.DirName().Append( + full_path.RemoveExtension().BaseName().value() + + FILE_PATH_LITERAL("_files")); bool result = web_contents_->SavePage(full_path, - full_path.DirName(), + saved_main_directory_path, save_type); download_manager->RemoveObserver(this); // If initialization fails which means fail to create |DownloadItem|, we need diff --git a/atom/browser/atom_browser_context.cc b/atom/browser/atom_browser_context.cc index 6823fbaee9..6cfb160489 100644 --- a/atom/browser/atom_browser_context.cc +++ b/atom/browser/atom_browser_context.cc @@ -60,7 +60,8 @@ std::string RemoveWhitespace(const std::string& str) { AtomBrowserContext::AtomBrowserContext(const std::string& partition, bool in_memory) : brightray::BrowserContext(partition, in_memory), - job_factory_(new AtomURLRequestJobFactory) { + job_factory_(new AtomURLRequestJobFactory), + allow_ntlm_everywhere_(false) { } AtomBrowserContext::~AtomBrowserContext() { @@ -168,6 +169,16 @@ void AtomBrowserContext::RegisterPrefs(PrefRegistrySimple* pref_registry) { base::FilePath()); } +bool AtomBrowserContext::AllowNTLMCredentialsForDomain(const GURL& origin) { + if (allow_ntlm_everywhere_) + return true; + return Delegate::AllowNTLMCredentialsForDomain(origin); +} + +void AtomBrowserContext::AllowNTLMCredentialsForAllDomains(bool should_allow) { + allow_ntlm_everywhere_ = should_allow; +} + } // namespace atom namespace brightray { diff --git a/atom/browser/atom_browser_context.h b/atom/browser/atom_browser_context.h index 839359c1ef..aafa092442 100644 --- a/atom/browser/atom_browser_context.h +++ b/atom/browser/atom_browser_context.h @@ -28,6 +28,7 @@ class AtomBrowserContext : public brightray::BrowserContext { net::HttpCache::BackendFactory* CreateHttpCacheBackendFactory( const base::FilePath& base_path) override; net::SSLConfigService* CreateSSLConfigService() override; + bool AllowNTLMCredentialsForDomain(const GURL& auth_origin) override; // content::BrowserContext: content::DownloadManagerDelegate* GetDownloadManagerDelegate() override; @@ -36,6 +37,8 @@ class AtomBrowserContext : public brightray::BrowserContext { // brightray::BrowserContext: void RegisterPrefs(PrefRegistrySimple* pref_registry) override; + void AllowNTLMCredentialsForAllDomains(bool should_allow); + AtomURLRequestJobFactory* job_factory() const { return job_factory_; } private: @@ -45,6 +48,8 @@ class AtomBrowserContext : public brightray::BrowserContext { // Managed by brightray::BrowserContext. AtomURLRequestJobFactory* job_factory_; + bool allow_ntlm_everywhere_; + DISALLOW_COPY_AND_ASSIGN(AtomBrowserContext); }; diff --git a/atom/browser/atom_ssl_config_service.cc b/atom/browser/atom_ssl_config_service.cc index f19dbacf7d..0a47067b0a 100644 --- a/atom/browser/atom_ssl_config_service.cc +++ b/atom/browser/atom_ssl_config_service.cc @@ -5,11 +5,14 @@ #include "atom/browser/atom_ssl_config_service.h" #include +#include #include "base/command_line.h" +#include "base/strings/string_split.h" #include "atom/common/options_switches.h" #include "content/public/browser/browser_thread.h" #include "net/socket/ssl_client_socket.h" +#include "net/ssl/ssl_cipher_suite_names.h" namespace atom { @@ -26,6 +29,23 @@ uint16 GetSSLProtocolVersion(const std::string& version_string) { return version; } +std::vector ParseCipherSuites( + const std::vector& cipher_strings) { + std::vector cipher_suites; + cipher_suites.reserve(cipher_strings.size()); + + for (auto& cipher_string : cipher_strings) { + uint16 cipher_suite = 0; + if (!net::ParseSSLCipherString(cipher_string, &cipher_suite)) { + LOG(ERROR) << "Ignoring unrecognised cipher suite : " + << cipher_string; + continue; + } + cipher_suites.push_back(cipher_suite); + } + return cipher_suites; +} + } // namespace AtomSSLConfigService::AtomSSLConfigService() { @@ -35,6 +55,13 @@ AtomSSLConfigService::AtomSSLConfigService() { cmd_line->GetSwitchValueASCII(switches::kSSLVersionFallbackMin); config_.version_fallback_min = GetSSLProtocolVersion(version_string); } + + if (cmd_line->HasSwitch(switches::kCipherSuiteBlacklist)) { + auto cipher_strings = base::SplitString( + cmd_line->GetSwitchValueASCII(switches::kCipherSuiteBlacklist), + ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + config_.disabled_cipher_suites = ParseCipherSuites(cipher_strings); + } } AtomSSLConfigService::~AtomSSLConfigService() { diff --git a/atom/browser/ui/tray_icon.cc b/atom/browser/ui/tray_icon.cc index 12c6be2ea7..d2c6bc1b25 100644 --- a/atom/browser/ui/tray_icon.cc +++ b/atom/browser/ui/tray_icon.cc @@ -55,7 +55,7 @@ void TrayIcon::NotifyRightClicked(const gfx::Rect& bounds, int modifiers) { OnRightClicked(bounds, modifiers)); } -void TrayIcon::NotfiyDropFiles(const std::vector& files) { +void TrayIcon::NotifyDropFiles(const std::vector& files) { FOR_EACH_OBSERVER(TrayIconObserver, observers_, OnDropFiles(files)); } diff --git a/atom/browser/ui/tray_icon.h b/atom/browser/ui/tray_icon.h index af774ddbfb..539fe04f4b 100644 --- a/atom/browser/ui/tray_icon.h +++ b/atom/browser/ui/tray_icon.h @@ -61,7 +61,7 @@ class TrayIcon { void NotifyBalloonClosed(); void NotifyRightClicked(const gfx::Rect& bounds = gfx::Rect(), int modifiers = 0); - void NotfiyDropFiles(const std::vector& files); + void NotifyDropFiles(const std::vector& files); protected: TrayIcon(); diff --git a/atom/browser/ui/tray_icon_cocoa.mm b/atom/browser/ui/tray_icon_cocoa.mm index ec6a6a3e19..34ca4e9a91 100644 --- a/atom/browser/ui/tray_icon_cocoa.mm +++ b/atom/browser/ui/tray_icon_cocoa.mm @@ -265,7 +265,7 @@ const CGFloat kVerticalTitleMargin = 2; NSArray* files = [pboard propertyListForType:NSFilenamesPboardType]; for (NSString* file in files) dropFiles.push_back(base::SysNSStringToUTF8(file)); - trayIcon_->NotfiyDropFiles(dropFiles); + trayIcon_->NotifyDropFiles(dropFiles); return YES; } return NO; diff --git a/atom/common/lib/asar.coffee b/atom/common/lib/asar.coffee index 22d0e70b34..d2a7799fa6 100644 --- a/atom/common/lib/asar.coffee +++ b/atom/common/lib/asar.coffee @@ -263,7 +263,9 @@ exports.wrapFsWithAsar = (fs) -> info = archive.getFileInfo filePath notFoundError asarPath, filePath unless info - return new Buffer(0) if info.size is 0 + + if info.size is 0 + return if options then '' else new Buffer(0) if info.unpacked realPath = archive.copyFileOut filePath diff --git a/atom/common/options_switches.cc b/atom/common/options_switches.cc index e05768b523..8ea16f27b4 100644 --- a/atom/common/options_switches.cc +++ b/atom/common/options_switches.cc @@ -116,6 +116,9 @@ const char kRegisterStandardSchemes[] = "register-standard-schemes"; // TLS fallback will accept. const char kSSLVersionFallbackMin[] = "ssl-version-fallback-min"; +// Comma-separated list of SSL cipher suites to disable. +const char kCipherSuiteBlacklist[] = "cipher-suite-blacklist"; + // The browser process app model ID const char kAppUserModelId[] = "app-user-model-id"; diff --git a/atom/common/options_switches.h b/atom/common/options_switches.h index c568804c4d..33c2790cc1 100644 --- a/atom/common/options_switches.h +++ b/atom/common/options_switches.h @@ -59,6 +59,7 @@ extern const char kPageVisibility[]; extern const char kDisableHttpCache[]; extern const char kRegisterStandardSchemes[]; extern const char kSSLVersionFallbackMin[]; +extern const char kCipherSuiteBlacklist[]; extern const char kAppUserModelId[]; diff --git a/docs-translations/zh-TW/README.md b/docs-translations/zh-TW/README.md index cc75ba51c1..1e69c97443 100644 --- a/docs-translations/zh-TW/README.md +++ b/docs-translations/zh-TW/README.md @@ -1,7 +1,9 @@ ## 導引 +* [支援平台](tutorial/supported-platforms.md) * [應用程式發布](tutorial/application-distribution.md) * [應用程式打包](tutorial/application-packaging.md) +* [Mac App Store 上架指引](tutorial/mac-app-store-submission-guide.md) * [使用原生 node 模組](tutorial/using-native-node-modules.md) * [主行程 Debug](tutorial/debugging-main-process.md) * [使用 Selenium 和 WebDriver](tutorial/using-selenium-and-webdriver.md) @@ -64,7 +66,7 @@ * [源碼目錄結構](development/source-code-directory-structure.md) * [與 NW.js (原名node-webkit) 在技術上的差異](development/atom-shell-vs-node-webkit.md) * [構建系統概況](development/build-system-overview.md) -* [構建步驟 (Mac)](development/build-instructions-mac.md) +* [構建步驟 (OS X)](development/build-instructions-osx.md) * [構建步驟 (Windows)](development/build-instructions-windows.md) * [構建步驟 (Linux)](development/build-instructions-linux.md) * [在 debugger 中使用 symbol server](development/setting-up-symbol-server.md) diff --git a/docs-translations/zh-TW/tutorial/quick-start.md b/docs-translations/zh-TW/tutorial/quick-start.md index aee2baa713..4655549167 100644 --- a/docs-translations/zh-TW/tutorial/quick-start.md +++ b/docs-translations/zh-TW/tutorial/quick-start.md @@ -3,7 +3,7 @@ ## 簡介 Electron 可以讓你使用純 JavaScript 提供豐富的原生的 APIs 來創造桌面應用程式。 -你可以把它視為一個 io.js 的變體,專注於桌面應用程式而不是 web 伺服器。 +你可以把它視為一個 Node.js 的變體,專注於桌面應用程式而不是 web 伺服器。 這不表示 Electron 是一個用 JavaScript 去綁定 GUI 函式庫。取而代之的,Electron 是使用網頁介面來作為它的 GUI , 所以你可以把它看作是一個被 JavaScript 所控制且精簡化的 Chromium 瀏覽器。 @@ -19,7 +19,7 @@ Electron 可以讓你使用純 JavaScript 提供豐富的原生的 APIs 來創 每一個網頁在 Electron 裏執行各自的行程,被稱為 __渲染行程__。 在一般瀏覽器中,網頁通常會在沙盒環境下運行,並且不允許存取原生資源。然而, -Electron 的用戶擁有在網頁中呼叫 io.js APIs 的能力,允許低級別操作與作業系統的交互作用。 +Electron 的用戶擁有在網頁中呼叫 Node.js APIs 的能力,允許低級別操作與作業系統的交互作用。 ## 主行程與渲染行程的區別 @@ -110,7 +110,7 @@ app.on('ready', function() {           

Hello World!

-    We are using io.js +    We are using Node.js     and Electron .    diff --git a/docs/README.md b/docs/README.md index a0d91a5459..754048f5e3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -66,7 +66,7 @@ * [Source Code Directory Structure](development/source-code-directory-structure.md) * [Technical Differences to NW.js (formerly node-webkit)](development/atom-shell-vs-node-webkit.md) * [Build System Overview](development/build-system-overview.md) -* [Build Instructions (Mac)](development/build-instructions-osx.md) +* [Build Instructions (OS X)](development/build-instructions-osx.md) * [Build Instructions (Windows)](development/build-instructions-windows.md) * [Build Instructions (Linux)](development/build-instructions-linux.md) * [Setting Up Symbol Server in debugger](development/setting-up-symbol-server.md) diff --git a/docs/api/app.md b/docs/api/app.md index 0b5780aab7..bd49919ce7 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -99,7 +99,7 @@ You should call `event.preventDefault()` if you want to handle this event. Returns: * `event` Event -* `hasVisibleWindows` Bool +* `hasVisibleWindows` Boolean Emitted when the application is activated, which usually happens when clicks on the applications's dock icon. @@ -280,6 +280,13 @@ Adds `tasks` to the [Tasks][tasks] category of the JumpList on Windows. consists of two or more icons, set this value to identify the icon. If an icon file consists of one icon, this value is 0. +### `app.allowNTLMCredentialsForAllDomains(allow)` + +* `allow` Boolean + +Dynamically sets whether to always send credentials for HTTP NTLM or Negotiate +authentication. + ### `app.commandLine.appendSwitch(switch[, value])` Append a switch (with optional `value`) to Chromium's command line. diff --git a/docs/api/chrome-command-line-switches.md b/docs/api/chrome-command-line-switches.md index c2a39126f6..69e785f79e 100644 --- a/docs/api/chrome-command-line-switches.md +++ b/docs/api/chrome-command-line-switches.md @@ -92,11 +92,17 @@ Enables net log events to be saved and writes them to `path`. Sets the minimum SSL/TLS version ("tls1", "tls1.1" or "tls1.2") that TLS fallback will accept. +## --cipher-suite-blacklist=`cipher_suites` + +Specify comma-separated list of SSL cipher suites to disable. + ## --enable-logging Prints Chromium's logging into console. -This switch can not be used in `app.commandLine.appendSwitch` since it is parsed earlier than user's app is loaded. +This switch can not be used in `app.commandLine.appendSwitch` since it is parsed +earlier than user's app is loaded, but you can set the `ELECTRON_ENABLE_LOGGING` +environment variable to achieve the same effect. ## --v=`log_level` diff --git a/docs/api/frameless-window.md b/docs/api/frameless-window.md index 8d64a6fcd7..707a928f9d 100644 --- a/docs/api/frameless-window.md +++ b/docs/api/frameless-window.md @@ -1,6 +1,6 @@ # Frameless Window -A frameless window is a window that has no [chrome](https://developer.mozilla.org/en-US/docs/Glossary/Chrome), the parts of the window, like toolbars, that are not a part of the webp page. These are options on the [`BrowserWindow`](browser-window.md) class. +A frameless window is a window that has no [chrome](https://developer.mozilla.org/en-US/docs/Glossary/Chrome), the parts of the window, like toolbars, that are not a part of the web page. These are options on the [`BrowserWindow`](browser-window.md) class. ## Create a frameless window @@ -13,7 +13,7 @@ var BrowserWindow = require('browser-window'); var win = new BrowserWindow({ width: 800, height: 600, frame: false }); ``` -### Alternatives on Mac +### Alternatives on OS X On Mac OS X 10.10 Yosemite and newer, there's an alternative way to specify a chromeless window. Instead of setting `frame` to `false` which disables diff --git a/docs/tutorial/mac-app-store-submission-guide.md b/docs/tutorial/mac-app-store-submission-guide.md index ccd0ead858..fb04a5573b 100644 --- a/docs/tutorial/mac-app-store-submission-guide.md +++ b/docs/tutorial/mac-app-store-submission-guide.md @@ -1,29 +1,29 @@ # Mac App Store Submission Guide -Since v0.34.0, Electron allows submitting packaged apps to Mac App Store (MAS), -this guide provides information on how to submit your app, and the limitations -of the MAS build. +Since v0.34.0, Electron allows submitting packaged apps to the Mac App Store +(MAS). This guide provides information on: how to submit your app and the +limitations of the MAS build. -## How to submit your app +## How to Submit Your App -Following steps introduces a simple way to submit your app to Mac App Store, but -it doesn't make sure your app gets approved by Apple, you still have to read -apple's [Submitting Your App][submitting-your-app] guide on how to meet Mac -App Store's requirements. +The following steps introduce a simple way to submit your app to Mac App Store. +However, these steps do not ensure sure your app will be approved by Apple; you +still need to read Apple's [Submitting Your App][submitting-your-app] guide on +how to meet the Mac App Store requirements. -### Get certificate +### Get Certificate -To submit your app to Mac App Store, you have to get a certificate from Apple -first, you can follow [existing guides][nwjs-guide] on web. +To submit your app to the Mac App Store, you first must get a certificate from +Apple. You can follow these [existing guides][nwjs-guide] on web. -### Sign your app +### Sign Your App -After getting the certificate, you can package your app by following -[Application Distribution](application-distribution.md), and then sign your app. -The step is basically the same with other programs, the key is to sign every -dependency of Electron one by one. +After getting the certificate from Apple, you can package your app by following +[Application Distribution](application-distribution.md), and then proceed to +signing your app. This step is basically the same with other programs, but the +key is to sign every dependency of Electron one by one. -First you need to prepare two entitlements files. +First, you need to prepare two entitlements files. `child.plist`: @@ -53,7 +53,7 @@ First you need to prepare two entitlements files. ``` -And then sign your app with following script: +And then sign your app with the following script: ```bash #!/bin/bash @@ -79,33 +79,34 @@ codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP codesign -fs "$APP_KEY" --entitlements parent.plist "$APP_PATH" productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$APP_PATH" ``` +a +If you are new to app sandboxing under OS X, you should also read through +Apple's [Enabling App Sandbox][enable-app-sandbox] to have a basic idea, then +add keys for the permissions needed by your app to the entitlements files. -If you are new to app sandboxing of OS X, you should also go through Apple's -[Enabling App Sandbox][enable-app-sandbox] to have a basic idea, and add keys -for the permissions needed by your app to the entitlements files. +### Upload Your App and Submit for Review -### Upload your app and submit for review - -After signing your app you can use Application Loader to upload it to iTunes -Connect for processing, make sure you have [created a record][create-record] +After signing your app, you can use Application Loader to upload it to iTunes +Connect for processing, making sure you have [created a record][create-record] before uploading. Then you can [submit your app for review][submit-for-review]. -## Limitations of MAS build +## Limitations of MAS Build -In order to satisfy requirements for app sandboxing, following modules have been -disabled in MAS build: +In order to satisfy all requirements for app sandboxing, the following modules +have been disabled in the MAS build: * `crash-reporter` * `auto-updater` -and following behaviors have been changed: +and the following behaviors have been changed: * Video capture may not work for some machines. * Certain accessibility features may not work. * Apps will not be aware of DNS changes. -Also due to the usage of app sandboxing, the resources can be accessed by the -app is strictly limited, you can read [App Sandboxing][app-sandboxing] for more. +Also, due to the usage of app sandboxing, the resources which can be accessed by + the app are strictly limited; you can read [App Sandboxing][app-sandboxing] for + more information. [submitting-your-app]: https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/AppDistributionGuide/SubmittingYourApp/SubmittingYourApp.html [nwjs-guide]: https://github.com/nwjs/nw.js/wiki/Mac-App-Store-%28MAS%29-Submission-Guideline#first-steps diff --git a/docs/tutorial/quick-start.md b/docs/tutorial/quick-start.md index 5300d754a6..052da3d91b 100644 --- a/docs/tutorial/quick-start.md +++ b/docs/tutorial/quick-start.md @@ -130,8 +130,9 @@ Finally the `index.html` is the web page you want to show:

Hello World!

- We are using Node.js - and Electron . + We are using node , + Chrome , + and Electron . ``` @@ -188,3 +189,19 @@ it from [here](https://github.com/atom/electron/releases). After you're done writing your app, you can create a distribution by following the [Application Distribution](./application-distribution.md) guide and then executing the packaged app. + +### Try this Example + +Clone and run the code in this tutorial by using the [`atom/electron-quick-start`](https://github.com/atom/electron-quick-start) +repository. + +**Note**: Running this requires [Git](https://git-scm.com) and [Node.js](https://nodejs.org/en/download/) (which includes [npm](https://npmjs.org)) on your system. + +```bash +# Clone the repository +$ git clone https://github.com/atom/electron-quick-start +# Go into the repository +$ cd electron-quick-start +# Install dependencies and run the app +$ npm install && npm start +``` diff --git a/spec/api-browser-window-spec.coffee b/spec/api-browser-window-spec.coffee index 0f9b376784..1218d27b7f 100644 --- a/spec/api-browser-window-spec.coffee +++ b/spec/api-browser-window-spec.coffee @@ -303,13 +303,22 @@ describe 'browser-window module', -> done() describe 'save page', -> - savePagePath = path.join fixtures, 'save_page.html' + savePageDir = path.join fixtures, 'save_page' + savePageHtmlPath = path.join savePageDir, 'save_page.html' + savePageJsPath = path.join savePageDir, 'save_page_files', 'test.js' + savePageCssPath = path.join savePageDir, 'save_page_files', 'test.css' it 'should save page', (done) -> w.webContents.on 'did-finish-load', -> - w.webContents.savePage savePagePath, 'HTMLComplete', (error) -> + w.webContents.savePage savePageHtmlPath, 'HTMLComplete', (error) -> assert.equal error, null - assert fs.existsSync savePagePath - fs.unlinkSync savePagePath + assert fs.existsSync savePageHtmlPath + assert fs.existsSync savePageJsPath + assert fs.existsSync savePageCssPath + fs.unlinkSync savePageCssPath + fs.unlinkSync savePageJsPath + fs.unlinkSync savePageHtmlPath + fs.rmdirSync path.join savePageDir, 'save_page_files' + fs.rmdirSync savePageDir done() - w.loadUrl "file://#{fixtures}/api/blank.html" + w.loadUrl "file://#{fixtures}/pages/save_page/index.html" diff --git a/spec/fixtures/pages/save_page/index.html b/spec/fixtures/pages/save_page/index.html new file mode 100644 index 0000000000..829233bb86 --- /dev/null +++ b/spec/fixtures/pages/save_page/index.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/spec/fixtures/pages/save_page/test.css b/spec/fixtures/pages/save_page/test.css new file mode 100644 index 0000000000..f7df9d4fda --- /dev/null +++ b/spec/fixtures/pages/save_page/test.css @@ -0,0 +1 @@ +h1 { } diff --git a/spec/fixtures/pages/save_page/test.js b/spec/fixtures/pages/save_page/test.js new file mode 100644 index 0000000000..3d79457383 --- /dev/null +++ b/spec/fixtures/pages/save_page/test.js @@ -0,0 +1 @@ +console.log('save_page'); diff --git a/vendor/brightray b/vendor/brightray index fe2dd437c9..f1cbfd1d45 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit fe2dd437c9ef7877bf9d454db8ae401965cd7cb0 +Subproject commit f1cbfd1d457f9b40bca23a2f30948a093d6048a9