Merge pull request #3 from atom/master

Update from original
This commit is contained in:
Heilig Benedek 2015-11-14 21:11:26 +01:00
commit 9987082de5
155 changed files with 2588 additions and 753 deletions

View file

@ -16,6 +16,7 @@
#include "base/debug/stack_trace.h" #include "base/debug/stack_trace.h"
#include "base/environment.h" #include "base/environment.h"
#include "base/logging.h" #include "base/logging.h"
#include "chrome/common/chrome_paths.h"
#include "content/public/common/content_switches.h" #include "content/public/common/content_switches.h"
#include "ui/base/resource/resource_bundle.h" #include "ui/base/resource/resource_bundle.h"
@ -79,6 +80,8 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
if (enable_stack_dumping) if (enable_stack_dumping)
base::debug::EnableInProcessStackDumping(); base::debug::EnableInProcessStackDumping();
chrome::RegisterPathProvider();
return brightray::MainDelegate::BasicStartupComplete(exit_code); return brightray::MainDelegate::BasicStartupComplete(exit_code);
} }

View file

@ -24,6 +24,7 @@
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/path_service.h" #include "base/path_service.h"
#include "brightray/browser/brightray_paths.h" #include "brightray/browser/brightray_paths.h"
#include "chrome/common/chrome_paths.h"
#include "content/public/browser/client_certificate_delegate.h" #include "content/public/browser/client_certificate_delegate.h"
#include "content/public/browser/gpu_data_manager.h" #include "content/public/browser/gpu_data_manager.h"
#include "content/public/common/content_switches.h" #include "content/public/common/content_switches.h"
@ -99,12 +100,22 @@ int GetPathConstant(const std::string& name) {
return base::DIR_HOME; return base::DIR_HOME;
else if (name == "temp") else if (name == "temp")
return base::DIR_TEMP; return base::DIR_TEMP;
else if (name == "userDesktop") else if (name == "userDesktop" || name == "desktop")
return base::DIR_USER_DESKTOP; return base::DIR_USER_DESKTOP;
else if (name == "exe") else if (name == "exe")
return base::FILE_EXE; return base::FILE_EXE;
else if (name == "module") else if (name == "module")
return base::FILE_MODULE; return base::FILE_MODULE;
else if (name == "documents")
return chrome::DIR_USER_DOCUMENTS;
else if (name == "downloads")
return chrome::DIR_DEFAULT_DOWNLOADS;
else if (name == "music")
return chrome::DIR_USER_MUSIC;
else if (name == "pictures")
return chrome::DIR_USER_PICTURES;
else if (name == "videos")
return chrome::DIR_USER_VIDEOS;
else else
return -1; return -1;
} }

View file

@ -81,7 +81,7 @@ void AutoUpdater::OnWindowAllClosed() {
mate::ObjectTemplateBuilder AutoUpdater::GetObjectTemplateBuilder( mate::ObjectTemplateBuilder AutoUpdater::GetObjectTemplateBuilder(
v8::Isolate* isolate) { v8::Isolate* isolate) {
return mate::ObjectTemplateBuilder(isolate) return mate::ObjectTemplateBuilder(isolate)
.SetMethod("setFeedUrl", &auto_updater::AutoUpdater::SetFeedURL) .SetMethod("setFeedURL", &auto_updater::AutoUpdater::SetFeedURL)
.SetMethod("checkForUpdates", &auto_updater::AutoUpdater::CheckForUpdates) .SetMethod("checkForUpdates", &auto_updater::AutoUpdater::CheckForUpdates)
.SetMethod("quitAndInstall", &AutoUpdater::QuitAndInstall); .SetMethod("quitAndInstall", &AutoUpdater::QuitAndInstall);
} }

View file

@ -204,7 +204,7 @@ void Cookies::GetCookiesOnIOThread(scoped_ptr<base::DictionaryValue> filter,
Passed(&filter), callback))) { Passed(&filter), callback))) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&RunGetCookiesCallbackOnUIThread, isolate(), base::Bind(&RunGetCookiesCallbackOnUIThread, isolate(),
"Url is not valid", net::CookieList(), callback)); "URL is not valid", net::CookieList(), callback));
} }
} }
@ -229,7 +229,7 @@ void Cookies::Remove(const mate::Dictionary& details,
error_message = "Details(url, name) of removing cookie are required."; error_message = "Details(url, name) of removing cookie are required.";
} }
if (error_message.empty() && !url.is_valid()) { if (error_message.empty() && !url.is_valid()) {
error_message = "Url is not valid."; error_message = "URL is not valid.";
} }
if (!error_message.empty()) { if (!error_message.empty()) {
RunRemoveCookiesCallbackOnUIThread(isolate(), error_message, callback); RunRemoveCookiesCallbackOnUIThread(isolate(), error_message, callback);
@ -261,7 +261,7 @@ void Cookies::Set(const base::DictionaryValue& options,
GURL gurl(url); GURL gurl(url);
if (error_message.empty() && !gurl.is_valid()) { if (error_message.empty() && !gurl.is_valid()) {
error_message = "Url is not valid."; error_message = "URL is not valid.";
} }
if (!error_message.empty()) { if (!error_message.empty()) {

View file

@ -103,7 +103,7 @@ int64 DownloadItem::GetTotalBytes() {
return download_item_->GetTotalBytes(); return download_item_->GetTotalBytes();
} }
const GURL& DownloadItem::GetUrl() { const GURL& DownloadItem::GetURL() {
return download_item_->GetURL(); return download_item_->GetURL();
} }
@ -116,7 +116,7 @@ bool DownloadItem::HasUserGesture() {
} }
std::string DownloadItem::GetFilename() { std::string DownloadItem::GetFilename() {
return base::UTF16ToUTF8(net::GenerateFileName(GetUrl(), return base::UTF16ToUTF8(net::GenerateFileName(GetURL(),
GetContentDisposition(), GetContentDisposition(),
std::string(), std::string(),
download_item_->GetSuggestedFilename(), download_item_->GetSuggestedFilename(),
@ -152,7 +152,7 @@ mate::ObjectTemplateBuilder DownloadItem::GetObjectTemplateBuilder(
.SetMethod("cancel", &DownloadItem::Cancel) .SetMethod("cancel", &DownloadItem::Cancel)
.SetMethod("getReceivedBytes", &DownloadItem::GetReceivedBytes) .SetMethod("getReceivedBytes", &DownloadItem::GetReceivedBytes)
.SetMethod("getTotalBytes", &DownloadItem::GetTotalBytes) .SetMethod("getTotalBytes", &DownloadItem::GetTotalBytes)
.SetMethod("getUrl", &DownloadItem::GetUrl) .SetMethod("getURL", &DownloadItem::GetURL)
.SetMethod("getMimeType", &DownloadItem::GetMimeType) .SetMethod("getMimeType", &DownloadItem::GetMimeType)
.SetMethod("hasUserGesture", &DownloadItem::HasUserGesture) .SetMethod("hasUserGesture", &DownloadItem::HasUserGesture)
.SetMethod("getFilename", &DownloadItem::GetFilename) .SetMethod("getFilename", &DownloadItem::GetFilename)

View file

@ -49,7 +49,7 @@ class DownloadItem : public mate::EventEmitter,
bool HasUserGesture(); bool HasUserGesture();
std::string GetFilename(); std::string GetFilename();
std::string GetContentDisposition(); std::string GetContentDisposition();
const GURL& GetUrl(); const GURL& GetURL();
void SetSavePath(const base::FilePath& path); void SetSavePath(const base::FilePath& path);
private: private:

View file

@ -37,7 +37,7 @@ mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder(
.SetMethod("registerBufferProtocol", .SetMethod("registerBufferProtocol",
&Protocol::RegisterProtocol<URLRequestBufferJob>) &Protocol::RegisterProtocol<URLRequestBufferJob>)
.SetMethod("registerFileProtocol", .SetMethod("registerFileProtocol",
&Protocol::RegisterProtocol<UrlRequestAsyncAsarJob>) &Protocol::RegisterProtocol<URLRequestAsyncAsarJob>)
.SetMethod("registerHttpProtocol", .SetMethod("registerHttpProtocol",
&Protocol::RegisterProtocol<URLRequestFetchJob>) &Protocol::RegisterProtocol<URLRequestFetchJob>)
.SetMethod("unregisterProtocol", &Protocol::UnregisterProtocol) .SetMethod("unregisterProtocol", &Protocol::UnregisterProtocol)
@ -47,7 +47,7 @@ mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder(
.SetMethod("interceptBufferProtocol", .SetMethod("interceptBufferProtocol",
&Protocol::InterceptProtocol<URLRequestBufferJob>) &Protocol::InterceptProtocol<URLRequestBufferJob>)
.SetMethod("interceptFileProtocol", .SetMethod("interceptFileProtocol",
&Protocol::InterceptProtocol<UrlRequestAsyncAsarJob>) &Protocol::InterceptProtocol<URLRequestAsyncAsarJob>)
.SetMethod("interceptHttpProtocol", .SetMethod("interceptHttpProtocol",
&Protocol::InterceptProtocol<URLRequestFetchJob>) &Protocol::InterceptProtocol<URLRequestFetchJob>)
.SetMethod("uninterceptProtocol", &Protocol::UninterceptProtocol); .SetMethod("uninterceptProtocol", &Protocol::UninterceptProtocol);

View file

@ -44,21 +44,21 @@ mate::Wrappable* Tray::New(v8::Isolate* isolate, const gfx::Image& image) {
void Tray::OnClicked(const gfx::Rect& bounds, int modifiers) { void Tray::OnClicked(const gfx::Rect& bounds, int modifiers) {
v8::Locker locker(isolate()); v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate()); v8::HandleScope handle_scope(isolate());
EmitCustomEvent("clicked", EmitCustomEvent("click",
ModifiersToObject(isolate(), modifiers), bounds); ModifiersToObject(isolate(), modifiers), bounds);
} }
void Tray::OnDoubleClicked(const gfx::Rect& bounds, int modifiers) { void Tray::OnDoubleClicked(const gfx::Rect& bounds, int modifiers) {
v8::Locker locker(isolate()); v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate()); v8::HandleScope handle_scope(isolate());
EmitCustomEvent("double-clicked", EmitCustomEvent("double-click",
ModifiersToObject(isolate(), modifiers), bounds); ModifiersToObject(isolate(), modifiers), bounds);
} }
void Tray::OnRightClicked(const gfx::Rect& bounds, int modifiers) { void Tray::OnRightClicked(const gfx::Rect& bounds, int modifiers) {
v8::Locker locker(isolate()); v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate()); v8::HandleScope handle_scope(isolate());
EmitCustomEvent("right-clicked", EmitCustomEvent("right-click",
ModifiersToObject(isolate(), modifiers), bounds); ModifiersToObject(isolate(), modifiers), bounds);
} }
@ -67,7 +67,7 @@ void Tray::OnBalloonShow() {
} }
void Tray::OnBalloonClicked() { void Tray::OnBalloonClicked() {
Emit("balloon-clicked"); Emit("balloon-click");
} }
void Tray::OnBalloonClosed() { void Tray::OnBalloonClosed() {

View file

@ -1003,8 +1003,8 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
.SetMethod("isAlive", &WebContents::IsAlive, true) .SetMethod("isAlive", &WebContents::IsAlive, true)
.SetMethod("getId", &WebContents::GetID) .SetMethod("getId", &WebContents::GetID)
.SetMethod("equal", &WebContents::Equal) .SetMethod("equal", &WebContents::Equal)
.SetMethod("_loadUrl", &WebContents::LoadURL) .SetMethod("_loadURL", &WebContents::LoadURL)
.SetMethod("_getUrl", &WebContents::GetURL) .SetMethod("_getURL", &WebContents::GetURL)
.SetMethod("getTitle", &WebContents::GetTitle) .SetMethod("getTitle", &WebContents::GetTitle)
.SetMethod("isLoading", &WebContents::IsLoading) .SetMethod("isLoading", &WebContents::IsLoading)
.SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse) .SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse)

View file

@ -127,16 +127,16 @@ Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) {
// Use options.webPreferences to create WebContents. // Use options.webPreferences to create WebContents.
mate::Dictionary web_preferences = mate::Dictionary::CreateEmpty(isolate); mate::Dictionary web_preferences = mate::Dictionary::CreateEmpty(isolate);
options.Get(switches::kWebPreferences, &web_preferences); options.Get(options::kWebPreferences, &web_preferences);
// Be compatible with old options which are now in web_preferences. // Be compatible with old options which are now in web_preferences.
v8::Local<v8::Value> value; v8::Local<v8::Value> value;
if (options.Get(switches::kNodeIntegration, &value)) if (options.Get(options::kNodeIntegration, &value))
web_preferences.Set(switches::kNodeIntegration, value); web_preferences.Set(options::kNodeIntegration, value);
if (options.Get(switches::kPreloadScript, &value)) if (options.Get(options::kPreloadScript, &value))
web_preferences.Set(switches::kPreloadScript, value); web_preferences.Set(options::kPreloadScript, value);
if (options.Get(switches::kZoomFactor, &value)) if (options.Get(options::kZoomFactor, &value))
web_preferences.Set(switches::kZoomFactor, value); web_preferences.Set(options::kZoomFactor, value);
// Creates the WebContents used by BrowserWindow. // Creates the WebContents used by BrowserWindow.
auto web_contents = WebContents::Create(isolate, web_preferences); auto web_contents = WebContents::Create(isolate, web_preferences);

View file

@ -1,5 +1,5 @@
deprecate = require 'deprecate' electron = require 'electron'
EventEmitter = require('events').EventEmitter {EventEmitter} = require 'events'
bindings = process.atomBinding 'app' bindings = process.atomBinding 'app'
sessionBindings = process.atomBinding 'session' sessionBindings = process.atomBinding 'session'
@ -9,10 +9,10 @@ app = bindings.app
app.__proto__ = EventEmitter.prototype app.__proto__ = EventEmitter.prototype
app.setApplicationMenu = (menu) -> app.setApplicationMenu = (menu) ->
require('menu').setApplicationMenu menu electron.Menu.setApplicationMenu menu
app.getApplicationMenu = -> app.getApplicationMenu = ->
require('menu').getApplicationMenu() electron.Menu.getApplicationMenu()
app.commandLine = app.commandLine =
appendSwitch: bindings.appendSwitch, appendSwitch: bindings.appendSwitch,
@ -39,6 +39,7 @@ app.getAppPath = ->
app.resolveProxy = (url, callback) -> @defaultSession.resolveProxy url, callback app.resolveProxy = (url, callback) -> @defaultSession.resolveProxy url, callback
# Deprecated. # Deprecated.
{deprecate} = electron
app.getHomeDir = deprecate 'app.getHomeDir', 'app.getPath', -> app.getHomeDir = deprecate 'app.getHomeDir', 'app.getPath', ->
@getPath 'home' @getPath 'home'
app.getDataPath = deprecate 'app.getDataPath', 'app.getPath', -> app.getDataPath = deprecate 'app.getDataPath', 'app.getPath', ->
@ -62,10 +63,11 @@ wrapDownloadItem = (downloadItem) ->
# downloadItem is an EventEmitter. # downloadItem is an EventEmitter.
downloadItem.__proto__ = EventEmitter.prototype downloadItem.__proto__ = EventEmitter.prototype
# Deprecated. # Deprecated.
deprecate.property downloadItem, 'url', 'getUrl' deprecate.property downloadItem, 'url', 'getURL'
deprecate.property downloadItem, 'filename', 'getFilename' deprecate.property downloadItem, 'filename', 'getFilename'
deprecate.property downloadItem, 'mimeType', 'getMimeType' deprecate.property downloadItem, 'mimeType', 'getMimeType'
deprecate.property downloadItem, 'hasUserGesture', 'hasUserGesture' deprecate.property downloadItem, 'hasUserGesture', 'hasUserGesture'
deprecate.rename downloadItem, 'getUrl', 'getURL'
downloadItemBindings._setWrapDownloadItem wrapDownloadItem downloadItemBindings._setWrapDownloadItem wrapDownloadItem
# Only one App object pemitted. # Only one App object pemitted.

View file

@ -1,7 +1,12 @@
switch process.platform {deprecate} = require 'electron'
when 'win32'
module.exports = require './auto-updater/auto-updater-win' autoUpdater =
when 'darwin' if process.platform is 'win32'
module.exports = require './auto-updater/auto-updater-mac' require './auto-updater/auto-updater-win'
else else
throw new Error('auto-updater is not implemented on this platform') require './auto-updater/auto-updater-native'
# Deprecated.
deprecate.rename autoUpdater, 'setFeedUrl', 'setFeedURL'
module.exports = autoUpdater

View file

@ -1,6 +1,6 @@
app = require 'app' {app} = require 'electron'
url = require 'url'
{EventEmitter} = require 'events' {EventEmitter} = require 'events'
url = require 'url'
squirrelUpdate = require './squirrel-update-win' squirrelUpdate = require './squirrel-update-win'
@ -9,28 +9,28 @@ class AutoUpdater extends EventEmitter
squirrelUpdate.processStart() squirrelUpdate.processStart()
app.quit() app.quit()
setFeedUrl: (updateUrl) -> setFeedURL: (updateURL) ->
@updateUrl = updateUrl @updateURL = updateURL
checkForUpdates: -> checkForUpdates: ->
return @emitError 'Update URL is not set' unless @updateUrl return @emitError 'Update URL is not set' unless @updateURL
return @emitError 'Can not find Squirrel' unless squirrelUpdate.supported() return @emitError 'Can not find Squirrel' unless squirrelUpdate.supported()
@emit 'checking-for-update' @emit 'checking-for-update'
squirrelUpdate.download @updateUrl, (error, update) => squirrelUpdate.download @updateURL, (error, update) =>
return @emitError error if error? return @emitError error if error?
return @emit 'update-not-available' unless update? return @emit 'update-not-available' unless update?
@emit 'update-available' @emit 'update-available'
squirrelUpdate.update @updateUrl, (error) => squirrelUpdate.update @updateURL, (error) =>
return @emitError error if error? return @emitError error if error?
{releaseNotes, version} = update {releaseNotes, version} = update
# Following information is not available on Windows, so fake them. # Following information is not available on Windows, so fake them.
date = new Date date = new Date
url = @updateUrl url = @updateURL
@emit 'update-downloaded', {}, releaseNotes, version, date, url, => @quitAndInstall() @emit 'update-downloaded', {}, releaseNotes, version, date, url, => @quitAndInstall()

View file

@ -41,8 +41,8 @@ exports.processStart = (callback) ->
spawnUpdate ['--processStart', exeName], true, -> spawnUpdate ['--processStart', exeName], true, ->
# Download the releases specified by the URL and write new results to stdout. # Download the releases specified by the URL and write new results to stdout.
exports.download = (updateUrl, callback) -> exports.download = (updateURL, callback) ->
spawnUpdate ['--download', updateUrl], false, (error, stdout) -> spawnUpdate ['--download', updateURL], false, (error, stdout) ->
return callback(error) if error? return callback(error) if error?
try try
@ -55,8 +55,8 @@ exports.download = (updateUrl, callback) ->
callback null, update callback null, update
# Update the application to the latest remote version specified by URL. # Update the application to the latest remote version specified by URL.
exports.update = (updateUrl, callback) -> exports.update = (updateURL, callback) ->
spawnUpdate ['--update', updateUrl], false, callback spawnUpdate ['--update', updateURL], false, callback
# Is the Update.exe installed with the current application? # Is the Update.exe installed with the current application?
exports.supported = -> exports.supported = ->

View file

@ -1,9 +1,7 @@
EventEmitter = require('events').EventEmitter {app, ipcMain, deprecate} = require 'electron'
app = require 'app' {EventEmitter} = require 'events'
ipc = require 'ipc-main'
deprecate = require 'deprecate'
BrowserWindow = process.atomBinding('window').BrowserWindow {BrowserWindow} = process.atomBinding 'window'
BrowserWindow::__proto__ = EventEmitter.prototype BrowserWindow::__proto__ = EventEmitter.prototype
BrowserWindow::_init = -> BrowserWindow::_init = ->
@ -15,7 +13,7 @@ BrowserWindow::_init = ->
# Make new windows requested by links behave like "window.open" # Make new windows requested by links behave like "window.open"
@webContents.on '-new-window', (event, url, frameName) -> @webContents.on '-new-window', (event, url, frameName) ->
options = show: true, width: 800, height: 600 options = show: true, width: 800, height: 600
ipc.emit 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', event, url, frameName, options ipcMain.emit 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', event, url, frameName, options
# window.resizeTo(...) # window.resizeTo(...)
# window.moveTo(...) # window.moveTo(...)
@ -71,7 +69,8 @@ BrowserWindow.fromDevToolsWebContents = (webContents) ->
return window for window in windows when window.devToolsWebContents?.equal webContents return window for window in windows when window.devToolsWebContents?.equal webContents
# Helpers. # Helpers.
BrowserWindow::loadUrl = -> @webContents.loadUrl.apply @webContents, arguments BrowserWindow::loadURL = -> @webContents.loadURL.apply @webContents, arguments
BrowserWindow::getURL = -> @webContents.getURL()
BrowserWindow::reload = -> @webContents.reload.apply @webContents, arguments BrowserWindow::reload = -> @webContents.reload.apply @webContents, arguments
BrowserWindow::send = -> @webContents.send.apply @webContents, arguments BrowserWindow::send = -> @webContents.send.apply @webContents, arguments
BrowserWindow::openDevTools = -> @webContents.openDevTools.apply @webContents, arguments BrowserWindow::openDevTools = -> @webContents.openDevTools.apply @webContents, arguments
@ -82,14 +81,12 @@ BrowserWindow::inspectElement = -> @webContents.inspectElement.apply @webContent
BrowserWindow::inspectServiceWorker = -> @webContents.inspectServiceWorker() BrowserWindow::inspectServiceWorker = -> @webContents.inspectServiceWorker()
# Deprecated. # Deprecated.
deprecate.rename BrowserWindow, 'restart', 'reload'
deprecate.member BrowserWindow, 'undo', 'webContents' deprecate.member BrowserWindow, 'undo', 'webContents'
deprecate.member BrowserWindow, 'redo', 'webContents' deprecate.member BrowserWindow, 'redo', 'webContents'
deprecate.member BrowserWindow, 'cut', 'webContents' deprecate.member BrowserWindow, 'cut', 'webContents'
deprecate.member BrowserWindow, 'copy', 'webContents' deprecate.member BrowserWindow, 'copy', 'webContents'
deprecate.member BrowserWindow, 'paste', 'webContents' deprecate.member BrowserWindow, 'paste', 'webContents'
deprecate.member BrowserWindow, 'selectAll', 'webContents' deprecate.member BrowserWindow, 'selectAll', 'webContents'
deprecate.member BrowserWindow, 'getUrl', 'webContents'
deprecate.member BrowserWindow, 'reloadIgnoringCache', 'webContents' deprecate.member BrowserWindow, 'reloadIgnoringCache', 'webContents'
deprecate.member BrowserWindow, 'getPageTitle', 'webContents' deprecate.member BrowserWindow, 'getPageTitle', 'webContents'
deprecate.member BrowserWindow, 'isLoading', 'webContents' deprecate.member BrowserWindow, 'isLoading', 'webContents'
@ -99,5 +96,8 @@ deprecate.member BrowserWindow, 'isCrashed', 'webContents'
deprecate.member BrowserWindow, 'executeJavaScriptInDevTools', 'webContents' deprecate.member BrowserWindow, 'executeJavaScriptInDevTools', 'webContents'
deprecate.member BrowserWindow, 'print', 'webContents' deprecate.member BrowserWindow, 'print', 'webContents'
deprecate.member BrowserWindow, 'printToPDF', 'webContents' deprecate.member BrowserWindow, 'printToPDF', 'webContents'
deprecate.rename BrowserWindow, 'restart', 'reload'
deprecate.rename BrowserWindow, 'loadUrl', 'loadURL'
deprecate.rename BrowserWindow, 'getUrl', 'getURL'
module.exports = BrowserWindow module.exports = BrowserWindow

View file

@ -1,7 +1,7 @@
{app, BrowserWindow} = require 'electron'
binding = process.atomBinding 'dialog' binding = process.atomBinding 'dialog'
v8Util = process.atomBinding 'v8_util' v8Util = process.atomBinding 'v8_util'
app = require 'app'
BrowserWindow = require 'browser-window'
fileDialogProperties = fileDialogProperties =
openFile: 1 << 0 openFile: 1 << 0

View file

@ -0,0 +1,52 @@
# Import common modules.
module.exports = require '../../../../common/api/lib/exports/electron'
Object.defineProperties module.exports,
# Browser side modules, please sort with alphabet order.
app:
enumerable: true
get: -> require '../app'
autoUpdater:
enumerable: true
get: -> require '../auto-updater'
BrowserWindow:
enumerable: true
get: -> require '../browser-window'
contentTracing:
enumerable: true
get: -> require '../content-tracing'
dialog:
enumerable: true
get: -> require '../dialog'
ipcMain:
enumerable: true
get: -> require '../ipc-main'
globalShortcut:
enumerable: true
get: -> require '../global-shortcut'
Menu:
enumerable: true
get: -> require '../menu'
MenuItem:
enumerable: true
get: -> require '../menu-item'
powerMonitor:
enumerable: true
get: -> require '../power-monitor'
powerSaveBlocker:
enumerable: true
get: -> require '../power-save-blocker'
protocol:
enumerable: true
get: -> require '../protocol'
screen:
enumerable: true
get: -> require '../screen'
Tray:
enumerable: true
get: -> require '../tray'
# The internal modules, invisible unless you know their names.
NavigationController:
get: -> require '../navigation-controller'
webContents:
get: -> require '../web-contents'

View file

@ -1,5 +1,3 @@
bindings = process.atomBinding 'global_shortcut' {globalShortcut} = process.atomBinding 'global_shortcut'
globalShortcut = bindings.globalShortcut
module.exports = globalShortcut module.exports = globalShortcut

View file

@ -1,6 +1,6 @@
deprecate = require 'deprecate' {deprecate, ipcMain} = require 'electron'
# This module is deprecated, we mirror everything from ipcMain. # This module is deprecated, we mirror everything from ipcMain.
deprecate.warn 'ipc module', 'ipcMain module' deprecate.warn 'ipc module', 'ipcMain module'
module.exports = require 'ipc-main' module.exports = ipcMain

View file

@ -1,4 +1,3 @@
BrowserWindow = require 'browser-window'
v8Util = process.atomBinding 'v8_util' v8Util = process.atomBinding 'v8_util'
nextCommandId = 0 nextCommandId = 0
@ -18,7 +17,7 @@ class MenuItem
@types = ['normal', 'separator', 'submenu', 'checkbox', 'radio'] @types = ['normal', 'separator', 'submenu', 'checkbox', 'radio']
constructor: (options) -> constructor: (options) ->
Menu = require 'menu' {Menu} = require 'electron'
{click, @selector, @type, @role, @label, @sublabel, @accelerator, @icon, @enabled, @visible, @checked, @submenu} = options {click, @selector, @type, @role, @label, @sublabel, @accelerator, @icon, @enabled, @visible, @checked, @submenu} = options

View file

@ -1,8 +1,7 @@
BrowserWindow = require 'browser-window' {BrowserWindow, MenuItem} = require 'electron'
EventEmitter = require('events').EventEmitter {EventEmitter} = require 'events'
MenuItem = require 'menu-item'
v8Util = process.atomBinding 'v8_util'
v8Util = process.atomBinding 'v8_util'
bindings = process.atomBinding 'menu' bindings = process.atomBinding 'menu'
# Automatically generated radio menu item's group id. # Automatically generated radio menu item's group id.

View file

@ -1,15 +1,15 @@
ipc = require 'ipc-main' {ipcMain} = require 'electron'
# The history operation in renderer is redirected to browser. # The history operation in renderer is redirected to browser.
ipc.on 'ATOM_SHELL_NAVIGATION_CONTROLLER', (event, method, args...) -> ipcMain.on 'ATOM_SHELL_NAVIGATION_CONTROLLER', (event, method, args...) ->
event.sender[method] args... event.sender[method] args...
ipc.on 'ATOM_SHELL_SYNC_NAVIGATION_CONTROLLER', (event, method, args...) -> ipcMain.on 'ATOM_SHELL_SYNC_NAVIGATION_CONTROLLER', (event, method, args...) ->
event.returnValue = event.sender[method] args... event.returnValue = event.sender[method] args...
# JavaScript implementation of Chromium's NavigationController. # JavaScript implementation of Chromium's NavigationController.
# Instead of relying on Chromium for history control, we compeletely do history # Instead of relying on Chromium for history control, we compeletely do history
# control on user land, and only rely on WebContents.loadUrl for navigation. # 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 # This helps us avoid Chromium's various optimizations so we can ensure renderer
# process is restarted everytime. # process is restarted everytime.
class NavigationController class NavigationController
@ -17,9 +17,9 @@ class NavigationController
@clearHistory() @clearHistory()
# webContents may have already navigated to a page. # webContents may have already navigated to a page.
if @webContents._getUrl() if @webContents._getURL()
@currentIndex++ @currentIndex++
@history.push @webContents._getUrl() @history.push @webContents._getURL()
@webContents.on 'navigation-entry-commited', (event, url, inPage, replaceEntry) => @webContents.on 'navigation-entry-commited', (event, url, inPage, replaceEntry) =>
if @inPageIndex > -1 and not inPage if @inPageIndex > -1 and not inPage
@ -42,12 +42,12 @@ class NavigationController
@currentIndex++ @currentIndex++
@history.push url @history.push url
loadUrl: (url, options={}) -> loadURL: (url, options={}) ->
@pendingIndex = -1 @pendingIndex = -1
@webContents._loadUrl url, options @webContents._loadURL url, options
@webContents.emit 'load-url', url, options @webContents.emit 'load-url', url, options
getUrl: -> getURL: ->
if @currentIndex is -1 if @currentIndex is -1
'' ''
else else
@ -59,7 +59,7 @@ class NavigationController
reload: -> reload: ->
@pendingIndex = @currentIndex @pendingIndex = @currentIndex
@webContents._loadUrl @getUrl(), {} @webContents._loadURL @getURL(), {}
reloadIgnoringCache: -> reloadIgnoringCache: ->
@webContents._reloadIgnoringCache() # Rely on WebContents to clear cache. @webContents._reloadIgnoringCache() # Rely on WebContents to clear cache.
@ -89,7 +89,7 @@ class NavigationController
if @inPageIndex > -1 and @pendingIndex >= @inPageIndex if @inPageIndex > -1 and @pendingIndex >= @inPageIndex
@webContents._goBack() @webContents._goBack()
else else
@webContents._loadUrl @history[@pendingIndex], {} @webContents._loadURL @history[@pendingIndex], {}
goForward: -> goForward: ->
return unless @canGoForward() return unless @canGoForward()
@ -97,12 +97,12 @@ class NavigationController
if @inPageIndex > -1 and @pendingIndex >= @inPageIndex if @inPageIndex > -1 and @pendingIndex >= @inPageIndex
@webContents._goForward() @webContents._goForward()
else else
@webContents._loadUrl @history[@pendingIndex], {} @webContents._loadURL @history[@pendingIndex], {}
goToIndex: (index) -> goToIndex: (index) ->
return unless @canGoToIndex index return unless @canGoToIndex index
@pendingIndex = index @pendingIndex = index
@webContents._loadUrl @history[@pendingIndex], {} @webContents._loadURL @history[@pendingIndex], {}
goToOffset: (offset) -> goToOffset: (offset) ->
return unless @canGoToOffset offset return unless @canGoToOffset offset

View file

@ -1,5 +1,6 @@
powerMonitor = process.atomBinding('power_monitor').powerMonitor {EventEmitter} = require 'events'
EventEmitter = require('events').EventEmitter
{powerMonitor} = process.atomBinding 'power_monitor'
powerMonitor.__proto__ = EventEmitter.prototype powerMonitor.__proto__ = EventEmitter.prototype

View file

@ -1,3 +1,3 @@
bindings = process.atomBinding 'power_save_blocker' {powerSaveBlocker} = process.atomBinding 'power_save_blocker'
module.exports = bindings.powerSaveBlocker module.exports = powerSaveBlocker

View file

@ -1,7 +1,8 @@
app = require 'app' {app} = require 'electron'
throw new Error('Can not initialize protocol module before app is ready') unless app.isReady() throw new Error('Can not initialize protocol module before app is ready') unless app.isReady()
protocol = process.atomBinding('protocol').protocol {protocol} = process.atomBinding 'protocol'
# Warn about removed APIs. # Warn about removed APIs.
logAndThrow = (callback, message) -> logAndThrow = (callback, message) ->

View file

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

View file

@ -1,14 +1,19 @@
EventEmitter = require('events').EventEmitter {deprecate} = require 'electron'
bindings = process.atomBinding 'tray' {EventEmitter} = require 'events'
Tray = bindings.Tray {Tray} = process.atomBinding 'tray'
Tray::__proto__ = EventEmitter.prototype Tray::__proto__ = EventEmitter.prototype
Tray::_init = ->
# Deprecated.
deprecate.rename this, 'popContextMenu', 'popUpContextMenu'
deprecate.event this, 'clicked', 'click'
deprecate.event this, 'double-clicked', 'double-click'
deprecate.event this, 'right-clicked', 'right-click'
deprecate.event this, 'balloon-clicked', 'balloon-click'
Tray::setContextMenu = (menu) -> Tray::setContextMenu = (menu) ->
@_setContextMenu menu @_setContextMenu menu
@menu = menu # Keep a strong reference of menu. @menu = menu # Keep a strong reference of menu.
# Keep compatibility with old APIs.
Tray::popContextMenu = Tray::popUpContextMenu
module.exports = Tray module.exports = Tray

View file

@ -1,8 +1,7 @@
EventEmitter = require('events').EventEmitter {EventEmitter} = require 'events'
Menu = require './menu' {deprecate, ipcMain, NavigationController, Menu} = require 'electron'
NavigationController = require './navigation-controller'
binding = process.atomBinding 'web_contents' binding = process.atomBinding 'web_contents'
ipc = require 'ipc-main'
nextId = 0 nextId = 0
getNextId = -> ++nextId getNextId = -> ++nextId
@ -46,7 +45,7 @@ wrapWebContents = (webContents) ->
# Make sure webContents.executeJavaScript would run the code only when the # Make sure webContents.executeJavaScript would run the code only when the
# web contents has been loaded. # web contents has been loaded.
webContents.executeJavaScript = (code, hasUserGesture=false) -> webContents.executeJavaScript = (code, hasUserGesture=false) ->
if @getUrl() and not @isLoading() if @getURL() and not @isLoading()
@_executeJavaScript code, hasUserGesture @_executeJavaScript code, hasUserGesture
else else
webContents.once 'did-finish-load', @_executeJavaScript.bind(this, code, hasUserGesture) webContents.once 'did-finish-load', @_executeJavaScript.bind(this, code, hasUserGesture)
@ -60,17 +59,21 @@ wrapWebContents = (webContents) ->
# Dispatch IPC messages to the ipc module. # Dispatch IPC messages to the ipc module.
webContents.on 'ipc-message', (event, packed) -> webContents.on 'ipc-message', (event, packed) ->
[channel, args...] = packed [channel, args...] = packed
ipc.emit channel, event, args... ipcMain.emit channel, event, args...
webContents.on 'ipc-message-sync', (event, packed) -> webContents.on 'ipc-message-sync', (event, packed) ->
[channel, args...] = packed [channel, args...] = packed
Object.defineProperty event, 'returnValue', set: (value) -> event.sendReply JSON.stringify(value) Object.defineProperty event, 'returnValue', set: (value) -> event.sendReply JSON.stringify(value)
ipc.emit channel, event, args... ipcMain.emit channel, event, args...
# Handle context menu action request from pepper plugin. # Handle context menu action request from pepper plugin.
webContents.on 'pepper-context-menu', (event, params) -> webContents.on 'pepper-context-menu', (event, params) ->
menu = Menu.buildFromTemplate params.menu menu = Menu.buildFromTemplate params.menu
menu.popup params.x, params.y menu.popup params.x, params.y
# Deprecated.
deprecate.rename webContents, 'loadUrl', 'loadURL'
deprecate.rename webContents, 'getUrl', 'getURL'
webContents.printToPDF = (options, callback) -> webContents.printToPDF = (options, callback) ->
printingSetting = printingSetting =
pageRage: [] pageRage: []

View file

@ -18,7 +18,7 @@ namespace {
// Notice that we just combined the api key with the url together here, because // Notice that we just combined the api key with the url together here, because
// if we use the standard {url: key} format Chromium would override our key with // if we use the standard {url: key} format Chromium would override our key with
// the predefined one in common.gypi of libchromiumcontent, which is empty. // the predefined one in common.gypi of libchromiumcontent, which is empty.
const char* kGeolocationProviderUrl = const char* kGeolocationProviderURL =
"https://www.googleapis.com/geolocation/v1/geolocate?key=" "https://www.googleapis.com/geolocation/v1/geolocate?key="
GOOGLEAPIS_API_KEY; GOOGLEAPIS_API_KEY;
@ -35,11 +35,11 @@ void AtomAccessTokenStore::LoadAccessTokens(
const LoadAccessTokensCallbackType& callback) { const LoadAccessTokensCallbackType& callback) {
AccessTokenSet access_token_set; AccessTokenSet access_token_set;
// Equivelent to access_token_set[kGeolocationProviderUrl]. // Equivelent to access_token_set[kGeolocationProviderURL].
// Somehow base::string16 is causing compilation errors when used in a pair // Somehow base::string16 is causing compilation errors when used in a pair
// of std::map on Linux, this can work around it. // of std::map on Linux, this can work around it.
std::pair<GURL, base::string16> token_pair; std::pair<GURL, base::string16> token_pair;
token_pair.first = GURL(kGeolocationProviderUrl); token_pair.first = GURL(kGeolocationProviderURL);
access_token_set.insert(token_pair); access_token_set.insert(token_pair);
auto browser_context = AtomBrowserMainParts::Get()->browser_context(); auto browser_context = AtomBrowserMainParts::Get()->browser_context();

View file

@ -1,5 +1,6 @@
var app = require('app'); const electron = require('electron');
var BrowserWindow = require('browser-window'); const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
var mainWindow = null; var mainWindow = null;
@ -15,6 +16,6 @@ app.on('ready', function() {
autoHideMenuBar: true, autoHideMenuBar: true,
useContentSize: true, useContentSize: true,
}); });
mainWindow.loadUrl('file://' + __dirname + '/index.html'); mainWindow.loadURL('file://' + __dirname + '/index.html');
mainWindow.focus(); mainWindow.focus();
}); });

View file

@ -57,13 +57,17 @@
</head> </head>
<body> <body>
<script> <script>
var execPath = require('remote').process.execPath; const electron = require('electron');
const remote = electron.remote;
const shell = electron.shell;
var execPath = remote.process.execPath;
var command = execPath + ' path-to-your-app'; var command = execPath + ' path-to-your-app';
document.onclick = function(e) { document.onclick = function(e) {
e.preventDefault(); e.preventDefault();
if (e.target.tagName == 'A') if (e.target.tagName == 'A')
require('shell').openExternal(e.target.href); shell.openExternal(e.target.href);
return false; return false;
}; };
document.ondragover = document.ondrop = function(e) { document.ondragover = document.ondrop = function(e) {

View file

@ -1,9 +1,11 @@
var app = require('app'); const electron = require('electron');
var dialog = require('dialog'); const app = electron.app;
const dialog = electron.dialog;
const shell = electron.shell;
const Menu = electron.Menu;
var fs = require('fs'); var fs = require('fs');
var path = require('path'); var path = require('path');
var Menu = require('menu');
var BrowserWindow = require('browser-window');
// Quit when all windows are closed and no other one is listening to this. // Quit when all windows are closed and no other one is listening to this.
app.on('window-all-closed', function() { app.on('window-all-closed', function() {
@ -142,19 +144,19 @@ app.once('ready', function() {
submenu: [ submenu: [
{ {
label: 'Learn More', label: 'Learn More',
click: function() { require('shell').openExternal('http://electron.atom.io') } click: function() { shell.openExternal('http://electron.atom.io') }
}, },
{ {
label: 'Documentation', label: 'Documentation',
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') } click: function() { shell.openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
}, },
{ {
label: 'Community Discussions', label: 'Community Discussions',
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') } click: function() { shell.openExternal('https://discuss.atom.io/c/electron') }
}, },
{ {
label: 'Search Issues', label: 'Search Issues',
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') } click: function() { shell.openExternal('https://github.com/atom/electron/issues') }
} }
] ]
}, },
@ -269,5 +271,5 @@ if (option.file && !option.webdriver) {
console.log(helpMessage); console.log(helpMessage);
process.exit(0); process.exit(0);
} else { } else {
require('./default_app.js'); require('./default_app');
} }

View file

@ -4,7 +4,10 @@
#include "atom/browser/javascript_environment.h" #include "atom/browser/javascript_environment.h"
#include <string>
#include "base/command_line.h" #include "base/command_line.h"
#include "content/public/common/content_switches.h"
#include "gin/array_buffer.h" #include "gin/array_buffer.h"
#include "gin/v8_initializer.h" #include "gin/v8_initializer.h"
@ -27,6 +30,12 @@ bool JavascriptEnvironment::Initialize() {
const char expose_debug_as[] = "--expose_debug_as=v8debug"; const char expose_debug_as[] = "--expose_debug_as=v8debug";
v8::V8::SetFlagsFromString(expose_debug_as, sizeof(expose_debug_as) - 1); v8::V8::SetFlagsFromString(expose_debug_as, sizeof(expose_debug_as) - 1);
} }
// --js-flags.
std::string js_flags = cmd->GetSwitchValueASCII(switches::kJavaScriptFlags);
if (!js_flags.empty())
v8::V8::SetFlagsFromString(js_flags.c_str(), js_flags.size());
gin::IsolateHolder::Initialize(gin::IsolateHolder::kNonStrictMode, gin::IsolateHolder::Initialize(gin::IsolateHolder::kNonStrictMode,
gin::ArrayBufferAllocator::SharedInstance()); gin::ArrayBufferAllocator::SharedInstance());
return true; return true;

View file

@ -1,4 +1,4 @@
app = require 'app' electron = require 'electron'
fs = require 'fs' fs = require 'fs'
path = require 'path' path = require 'path'
url = require 'url' url = require 'url'
@ -40,6 +40,7 @@ loadedExtensions = null
loadedExtensionsPath = null loadedExtensionsPath = null
# Persistent loaded extensions. # Persistent loaded extensions.
{app} = electron
app.on 'will-quit', -> app.on 'will-quit', ->
try try
loadedExtensions = Object.keys(extensionInfoMap).map (key) -> extensionInfoMap[key].srcDirectory loadedExtensions = Object.keys(extensionInfoMap).map (key) -> extensionInfoMap[key].srcDirectory
@ -51,8 +52,7 @@ app.on 'will-quit', ->
# We can not use protocol or BrowserWindow until app is ready. # We can not use protocol or BrowserWindow until app is ready.
app.once 'ready', -> app.once 'ready', ->
protocol = require 'protocol' {protocol, BrowserWindow} = electron
BrowserWindow = require 'browser-window'
# Load persistented extensions. # Load persistented extensions.
loadedExtensionsPath = path.join app.getPath('userData'), 'DevTools Extensions' loadedExtensionsPath = path.join app.getPath('userData'), 'DevTools Extensions'

View file

@ -1,5 +1,5 @@
ipc = require 'ipc-main' {ipcMain, webContents} = require 'electron'
webContents = require 'web-contents'
webViewManager = null # Doesn't exist in early initialization. webViewManager = null # Doesn't exist in early initialization.
supportedWebViewEvents = [ supportedWebViewEvents = [
@ -79,7 +79,7 @@ createGuest = (embedder, params) ->
opts = {} opts = {}
opts.httpReferrer = params.httpreferrer if params.httpreferrer opts.httpReferrer = params.httpreferrer if params.httpreferrer
opts.userAgent = params.useragent if params.useragent opts.userAgent = params.useragent if params.useragent
@loadUrl params.src, opts @loadURL params.src, opts
if params.allowtransparency? if params.allowtransparency?
@setAllowTransparency params.allowtransparency @setAllowTransparency params.allowtransparency
@ -122,7 +122,7 @@ attachGuest = (embedder, elementInstanceId, guestInstanceId, params) ->
nodeIntegration: params.nodeintegration ? false nodeIntegration: params.nodeintegration ? false
plugins: params.plugins plugins: params.plugins
webSecurity: !params.disablewebsecurity webSecurity: !params.disablewebsecurity
webPreferences.preloadUrl = params.preload if params.preload webPreferences.preloadURL = params.preload if params.preload
webViewManager.addGuest guestInstanceId, elementInstanceId, embedder, guest, webPreferences webViewManager.addGuest guestInstanceId, elementInstanceId, embedder, guest, webPreferences
guest.attachParams = params guest.attachParams = params
@ -140,19 +140,19 @@ destroyGuest = (embedder, id) ->
delete reverseEmbedderElementsMap[id] delete reverseEmbedderElementsMap[id]
delete embedderElementsMap[key] delete embedderElementsMap[key]
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', (event, params, requestId) -> ipcMain.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', (event, params, requestId) ->
event.sender.send "ATOM_SHELL_RESPONSE_#{requestId}", createGuest(event.sender, params) event.sender.send "ATOM_SHELL_RESPONSE_#{requestId}", createGuest(event.sender, params)
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', (event, elementInstanceId, guestInstanceId, params) -> ipcMain.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', (event, elementInstanceId, guestInstanceId, params) ->
attachGuest event.sender, elementInstanceId, guestInstanceId, params attachGuest event.sender, elementInstanceId, guestInstanceId, params
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', (event, id) -> ipcMain.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', (event, id) ->
destroyGuest event.sender, id destroyGuest event.sender, id
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_SIZE', (event, id, params) -> ipcMain.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_SIZE', (event, id, params) ->
guestInstances[id]?.guest.setSize params guestInstances[id]?.guest.setSize params
ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_ALLOW_TRANSPARENCY', (event, id, allowtransparency) -> ipcMain.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_ALLOW_TRANSPARENCY', (event, id, allowtransparency) ->
guestInstances[id]?.guest.setAllowTransparency allowtransparency guestInstances[id]?.guest.setAllowTransparency allowtransparency
# Returns WebContents from its guest id. # Returns WebContents from its guest id.

View file

@ -1,6 +1,5 @@
ipc = require 'ipc-main' {ipcMain, BrowserWindow} = require 'electron'
v8Util = process.atomBinding 'v8_util' v8Util = process.atomBinding 'v8_util'
BrowserWindow = require 'browser-window'
frameToGuest = {} frameToGuest = {}
@ -28,11 +27,11 @@ mergeBrowserWindowOptions = (embedder, options) ->
createGuest = (embedder, url, frameName, options) -> createGuest = (embedder, url, frameName, options) ->
guest = frameToGuest[frameName] guest = frameToGuest[frameName]
if frameName and guest? if frameName and guest?
guest.loadUrl url guest.loadURL url
return guest.id return guest.id
guest = new BrowserWindow(options) guest = new BrowserWindow(options)
guest.loadUrl url guest.loadURL url
# Remember the embedder, will be used by window.opener methods. # Remember the embedder, will be used by window.opener methods.
v8Util.setHiddenValue guest.webContents, 'embedder', embedder v8Util.setHiddenValue guest.webContents, 'embedder', embedder
@ -58,7 +57,7 @@ createGuest = (embedder, url, frameName, options) ->
guest.id guest.id
# Routed window.open messages. # Routed window.open messages.
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', (event, args...) -> ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', (event, args...) ->
[url, frameName, options] = args [url, frameName, options] = args
options = mergeBrowserWindowOptions event.sender, options options = mergeBrowserWindowOptions event.sender, options
event.sender.emit 'new-window', event, url, frameName, 'new-window', options event.sender.emit 'new-window', event, url, frameName, 'new-window', options
@ -67,26 +66,26 @@ ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', (event, args...) ->
else else
event.returnValue = createGuest event.sender, url, frameName, options event.returnValue = createGuest event.sender, url, frameName, options
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', (event, guestId) -> ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', (event, guestId) ->
BrowserWindow.fromId(guestId)?.destroy() BrowserWindow.fromId(guestId)?.destroy()
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', (event, guestId, method, args...) -> ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', (event, guestId, method, args...) ->
BrowserWindow.fromId(guestId)?[method] args... BrowserWindow.fromId(guestId)?[method] args...
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', (event, guestId, message, targetOrigin) -> ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', (event, guestId, message, targetOrigin) ->
guestContents = BrowserWindow.fromId(guestId)?.webContents guestContents = BrowserWindow.fromId(guestId)?.webContents
if guestContents?.getUrl().indexOf(targetOrigin) is 0 or targetOrigin is '*' if guestContents?.getURL().indexOf(targetOrigin) is 0 or targetOrigin is '*'
guestContents.send 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', guestId, message, targetOrigin guestContents.send 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', guestId, message, targetOrigin
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', (event, guestId, message, targetOrigin, sourceOrigin) -> ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', (event, guestId, message, targetOrigin, sourceOrigin) ->
embedder = v8Util.getHiddenValue event.sender, 'embedder' embedder = v8Util.getHiddenValue event.sender, 'embedder'
if embedder?.getUrl().indexOf(targetOrigin) is 0 or targetOrigin is '*' if embedder?.getURL().indexOf(targetOrigin) is 0 or targetOrigin is '*'
embedder.send 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', guestId, message, sourceOrigin embedder.send 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', guestId, message, sourceOrigin
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', (event, guestId, method, args...) -> ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', (event, guestId, method, args...) ->
BrowserWindow.fromId(guestId)?.webContents?[method] args... BrowserWindow.fromId(guestId)?.webContents?[method] args...
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_GET_GUEST_ID', (event) -> ipcMain.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_GET_GUEST_ID', (event) ->
embedder = v8Util.getHiddenValue event.sender, 'embedder' embedder = v8Util.getHiddenValue event.sender, 'embedder'
if embedder? if embedder?
guest = BrowserWindow.fromWebContents event.sender guest = BrowserWindow.fromWebContents event.sender

View file

@ -13,10 +13,12 @@ require path.resolve(__dirname, '..', '..', 'common', 'lib', 'reset-search-paths
# Import common settings. # Import common settings.
require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init') require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init')
# Add browser/api/lib to module search paths, which contains javascript part of
# Electron's built-in libraries.
globalPaths = Module.globalPaths globalPaths = Module.globalPaths
globalPaths.push path.resolve(__dirname, '..', 'api', 'lib') unless process.env.ELECTRON_HIDE_INTERNAL_MODULES
globalPaths.push path.resolve(__dirname, '..', 'api', 'lib')
# Expose public APIs.
globalPaths.push path.resolve(__dirname, '..', 'api', 'lib', 'exports')
if process.platform is 'win32' if process.platform is 'win32'
# Redirect node's console to use our own implementations, since node can not # Redirect node's console to use our own implementations, since node can not
@ -44,12 +46,13 @@ process.on 'uncaughtException', (error) ->
return return
# Show error in GUI. # Show error in GUI.
{dialog} = require 'electron'
stack = error.stack ? "#{error.name}: #{error.message}" stack = error.stack ? "#{error.name}: #{error.message}"
message = "Uncaught Exception:\n#{stack}" message = "Uncaught Exception:\n#{stack}"
require('dialog').showErrorBox 'A JavaScript error occurred in the main process', message dialog.showErrorBox 'A JavaScript error occurred in the main process', message
# Emit 'exit' event on quit. # Emit 'exit' event on quit.
app = require 'app' {app} = require 'electron'
app.on 'quit', -> app.on 'quit', ->
process.emit 'exit' process.emit 'exit'

View file

@ -1,4 +1,4 @@
EventEmitter = require('events').EventEmitter {EventEmitter} = require 'events'
v8Util = process.atomBinding 'v8_util' v8Util = process.atomBinding 'v8_util'
class ObjectsRegistry extends EventEmitter class ObjectsRegistry extends EventEmitter

View file

@ -1,8 +1,11 @@
ipc = require 'ipc-main'
path = require 'path' path = require 'path'
objectsRegistry = require './objects-registry.js'
electron = require 'electron'
{ipcMain} = electron
objectsRegistry = require './objects-registry'
v8Util = process.atomBinding 'v8_util' v8Util = process.atomBinding 'v8_util'
IDWeakMap = process.atomBinding('id_weak_map').IDWeakMap {IDWeakMap} = process.atomBinding 'id_weak_map'
# Convert a real value into meta data. # Convert a real value into meta data.
valueToMeta = (sender, value, optimizeSimpleObject=false) -> valueToMeta = (sender, value, optimizeSimpleObject=false) ->
@ -13,7 +16,7 @@ valueToMeta = (sender, value, optimizeSimpleObject=false) ->
meta.type = 'array' if Array.isArray value meta.type = 'array' if Array.isArray value
meta.type = 'error' if value instanceof Error meta.type = 'error' if value instanceof Error
meta.type = 'date' if value instanceof Date meta.type = 'date' if value instanceof Date
meta.type = 'promise' if value? and value.constructor.name is 'Promise' meta.type = 'promise' if value?.constructor.name is 'Promise'
# Treat simple objects as value. # Treat simple objects as value.
if optimizeSimpleObject and meta.type is 'object' and v8Util.getHiddenValue value, 'simple' if optimizeSimpleObject and meta.type is 'object' and v8Util.getHiddenValue value, 'simple'
@ -115,28 +118,34 @@ callFunction = (event, func, caller, args) ->
process.on 'ATOM_BROWSER_RELEASE_RENDER_VIEW', (id) -> process.on 'ATOM_BROWSER_RELEASE_RENDER_VIEW', (id) ->
objectsRegistry.clear id objectsRegistry.clear id
ipc.on 'ATOM_BROWSER_REQUIRE', (event, module) -> ipcMain.on 'ATOM_BROWSER_REQUIRE', (event, module) ->
try try
event.returnValue = valueToMeta event.sender, process.mainModule.require(module) event.returnValue = valueToMeta event.sender, process.mainModule.require(module)
catch e catch e
event.returnValue = exceptionToMeta e event.returnValue = exceptionToMeta e
ipc.on 'ATOM_BROWSER_GLOBAL', (event, name) -> ipcMain.on 'ATOM_BROWSER_GET_BUILTIN', (event, module) ->
try
event.returnValue = valueToMeta event.sender, electron[module]
catch e
event.returnValue = exceptionToMeta e
ipcMain.on 'ATOM_BROWSER_GLOBAL', (event, name) ->
try try
event.returnValue = valueToMeta event.sender, global[name] event.returnValue = valueToMeta event.sender, global[name]
catch e catch e
event.returnValue = exceptionToMeta e event.returnValue = exceptionToMeta e
ipc.on 'ATOM_BROWSER_CURRENT_WINDOW', (event) -> ipcMain.on 'ATOM_BROWSER_CURRENT_WINDOW', (event) ->
try try
event.returnValue = valueToMeta event.sender, event.sender.getOwnerBrowserWindow() event.returnValue = valueToMeta event.sender, event.sender.getOwnerBrowserWindow()
catch e catch e
event.returnValue = exceptionToMeta e event.returnValue = exceptionToMeta e
ipc.on 'ATOM_BROWSER_CURRENT_WEB_CONTENTS', (event) -> ipcMain.on 'ATOM_BROWSER_CURRENT_WEB_CONTENTS', (event) ->
event.returnValue = valueToMeta event.sender, event.sender event.returnValue = valueToMeta event.sender, event.sender
ipc.on 'ATOM_BROWSER_CONSTRUCTOR', (event, id, args) -> ipcMain.on 'ATOM_BROWSER_CONSTRUCTOR', (event, id, args) ->
try try
args = unwrapArgs event.sender, args args = unwrapArgs event.sender, args
constructor = objectsRegistry.get id constructor = objectsRegistry.get id
@ -147,7 +156,7 @@ ipc.on 'ATOM_BROWSER_CONSTRUCTOR', (event, id, args) ->
catch e catch e
event.returnValue = exceptionToMeta e event.returnValue = exceptionToMeta e
ipc.on 'ATOM_BROWSER_FUNCTION_CALL', (event, id, args) -> ipcMain.on 'ATOM_BROWSER_FUNCTION_CALL', (event, id, args) ->
try try
args = unwrapArgs event.sender, args args = unwrapArgs event.sender, args
func = objectsRegistry.get id func = objectsRegistry.get id
@ -155,7 +164,7 @@ ipc.on 'ATOM_BROWSER_FUNCTION_CALL', (event, id, args) ->
catch e catch e
event.returnValue = exceptionToMeta e event.returnValue = exceptionToMeta e
ipc.on 'ATOM_BROWSER_MEMBER_CONSTRUCTOR', (event, id, method, args) -> ipcMain.on 'ATOM_BROWSER_MEMBER_CONSTRUCTOR', (event, id, method, args) ->
try try
args = unwrapArgs event.sender, args args = unwrapArgs event.sender, args
constructor = objectsRegistry.get(id)[method] constructor = objectsRegistry.get(id)[method]
@ -165,7 +174,7 @@ ipc.on 'ATOM_BROWSER_MEMBER_CONSTRUCTOR', (event, id, method, args) ->
catch e catch e
event.returnValue = exceptionToMeta e event.returnValue = exceptionToMeta e
ipc.on 'ATOM_BROWSER_MEMBER_CALL', (event, id, method, args) -> ipcMain.on 'ATOM_BROWSER_MEMBER_CALL', (event, id, method, args) ->
try try
args = unwrapArgs event.sender, args args = unwrapArgs event.sender, args
obj = objectsRegistry.get id obj = objectsRegistry.get id
@ -173,7 +182,7 @@ ipc.on 'ATOM_BROWSER_MEMBER_CALL', (event, id, method, args) ->
catch e catch e
event.returnValue = exceptionToMeta e event.returnValue = exceptionToMeta e
ipc.on 'ATOM_BROWSER_MEMBER_SET', (event, id, name, value) -> ipcMain.on 'ATOM_BROWSER_MEMBER_SET', (event, id, name, value) ->
try try
obj = objectsRegistry.get id obj = objectsRegistry.get id
obj[name] = value obj[name] = value
@ -181,19 +190,22 @@ ipc.on 'ATOM_BROWSER_MEMBER_SET', (event, id, name, value) ->
catch e catch e
event.returnValue = exceptionToMeta e event.returnValue = exceptionToMeta e
ipc.on 'ATOM_BROWSER_MEMBER_GET', (event, id, name) -> ipcMain.on 'ATOM_BROWSER_MEMBER_GET', (event, id, name) ->
try try
obj = objectsRegistry.get id obj = objectsRegistry.get id
event.returnValue = valueToMeta event.sender, obj[name] event.returnValue = valueToMeta event.sender, obj[name]
catch e catch e
event.returnValue = exceptionToMeta e event.returnValue = exceptionToMeta e
ipc.on 'ATOM_BROWSER_DEREFERENCE', (event, id) -> ipcMain.on 'ATOM_BROWSER_DEREFERENCE', (event, id) ->
objectsRegistry.remove event.sender.getId(), id objectsRegistry.remove event.sender.getId(), id
ipc.on 'ATOM_BROWSER_GUEST_WEB_CONTENTS', (event, guestInstanceId) -> ipcMain.on 'ATOM_BROWSER_GUEST_WEB_CONTENTS', (event, guestInstanceId) ->
try try
guestViewManager = require './guest-view-manager' guestViewManager = require './guest-view-manager'
event.returnValue = valueToMeta event.sender, guestViewManager.getGuest(guestInstanceId) event.returnValue = valueToMeta event.sender, guestViewManager.getGuest(guestInstanceId)
catch e catch e
event.returnValue = exceptionToMeta e event.returnValue = exceptionToMeta e
ipcMain.on 'ATOM_BROWSER_LIST_MODULES', (event) ->
event.returnValue = (name for name of electron)

View file

@ -56,16 +56,16 @@ NativeWindow::NativeWindow(
aspect_ratio_(0.0), aspect_ratio_(0.0),
inspectable_web_contents_(inspectable_web_contents), inspectable_web_contents_(inspectable_web_contents),
weak_factory_(this) { weak_factory_(this) {
options.Get(switches::kFrame, &has_frame_); options.Get(options::kFrame, &has_frame_);
options.Get(switches::kTransparent, &transparent_); options.Get(options::kTransparent, &transparent_);
options.Get(switches::kEnableLargerThanScreen, &enable_larger_than_screen_); options.Get(options::kEnableLargerThanScreen, &enable_larger_than_screen_);
// Tell the content module to initialize renderer widget with transparent // Tell the content module to initialize renderer widget with transparent
// mode. // mode.
ui::GpuSwitchingManager::SetTransparent(transparent_); ui::GpuSwitchingManager::SetTransparent(transparent_);
// Read icon before window is created. // Read icon before window is created.
options.Get(switches::kIcon, &icon_); options.Get(options::kIcon, &icon_);
WindowList::AddWindow(this); WindowList::AddWindow(this);
} }
@ -91,25 +91,25 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) {
// Setup window from options. // Setup window from options.
int x = -1, y = -1; int x = -1, y = -1;
bool center; bool center;
if (options.Get(switches::kX, &x) && options.Get(switches::kY, &y)) { if (options.Get(options::kX, &x) && options.Get(options::kY, &y)) {
SetPosition(gfx::Point(x, y)); SetPosition(gfx::Point(x, y));
} else if (options.Get(switches::kCenter, &center) && center) { } else if (options.Get(options::kCenter, &center) && center) {
Center(); Center();
} }
// On Linux and Window we may already have maximum size defined. // On Linux and Window we may already have maximum size defined.
extensions::SizeConstraints size_constraints(GetContentSizeConstraints()); extensions::SizeConstraints size_constraints(GetContentSizeConstraints());
int min_height = 0, min_width = 0; int min_height = 0, min_width = 0;
if (options.Get(switches::kMinHeight, &min_height) | if (options.Get(options::kMinHeight, &min_height) |
options.Get(switches::kMinWidth, &min_width)) { options.Get(options::kMinWidth, &min_width)) {
size_constraints.set_minimum_size(gfx::Size(min_width, min_height)); size_constraints.set_minimum_size(gfx::Size(min_width, min_height));
} }
int max_height = INT_MAX, max_width = INT_MAX; int max_height = INT_MAX, max_width = INT_MAX;
if (options.Get(switches::kMaxHeight, &max_height) | if (options.Get(options::kMaxHeight, &max_height) |
options.Get(switches::kMaxWidth, &max_width)) { options.Get(options::kMaxWidth, &max_width)) {
size_constraints.set_maximum_size(gfx::Size(max_width, max_height)); size_constraints.set_maximum_size(gfx::Size(max_width, max_height));
} }
bool use_content_size = false; bool use_content_size = false;
options.Get(switches::kUseContentSize, &use_content_size); options.Get(options::kUseContentSize, &use_content_size);
if (use_content_size) { if (use_content_size) {
SetContentSizeConstraints(size_constraints); SetContentSizeConstraints(size_constraints);
} else { } else {
@ -117,39 +117,39 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) {
} }
#if defined(OS_WIN) || defined(USE_X11) #if defined(OS_WIN) || defined(USE_X11)
bool resizable; bool resizable;
if (options.Get(switches::kResizable, &resizable)) { if (options.Get(options::kResizable, &resizable)) {
SetResizable(resizable); SetResizable(resizable);
} }
#endif #endif
bool top; bool top;
if (options.Get(switches::kAlwaysOnTop, &top) && top) { if (options.Get(options::kAlwaysOnTop, &top) && top) {
SetAlwaysOnTop(true); SetAlwaysOnTop(true);
} }
#if defined(OS_MACOSX) || defined(OS_WIN) #if defined(OS_MACOSX) || defined(OS_WIN)
bool fullscreen; bool fullscreen;
if (options.Get(switches::kFullscreen, &fullscreen) && fullscreen) { if (options.Get(options::kFullscreen, &fullscreen) && fullscreen) {
SetFullScreen(true); SetFullScreen(true);
} }
#endif #endif
bool skip; bool skip;
if (options.Get(switches::kSkipTaskbar, &skip) && skip) { if (options.Get(options::kSkipTaskbar, &skip) && skip) {
SetSkipTaskbar(skip); SetSkipTaskbar(skip);
} }
bool kiosk; bool kiosk;
if (options.Get(switches::kKiosk, &kiosk) && kiosk) { if (options.Get(options::kKiosk, &kiosk) && kiosk) {
SetKiosk(kiosk); SetKiosk(kiosk);
} }
std::string color; std::string color;
if (options.Get(switches::kBackgroundColor, &color)) { if (options.Get(options::kBackgroundColor, &color)) {
SetBackgroundColor(color); SetBackgroundColor(color);
} }
std::string title("Electron"); std::string title("Electron");
options.Get(switches::kTitle, &title); options.Get(options::kTitle, &title);
SetTitle(title); SetTitle(title);
// Then show it. // Then show it.
bool show = true; bool show = true;
options.Get(switches::kShow, &show); options.Get(options::kShow, &show);
if (show) if (show)
Show(); Show();
} }
@ -512,7 +512,7 @@ void NativeWindow::TitleWasSet(content::NavigationEntry* entry,
FOR_EACH_OBSERVER(NativeWindowObserver, FOR_EACH_OBSERVER(NativeWindowObserver,
observers_, observers_,
OnPageTitleUpdated(&prevent_default, text)); OnPageTitleUpdated(&prevent_default, text));
if (!prevent_default) if (!prevent_default && !is_closed_)
SetTitle(text); SetTitle(text);
} }

View file

@ -320,8 +320,8 @@ NativeWindowMac::NativeWindowMac(
is_kiosk_(false), is_kiosk_(false),
attention_request_id_(0) { attention_request_id_(0) {
int width = 800, height = 600; int width = 800, height = 600;
options.Get(switches::kWidth, &width); options.Get(options::kWidth, &width);
options.Get(switches::kHeight, &height); options.Get(options::kHeight, &height);
NSRect main_screen_rect = [[[NSScreen screens] objectAtIndex:0] frame]; NSRect main_screen_rect = [[[NSScreen screens] objectAtIndex:0] frame];
NSRect cocoa_bounds = NSMakeRect( NSRect cocoa_bounds = NSMakeRect(
@ -331,14 +331,14 @@ NativeWindowMac::NativeWindowMac(
height); height);
bool useStandardWindow = true; bool useStandardWindow = true;
options.Get(switches::kStandardWindow, &useStandardWindow); options.Get(options::kStandardWindow, &useStandardWindow);
bool resizable = true; bool resizable = true;
options.Get(switches::kResizable, &resizable); options.Get(options::kResizable, &resizable);
// New title bar styles are available in Yosemite or newer // New title bar styles are available in Yosemite or newer
std::string titleBarStyle; std::string titleBarStyle;
if (base::mac::IsOSYosemiteOrLater()) if (base::mac::IsOSYosemiteOrLater())
options.Get(switches::kTitleBarStyle, &titleBarStyle); options.Get(options::kTitleBarStyle, &titleBarStyle);
NSUInteger styleMask = NSTitledWindowMask | NSClosableWindowMask | NSUInteger styleMask = NSTitledWindowMask | NSClosableWindowMask |
NSMiniaturizableWindowMask; NSMiniaturizableWindowMask;
@ -394,23 +394,23 @@ NativeWindowMac::NativeWindowMac(
// On OS X the initial window size doesn't include window frame. // On OS X the initial window size doesn't include window frame.
bool use_content_size = false; bool use_content_size = false;
options.Get(switches::kUseContentSize, &use_content_size); options.Get(options::kUseContentSize, &use_content_size);
if (!has_frame() || !use_content_size) if (!has_frame() || !use_content_size)
SetSize(gfx::Size(width, height)); SetSize(gfx::Size(width, height));
// Enable the NSView to accept first mouse event. // Enable the NSView to accept first mouse event.
bool acceptsFirstMouse = false; bool acceptsFirstMouse = false;
options.Get(switches::kAcceptFirstMouse, &acceptsFirstMouse); options.Get(options::kAcceptFirstMouse, &acceptsFirstMouse);
[window_ setAcceptsFirstMouse:acceptsFirstMouse]; [window_ setAcceptsFirstMouse:acceptsFirstMouse];
// Disable auto-hiding cursor. // Disable auto-hiding cursor.
bool disableAutoHideCursor = false; bool disableAutoHideCursor = false;
options.Get(switches::kDisableAutoHideCursor, &disableAutoHideCursor); options.Get(options::kDisableAutoHideCursor, &disableAutoHideCursor);
[window_ setDisableAutoHideCursor:disableAutoHideCursor]; [window_ setDisableAutoHideCursor:disableAutoHideCursor];
// Disable fullscreen button when 'fullscreen' is specified to false. // Disable fullscreen button when 'fullscreen' is specified to false.
bool fullscreen; bool fullscreen;
if (!(options.Get(switches::kFullscreen, &fullscreen) && if (!(options.Get(options::kFullscreen, &fullscreen) &&
!fullscreen)) { !fullscreen)) {
NSUInteger collectionBehavior = [window_ collectionBehavior]; NSUInteger collectionBehavior = [window_ collectionBehavior];
collectionBehavior |= NSWindowCollectionBehaviorFullScreenPrimary; collectionBehavior |= NSWindowCollectionBehaviorFullScreenPrimary;

View file

@ -132,13 +132,13 @@ NativeWindowViews::NativeWindowViews(
keyboard_event_handler_(new views::UnhandledKeyboardEventHandler), keyboard_event_handler_(new views::UnhandledKeyboardEventHandler),
use_content_size_(false), use_content_size_(false),
resizable_(true) { resizable_(true) {
options.Get(switches::kTitle, &title_); options.Get(options::kTitle, &title_);
options.Get(switches::kAutoHideMenuBar, &menu_bar_autohide_); options.Get(options::kAutoHideMenuBar, &menu_bar_autohide_);
#if defined(OS_WIN) #if defined(OS_WIN)
// On Windows we rely on the CanResize() to indicate whether window can be // On Windows we rely on the CanResize() to indicate whether window can be
// resized, and it should be set before window is created. // resized, and it should be set before window is created.
options.Get(switches::kResizable, &resizable_); options.Get(options::kResizable, &resizable_);
#endif #endif
if (enable_larger_than_screen()) if (enable_larger_than_screen())
@ -150,8 +150,8 @@ NativeWindowViews::NativeWindowViews(
gfx::Size(), gfx::Size(INT_MAX / 10, INT_MAX / 10))); gfx::Size(), gfx::Size(INT_MAX / 10, INT_MAX / 10)));
int width = 800, height = 600; int width = 800, height = 600;
options.Get(switches::kWidth, &width); options.Get(options::kWidth, &width);
options.Get(switches::kHeight, &height); options.Get(options::kHeight, &height);
gfx::Rect bounds(0, 0, width, height); gfx::Rect bounds(0, 0, width, height);
widget_size_ = bounds.size(); widget_size_ = bounds.size();
@ -187,7 +187,7 @@ NativeWindowViews::NativeWindowViews(
window_->Init(params); window_->Init(params);
bool fullscreen = false; bool fullscreen = false;
options.Get(switches::kFullscreen, &fullscreen); options.Get(options::kFullscreen, &fullscreen);
#if defined(USE_X11) #if defined(USE_X11)
// Start monitoring window states. // Start monitoring window states.
@ -195,7 +195,7 @@ NativeWindowViews::NativeWindowViews(
// Set _GTK_THEME_VARIANT to dark if we have "dark-theme" option set. // Set _GTK_THEME_VARIANT to dark if we have "dark-theme" option set.
bool use_dark_theme = false; bool use_dark_theme = false;
if (options.Get(switches::kDarkTheme, &use_dark_theme) && use_dark_theme) { if (options.Get(options::kDarkTheme, &use_dark_theme) && use_dark_theme) {
XDisplay* xdisplay = gfx::GetXDisplay(); XDisplay* xdisplay = gfx::GetXDisplay();
XChangeProperty(xdisplay, GetAcceleratedWidget(), XChangeProperty(xdisplay, GetAcceleratedWidget(),
XInternAtom(xdisplay, "_GTK_THEME_VARIANT", False), XInternAtom(xdisplay, "_GTK_THEME_VARIANT", False),
@ -209,7 +209,7 @@ NativeWindowViews::NativeWindowViews(
// to manually set the _NET_WM_STATE. // to manually set the _NET_WM_STATE.
std::vector<::Atom> state_atom_list; std::vector<::Atom> state_atom_list;
bool skip_taskbar = false; bool skip_taskbar = false;
if (options.Get(switches::kSkipTaskbar, &skip_taskbar) && skip_taskbar) { if (options.Get(options::kSkipTaskbar, &skip_taskbar) && skip_taskbar) {
state_atom_list.push_back(GetAtom("_NET_WM_STATE_SKIP_TASKBAR")); state_atom_list.push_back(GetAtom("_NET_WM_STATE_SKIP_TASKBAR"));
} }
@ -223,7 +223,7 @@ NativeWindowViews::NativeWindowViews(
// Set the _NET_WM_WINDOW_TYPE. // Set the _NET_WM_WINDOW_TYPE.
std::string window_type; std::string window_type;
if (options.Get(switches::kType, &window_type)) if (options.Get(options::kType, &window_type))
SetWindowType(GetAcceleratedWidget(), window_type); SetWindowType(GetAcceleratedWidget(), window_type);
#endif #endif
@ -274,7 +274,7 @@ NativeWindowViews::NativeWindowViews(
gfx::Size size = bounds.size(); gfx::Size size = bounds.size();
if (has_frame() && if (has_frame() &&
options.Get(switches::kUseContentSize, &use_content_size_) && options.Get(options::kUseContentSize, &use_content_size_) &&
use_content_size_) use_content_size_)
size = ContentSizeToWindowSize(size); size = ContentSizeToWindowSize(size);

View file

@ -6,13 +6,13 @@
namespace atom { namespace atom {
UrlRequestAsyncAsarJob::UrlRequestAsyncAsarJob( URLRequestAsyncAsarJob::URLRequestAsyncAsarJob(
net::URLRequest* request, net::URLRequest* request,
net::NetworkDelegate* network_delegate) net::NetworkDelegate* network_delegate)
: JsAsker<asar::URLRequestAsarJob>(request, network_delegate) { : JsAsker<asar::URLRequestAsarJob>(request, network_delegate) {
} }
void UrlRequestAsyncAsarJob::StartAsync(scoped_ptr<base::Value> options) { void URLRequestAsyncAsarJob::StartAsync(scoped_ptr<base::Value> options) {
base::FilePath::StringType file_path; base::FilePath::StringType file_path;
if (options->IsType(base::Value::TYPE_DICTIONARY)) { if (options->IsType(base::Value::TYPE_DICTIONARY)) {
static_cast<base::DictionaryValue*>(options.get())->GetString( static_cast<base::DictionaryValue*>(options.get())->GetString(

View file

@ -11,15 +11,15 @@
namespace atom { namespace atom {
// Like URLRequestAsarJob, but asks the JavaScript handler for file path. // Like URLRequestAsarJob, but asks the JavaScript handler for file path.
class UrlRequestAsyncAsarJob : public JsAsker<asar::URLRequestAsarJob> { class URLRequestAsyncAsarJob : public JsAsker<asar::URLRequestAsarJob> {
public: public:
UrlRequestAsyncAsarJob(net::URLRequest*, net::NetworkDelegate*); URLRequestAsyncAsarJob(net::URLRequest*, net::NetworkDelegate*);
// JsAsker: // JsAsker:
void StartAsync(scoped_ptr<base::Value> options) override; void StartAsync(scoped_ptr<base::Value> options) override;
private: private:
DISALLOW_COPY_AND_ASSIGN(UrlRequestAsyncAsarJob); DISALLOW_COPY_AND_ASSIGN(URLRequestAsyncAsarJob);
}; };
} // namespace atom } // namespace atom

View file

@ -25,13 +25,23 @@ namespace atom {
namespace { namespace {
// Array of available web runtime features. // Array of available web runtime features.
const char* kWebRuntimeFeatures[] = { struct FeaturePair {
switches::kExperimentalFeatures, const char* name;
switches::kExperimentalCanvasFeatures, const char* cmd;
switches::kOverlayScrollbars, };
switches::kOverlayFullscreenVideo, FeaturePair kWebRuntimeFeatures[] = {
switches::kSharedWorker, { options::kExperimentalFeatures,
switches::kPageVisibility, switches::kExperimentalFeatures },
{ options::kExperimentalCanvasFeatures,
switches::kExperimentalCanvasFeatures },
{ options::kOverlayScrollbars,
switches::kOverlayScrollbars },
{ options::kOverlayFullscreenVideo,
switches::kOverlayFullscreenVideo },
{ options::kSharedWorker,
switches::kSharedWorker },
{ options::kPageVisibility,
switches::kPageVisibility },
}; };
} // namespace } // namespace
@ -69,7 +79,7 @@ void WebContentsPreferences::AppendExtraCommandLineSwitches(
bool b; bool b;
#if defined(OS_WIN) #if defined(OS_WIN)
// Check if DirectWrite is disabled. // Check if DirectWrite is disabled.
if (web_preferences.GetBoolean(switches::kDirectWrite, &b) && !b) if (web_preferences.GetBoolean(options::kDirectWrite, &b) && !b)
command_line->AppendSwitch(::switches::kDisableDirectWrite); command_line->AppendSwitch(::switches::kDisableDirectWrite);
#endif #endif
@ -80,17 +90,17 @@ void WebContentsPreferences::AppendExtraCommandLineSwitches(
// This set of options are not availabe in WebPreferences, so we have to pass // This set of options are not availabe in WebPreferences, so we have to pass
// them via command line and enable them in renderer procss. // them via command line and enable them in renderer procss.
for (size_t i = 0; i < arraysize(kWebRuntimeFeatures); ++i) { for (size_t i = 0; i < arraysize(kWebRuntimeFeatures); ++i) {
const char* feature = kWebRuntimeFeatures[i]; const auto& feature = kWebRuntimeFeatures[i];
if (web_preferences.GetBoolean(feature, &b)) if (web_preferences.GetBoolean(feature.name, &b))
command_line->AppendSwitchASCII(feature, b ? "true" : "false"); command_line->AppendSwitchASCII(feature.cmd, b ? "true" : "false");
} }
// Check if we have node integration specified. // Check if we have node integration specified.
bool node_integration = true; bool node_integration = true;
web_preferences.GetBoolean(switches::kNodeIntegration, &node_integration); web_preferences.GetBoolean(options::kNodeIntegration, &node_integration);
// Be compatible with old API of "node-integration" option. // Be compatible with old API of "node-integration" option.
std::string old_token; std::string old_token;
if (web_preferences.GetString(switches::kNodeIntegration, &old_token) && if (web_preferences.GetString(options::kNodeIntegration, &old_token) &&
old_token != "disable") old_token != "disable")
node_integration = true; node_integration = true;
command_line->AppendSwitchASCII(switches::kNodeIntegration, command_line->AppendSwitchASCII(switches::kNodeIntegration,
@ -98,12 +108,12 @@ void WebContentsPreferences::AppendExtraCommandLineSwitches(
// The preload script. // The preload script.
base::FilePath::StringType preload; base::FilePath::StringType preload;
if (web_preferences.GetString(switches::kPreloadScript, &preload)) { if (web_preferences.GetString(options::kPreloadScript, &preload)) {
if (base::FilePath(preload).IsAbsolute()) if (base::FilePath(preload).IsAbsolute())
command_line->AppendSwitchNative(switches::kPreloadScript, preload); command_line->AppendSwitchNative(switches::kPreloadScript, preload);
else else
LOG(ERROR) << "preload script must have absolute path."; LOG(ERROR) << "preload script must have absolute path.";
} else if (web_preferences.GetString(switches::kPreloadUrl, &preload)) { } else if (web_preferences.GetString(options::kPreloadURL, &preload)) {
// Translate to file path if there is "preload-url" option. // Translate to file path if there is "preload-url" option.
base::FilePath preload_path; base::FilePath preload_path;
if (net::FileURLToFilePath(GURL(preload), &preload_path)) if (net::FileURLToFilePath(GURL(preload), &preload_path))
@ -114,15 +124,14 @@ void WebContentsPreferences::AppendExtraCommandLineSwitches(
// The zoom factor. // The zoom factor.
double zoom_factor = 1.0; double zoom_factor = 1.0;
if (web_preferences.GetDouble(switches::kZoomFactor, &zoom_factor) && if (web_preferences.GetDouble(options::kZoomFactor, &zoom_factor) &&
zoom_factor != 1.0) zoom_factor != 1.0)
command_line->AppendSwitchASCII(switches::kZoomFactor, command_line->AppendSwitchASCII(switches::kZoomFactor,
base::DoubleToString(zoom_factor)); base::DoubleToString(zoom_factor));
// --guest-instance-id, which is used to identify guest WebContents. // --guest-instance-id, which is used to identify guest WebContents.
int guest_instance_id; int guest_instance_id;
if (web_preferences.GetInteger(switches::kGuestInstanceID, if (web_preferences.GetInteger(options::kGuestInstanceID, &guest_instance_id))
&guest_instance_id))
command_line->AppendSwitchASCII(switches::kGuestInstanceID, command_line->AppendSwitchASCII(switches::kGuestInstanceID,
base::IntToString(guest_instance_id)); base::IntToString(guest_instance_id));
} }
@ -152,8 +161,7 @@ void WebContentsPreferences::OverrideWebkitPrefs(
prefs->allow_displaying_insecure_content = !b; prefs->allow_displaying_insecure_content = !b;
prefs->allow_running_insecure_content = !b; prefs->allow_running_insecure_content = !b;
} }
if (self->web_preferences_.GetBoolean("allowDisplayingInsecureContent", if (self->web_preferences_.GetBoolean("allowDisplayingInsecureContent", &b))
&b))
prefs->allow_displaying_insecure_content = b; prefs->allow_displaying_insecure_content = b;
if (self->web_preferences_.GetBoolean("allowRunningInsecureContent", &b)) if (self->web_preferences_.GetBoolean("allowRunningInsecureContent", &b))
prefs->allow_running_insecure_content = b; prefs->allow_running_insecure_content = b;

View file

@ -168,7 +168,8 @@ mate::ObjectTemplateBuilder NativeImage::GetObjectTemplateBuilder(
template_.Reset(isolate, mate::ObjectTemplateBuilder(isolate) template_.Reset(isolate, mate::ObjectTemplateBuilder(isolate)
.SetMethod("toPng", &NativeImage::ToPNG) .SetMethod("toPng", &NativeImage::ToPNG)
.SetMethod("toJpeg", &NativeImage::ToJPEG) .SetMethod("toJpeg", &NativeImage::ToJPEG)
.SetMethod("toDataUrl", &NativeImage::ToDataURL) .SetMethod("toDataURL", &NativeImage::ToDataURL)
.SetMethod("toDataUrl", &NativeImage::ToDataURL) // deprecated.
.SetMethod("isEmpty", &NativeImage::IsEmpty) .SetMethod("isEmpty", &NativeImage::IsEmpty)
.SetMethod("getSize", &NativeImage::GetSize) .SetMethod("getSize", &NativeImage::GetSize)
.SetMethod("setTemplateImage", &NativeImage::SetTemplateImage) .SetMethod("setTemplateImage", &NativeImage::SetTemplateImage)
@ -309,7 +310,7 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
dict.SetMethod("createEmpty", &atom::api::NativeImage::CreateEmpty); dict.SetMethod("createEmpty", &atom::api::NativeImage::CreateEmpty);
dict.SetMethod("createFromPath", &atom::api::NativeImage::CreateFromPath); dict.SetMethod("createFromPath", &atom::api::NativeImage::CreateFromPath);
dict.SetMethod("createFromBuffer", &atom::api::NativeImage::CreateFromBuffer); dict.SetMethod("createFromBuffer", &atom::api::NativeImage::CreateFromBuffer);
dict.SetMethod("createFromDataUrl", dict.SetMethod("createFromDataURL",
&atom::api::NativeImage::CreateFromDataURL); &atom::api::NativeImage::CreateFromDataURL);
} }

View file

@ -1,5 +1,5 @@
if process.platform is 'linux' and process.type is 'renderer' if process.platform is 'linux' and process.type is 'renderer'
# On Linux we could not access clipboard in renderer process. # On Linux we could not access clipboard in renderer process.
module.exports = require('remote').require 'clipboard' module.exports = require('electron').remote.clipboard
else else
module.exports = process.atomBinding 'clipboard' module.exports = process.atomBinding 'clipboard'

View file

@ -1,22 +1,26 @@
binding = process.atomBinding 'crash_reporter'
fs = require 'fs' fs = require 'fs'
os = require 'os' os = require 'os'
path = require 'path' path = require 'path'
{spawn} = require 'child_process' {spawn} = require 'child_process'
electron = require 'electron'
binding = process.atomBinding 'crash_reporter'
class CrashReporter class CrashReporter
start: (options={}) -> start: (options={}) ->
{@productName, companyName, submitUrl, autoSubmit, ignoreSystemCrashHandler, extra} = options {@productName, companyName, submitURL, autoSubmit, ignoreSystemCrashHandler, extra} = options
app = # Deprecated.
if process.type is 'browser' {deprecate} = electron
require 'app' if options.submitUrl
else submitURL ?= options.submitUrl
require('remote').require 'app' deprecate.warn 'submitUrl', 'submitURL'
{app} = if process.type is 'browser' then electron else electron.remote
@productName ?= app.getName() @productName ?= app.getName()
companyName ?= 'GitHub, Inc' companyName ?= 'GitHub, Inc'
submitUrl ?= 'http://54.249.141.255:1127/post' submitURL ?= 'http://54.249.141.255:1127/post'
autoSubmit ?= true autoSubmit ?= true
ignoreSystemCrashHandler ?= false ignoreSystemCrashHandler ?= false
extra ?= {} extra ?= {}
@ -25,11 +29,11 @@ class CrashReporter
extra._companyName ?= companyName extra._companyName ?= companyName
extra._version ?= app.getVersion() extra._version ?= app.getVersion()
start = => binding.start @productName, companyName, submitUrl, autoSubmit, ignoreSystemCrashHandler, extra start = => binding.start @productName, companyName, submitURL, autoSubmit, ignoreSystemCrashHandler, extra
if process.platform is 'win32' if process.platform is 'win32'
args = [ args = [
"--reporter-url=#{submitUrl}" "--reporter-url=#{submitURL}"
"--application-name=#{@productName}" "--application-name=#{@productName}"
"--v=1" "--v=1"
] ]

View file

@ -42,12 +42,15 @@ deprecate.property = (object, property, method) ->
# Deprecate an event. # Deprecate an event.
deprecate.event = (emitter, oldName, newName, fn) -> deprecate.event = (emitter, oldName, newName, fn) ->
warned = false warned = false
emitter.on newName, -> emitter.on newName, (args...) ->
if @listenerCount(oldName) > 0 # there is listeners for old API. if @listenerCount(oldName) > 0 # there is listeners for old API.
unless warned or process.noDeprecation unless warned or process.noDeprecation
warned = true warned = true
deprecate.warn "'#{oldName}' event", "'#{newName}' event" deprecate.warn "'#{oldName}' event", "'#{newName}' event"
fn.apply this, arguments if fn?
fn.apply this, arguments
else
@emit oldName, args...
# Print deprecate warning. # Print deprecate warning.
deprecate.warn = (oldName, newName) -> deprecate.warn = (oldName, newName) ->

View file

@ -0,0 +1,27 @@
# Do not expose the internal modules to `require`.
exports.hideInternalModules = ->
{globalPaths} = require 'module'
if globalPaths.length is 3
# Remove the "common/api/lib" and "browser-or-renderer/api/lib".
globalPaths.splice 0, 2
Object.defineProperties exports,
# Common modules, please sort with alphabet order.
clipboard:
# Must be enumerable, otherwise it woulde be invisible to remote module.
enumerable: true
get: -> require '../clipboard'
crashReporter:
enumerable: true
get: -> require '../crash-reporter'
nativeImage:
enumerable: true
get: -> require '../native-image'
shell:
enumerable: true
get: -> require '../shell'
# The internal modules, invisible unless you know their names.
CallbacksRegistry:
get: -> require '../callbacks-registry'
deprecate:
get: -> require '../deprecate'

View file

@ -1 +1,7 @@
module.exports = process.atomBinding 'native_image' {deprecate} = require 'electron'
nativeImage = process.atomBinding 'native_image'
# Deprecated.
deprecate.rename nativeImage, 'createFromDataUrl', 'createFromDataURL'
module.exports = nativeImage

View file

@ -9,8 +9,9 @@ process.atomBinding = (name) ->
catch e catch e
process.binding "atom_common_#{name}" if /No such module/.test e.message process.binding "atom_common_#{name}" if /No such module/.test e.message
# Add common/api/lib to module search paths. unless process.env.ELECTRON_HIDE_INTERNAL_MODULES
Module.globalPaths.push path.resolve(__dirname, '..', 'api', 'lib') # Add common/api/lib to module search paths.
Module.globalPaths.push path.resolve(__dirname, '..', 'api', 'lib')
# setImmediate and process.nextTick makes use of uv_check and uv_prepare to # setImmediate and process.nextTick makes use of uv_check and uv_prepare to
# run the callbacks, however since we only run uv loop on requests, the # run the callbacks, however since we only run uv loop on requests, the

View file

@ -21,6 +21,9 @@ struct Converter<base::FilePath> {
static bool FromV8(v8::Isolate* isolate, static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val, v8::Local<v8::Value> val,
base::FilePath* out) { base::FilePath* out) {
if (val->IsNull())
return true;
base::FilePath::StringType path; base::FilePath::StringType path;
if (Converter<base::FilePath::StringType>::FromV8(isolate, val, &path)) { if (Converter<base::FilePath::StringType>::FromV8(isolate, val, &path)) {
*out = base::FilePath(path); *out = base::FilePath(path);

View file

@ -6,7 +6,7 @@
namespace atom { namespace atom {
namespace switches { namespace options {
const char kTitle[] = "title"; const char kTitle[] = "title";
const char kIcon[] = "icon"; const char kIcon[] = "icon";
@ -77,7 +77,7 @@ const char kZoomFactor[] = "zoomFactor";
const char kPreloadScript[] = "preload"; const char kPreloadScript[] = "preload";
// Like --preload, but the passed argument is an URL. // Like --preload, but the passed argument is an URL.
const char kPreloadUrl[] = "preloadUrl"; const char kPreloadURL[] = "preloadURL";
// Enable the node integration. // Enable the node integration.
const char kNodeIntegration[] = "nodeIntegration"; const char kNodeIntegration[] = "nodeIntegration";
@ -85,6 +85,12 @@ const char kNodeIntegration[] = "nodeIntegration";
// Instancd ID of guest WebContents. // Instancd ID of guest WebContents.
const char kGuestInstanceID[] = "guestInstanceId"; const char kGuestInstanceID[] = "guestInstanceId";
// Set page visiblity to always visible.
const char kPageVisibility[] = "pageVisibility";
// Enable DirectWrite on Windows.
const char kDirectWrite[] = "directWrite";
// Web runtime features. // Web runtime features.
const char kExperimentalFeatures[] = "experimentalFeatures"; const char kExperimentalFeatures[] = "experimentalFeatures";
const char kExperimentalCanvasFeatures[] = "experimentalCanvasFeatures"; const char kExperimentalCanvasFeatures[] = "experimentalCanvasFeatures";
@ -92,6 +98,10 @@ const char kOverlayScrollbars[] = "overlayScrollbars";
const char kOverlayFullscreenVideo[] = "overlayFullscreenVideo"; const char kOverlayFullscreenVideo[] = "overlayFullscreenVideo";
const char kSharedWorker[] = "sharedWorker"; const char kSharedWorker[] = "sharedWorker";
} // namespace options
namespace switches {
// Enable plugins. // Enable plugins.
const char kEnablePlugins[] = "enable-plugins"; const char kEnablePlugins[] = "enable-plugins";
@ -101,12 +111,6 @@ const char kPpapiFlashPath[] = "ppapi-flash-path";
// Ppapi Flash version. // Ppapi Flash version.
const char kPpapiFlashVersion[] = "ppapi-flash-version"; const char kPpapiFlashVersion[] = "ppapi-flash-version";
// Set page visiblity to always visible.
const char kPageVisibility[] = "page-visibility";
// Enable DirectWrite on Windows.
const char kDirectWrite[] = "direct-write";
// Path to client certificate. // Path to client certificate.
const char kClientCertificate[] = "client-certificate"; const char kClientCertificate[] = "client-certificate";
@ -126,6 +130,19 @@ const char kCipherSuiteBlacklist[] = "cipher-suite-blacklist";
// The browser process app model ID // The browser process app model ID
const char kAppUserModelId[] = "app-user-model-id"; const char kAppUserModelId[] = "app-user-model-id";
// The command line switch versions of the options.
const char kZoomFactor[] = "zoom-factor";
const char kPreloadScript[] = "preload";
const char kPreloadURL[] = "preload-url";
const char kNodeIntegration[] = "node-integration";
const char kGuestInstanceID[] = "guest-instance-id";
const char kExperimentalFeatures[] = "experimental-features";
const char kExperimentalCanvasFeatures[] = "experimental-canvas-features";
const char kOverlayScrollbars[] = "overlay-scrollbars";
const char kOverlayFullscreenVideo[] = "overlay-fullscreen-video";
const char kSharedWorker[] = "shared-worker";
const char kPageVisibility[] = "page-visiblity";
} // namespace switches } // namespace switches
} // namespace atom } // namespace atom

View file

@ -7,7 +7,7 @@
namespace atom { namespace atom {
namespace switches { namespace options {
extern const char kTitle[]; extern const char kTitle[];
extern const char kIcon[]; extern const char kIcon[];
@ -41,9 +41,10 @@ extern const char kBackgroundColor[];
extern const char kWebPreferences[]; extern const char kWebPreferences[];
// WebPreferences. // WebPreferences.
extern const char kDirectWrite[];
extern const char kZoomFactor[]; extern const char kZoomFactor[];
extern const char kPreloadScript[]; extern const char kPreloadScript[];
extern const char kPreloadUrl[]; extern const char kPreloadURL[];
extern const char kNodeIntegration[]; extern const char kNodeIntegration[];
extern const char kGuestInstanceID[]; extern const char kGuestInstanceID[];
extern const char kExperimentalFeatures[]; extern const char kExperimentalFeatures[];
@ -52,9 +53,14 @@ extern const char kOverlayScrollbars[];
extern const char kOverlayFullscreenVideo[]; extern const char kOverlayFullscreenVideo[];
extern const char kSharedWorker[]; extern const char kSharedWorker[];
extern const char kPageVisibility[]; extern const char kPageVisibility[];
extern const char kDirectWrite[];
} // namespace options
// Following are actually command line switches, should be moved to other files. // Following are actually command line switches, should be moved to other files.
namespace switches {
extern const char kEnablePlugins[]; extern const char kEnablePlugins[];
extern const char kPpapiFlashPath[]; extern const char kPpapiFlashPath[];
extern const char kPpapiFlashVersion[]; extern const char kPpapiFlashVersion[];
@ -65,6 +71,18 @@ extern const char kSSLVersionFallbackMin[];
extern const char kCipherSuiteBlacklist[]; extern const char kCipherSuiteBlacklist[];
extern const char kAppUserModelId[]; extern const char kAppUserModelId[];
extern const char kZoomFactor[];
extern const char kPreloadScript[];
extern const char kPreloadURL[];
extern const char kNodeIntegration[];
extern const char kGuestInstanceID[];
extern const char kExperimentalFeatures[];
extern const char kExperimentalCanvasFeatures[];
extern const char kOverlayScrollbars[];
extern const char kOverlayFullscreenVideo[];
extern const char kSharedWorker[];
extern const char kPageVisibility[];
} // namespace switches } // namespace switches
} // namespace atom } // namespace atom

View file

@ -307,8 +307,8 @@ bool OpenExternal(const GURL& url) {
// "Some versions of windows (Win2k before SP3, Win XP before SP1) crash in // "Some versions of windows (Win2k before SP3, Win XP before SP1) crash in
// ShellExecute on long URLs (bug 161357 on bugzilla.mozilla.org). IE 5 and 6 // ShellExecute on long URLs (bug 161357 on bugzilla.mozilla.org). IE 5 and 6
// support URLS of 2083 chars in length, 2K is safe." // support URLS of 2083 chars in length, 2K is safe."
const size_t kMaxUrlLength = 2048; const size_t kMaxURLLength = 2048;
if (escaped_url.length() > kMaxUrlLength) { if (escaped_url.length() > kMaxURLLength) {
NOTREACHED(); NOTREACHED();
return false; return false;
} }

View file

@ -98,7 +98,7 @@ void WebFrame::RegisterURLSchemeAsSecure(const std::string& scheme) {
blink::WebString::fromUTF8(scheme)); blink::WebString::fromUTF8(scheme));
} }
void WebFrame::RegisterURLSchemeAsBypassingCsp(const std::string& scheme) { void WebFrame::RegisterURLSchemeAsBypassingCSP(const std::string& scheme) {
// Register scheme to bypass pages's Content Security Policy. // Register scheme to bypass pages's Content Security Policy.
blink::WebSecurityPolicy::registerURLSchemeAsBypassingContentSecurityPolicy( blink::WebSecurityPolicy::registerURLSchemeAsBypassingContentSecurityPolicy(
blink::WebString::fromUTF8(scheme)); blink::WebString::fromUTF8(scheme));
@ -129,11 +129,11 @@ mate::ObjectTemplateBuilder WebFrame::GetObjectTemplateBuilder(
&WebFrame::RegisterElementResizeCallback) &WebFrame::RegisterElementResizeCallback)
.SetMethod("attachGuest", &WebFrame::AttachGuest) .SetMethod("attachGuest", &WebFrame::AttachGuest)
.SetMethod("setSpellCheckProvider", &WebFrame::SetSpellCheckProvider) .SetMethod("setSpellCheckProvider", &WebFrame::SetSpellCheckProvider)
.SetMethod("registerUrlSchemeAsSecure", .SetMethod("registerURLSchemeAsSecure",
&WebFrame::RegisterURLSchemeAsSecure) &WebFrame::RegisterURLSchemeAsSecure)
.SetMethod("registerUrlSchemeAsBypassingCsp", .SetMethod("registerURLSchemeAsBypassingCSP",
&WebFrame::RegisterURLSchemeAsBypassingCsp) &WebFrame::RegisterURLSchemeAsBypassingCSP)
.SetMethod("registerUrlSchemeAsPrivileged", .SetMethod("registerURLSchemeAsPrivileged",
&WebFrame::RegisterURLSchemeAsPrivileged); &WebFrame::RegisterURLSchemeAsPrivileged);
} }

View file

@ -57,7 +57,7 @@ class WebFrame : public mate::Wrappable {
v8::Local<v8::Object> provider); v8::Local<v8::Object> provider);
void RegisterURLSchemeAsSecure(const std::string& scheme); void RegisterURLSchemeAsSecure(const std::string& scheme);
void RegisterURLSchemeAsBypassingCsp(const std::string& scheme); void RegisterURLSchemeAsBypassingCSP(const std::string& scheme);
void RegisterURLSchemeAsPrivileged(const std::string& scheme); void RegisterURLSchemeAsPrivileged(const std::string& scheme);
// mate::Wrappable: // mate::Wrappable:

View file

@ -0,0 +1,17 @@
# Import common modules.
module.exports = require '../../../../common/api/lib/exports/electron'
Object.defineProperties module.exports,
# Renderer side modules, please sort with alphabet order.
ipcRenderer:
enumerable: true
get: -> require '../ipc-renderer'
remote:
enumerable: true
get: -> require '../remote'
screen:
enumerable: true
get: -> require '../screen'
webFrame:
enumerable: true
get: -> require '../web-frame'

View file

@ -1,5 +1,4 @@
deprecate = require 'deprecate' {ipcRenderer, deprecate} = require 'electron'
ipcRenderer = require 'ipc-renderer'
{EventEmitter} = require 'events' {EventEmitter} = require 'events'
# This module is deprecated, we mirror everything from ipcRenderer. # This module is deprecated, we mirror everything from ipcRenderer.

View file

@ -1,6 +1,5 @@
ipc = require 'ipc-renderer' {ipcRenderer, CallbacksRegistry} = require 'electron'
v8Util = process.atomBinding 'v8_util' v8Util = process.atomBinding 'v8_util'
CallbacksRegistry = require 'callbacks-registry'
callbacksRegistry = new CallbacksRegistry callbacksRegistry = new CallbacksRegistry
@ -19,7 +18,7 @@ wrapArgs = (args, visited=[]) ->
type: 'array', value: wrapArgs(value, visited) type: 'array', value: wrapArgs(value, visited)
else if Buffer.isBuffer value else if Buffer.isBuffer value
type: 'buffer', value: Array::slice.call(value, 0) type: 'buffer', value: Array::slice.call(value, 0)
else if value? and value.constructor.name is 'Promise' else if value?.constructor.name is 'Promise'
type: 'promise', then: valueToMeta(value.then.bind(value)) type: 'promise', then: valueToMeta(value.then.bind(value))
else if value? and typeof value is 'object' and v8Util.getHiddenValue value, 'atomId' else if value? and typeof value is 'object' and v8Util.getHiddenValue value, 'atomId'
type: 'remote-object', id: v8Util.getHiddenValue value, 'atomId' type: 'remote-object', id: v8Util.getHiddenValue value, 'atomId'
@ -58,7 +57,7 @@ metaToValue = (meta) ->
constructor: -> constructor: ->
if @constructor == RemoteFunction if @constructor == RemoteFunction
# Constructor call. # Constructor call.
obj = ipc.sendSync 'ATOM_BROWSER_CONSTRUCTOR', meta.id, wrapArgs(arguments) obj = ipcRenderer.sendSync 'ATOM_BROWSER_CONSTRUCTOR', meta.id, wrapArgs(arguments)
# Returning object in constructor will replace constructed object # Returning object in constructor will replace constructed object
# with the returned object. # with the returned object.
@ -66,7 +65,7 @@ metaToValue = (meta) ->
return metaToValue obj return metaToValue obj
else else
# Function call. # Function call.
ret = ipc.sendSync 'ATOM_BROWSER_FUNCTION_CALL', meta.id, wrapArgs(arguments) ret = ipcRenderer.sendSync 'ATOM_BROWSER_FUNCTION_CALL', meta.id, wrapArgs(arguments)
return metaToValue ret return metaToValue ret
else else
ret = v8Util.createObjectWithName meta.name ret = v8Util.createObjectWithName meta.name
@ -80,11 +79,11 @@ metaToValue = (meta) ->
constructor: -> constructor: ->
if @constructor is RemoteMemberFunction if @constructor is RemoteMemberFunction
# Constructor call. # Constructor call.
obj = ipc.sendSync 'ATOM_BROWSER_MEMBER_CONSTRUCTOR', meta.id, member.name, wrapArgs(arguments) obj = ipcRenderer.sendSync 'ATOM_BROWSER_MEMBER_CONSTRUCTOR', meta.id, member.name, wrapArgs(arguments)
return metaToValue obj return metaToValue obj
else else
# Call member function. # Call member function.
ret = ipc.sendSync 'ATOM_BROWSER_MEMBER_CALL', meta.id, member.name, wrapArgs(arguments) ret = ipcRenderer.sendSync 'ATOM_BROWSER_MEMBER_CALL', meta.id, member.name, wrapArgs(arguments)
return metaToValue ret return metaToValue ret
else else
Object.defineProperty ret, member.name, Object.defineProperty ret, member.name,
@ -92,18 +91,18 @@ metaToValue = (meta) ->
configurable: false, configurable: false,
set: (value) -> set: (value) ->
# Set member data. # Set member data.
ipc.sendSync 'ATOM_BROWSER_MEMBER_SET', meta.id, member.name, value ipcRenderer.sendSync 'ATOM_BROWSER_MEMBER_SET', meta.id, member.name, value
value value
get: -> get: ->
# Get member data. # Get member data.
ret = ipc.sendSync 'ATOM_BROWSER_MEMBER_GET', meta.id, member.name ret = ipcRenderer.sendSync 'ATOM_BROWSER_MEMBER_GET', meta.id, member.name
metaToValue ret metaToValue ret
# Track delegate object's life time, and tell the browser to clean up # Track delegate object's life time, and tell the browser to clean up
# when the object is GCed. # when the object is GCed.
v8Util.setDestructor ret, -> v8Util.setDestructor ret, ->
ipc.send 'ATOM_BROWSER_DEREFERENCE', meta.id ipcRenderer.send 'ATOM_BROWSER_DEREFERENCE', meta.id
# Remember object's id. # Remember object's id.
v8Util.setHiddenValue ret, 'atomId', meta.id v8Util.setHiddenValue ret, 'atomId', meta.id
@ -119,13 +118,20 @@ metaToPlainObject = (meta) ->
obj obj
# Browser calls a callback in renderer. # Browser calls a callback in renderer.
ipc.on 'ATOM_RENDERER_CALLBACK', (event, id, args) -> ipcRenderer.on 'ATOM_RENDERER_CALLBACK', (event, id, args) ->
callbacksRegistry.apply id, metaToValue(args) callbacksRegistry.apply id, metaToValue(args)
# A callback in browser is released. # A callback in browser is released.
ipc.on 'ATOM_RENDERER_RELEASE_CALLBACK', (event, id) -> ipcRenderer.on 'ATOM_RENDERER_RELEASE_CALLBACK', (event, id) ->
callbacksRegistry.remove id callbacksRegistry.remove id
# List all built-in modules in browser process.
browserModules = ipcRenderer.sendSync 'ATOM_BROWSER_LIST_MODULES'
# And add a helper receiver for each one.
for name in browserModules
do (name) ->
Object.defineProperty exports, name, get: -> exports.getBuiltin name
# Get remote module. # Get remote module.
# (Just like node's require, the modules are cached permanently, note that this # (Just like node's require, the modules are cached permanently, note that this
# is safe leak since the object is not expected to get freed in browser) # is safe leak since the object is not expected to get freed in browser)
@ -133,26 +139,37 @@ moduleCache = {}
exports.require = (module) -> exports.require = (module) ->
return moduleCache[module] if moduleCache[module]? return moduleCache[module] if moduleCache[module]?
meta = ipc.sendSync 'ATOM_BROWSER_REQUIRE', module meta = ipcRenderer.sendSync 'ATOM_BROWSER_REQUIRE', module
moduleCache[module] = metaToValue meta moduleCache[module] = metaToValue meta
# Optimize require('electron').
moduleCache.electron = exports
# Alias to remote.require('electron').xxx.
builtinCache = {}
exports.getBuiltin = (module) ->
return builtinCache[module] if builtinCache[module]?
meta = ipcRenderer.sendSync 'ATOM_BROWSER_GET_BUILTIN', module
builtinCache[module] = metaToValue meta
# Get current BrowserWindow object. # Get current BrowserWindow object.
windowCache = null windowCache = null
exports.getCurrentWindow = -> exports.getCurrentWindow = ->
return windowCache if windowCache? return windowCache if windowCache?
meta = ipc.sendSync 'ATOM_BROWSER_CURRENT_WINDOW' meta = ipcRenderer.sendSync 'ATOM_BROWSER_CURRENT_WINDOW'
windowCache = metaToValue meta windowCache = metaToValue meta
# Get current WebContents object. # Get current WebContents object.
webContentsCache = null webContentsCache = null
exports.getCurrentWebContents = -> exports.getCurrentWebContents = ->
return webContentsCache if webContentsCache? return webContentsCache if webContentsCache?
meta = ipc.sendSync 'ATOM_BROWSER_CURRENT_WEB_CONTENTS' meta = ipcRenderer.sendSync 'ATOM_BROWSER_CURRENT_WEB_CONTENTS'
webContentsCache = metaToValue meta webContentsCache = metaToValue meta
# Get a global object in browser. # Get a global object in browser.
exports.getGlobal = (name) -> exports.getGlobal = (name) ->
meta = ipc.sendSync 'ATOM_BROWSER_GLOBAL', name meta = ipcRenderer.sendSync 'ATOM_BROWSER_GLOBAL', name
metaToValue meta metaToValue meta
# Get the process object in browser. # Get the process object in browser.
@ -169,5 +186,5 @@ exports.createFunctionWithReturnValue = (returnValue) ->
# Get the guest WebContents from guestInstanceId. # Get the guest WebContents from guestInstanceId.
exports.getGuestWebContents = (guestInstanceId) -> exports.getGuestWebContents = (guestInstanceId) ->
meta = ipc.sendSync 'ATOM_BROWSER_GUEST_WEB_CONTENTS', guestInstanceId meta = ipcRenderer.sendSync 'ATOM_BROWSER_GUEST_WEB_CONTENTS', guestInstanceId
metaToValue meta metaToValue meta

View file

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

View file

@ -1 +1,9 @@
module.exports = process.atomBinding('web_frame').webFrame {deprecate} = require 'electron'
{webFrame} = process.atomBinding 'web_frame'
# Deprecated.
deprecate.rename webFrame, 'registerUrlSchemeAsSecure', 'registerURLSchemeAsSecure'
deprecate.rename webFrame, 'registerUrlSchemeAsBypassingCSP', 'registerURLSchemeAsBypassingCSP'
deprecate.rename webFrame, 'registerUrlSchemeAsPrivileged', 'registerURLSchemeAsPrivileged'
module.exports = webFrame

View file

@ -13,10 +13,12 @@ require path.resolve(__dirname, '..', '..', 'common', 'lib', 'reset-search-paths
# Import common settings. # Import common settings.
require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init') require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init')
# Add renderer/api/lib to require's search paths, which contains javascript part
# of Atom's built-in libraries.
globalPaths = Module.globalPaths globalPaths = Module.globalPaths
globalPaths.push path.resolve(__dirname, '..', 'api', 'lib') unless process.env.ELECTRON_HIDE_INTERNAL_MODULES
globalPaths.push path.resolve(__dirname, '..', 'api', 'lib')
# Expose public APIs.
globalPaths.push path.resolve(__dirname, '..', 'api', 'lib', 'exports')
# The global variable will be used by ipc for event dispatching # The global variable will be used by ipc for event dispatching
v8Util = process.atomBinding 'v8_util' v8Util = process.atomBinding 'v8_util'
@ -25,10 +27,10 @@ v8Util.setHiddenValue global, 'ipc', new events.EventEmitter
# Process command line arguments. # Process command line arguments.
nodeIntegration = 'false' nodeIntegration = 'false'
for arg in process.argv for arg in process.argv
if arg.indexOf('--guestInstanceId=') == 0 if arg.indexOf('--guest-instance-id=') == 0
# This is a guest web view. # This is a guest web view.
process.guestInstanceId = parseInt arg.substr(arg.indexOf('=') + 1) process.guestInstanceId = parseInt arg.substr(arg.indexOf('=') + 1)
else if arg.indexOf('--nodeIntegration=') == 0 else if arg.indexOf('--node-integration=') == 0
nodeIntegration = arg.substr arg.indexOf('=') + 1 nodeIntegration = arg.substr arg.indexOf('=') + 1
else if arg.indexOf('--preload=') == 0 else if arg.indexOf('--preload=') == 0
preloadScript = arg.substr arg.indexOf('=') + 1 preloadScript = arg.substr arg.indexOf('=') + 1

View file

@ -32,8 +32,8 @@ convertToMenuTemplate = (items) ->
template template
createMenu = (x, y, items, document) -> createMenu = (x, y, items, document) ->
remote = require 'remote' {remote} = require 'electron'
Menu = remote.require 'menu' {Menu} = remote
menu = Menu.buildFromTemplate convertToMenuTemplate(items) menu = Menu.buildFromTemplate convertToMenuTemplate(items)
# The menu is expected to show asynchronously. # The menu is expected to show asynchronously.
@ -42,8 +42,8 @@ createMenu = (x, y, items, document) ->
DevToolsAPI.contextMenuCleared() DevToolsAPI.contextMenuCleared()
showFileChooserDialog = (callback) -> showFileChooserDialog = (callback) ->
remote = require 'remote' {remote} = require 'electron'
dialog = remote.require 'dialog' {dialog} = remote
files = dialog.showOpenDialog {} files = dialog.showOpenDialog {}
callback pathToHtml5FileObject files[0] if files? callback pathToHtml5FileObject files[0] if files?

View file

@ -1,9 +1,8 @@
ipc = require 'ipc-renderer' {ipcRenderer, remote} = require 'electron'
remote = require 'remote'
# Helper function to resolve relative url. # Helper function to resolve relative url.
a = window.top.document.createElement 'a' a = window.top.document.createElement 'a'
resolveUrl = (url) -> resolveURL = (url) ->
a.href = url a.href = url
a.href a.href
@ -11,24 +10,24 @@ resolveUrl = (url) ->
class BrowserWindowProxy class BrowserWindowProxy
constructor: (@guestId) -> constructor: (@guestId) ->
@closed = false @closed = false
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED', (event, guestId) => ipcRenderer.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED', (event, guestId) =>
if guestId is @guestId if guestId is @guestId
@closed = true @closed = true
close: -> close: ->
ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', @guestId ipcRenderer.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', @guestId
focus: -> focus: ->
ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', @guestId, 'focus' ipcRenderer.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', @guestId, 'focus'
blur: -> blur: ->
ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', @guestId, 'blur' ipcRenderer.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', @guestId, 'blur'
postMessage: (message, targetOrigin='*') -> postMessage: (message, targetOrigin='*') ->
ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', @guestId, message, targetOrigin ipcRenderer.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', @guestId, message, targetOrigin
eval: (args...) -> eval: (args...) ->
ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', @guestId, 'executeJavaScript', args... ipcRenderer.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', @guestId, 'executeJavaScript', args...
unless process.guestInstanceId? unless process.guestInstanceId?
# Override default window.close. # Override default window.close.
@ -56,11 +55,11 @@ window.open = (url, frameName='', features='') ->
options.height ?= 600 options.height ?= 600
# Resolve relative urls. # Resolve relative urls.
url = resolveUrl url url = resolveURL url
(options[name] = parseInt(options[name], 10) if options[name]?) for name in ints (options[name] = parseInt(options[name], 10) if options[name]?) for name in ints
guestId = ipc.sendSync 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', url, frameName, options guestId = ipcRenderer.sendSync 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', url, frameName, options
if guestId if guestId
new BrowserWindowProxy(guestId) new BrowserWindowProxy(guestId)
else else
@ -68,32 +67,30 @@ window.open = (url, frameName='', features='') ->
# Use the dialog API to implement alert(). # Use the dialog API to implement alert().
window.alert = (message, title='') -> window.alert = (message, title='') ->
dialog = remote.require 'dialog'
buttons = ['OK'] buttons = ['OK']
message = message.toString() message = message.toString()
dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons} remote.dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons}
# Alert should always return undefined. # Alert should always return undefined.
return return
# And the confirm(). # And the confirm().
window.confirm = (message, title='') -> window.confirm = (message, title='') ->
dialog = remote.require 'dialog'
buttons = ['OK', 'Cancel'] buttons = ['OK', 'Cancel']
cancelId = 1 cancelId = 1
not dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons, cancelId} not remote.dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons, cancelId}
# But we do not support prompt(). # But we do not support prompt().
window.prompt = -> window.prompt = ->
throw new Error('prompt() is and will not be supported.') throw new Error('prompt() is and will not be supported.')
# Implement window.postMessage if current window is a guest window. # Implement window.postMessage if current window is a guest window.
guestId = ipc.sendSync 'ATOM_SHELL_GUEST_WINDOW_MANAGER_GET_GUEST_ID' guestId = ipcRenderer.sendSync 'ATOM_SHELL_GUEST_WINDOW_MANAGER_GET_GUEST_ID'
if guestId? if guestId?
window.opener = window.opener =
postMessage: (message, targetOrigin='*') -> postMessage: (message, targetOrigin='*') ->
ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', guestId, message, targetOrigin, location.origin ipcRenderer.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', guestId, message, targetOrigin, location.origin
ipc.on 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', (event, guestId, message, sourceOrigin) -> ipcRenderer.on 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', (event, guestId, message, sourceOrigin) ->
# Manually dispatch event instead of using postMessage because we also need to # Manually dispatch event instead of using postMessage because we also need to
# set event.source. # set event.source.
event = document.createEvent 'Event' event = document.createEvent 'Event'
@ -105,10 +102,10 @@ ipc.on 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', (event, guestId, message, sourceOr
# Forward history operations to browser. # Forward history operations to browser.
sendHistoryOperation = (args...) -> sendHistoryOperation = (args...) ->
ipc.send 'ATOM_SHELL_NAVIGATION_CONTROLLER', args... ipcRenderer.send 'ATOM_SHELL_NAVIGATION_CONTROLLER', args...
getHistoryOperation = (args...) -> getHistoryOperation = (args...) ->
ipc.sendSync 'ATOM_SHELL_SYNC_NAVIGATION_CONTROLLER', args... ipcRenderer.sendSync 'ATOM_SHELL_SYNC_NAVIGATION_CONTROLLER', args...
window.history.back = -> sendHistoryOperation 'goBack' window.history.back = -> sendHistoryOperation 'goBack'
window.history.forward = -> sendHistoryOperation 'goForward' window.history.forward = -> sendHistoryOperation 'goForward'

View file

@ -1,19 +1,18 @@
ipc = require 'ipc-renderer' {ipcRenderer, webFrame} = require 'electron'
webFrame = require 'web-frame'
requestId = 0 requestId = 0
WEB_VIEW_EVENTS = WEB_VIEW_EVENTS =
'load-commit': ['url', 'isMainFrame'] 'load-commit': ['url', 'isMainFrame']
'did-finish-load': [] 'did-finish-load': []
'did-fail-load': ['errorCode', 'errorDescription', 'validatedUrl'] 'did-fail-load': ['errorCode', 'errorDescription', 'validatedURL']
'did-frame-finish-load': ['isMainFrame'] 'did-frame-finish-load': ['isMainFrame']
'did-start-loading': [] 'did-start-loading': []
'did-stop-loading': [] 'did-stop-loading': []
'did-get-response-details': ['status', 'newUrl', 'originalUrl', 'did-get-response-details': ['status', 'newURL', 'originalURL',
'httpResponseCode', 'requestMethod', 'referrer', 'httpResponseCode', 'requestMethod', 'referrer',
'headers'] 'headers']
'did-get-redirect-request': ['oldUrl', 'newUrl', 'isMainFrame'] 'did-get-redirect-request': ['oldURL', 'newURL', 'isMainFrame']
'dom-ready': [] 'dom-ready': []
'console-message': ['level', 'message', 'line', 'sourceId'] 'console-message': ['level', 'message', 'line', 'sourceId']
'new-window': ['url', 'frameName', 'disposition', 'options'] 'new-window': ['url', 'frameName', 'disposition', 'options']
@ -37,40 +36,40 @@ dispatchEvent = (webView, event, args...) ->
module.exports = module.exports =
registerEvents: (webView, viewInstanceId) -> registerEvents: (webView, viewInstanceId) ->
ipc.on "ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-#{viewInstanceId}", (event, domEvent, args...) -> ipcRenderer.on "ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-#{viewInstanceId}", (event, domEvent, args...) ->
dispatchEvent webView, domEvent, args... dispatchEvent webView, domEvent, args...
ipc.on "ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-#{viewInstanceId}", (event, channel, args...) -> ipcRenderer.on "ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-#{viewInstanceId}", (event, channel, args...) ->
domEvent = new Event('ipc-message') domEvent = new Event('ipc-message')
domEvent.channel = channel domEvent.channel = channel
domEvent.args = [args...] domEvent.args = [args...]
webView.dispatchEvent domEvent webView.dispatchEvent domEvent
ipc.on "ATOM_SHELL_GUEST_VIEW_INTERNAL_SIZE_CHANGED-#{viewInstanceId}", (event, args...) -> ipcRenderer.on "ATOM_SHELL_GUEST_VIEW_INTERNAL_SIZE_CHANGED-#{viewInstanceId}", (event, args...) ->
domEvent = new Event('size-changed') domEvent = new Event('size-changed')
for f, i in ['oldWidth', 'oldHeight', 'newWidth', 'newHeight'] for f, i in ['oldWidth', 'oldHeight', 'newWidth', 'newHeight']
domEvent[f] = args[i] domEvent[f] = args[i]
webView.onSizeChanged domEvent webView.onSizeChanged domEvent
deregisterEvents: (viewInstanceId) -> deregisterEvents: (viewInstanceId) ->
ipc.removeAllListeners "ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-#{viewInstanceId}" ipcRenderer.removeAllListeners "ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-#{viewInstanceId}"
ipc.removeAllListeners "ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-#{viewInstanceId}" ipcRenderer.removeAllListeners "ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-#{viewInstanceId}"
ipc.removeAllListeners "ATOM_SHELL_GUEST_VIEW_INTERNAL_SIZE_CHANGED-#{viewInstanceId}" ipcRenderer.removeAllListeners "ATOM_SHELL_GUEST_VIEW_INTERNAL_SIZE_CHANGED-#{viewInstanceId}"
createGuest: (params, callback) -> createGuest: (params, callback) ->
requestId++ requestId++
ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', params, requestId ipcRenderer.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', params, requestId
ipc.once "ATOM_SHELL_RESPONSE_#{requestId}", callback ipcRenderer.once "ATOM_SHELL_RESPONSE_#{requestId}", callback
attachGuest: (elementInstanceId, guestInstanceId, params) -> attachGuest: (elementInstanceId, guestInstanceId, params) ->
ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', elementInstanceId, guestInstanceId, params ipcRenderer.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', elementInstanceId, guestInstanceId, params
webFrame.attachGuest elementInstanceId webFrame.attachGuest elementInstanceId
destroyGuest: (guestInstanceId) -> destroyGuest: (guestInstanceId) ->
ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', guestInstanceId ipcRenderer.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', guestInstanceId
setSize: (guestInstanceId, params) -> setSize: (guestInstanceId, params) ->
ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_SIZE', guestInstanceId, params ipcRenderer.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_SIZE', guestInstanceId, params
setAllowTransparency: (guestInstanceId, allowtransparency) -> setAllowTransparency: (guestInstanceId, allowtransparency) ->
ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_ALLOW_TRANSPARENCY', guestInstanceId, allowtransparency ipcRenderer.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_ALLOW_TRANSPARENCY', guestInstanceId, allowtransparency

View file

@ -1,11 +1,12 @@
WebViewImpl = require './web-view' WebViewImpl = require './web-view'
guestViewInternal = require './guest-view-internal' guestViewInternal = require './guest-view-internal'
webViewConstants = require './web-view-constants' webViewConstants = require './web-view-constants'
remote = require 'remote'
{remote} = require 'electron'
# Helper function to resolve url set in attribute. # Helper function to resolve url set in attribute.
a = document.createElement 'a' a = document.createElement 'a'
resolveUrl = (url) -> resolveURL = (url) ->
a.href = url a.href = url
a.href a.href
@ -115,7 +116,7 @@ class SrcAttribute extends WebViewAttribute
getValue: -> getValue: ->
if @webViewImpl.webviewNode.hasAttribute @name if @webViewImpl.webviewNode.hasAttribute @name
resolveUrl @webViewImpl.webviewNode.getAttribute(@name) resolveURL @webViewImpl.webviewNode.getAttribute(@name)
else else
'' ''
@ -177,7 +178,7 @@ class SrcAttribute extends WebViewAttribute
if useragent then opts.userAgent = useragent if useragent then opts.userAgent = useragent
guestContents = remote.getGuestWebContents(@webViewImpl.guestInstanceId) guestContents = remote.getGuestWebContents(@webViewImpl.guestInstanceId)
guestContents.loadUrl @getValue(), opts guestContents.loadURL @getValue(), opts
# Attribute specifies HTTP referrer. # Attribute specifies HTTP referrer.
class HttpReferrerAttribute extends WebViewAttribute class HttpReferrerAttribute extends WebViewAttribute
@ -196,7 +197,7 @@ class PreloadAttribute extends WebViewAttribute
getValue: -> getValue: ->
return '' unless @webViewImpl.webviewNode.hasAttribute @name return '' unless @webViewImpl.webviewNode.hasAttribute @name
preload = resolveUrl @webViewImpl.webviewNode.getAttribute(@name) preload = resolveURL @webViewImpl.webviewNode.getAttribute(@name)
protocol = preload.substr 0, 5 protocol = preload.substr 0, 5
unless protocol is 'file:' unless protocol is 'file:'
console.error webViewConstants.ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE console.error webViewConstants.ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE

View file

@ -1,8 +1,8 @@
{deprecate, webFrame, remote} = require 'electron'
v8Util = process.atomBinding 'v8_util' v8Util = process.atomBinding 'v8_util'
guestViewInternal = require './guest-view-internal' guestViewInternal = require './guest-view-internal'
webViewConstants = require './web-view-constants' webViewConstants = require './web-view-constants'
webFrame = require 'web-frame'
remote = require 'remote'
# ID generator. # ID generator.
nextId = 0 nextId = 0
@ -252,49 +252,49 @@ registerWebViewElement = ->
# Public-facing API methods. # Public-facing API methods.
methods = [ methods = [
"getUrl" 'getURL'
"getTitle" 'getTitle'
"isLoading" 'isLoading'
"isWaitingForResponse" 'isWaitingForResponse'
"stop" 'stop'
"reload" 'reload'
"reloadIgnoringCache" 'reloadIgnoringCache'
"canGoBack" 'canGoBack'
"canGoForward" 'canGoForward'
"canGoToOffset" 'canGoToOffset'
"clearHistory" 'clearHistory'
"goBack" 'goBack'
"goForward" 'goForward'
"goToIndex" 'goToIndex'
"goToOffset" 'goToOffset'
"isCrashed" 'isCrashed'
"setUserAgent" 'setUserAgent'
"getUserAgent" 'getUserAgent'
"executeJavaScript" 'executeJavaScript'
"insertCSS" 'insertCSS'
"openDevTools" 'openDevTools'
"closeDevTools" 'closeDevTools'
"isDevToolsOpened" 'isDevToolsOpened'
"inspectElement" 'inspectElement'
"setAudioMuted" 'setAudioMuted'
"isAudioMuted" 'isAudioMuted'
"undo" 'undo'
"redo" 'redo'
"cut" 'cut'
"copy" 'copy'
"paste" 'paste'
"pasteAndMatchStyle" 'pasteAndMatchStyle'
"delete" 'delete'
"selectAll" 'selectAll'
"unselect" 'unselect'
"replace" 'replace'
"replaceMisspelling" 'replaceMisspelling'
"send" 'send'
"getId" 'getId'
"inspectServiceWorker" 'inspectServiceWorker'
"print" 'print'
"printToPDF" 'printToPDF'
"sendInputEvent" 'sendInputEvent'
] ]
# Forward proto.foo* method calls to WebViewImpl.foo*. # Forward proto.foo* method calls to WebViewImpl.foo*.
@ -304,6 +304,9 @@ registerWebViewElement = ->
internal.webContents[m] args... internal.webContents[m] args...
proto[m] = createHandler m for m in methods proto[m] = createHandler m for m in methods
# Deprecated.
deprecate.rename proto, 'getUrl', 'getURL'
window.WebView = webFrame.registerEmbedderCustomElement 'webview', window.WebView = webFrame.registerEmbedderCustomElement 'webview',
prototype: proto prototype: proto

View file

@ -0,0 +1,74 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/common/chrome_constants.h"
#define FPL FILE_PATH_LITERAL
namespace chrome {
#if defined(OS_MACOSX)
const base::FilePath::CharType kFrameworkName[] =
FPL(ATOM_PRODUCT_NAME " Framework.framework");
#endif // OS_MACOSX
// filenames
const base::FilePath::CharType kCacheDirname[] = FPL("Cache");
const base::FilePath::CharType kChannelIDFilename[] = FPL("Origin Bound Certs");
const base::FilePath::CharType kCookieFilename[] = FPL("Cookies");
const base::FilePath::CharType kCRLSetFilename[] =
FPL("Certificate Revocation Lists");
const base::FilePath::CharType kCustomDictionaryFileName[] =
FPL("Custom Dictionary.txt");
const base::FilePath::CharType kExtensionActivityLogFilename[] =
FPL("Extension Activity");
const base::FilePath::CharType kExtensionsCookieFilename[] =
FPL("Extension Cookies");
const base::FilePath::CharType kFirstRunSentinel[] = FPL("First Run");
const base::FilePath::CharType kGCMStoreDirname[] = FPL("GCM Store");
const base::FilePath::CharType kLocalStateFilename[] = FPL("Local State");
const base::FilePath::CharType kLocalStorePoolName[] = FPL("LocalStorePool");
const base::FilePath::CharType kMediaCacheDirname[] = FPL("Media Cache");
const base::FilePath::CharType kNetworkPersistentStateFilename[] =
FPL("Network Persistent State");
const base::FilePath::CharType kOfflinePageArchviesDirname[] =
FPL("Offline Pages/archives");
const base::FilePath::CharType kOfflinePageMetadataDirname[] =
FPL("Offline Pages/metadata");
const base::FilePath::CharType kPreferencesFilename[] = FPL("Preferences");
const base::FilePath::CharType kProtectedPreferencesFilenameDeprecated[] =
FPL("Protected Preferences");
const base::FilePath::CharType kReadmeFilename[] = FPL("README");
const base::FilePath::CharType kResetPromptMementoFilename[] =
FPL("Reset Prompt Memento");
const base::FilePath::CharType kSafeBrowsingBaseFilename[] =
FPL("Safe Browsing");
const base::FilePath::CharType kSecurePreferencesFilename[] =
FPL("Secure Preferences");
const base::FilePath::CharType kServiceStateFileName[] = FPL("Service State");
const base::FilePath::CharType kSingletonCookieFilename[] =
FPL("SingletonCookie");
const base::FilePath::CharType kSingletonLockFilename[] = FPL("SingletonLock");
const base::FilePath::CharType kSingletonSocketFilename[] =
FPL("SingletonSocket");
const base::FilePath::CharType kSupervisedUserSettingsFilename[] =
FPL("Managed Mode Settings");
const base::FilePath::CharType kThemePackFilename[] = FPL("Cached Theme.pak");
const base::FilePath::CharType kThemePackMaterialDesignFilename[] =
FPL("Cached Theme Material Design.pak");
const base::FilePath::CharType kWebAppDirname[] = FPL("Web Applications");
// File name of the Pepper Flash plugin on different platforms.
const base::FilePath::CharType kPepperFlashPluginFilename[] =
#if defined(OS_MACOSX)
FPL("PepperFlashPlayer.plugin");
#elif defined(OS_WIN)
FPL("pepflashplayer.dll");
#else // OS_LINUX, etc.
FPL("libpepflashplayer.so");
#endif
} // namespace chrome
#undef FPL

View file

@ -0,0 +1,58 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// A handful of resource-like constants related to the Chrome application.
#ifndef CHROME_COMMON_CHROME_CONSTANTS_H_
#define CHROME_COMMON_CHROME_CONSTANTS_H_
#include "base/files/file_path.h"
namespace chrome {
#if defined(OS_MACOSX)
// NOTE: if you change the value of kFrameworkName, please don't forget to
// update components/test/run_all_unittests.cc as well.
// TODO(tfarina): Remove the comment above, when you fix components to use plist
// on Mac.
extern const base::FilePath::CharType kFrameworkName[];
#endif // OS_MACOSX
// filenames
extern const base::FilePath::CharType kCacheDirname[];
extern const base::FilePath::CharType kChannelIDFilename[];
extern const base::FilePath::CharType kCookieFilename[];
extern const base::FilePath::CharType kCRLSetFilename[];
extern const base::FilePath::CharType kCustomDictionaryFileName[];
extern const base::FilePath::CharType kExtensionActivityLogFilename[];
extern const base::FilePath::CharType kExtensionsCookieFilename[];
extern const base::FilePath::CharType kFirstRunSentinel[];
extern const base::FilePath::CharType kGCMStoreDirname[];
extern const base::FilePath::CharType kLocalStateFilename[];
extern const base::FilePath::CharType kLocalStorePoolName[];
extern const base::FilePath::CharType kMediaCacheDirname[];
extern const base::FilePath::CharType kNetworkPersistentStateFilename[];
extern const base::FilePath::CharType kOfflinePageArchviesDirname[];
extern const base::FilePath::CharType kOfflinePageMetadataDirname[];
extern const base::FilePath::CharType kPreferencesFilename[];
extern const base::FilePath::CharType kProtectedPreferencesFilenameDeprecated[];
extern const base::FilePath::CharType kReadmeFilename[];
extern const base::FilePath::CharType kResetPromptMementoFilename[];
extern const base::FilePath::CharType kSafeBrowsingBaseFilename[];
extern const base::FilePath::CharType kSecurePreferencesFilename[];
extern const base::FilePath::CharType kServiceStateFileName[];
extern const base::FilePath::CharType kSingletonCookieFilename[];
extern const base::FilePath::CharType kSingletonLockFilename[];
extern const base::FilePath::CharType kSingletonSocketFilename[];
extern const base::FilePath::CharType kSupervisedUserSettingsFilename[];
extern const base::FilePath::CharType kThemePackFilename[];
extern const base::FilePath::CharType kThemePackMaterialDesignFilename[];
extern const base::FilePath::CharType kWebAppDirname[];
// File name of the Pepper Flash plugin on different platforms.
extern const base::FilePath::CharType kPepperFlashPluginFilename[];
} // namespace chrome
#endif // CHROME_COMMON_CHROME_CONSTANTS_H_

View file

@ -0,0 +1,610 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/common/chrome_paths.h"
#include "base/files/file_util.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/mac/bundle_locations.h"
#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/sys_info.h"
#include "base/threading/thread_restrictions.h"
#include "base/version.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths_internal.h"
#if defined(OS_ANDROID)
#include "base/android/path_utils.h"
#include "base/base_paths_android.h"
// ui/base must only be used on Android. See BUILD.gn for dependency info.
#include "ui/base/ui_base_paths.h" // nogncheck
#endif
#if defined(OS_MACOSX)
#include "base/mac/foundation_util.h"
#endif
#if defined(OS_WIN)
#include "base/win/registry.h"
#endif
namespace {
// The Pepper Flash plugins are in a directory with this name.
const base::FilePath::CharType kPepperFlashBaseDirectory[] =
FILE_PATH_LITERAL("PepperFlash");
#if defined(OS_MACOSX) && !defined(OS_IOS)
const base::FilePath::CharType kPepperFlashSystemBaseDirectory[] =
FILE_PATH_LITERAL("Internet Plug-Ins/PepperFlashPlayer");
const base::FilePath::CharType kFlashSystemBaseDirectory[] =
FILE_PATH_LITERAL("Internet Plug-Ins");
const base::FilePath::CharType kFlashSystemPluginName[] =
FILE_PATH_LITERAL("Flash Player.plugin");
#endif
const base::FilePath::CharType kInternalNaClPluginFileName[] =
FILE_PATH_LITERAL("internal-nacl-plugin");
#if defined(OS_LINUX)
// The path to the external extension <id>.json files.
// /usr/share seems like a good choice, see: http://www.pathname.com/fhs/
const base::FilePath::CharType kFilepathSinglePrefExtensions[] =
#if defined(GOOGLE_CHROME_BUILD)
FILE_PATH_LITERAL("/usr/share/google-chrome/extensions");
#else
FILE_PATH_LITERAL("/usr/share/chromium/extensions");
#endif // defined(GOOGLE_CHROME_BUILD)
// The path to the hint file that tells the pepper plugin loader
// where it can find the latest component updated flash.
const base::FilePath::CharType kComponentUpdatedFlashHint[] =
FILE_PATH_LITERAL("latest-component-updated-flash");
#endif // defined(OS_LINUX)
static base::LazyInstance<base::FilePath>
g_invalid_specified_user_data_dir = LAZY_INSTANCE_INITIALIZER;
// Gets the path for internal plugins.
bool GetInternalPluginsDirectory(base::FilePath* result) {
#if defined(OS_MACOSX) && !defined(OS_IOS)
// If called from Chrome, get internal plugins from a subdirectory of the
// framework.
if (base::mac::AmIBundled()) {
*result = chrome::GetFrameworkBundlePath();
DCHECK(!result->empty());
*result = result->Append("Internet Plug-Ins");
return true;
}
// In tests, just look in the module directory (below).
#endif
// The rest of the world expects plugins in the module directory.
return PathService::Get(base::DIR_MODULE, result);
}
#if defined(OS_WIN)
// Gets the Flash path if installed on the system. |is_npapi| determines whether
// to return the NPAPI of the PPAPI version of the system plugin.
bool GetSystemFlashFilename(base::FilePath* out_path, bool is_npapi) {
const wchar_t kNpapiFlashRegistryRoot[] =
L"SOFTWARE\\Macromedia\\FlashPlayerPlugin";
const wchar_t kPepperFlashRegistryRoot[] =
L"SOFTWARE\\Macromedia\\FlashPlayerPepper";
const wchar_t kFlashPlayerPathValueName[] = L"PlayerPath";
base::win::RegKey path_key(
HKEY_LOCAL_MACHINE,
is_npapi ? kNpapiFlashRegistryRoot : kPepperFlashRegistryRoot, KEY_READ);
base::string16 path_str;
if (FAILED(path_key.ReadValue(kFlashPlayerPathValueName, &path_str)))
return false;
*out_path = base::FilePath(path_str);
return true;
}
#endif
} // namespace
namespace chrome {
bool PathProvider(int key, base::FilePath* result) {
// Some keys are just aliases...
switch (key) {
case chrome::DIR_APP:
return PathService::Get(base::DIR_MODULE, result);
case chrome::DIR_LOGS:
#ifdef NDEBUG
// Release builds write to the data dir
return PathService::Get(chrome::DIR_USER_DATA, result);
#else
// Debug builds write next to the binary (in the build tree)
#if defined(OS_MACOSX)
if (!PathService::Get(base::DIR_EXE, result))
return false;
if (base::mac::AmIBundled()) {
// If we're called from chrome, dump it beside the app (outside the
// app bundle), if we're called from a unittest, we'll already
// outside the bundle so use the exe dir.
// exe_dir gave us .../Chromium.app/Contents/MacOS/Chromium.
*result = result->DirName();
*result = result->DirName();
*result = result->DirName();
}
return true;
#else
return PathService::Get(base::DIR_EXE, result);
#endif // defined(OS_MACOSX)
#endif // NDEBUG
case chrome::FILE_RESOURCE_MODULE:
return PathService::Get(base::FILE_MODULE, result);
}
// Assume that we will not need to create the directory if it does not exist.
// This flag can be set to true for the cases where we want to create it.
bool create_dir = false;
base::FilePath cur;
switch (key) {
case chrome::DIR_USER_DATA:
if (!GetDefaultUserDataDirectory(&cur)) {
NOTREACHED();
return false;
}
create_dir = true;
break;
case chrome::DIR_USER_DOCUMENTS:
if (!GetUserDocumentsDirectory(&cur))
return false;
create_dir = true;
break;
case chrome::DIR_USER_MUSIC:
if (!GetUserMusicDirectory(&cur))
return false;
break;
case chrome::DIR_USER_PICTURES:
if (!GetUserPicturesDirectory(&cur))
return false;
break;
case chrome::DIR_USER_VIDEOS:
if (!GetUserVideosDirectory(&cur))
return false;
break;
case chrome::DIR_DEFAULT_DOWNLOADS_SAFE:
#if defined(OS_WIN) || defined(OS_LINUX)
if (!GetUserDownloadsDirectorySafe(&cur))
return false;
break;
#else
// Fall through for all other platforms.
#endif
case chrome::DIR_DEFAULT_DOWNLOADS:
#if defined(OS_ANDROID)
if (!base::android::GetDownloadsDirectory(&cur))
return false;
#else
if (!GetUserDownloadsDirectory(&cur))
return false;
// Do not create the download directory here, we have done it twice now
// and annoyed a lot of users.
#endif
break;
case chrome::DIR_CRASH_DUMPS:
#if defined(OS_CHROMEOS)
// ChromeOS uses a separate directory. See http://crosbug.com/25089
cur = base::FilePath("/var/log/chrome");
#elif defined(OS_ANDROID)
if (!base::android::GetCacheDirectory(&cur))
return false;
#else
// The crash reports are always stored relative to the default user data
// directory. This avoids the problem of having to re-initialize the
// exception handler after parsing command line options, which may
// override the location of the app's profile directory.
if (!GetDefaultUserDataDirectory(&cur))
return false;
#endif
#if defined(OS_MACOSX)
cur = cur.Append(FILE_PATH_LITERAL("Crashpad"));
#else
cur = cur.Append(FILE_PATH_LITERAL("Crash Reports"));
#endif
create_dir = true;
break;
#if defined(OS_WIN)
case chrome::DIR_WATCHER_DATA:
// The watcher data is always stored relative to the default user data
// directory. This allows the watcher to be initialized before
// command-line options have been parsed.
if (!GetDefaultUserDataDirectory(&cur))
return false;
cur = cur.Append(FILE_PATH_LITERAL("Diagnostics"));
break;
#endif
case chrome::DIR_RESOURCES:
#if defined(OS_MACOSX)
cur = base::mac::FrameworkBundlePath();
cur = cur.Append(FILE_PATH_LITERAL("Resources"));
#else
if (!PathService::Get(chrome::DIR_APP, &cur))
return false;
cur = cur.Append(FILE_PATH_LITERAL("resources"));
#endif
break;
case chrome::DIR_INSPECTOR:
if (!PathService::Get(chrome::DIR_RESOURCES, &cur))
return false;
cur = cur.Append(FILE_PATH_LITERAL("inspector"));
break;
case chrome::DIR_APP_DICTIONARIES:
#if defined(OS_POSIX)
// We can't write into the EXE dir on Linux, so keep dictionaries
// alongside the safe browsing database in the user data dir.
// And we don't want to write into the bundle on the Mac, so push
// it to the user data dir there also.
if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
return false;
#else
if (!PathService::Get(base::DIR_EXE, &cur))
return false;
#endif
cur = cur.Append(FILE_PATH_LITERAL("Dictionaries"));
create_dir = true;
break;
case chrome::DIR_INTERNAL_PLUGINS:
if (!GetInternalPluginsDirectory(&cur))
return false;
break;
case chrome::DIR_PEPPER_FLASH_PLUGIN:
if (!GetInternalPluginsDirectory(&cur))
return false;
cur = cur.Append(kPepperFlashBaseDirectory);
break;
case chrome::DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN:
if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
return false;
cur = cur.Append(kPepperFlashBaseDirectory);
break;
case chrome::FILE_PEPPER_FLASH_SYSTEM_PLUGIN:
#if defined(OS_WIN)
if (!GetSystemFlashFilename(&cur, false))
return false;
#elif defined(OS_MACOSX) && !defined(OS_IOS)
if (!GetLocalLibraryDirectory(&cur))
return false;
cur = cur.Append(kPepperFlashSystemBaseDirectory);
cur = cur.Append(chrome::kPepperFlashPluginFilename);
#else
// Chrome on iOS does not supports PPAPI binaries, return false.
// TODO(wfh): If Adobe release PPAPI binaries for Linux, add support here.
return false;
#endif
break;
case chrome::FILE_FLASH_SYSTEM_PLUGIN:
#if defined(OS_WIN)
if (!GetSystemFlashFilename(&cur, true))
return false;
#elif defined(OS_MACOSX) && !defined(OS_IOS)
if (!GetLocalLibraryDirectory(&cur))
return false;
cur = cur.Append(kFlashSystemBaseDirectory);
cur = cur.Append(kFlashSystemPluginName);
#else
// Chrome on other platforms does not supports system NPAPI binaries.
return false;
#endif
break;
case chrome::FILE_LOCAL_STATE:
if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
return false;
cur = cur.Append(chrome::kLocalStateFilename);
break;
case chrome::FILE_RECORDED_SCRIPT:
if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
return false;
cur = cur.Append(FILE_PATH_LITERAL("script.log"));
break;
case chrome::FILE_PEPPER_FLASH_PLUGIN:
if (!PathService::Get(chrome::DIR_PEPPER_FLASH_PLUGIN, &cur))
return false;
cur = cur.Append(chrome::kPepperFlashPluginFilename);
break;
// TODO(teravest): Remove this case once the internal NaCl plugin is gone.
// We currently need a path here to look up whether the plugin is disabled
// and what its permissions are.
case chrome::FILE_NACL_PLUGIN:
if (!GetInternalPluginsDirectory(&cur))
return false;
cur = cur.Append(kInternalNaClPluginFileName);
break;
// PNaCl is currenly installable via the component updater or by being
// simply built-in. DIR_PNACL_BASE is used as the base directory for
// installation via component updater. DIR_PNACL_COMPONENT will be
// the final location of pnacl, which is a subdir of DIR_PNACL_BASE.
case chrome::DIR_PNACL_BASE:
if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
return false;
cur = cur.Append(FILE_PATH_LITERAL("pnacl"));
break;
// Where PNaCl files are ultimately located. The default finds the files
// inside the InternalPluginsDirectory / build directory, as if it
// was shipped along with chrome. The value can be overridden
// if it is installed via component updater.
case chrome::DIR_PNACL_COMPONENT:
#if defined(OS_MACOSX)
// PNaCl really belongs in the InternalPluginsDirectory but actually
// copying it there would result in the files also being shipped, which
// we don't want yet. So for now, just find them in the directory where
// they get built.
if (!PathService::Get(base::DIR_EXE, &cur))
return false;
if (base::mac::AmIBundled()) {
// If we're called from chrome, it's beside the app (outside the
// app bundle), if we're called from a unittest, we'll already be
// outside the bundle so use the exe dir.
// exe_dir gave us .../Chromium.app/Contents/MacOS/Chromium.
cur = cur.DirName();
cur = cur.DirName();
cur = cur.DirName();
}
#else
if (!GetInternalPluginsDirectory(&cur))
return false;
#endif
cur = cur.Append(FILE_PATH_LITERAL("pnacl"));
break;
#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
#if defined(WIDEVINE_CDM_IS_COMPONENT)
case chrome::DIR_COMPONENT_WIDEVINE_CDM:
if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
return false;
cur = cur.Append(FILE_PATH_LITERAL("WidevineCDM"));
break;
#endif // defined(WIDEVINE_CDM_IS_COMPONENT)
// TODO(xhwang): FILE_WIDEVINE_CDM_ADAPTER has different meanings.
// In the component case, this is the source adapter. Otherwise, it is the
// actual Pepper module that gets loaded.
case chrome::FILE_WIDEVINE_CDM_ADAPTER:
if (!GetInternalPluginsDirectory(&cur))
return false;
cur = cur.AppendASCII(kWidevineCdmAdapterFileName);
break;
#endif // defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS)
case chrome::FILE_RESOURCES_PACK:
#if defined(OS_MACOSX) && !defined(OS_IOS)
if (base::mac::AmIBundled()) {
cur = base::mac::FrameworkBundlePath();
cur = cur.Append(FILE_PATH_LITERAL("Resources"))
.Append(FILE_PATH_LITERAL("resources.pak"));
break;
}
#elif defined(OS_ANDROID)
if (!PathService::Get(ui::DIR_RESOURCE_PAKS_ANDROID, &cur))
return false;
#else
// If we're not bundled on mac or Android, resources.pak should be next
// to the binary (e.g., for unit tests).
if (!PathService::Get(base::DIR_MODULE, &cur))
return false;
#endif
cur = cur.Append(FILE_PATH_LITERAL("resources.pak"));
break;
case chrome::DIR_RESOURCES_EXTENSION:
if (!PathService::Get(base::DIR_MODULE, &cur))
return false;
cur = cur.Append(FILE_PATH_LITERAL("resources"))
.Append(FILE_PATH_LITERAL("extension"));
break;
#if defined(OS_CHROMEOS)
case chrome::DIR_CHROMEOS_WALLPAPERS:
if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
return false;
cur = cur.Append(FILE_PATH_LITERAL("wallpapers"));
break;
case chrome::DIR_CHROMEOS_WALLPAPER_THUMBNAILS:
if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
return false;
cur = cur.Append(FILE_PATH_LITERAL("wallpaper_thumbnails"));
break;
case chrome::DIR_CHROMEOS_CUSTOM_WALLPAPERS:
if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
return false;
cur = cur.Append(FILE_PATH_LITERAL("custom_wallpapers"));
break;
#endif
#if defined(ENABLE_SUPERVISED_USERS)
#if defined(OS_LINUX)
case chrome::DIR_SUPERVISED_USERS_DEFAULT_APPS:
if (!PathService::Get(chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS, &cur))
return false;
cur = cur.Append(FILE_PATH_LITERAL("managed_users"));
break;
#endif
case chrome::DIR_SUPERVISED_USER_INSTALLED_WHITELISTS:
if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
return false;
cur = cur.Append(FILE_PATH_LITERAL("SupervisedUserInstalledWhitelists"));
break;
#endif
// The following are only valid in the development environment, and
// will fail if executed from an installed executable (because the
// generated path won't exist).
case chrome::DIR_GEN_TEST_DATA:
#if defined(OS_ANDROID)
// On Android, our tests don't have permission to write to DIR_MODULE.
// gtest/test_runner.py pushes data to external storage.
if (!PathService::Get(base::DIR_ANDROID_EXTERNAL_STORAGE, &cur))
return false;
#else
if (!PathService::Get(base::DIR_MODULE, &cur))
return false;
#endif
cur = cur.Append(FILE_PATH_LITERAL("test_data"));
if (!base::PathExists(cur)) // We don't want to create this.
return false;
break;
case chrome::DIR_TEST_DATA:
if (!PathService::Get(base::DIR_SOURCE_ROOT, &cur))
return false;
cur = cur.Append(FILE_PATH_LITERAL("chrome"));
cur = cur.Append(FILE_PATH_LITERAL("test"));
cur = cur.Append(FILE_PATH_LITERAL("data"));
if (!base::PathExists(cur)) // We don't want to create this.
return false;
break;
case chrome::DIR_TEST_TOOLS:
if (!PathService::Get(base::DIR_SOURCE_ROOT, &cur))
return false;
cur = cur.Append(FILE_PATH_LITERAL("chrome"));
cur = cur.Append(FILE_PATH_LITERAL("tools"));
cur = cur.Append(FILE_PATH_LITERAL("test"));
if (!base::PathExists(cur)) // We don't want to create this
return false;
break;
#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)
case chrome::DIR_POLICY_FILES: {
#if defined(GOOGLE_CHROME_BUILD)
cur = base::FilePath(FILE_PATH_LITERAL("/etc/opt/chrome/policies"));
#else
cur = base::FilePath(FILE_PATH_LITERAL("/etc/chromium/policies"));
#endif
break;
}
#endif
#if defined(OS_MACOSX) && !defined(OS_IOS)
case chrome::DIR_USER_LIBRARY: {
if (!GetUserLibraryDirectory(&cur))
return false;
if (!base::PathExists(cur)) // We don't want to create this.
return false;
break;
}
case chrome::DIR_USER_APPLICATIONS: {
if (!GetUserApplicationsDirectory(&cur))
return false;
if (!base::PathExists(cur)) // We don't want to create this.
return false;
break;
}
#endif
#if defined(OS_CHROMEOS) || (defined(OS_LINUX) && defined(CHROMIUM_BUILD)) || \
(defined(OS_MACOSX) && !defined(OS_IOS))
case chrome::DIR_USER_EXTERNAL_EXTENSIONS: {
if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
return false;
cur = cur.Append(FILE_PATH_LITERAL("External Extensions"));
break;
}
#endif
#if defined(OS_LINUX)
case chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS: {
cur = base::FilePath(kFilepathSinglePrefExtensions);
break;
}
#endif
case chrome::DIR_EXTERNAL_EXTENSIONS:
#if defined(OS_MACOSX) && !defined(OS_IOS)
if (!chrome::GetGlobalApplicationSupportDirectory(&cur))
return false;
cur = cur.Append(FILE_PATH_LITERAL("Google"))
.Append(FILE_PATH_LITERAL("Chrome"))
.Append(FILE_PATH_LITERAL("External Extensions"));
create_dir = false;
#else
if (!PathService::Get(base::DIR_MODULE, &cur))
return false;
cur = cur.Append(FILE_PATH_LITERAL("extensions"));
create_dir = true;
#endif
break;
case chrome::DIR_DEFAULT_APPS:
#if defined(OS_MACOSX)
cur = base::mac::FrameworkBundlePath();
cur = cur.Append(FILE_PATH_LITERAL("Default Apps"));
#else
if (!PathService::Get(chrome::DIR_APP, &cur))
return false;
cur = cur.Append(FILE_PATH_LITERAL("default_apps"));
#endif
break;
#if defined(OS_LINUX) || (defined(OS_MACOSX) && !defined(OS_IOS))
case chrome::DIR_NATIVE_MESSAGING:
#if defined(OS_MACOSX)
#if defined(GOOGLE_CHROME_BUILD)
cur = base::FilePath(FILE_PATH_LITERAL(
"/Library/Google/Chrome/NativeMessagingHosts"));
#else
cur = base::FilePath(FILE_PATH_LITERAL(
"/Library/Application Support/Chromium/NativeMessagingHosts"));
#endif
#else // defined(OS_MACOSX)
#if defined(GOOGLE_CHROME_BUILD)
cur = base::FilePath(FILE_PATH_LITERAL(
"/etc/opt/chrome/native-messaging-hosts"));
#else
cur = base::FilePath(FILE_PATH_LITERAL(
"/etc/chromium/native-messaging-hosts"));
#endif
#endif // !defined(OS_MACOSX)
break;
case chrome::DIR_USER_NATIVE_MESSAGING:
if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
return false;
cur = cur.Append(FILE_PATH_LITERAL("NativeMessagingHosts"));
break;
#endif // defined(OS_LINUX) || (defined(OS_MACOSX) && !defined(OS_IOS))
#if !defined(OS_ANDROID)
case chrome::DIR_GLOBAL_GCM_STORE:
if (!PathService::Get(chrome::DIR_USER_DATA, &cur))
return false;
cur = cur.Append(kGCMStoreDirname);
break;
#endif // !defined(OS_ANDROID)
#if defined(OS_LINUX)
case chrome::FILE_COMPONENT_FLASH_HINT:
if (!PathService::Get(chrome::DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN,
&cur)) {
return false;
}
cur = cur.Append(kComponentUpdatedFlashHint);
break;
#endif // defined(OS_LINUX)
default:
return false;
}
// TODO(bauerb): http://crbug.com/259796
base::ThreadRestrictions::ScopedAllowIO allow_io;
if (create_dir && !base::PathExists(cur) &&
!base::CreateDirectory(cur))
return false;
*result = cur;
return true;
}
// This cannot be done as a static initializer sadly since Visual Studio will
// eliminate this object file if there is no direct entry point into it.
void RegisterPathProvider() {
PathService::RegisterProvider(PathProvider, PATH_START, PATH_END);
}
void SetInvalidSpecifiedUserDataDir(const base::FilePath& user_data_dir) {
g_invalid_specified_user_data_dir.Get() = user_data_dir;
}
const base::FilePath& GetInvalidSpecifiedUserDataDir() {
return g_invalid_specified_user_data_dir.Get();
}
} // namespace chrome

View file

@ -0,0 +1,152 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_COMMON_CHROME_PATHS_H__
#define CHROME_COMMON_CHROME_PATHS_H__
#include "build/build_config.h"
namespace base {
class FilePath;
}
// This file declares path keys for the chrome module. These can be used with
// the PathService to access various special directories and files.
namespace chrome {
enum {
PATH_START = 1000,
DIR_APP = PATH_START, // Directory where dlls and data reside.
DIR_LOGS, // Directory where logs should be written.
DIR_USER_DATA, // Directory where user data can be written.
DIR_CRASH_DUMPS, // Directory where crash dumps are written.
#if defined(OS_WIN)
DIR_WATCHER_DATA, // Directory where the Chrome watcher stores
// data.
#endif
DIR_RESOURCES, // Directory containing separate file resources
// used by Chrome at runtime.
DIR_INSPECTOR, // Directory where web inspector is located.
DIR_APP_DICTIONARIES, // Directory where the global dictionaries are.
DIR_USER_DOCUMENTS, // Directory for a user's "My Documents".
DIR_USER_MUSIC, // Directory for a user's music.
DIR_USER_PICTURES, // Directory for a user's pictures.
DIR_USER_VIDEOS, // Directory for a user's videos.
DIR_DEFAULT_DOWNLOADS_SAFE, // Directory for a user's
// "My Documents/Downloads", (Windows) or
// "Downloads". (Linux)
DIR_DEFAULT_DOWNLOADS, // Directory for a user's downloads.
DIR_INTERNAL_PLUGINS, // Directory where internal plugins reside.
#if defined(OS_POSIX) && !defined(OS_MACOSX)
DIR_POLICY_FILES, // Directory for system-wide read-only
// policy files that allow sys-admins
// to set policies for chrome. This directory
// contains subdirectories.
#endif
#if defined(OS_MACOSX) && !defined(OS_IOS)
DIR_USER_APPLICATIONS, // ~/Applications
DIR_USER_LIBRARY, // ~/Library
#endif
#if defined(OS_CHROMEOS) || (defined(OS_LINUX) && defined(CHROMIUM_BUILD)) || \
(defined(OS_MACOSX) && !defined(OS_IOS))
DIR_USER_EXTERNAL_EXTENSIONS, // Directory for per-user external extensions
// on Chrome Mac and Chromium Linux.
// On Chrome OS, this path is used for OEM
// customization. Getting this path does not
// create it.
#endif
#if defined(OS_LINUX)
DIR_STANDALONE_EXTERNAL_EXTENSIONS, // Directory for 'per-extension'
// definition manifest files that
// describe extensions which are to be
// installed when chrome is run.
#endif
DIR_EXTERNAL_EXTENSIONS, // Directory where installer places .crx files.
DIR_DEFAULT_APPS, // Directory where installer places .crx files
// to be installed when chrome is first run.
DIR_PEPPER_FLASH_PLUGIN, // Directory to the bundled Pepper Flash plugin,
// containing the plugin and the manifest.
DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN, // Base directory of the Pepper
// Flash plugins downloaded by the
// component updater.
FILE_RESOURCE_MODULE, // Full path and filename of the module that
// contains embedded resources (version,
// strings, images, etc.).
FILE_LOCAL_STATE, // Path and filename to the file in which
// machine/installation-specific state is saved.
FILE_RECORDED_SCRIPT, // Full path to the script.log file that
// contains recorded browser events for
// playback.
FILE_PEPPER_FLASH_PLUGIN, // Full path to the bundled Pepper Flash plugin
// file.
FILE_PEPPER_FLASH_SYSTEM_PLUGIN, // Full path to the system version of the
// Pepper Flash plugin, downloadable from
// Adobe website. Querying this path might
// succeed no matter the file exists or not.
FILE_FLASH_SYSTEM_PLUGIN, // Full path to the system version of NPAPI
// Flash plugin, downloadable from Adobe
// website. Querying this path might succeed no
// matter the file exists or not.
FILE_NACL_PLUGIN, // Full path to the internal NaCl plugin file.
DIR_PNACL_BASE, // Full path to the base dir for PNaCl.
DIR_PNACL_COMPONENT, // Full path to the latest PNaCl version
// (subdir of DIR_PNACL_BASE).
DIR_COMPONENT_WIDEVINE_CDM, // Directory that contains component-updated
// Widevine CDM files.
FILE_WIDEVINE_CDM_ADAPTER, // Full path to the Widevine CDM adapter file.
FILE_RESOURCES_PACK, // Full path to the .pak file containing
// binary data (e.g., html files and images
// used by internal pages).
DIR_RESOURCES_EXTENSION, // Full path to extension resources.
#if defined(OS_CHROMEOS)
DIR_CHROMEOS_WALLPAPERS, // Directory where downloaded chromeos
// wallpapers reside.
DIR_CHROMEOS_WALLPAPER_THUMBNAILS, // Directory where downloaded chromeos
// wallpaper thumbnails reside.
DIR_CHROMEOS_CUSTOM_WALLPAPERS, // Directory where custom wallpapers
// reside.
#endif
DIR_SUPERVISED_USERS_DEFAULT_APPS, // Directory where installer places .crx
// files to be installed when managed user
// session starts.
DIR_SUPERVISED_USER_INSTALLED_WHITELISTS, // Directory where sanitized
// supervised user whitelists are
// installed.
#if defined(OS_LINUX) || (defined(OS_MACOSX) && !defined(OS_IOS))
DIR_NATIVE_MESSAGING, // System directory where native messaging host
// manifest files are stored.
DIR_USER_NATIVE_MESSAGING, // Directory with Native Messaging Hosts
// installed per-user.
#endif
#if !defined(OS_ANDROID)
DIR_GLOBAL_GCM_STORE, // Directory where the global GCM instance
// stores its data.
#endif
// Valid only in development environment; TODO(darin): move these
DIR_GEN_TEST_DATA, // Directory where generated test data resides.
DIR_TEST_DATA, // Directory where unit test data resides.
DIR_TEST_TOOLS, // Directory where unit test tools reside.
#if defined(OS_LINUX)
FILE_COMPONENT_FLASH_HINT, // A file in a known location that points to
// the component updated flash plugin.
#endif // defined(OS_LINUX)
PATH_END
};
// Call once to register the provider for the path keys defined above.
void RegisterPathProvider();
// Get or set the invalid user data dir that was originally specified.
void SetInvalidSpecifiedUserDataDir(const base::FilePath& user_data_dir);
const base::FilePath& GetInvalidSpecifiedUserDataDir();
} // namespace chrome
#endif // CHROME_COMMON_CHROME_PATHS_H__

View file

@ -0,0 +1,112 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_COMMON_CHROME_PATHS_INTERNAL_H_
#define CHROME_COMMON_CHROME_PATHS_INTERNAL_H_
#include <string>
#include "build/build_config.h"
#if defined(OS_MACOSX)
#if defined(__OBJC__)
@class NSBundle;
#else
class NSBundle;
#endif
#endif
namespace base {
class FilePath;
}
namespace chrome {
// Get the path to the user's data directory, regardless of whether
// DIR_USER_DATA has been overridden by a command-line option.
bool GetDefaultUserDataDirectory(base::FilePath* result);
// Get the path to the user's cache directory. This is normally the
// same as the profile directory, but on Linux it can also be
// $XDG_CACHE_HOME and on Mac it can be under ~/Library/Caches.
// Note that the Chrome cache directories are actually subdirectories
// of this directory, with names like "Cache" and "Media Cache".
// This will always fill in |result| with a directory, sometimes
// just |profile_dir|.
void GetUserCacheDirectory(const base::FilePath& profile_dir, base::FilePath* result);
// Get the path to the user's documents directory.
bool GetUserDocumentsDirectory(base::FilePath* result);
#if defined(OS_WIN) || defined(OS_LINUX)
// Gets the path to a safe default download directory for a user.
bool GetUserDownloadsDirectorySafe(base::FilePath* result);
#endif
// Get the path to the user's downloads directory.
bool GetUserDownloadsDirectory(base::FilePath* result);
// Gets the path to the user's music directory.
bool GetUserMusicDirectory(base::FilePath* result);
// Gets the path to the user's pictures directory.
bool GetUserPicturesDirectory(base::FilePath* result);
// Gets the path to the user's videos directory.
bool GetUserVideosDirectory(base::FilePath* result);
#if defined(OS_MACOSX) && !defined(OS_IOS)
// The "versioned directory" is a directory in the browser .app bundle. It
// contains the bulk of the application, except for the things that the system
// requires be located at spepcific locations. The versioned directory is
// in the .app at Contents/Versions/w.x.y.z.
base::FilePath GetVersionedDirectory();
// This overrides the directory returned by |GetVersionedDirectory()|, to be
// used when |GetVersionedDirectory()| can't automatically determine the proper
// location. This is the case when the browser didn't load itself but by, e.g.,
// the app mode loader. This should be called before |ChromeMain()|. This takes
// ownership of the object |path| and the caller must not delete it.
void SetOverrideVersionedDirectory(const base::FilePath* path);
// Most of the application is further contained within the framework. The
// framework bundle is located within the versioned directory at a specific
// path. The only components in the versioned directory not included in the
// framework are things that also depend on the framework, such as the helper
// app bundle.
base::FilePath GetFrameworkBundlePath();
// Get the local library directory.
bool GetLocalLibraryDirectory(base::FilePath* result);
// Get the user library directory.
bool GetUserLibraryDirectory(base::FilePath* result);
// Get the user applications directory.
bool GetUserApplicationsDirectory(base::FilePath* result);
// Get the global Application Support directory (under /Library/).
bool GetGlobalApplicationSupportDirectory(base::FilePath* result);
// Returns the NSBundle for the outer browser application, even when running
// inside the helper. In unbundled applications, such as tests, returns nil.
NSBundle* OuterAppBundle();
// Get the user data directory for the Chrome browser bundle at |bundle|.
// |bundle| should be the same value that would be returned from +[NSBundle
// mainBundle] if Chrome were launched normaly. This is used by app shims,
// which run from a bundle which isn't Chrome itself, but which need access to
// the user data directory to connect to a UNIX-domain socket therein.
// Returns false if there was a problem fetching the app data directory.
bool GetUserDataDirectoryForBrowserBundle(NSBundle* bundle,
base::FilePath* result);
#endif // OS_MACOSX && !OS_IOS
// Checks if the |process_type| has the rights to access the profile.
bool ProcessNeedsProfileDir(const std::string& process_type);
} // namespace chrome
#endif // CHROME_COMMON_CHROME_PATHS_INTERNAL_H_

View file

@ -0,0 +1,145 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/common/chrome_paths_internal.h"
#include "base/base_paths.h"
#include "base/environment.h"
#include "base/files/file_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/nix/xdg_util.h"
#include "base/path_service.h"
#include "chrome/common/chrome_paths.h"
namespace chrome {
using base::nix::GetXDGDirectory;
using base::nix::GetXDGUserDirectory;
using base::nix::kDotConfigDir;
using base::nix::kXdgConfigHomeEnvVar;
namespace {
const char kDownloadsDir[] = "Downloads";
const char kMusicDir[] = "Music";
const char kPicturesDir[] = "Pictures";
const char kVideosDir[] = "Videos";
// Generic function for GetUser{Music,Pictures,Video}Directory.
bool GetUserMediaDirectory(const std::string& xdg_name,
const std::string& fallback_name,
base::FilePath* result) {
#if defined(OS_CHROMEOS)
// No local media directories on CrOS.
return false;
#else
*result = GetXDGUserDirectory(xdg_name.c_str(), fallback_name.c_str());
base::FilePath home;
PathService::Get(base::DIR_HOME, &home);
if (*result != home) {
base::FilePath desktop;
if (!PathService::Get(base::DIR_USER_DESKTOP, &desktop))
return false;
if (*result != desktop) {
return true;
}
}
*result = home.Append(fallback_name);
return true;
#endif
}
} // namespace
// See http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
// for a spec on where config files go. The net effect for most
// systems is we use ~/.config/chromium/ for Chromium and
// ~/.config/google-chrome/ for official builds.
// (This also helps us sidestep issues with other apps grabbing ~/.chromium .)
bool GetDefaultUserDataDirectory(base::FilePath* result) {
scoped_ptr<base::Environment> env(base::Environment::Create());
base::FilePath config_dir(GetXDGDirectory(env.get(),
kXdgConfigHomeEnvVar,
kDotConfigDir));
#if defined(GOOGLE_CHROME_BUILD)
*result = config_dir.Append("google-chrome");
#else
*result = config_dir.Append("chromium");
#endif
return true;
}
void GetUserCacheDirectory(const base::FilePath& profile_dir,
base::FilePath* result) {
// See http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
// for a spec on where cache files go. Our rule is:
// - if the user-data-dir in the standard place,
// use same subdirectory of the cache directory.
// (this maps ~/.config/google-chrome to ~/.cache/google-chrome as well
// as the same thing for ~/.config/chromium)
// - otherwise, use the profile dir directly.
// Default value in cases where any of the following fails.
*result = profile_dir;
scoped_ptr<base::Environment> env(base::Environment::Create());
base::FilePath cache_dir;
if (!PathService::Get(base::DIR_CACHE, &cache_dir))
return;
base::FilePath config_dir(GetXDGDirectory(env.get(),
kXdgConfigHomeEnvVar,
kDotConfigDir));
if (!config_dir.AppendRelativePath(profile_dir, &cache_dir))
return;
*result = cache_dir;
}
bool GetUserDocumentsDirectory(base::FilePath* result) {
*result = GetXDGUserDirectory("DOCUMENTS", "Documents");
return true;
}
bool GetUserDownloadsDirectorySafe(base::FilePath* result) {
base::FilePath home;
PathService::Get(base::DIR_HOME, &home);
*result = home.Append(kDownloadsDir);
return true;
}
bool GetUserDownloadsDirectory(base::FilePath* result) {
*result = GetXDGUserDirectory("DOWNLOAD", kDownloadsDir);
return true;
}
// We respect the user's preferred pictures location, unless it is
// ~ or their desktop directory, in which case we default to ~/Music.
bool GetUserMusicDirectory(base::FilePath* result) {
return GetUserMediaDirectory("MUSIC", kMusicDir, result);
}
// We respect the user's preferred pictures location, unless it is
// ~ or their desktop directory, in which case we default to ~/Pictures.
bool GetUserPicturesDirectory(base::FilePath* result) {
return GetUserMediaDirectory("PICTURES", kPicturesDir, result);
}
// We respect the user's preferred pictures location, unless it is
// ~ or their desktop directory, in which case we default to ~/Videos.
bool GetUserVideosDirectory(base::FilePath* result) {
return GetUserMediaDirectory("VIDEOS", kVideosDir, result);
}
bool ProcessNeedsProfileDir(const std::string& process_type) {
// For now we have no reason to forbid this on Linux as we don't
// have the roaming profile troubles there. Moreover the Linux breakpad needs
// profile dir access in all process if enabled on Linux.
return true;
}
} // namespace chrome

View file

@ -0,0 +1,251 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/common/chrome_paths_internal.h"
#import <Foundation/Foundation.h>
#include <string.h>
#include <string>
#include "base/base_paths.h"
#include "base/logging.h"
#import "base/mac/foundation_util.h"
#import "base/mac/scoped_nsautorelease_pool.h"
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
#include "chrome/common/chrome_constants.h"
namespace {
#if !defined(OS_IOS)
const base::FilePath* g_override_versioned_directory = NULL;
// Return a retained (NOT autoreleased) NSBundle* as the internal
// implementation of chrome::OuterAppBundle(), which should be the only
// caller.
NSBundle* OuterAppBundleInternal() {
base::mac::ScopedNSAutoreleasePool pool;
if (!base::mac::AmIBundled()) {
// If unbundled (as in a test), there's no app bundle.
return nil;
}
if (!base::mac::IsBackgroundOnlyProcess()) {
// Shortcut: in the browser process, just return the main app bundle.
return [[NSBundle mainBundle] retain];
}
// From C.app/Contents/Versions/1.2.3.4, go up three steps to get to C.app.
base::FilePath versioned_dir = chrome::GetVersionedDirectory();
base::FilePath outer_app_dir = versioned_dir.DirName().DirName().DirName();
const char* outer_app_dir_c = outer_app_dir.value().c_str();
NSString* outer_app_dir_ns = [NSString stringWithUTF8String:outer_app_dir_c];
return [[NSBundle bundleWithPath:outer_app_dir_ns] retain];
}
#endif // !defined(OS_IOS)
char* ProductDirNameForBundle(NSBundle* chrome_bundle) {
const char* product_dir_name = NULL;
#if !defined(OS_IOS)
base::mac::ScopedNSAutoreleasePool pool;
NSString* product_dir_name_ns =
[chrome_bundle objectForInfoDictionaryKey:@"CrProductDirName"];
product_dir_name = [product_dir_name_ns fileSystemRepresentation];
#else
DCHECK(!chrome_bundle);
#endif
if (!product_dir_name) {
#if defined(GOOGLE_CHROME_BUILD)
product_dir_name = "Google/Chrome";
#else
product_dir_name = "Chromium";
#endif
}
// Leaked, but the only caller initializes a static with this result, so it
// only happens once, and that's OK.
return strdup(product_dir_name);
}
// ProductDirName returns the name of the directory inside
// ~/Library/Application Support that should hold the product application
// data. This can be overridden by setting the CrProductDirName key in the
// outer browser .app's Info.plist. The default is "Google/Chrome" for
// officially-branded builds, and "Chromium" for unbranded builds. For the
// official canary channel, the Info.plist will have CrProductDirName set
// to "Google/Chrome Canary".
std::string ProductDirName() {
#if defined(OS_IOS)
static const char* product_dir_name = ProductDirNameForBundle(nil);
#else
// Use OuterAppBundle() to get the main app's bundle. This key needs to live
// in the main app's bundle because it will be set differently on the canary
// channel, and the autoupdate system dictates that there can be no
// differences between channels within the versioned directory. This would
// normally use base::mac::FrameworkBundle(), but that references the
// framework bundle within the versioned directory. Ordinarily, the profile
// should not be accessed from non-browser processes, but those processes do
// attempt to get the profile directory, so direct them to look in the outer
// browser .app's Info.plist for the CrProductDirName key.
static const char* product_dir_name =
ProductDirNameForBundle(chrome::OuterAppBundle());
#endif
return std::string(product_dir_name);
}
bool GetDefaultUserDataDirectoryForProduct(const std::string& product_dir,
base::FilePath* result) {
bool success = false;
if (result && PathService::Get(base::DIR_APP_DATA, result)) {
*result = result->Append(product_dir);
success = true;
}
return success;
}
} // namespace
namespace chrome {
bool GetDefaultUserDataDirectory(base::FilePath* result) {
return GetDefaultUserDataDirectoryForProduct(ProductDirName(), result);
}
bool GetUserDocumentsDirectory(base::FilePath* result) {
return base::mac::GetUserDirectory(NSDocumentDirectory, result);
}
void GetUserCacheDirectory(const base::FilePath& profile_dir,
base::FilePath* result) {
// If the profile directory is under ~/Library/Application Support,
// use a suitable cache directory under ~/Library/Caches. For
// example, a profile directory of ~/Library/Application
// Support/Google/Chrome/MyProfileName would use the cache directory
// ~/Library/Caches/Google/Chrome/MyProfileName.
// Default value in cases where any of the following fails.
*result = profile_dir;
base::FilePath app_data_dir;
if (!PathService::Get(base::DIR_APP_DATA, &app_data_dir))
return;
base::FilePath cache_dir;
if (!PathService::Get(base::DIR_CACHE, &cache_dir))
return;
if (!app_data_dir.AppendRelativePath(profile_dir, &cache_dir))
return;
*result = cache_dir;
}
bool GetUserDownloadsDirectory(base::FilePath* result) {
return base::mac::GetUserDirectory(NSDownloadsDirectory, result);
}
bool GetUserMusicDirectory(base::FilePath* result) {
return base::mac::GetUserDirectory(NSMusicDirectory, result);
}
bool GetUserPicturesDirectory(base::FilePath* result) {
return base::mac::GetUserDirectory(NSPicturesDirectory, result);
}
bool GetUserVideosDirectory(base::FilePath* result) {
return base::mac::GetUserDirectory(NSMoviesDirectory, result);
}
#if !defined(OS_IOS)
base::FilePath GetVersionedDirectory() {
if (g_override_versioned_directory)
return *g_override_versioned_directory;
// Start out with the path to the running executable.
base::FilePath path;
PathService::Get(base::FILE_EXE, &path);
// One step up to MacOS, another to Contents.
path = path.DirName().DirName();
DCHECK_EQ(path.BaseName().value(), "Contents");
if (base::mac::IsBackgroundOnlyProcess()) {
// path identifies the helper .app's Contents directory in the browser
// .app's versioned directory. Go up two steps to get to the browser
// .app's versioned directory.
path = path.DirName().DirName();
} else {
// Go into the versioned directory.
path = path.Append("Frameworks");
}
return path;
}
void SetOverrideVersionedDirectory(const base::FilePath* path) {
if (path != g_override_versioned_directory) {
delete g_override_versioned_directory;
g_override_versioned_directory = path;
}
}
base::FilePath GetFrameworkBundlePath() {
// It's tempting to use +[NSBundle bundleWithIdentifier:], but it's really
// slow (about 30ms on 10.5 and 10.6), despite Apple's documentation stating
// that it may be more efficient than +bundleForClass:. +bundleForClass:
// itself takes 1-2ms. Getting an NSBundle from a path, on the other hand,
// essentially takes no time at all, at least when the bundle has already
// been loaded as it will have been in this case. The FilePath operations
// needed to compute the framework's path are also effectively free, so that
// is the approach that is used here. NSBundle is also documented as being
// not thread-safe, and thread safety may be a concern here.
// The framework bundle is at a known path and name from the browser .app's
// versioned directory.
return GetVersionedDirectory().Append(kFrameworkName);
}
bool GetLocalLibraryDirectory(base::FilePath* result) {
return base::mac::GetLocalDirectory(NSLibraryDirectory, result);
}
bool GetUserLibraryDirectory(base::FilePath* result) {
return base::mac::GetUserDirectory(NSLibraryDirectory, result);
}
bool GetUserApplicationsDirectory(base::FilePath* result) {
return base::mac::GetUserDirectory(NSApplicationDirectory, result);
}
bool GetGlobalApplicationSupportDirectory(base::FilePath* result) {
return base::mac::GetLocalDirectory(NSApplicationSupportDirectory, result);
}
NSBundle* OuterAppBundle() {
// Cache this. Foundation leaks it anyway, and this should be the only call
// to OuterAppBundleInternal().
static NSBundle* bundle = OuterAppBundleInternal();
return bundle;
}
bool GetUserDataDirectoryForBrowserBundle(NSBundle* bundle,
base::FilePath* result) {
scoped_ptr<char, base::FreeDeleter>
product_dir_name(ProductDirNameForBundle(bundle));
return GetDefaultUserDataDirectoryForProduct(product_dir_name.get(), result);
}
#endif // !defined(OS_IOS)
bool ProcessNeedsProfileDir(const std::string& process_type) {
// For now we have no reason to forbid this on other MacOS as we don't
// have the roaming profile troubles there.
return true;
}
} // namespace chrome

View file

@ -0,0 +1,107 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/common/chrome_paths_internal.h"
#include <windows.h>
#include <knownfolders.h>
#include <shellapi.h>
#include <shlobj.h>
#include <shobjidl.h>
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "base/win/metro.h"
#include "base/win/scoped_co_mem.h"
#include "chrome/common/chrome_constants.h"
namespace chrome {
namespace {
// Generic function to call SHGetFolderPath().
bool GetUserDirectory(int csidl_folder, base::FilePath* result) {
// We need to go compute the value. It would be nice to support paths
// with names longer than MAX_PATH, but the system functions don't seem
// to be designed for it either, with the exception of GetTempPath
// (but other things will surely break if the temp path is too long,
// so we don't bother handling it.
wchar_t path_buf[MAX_PATH];
path_buf[0] = 0;
if (FAILED(SHGetFolderPath(NULL, csidl_folder, NULL,
SHGFP_TYPE_CURRENT, path_buf))) {
return false;
}
*result = base::FilePath(path_buf);
return true;
}
} // namespace
bool GetDefaultUserDataDirectory(base::FilePath* result) {
return PathService::Get(base::DIR_LOCAL_APP_DATA, result);
}
void GetUserCacheDirectory(const base::FilePath& profile_dir,
base::FilePath* result) {
// This function does more complicated things on Mac/Linux.
*result = profile_dir;
}
bool GetUserDocumentsDirectory(base::FilePath* result) {
return GetUserDirectory(CSIDL_MYDOCUMENTS, result);
}
// Return a default path for downloads that is safe.
// We just use 'Downloads' under DIR_USER_DOCUMENTS. Localizing
// 'downloads' is not a good idea because Chrome's UI language
// can be changed.
bool GetUserDownloadsDirectorySafe(base::FilePath* result) {
if (!GetUserDocumentsDirectory(result))
return false;
*result = result->Append(L"Downloads");
return true;
}
// On Vista and higher, use the downloads known folder. Since it can be
// relocated to point to a "dangerous" folder, callers should validate that the
// returned path is not dangerous before using it.
bool GetUserDownloadsDirectory(base::FilePath* result) {
typedef HRESULT (WINAPI *GetKnownFolderPath)(
REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR*);
GetKnownFolderPath f = reinterpret_cast<GetKnownFolderPath>(
GetProcAddress(GetModuleHandle(L"shell32.dll"), "SHGetKnownFolderPath"));
base::win::ScopedCoMem<wchar_t> path_buf;
if (f && SUCCEEDED(f(FOLDERID_Downloads, 0, NULL, &path_buf))) {
*result = base::FilePath(std::wstring(path_buf));
return true;
}
return GetUserDownloadsDirectorySafe(result);
}
bool GetUserMusicDirectory(base::FilePath* result) {
return GetUserDirectory(CSIDL_MYMUSIC, result);
}
bool GetUserPicturesDirectory(base::FilePath* result) {
return GetUserDirectory(CSIDL_MYPICTURES, result);
}
bool GetUserVideosDirectory(base::FilePath* result) {
return GetUserDirectory(CSIDL_MYVIDEO, result);
}
bool ProcessNeedsProfileDir(const std::string& process_type) {
// On windows we don't want subprocesses other than the browser process and
// service processes to be able to use the profile directory because if it
// lies on a network share the sandbox will prevent us from accessing it.
if (process_type.empty())
return true;
return false;
}
} // namespace chrome

View file

@ -34,6 +34,10 @@ HTTP 요청 캐시를 비활성화 합니다.
시스템 설정의 프록시 서버를 무시하고 지정한 서버로 연결합니다. HTTP와 HTTPS 요청에만 적용됩니다. 시스템 설정의 프록시 서버를 무시하고 지정한 서버로 연결합니다. HTTP와 HTTPS 요청에만 적용됩니다.
시스템 프록시 서버 설정을 무시하고 지정한 서버로 연결합니다.
이 스위치는 HTTP와 HTTPS 그리고 WebSocket 요청에만 적용됩니다.
그리고 모든 프록시 서버가 HTTPS가 WebSocket 요청을 지원하지 않고 있을 수 있으므로 사용시 주의해야 합니다.
## --proxy-pac-url=`url` ## --proxy-pac-url=`url`
지정한 `url`의 PAC 스크립트를 사용합니다. 지정한 `url`의 PAC 스크립트를 사용합니다.

View file

@ -107,6 +107,10 @@ __주의:__ `bounds`는 OS X 와 Windows에서만 작동합니다.
알림풍선이 시간이 지나 사라지거나 유저가 클릭하여 닫을 때 발생하는 이벤트입니다. 알림풍선이 시간이 지나 사라지거나 유저가 클릭하여 닫을 때 발생하는 이벤트입니다.
### Event: 'drop' _OS X_
드래그 가능한 아이템이 트레이 아이콘에 드롭되면 발생하는 이벤트입니다.
### Event: 'drop-files' _OS X_ ### Event: 'drop-files' _OS X_
* `event` * `event`
@ -114,6 +118,18 @@ __주의:__ `bounds`는 OS X 와 Windows에서만 작동합니다.
트레이 아이콘에 파일이 드롭되면 발생하는 이벤트입니다. 트레이 아이콘에 파일이 드롭되면 발생하는 이벤트입니다.
### Event: 'drag-enter' _OS X_
트레이 아이콘에 드래그 작업이 시작될 때 발생하는 이벤트입니다.
### Event: 'drag-leave' _OS X_
트레이 아이콘에 드래그 작업이 종료될 때 발생하는 이벤트입니다.
### Event: 'drag-end' _OS X_
트레이 아이콘에 드래그 작업이 종료되거나 다른 위치에서 종료될 때 발생하는 이벤트입니다.
## Methods ## Methods
`Tray` 모듈은 다음과 같은 메서드를 가지고 있습니다: `Tray` 모듈은 다음과 같은 메서드를 가지고 있습니다:

View file

@ -44,9 +44,12 @@ var webdriver = require('selenium-webdriver');
var driver = new webdriver.Builder() var driver = new webdriver.Builder()
// 작동하고 있는 크롬 드라이버의 포트 "9515"를 사용합니다. // 작동하고 있는 크롬 드라이버의 포트 "9515"를 사용합니다.
.usingServer('http://localhost:9515') .usingServer('http://localhost:9515')
.withCapabilities({chromeOptions: { .withCapabilities({
// 여기에 사용중인 Electron 바이너리의 경로를 지정하세요. chromeOptions: {
binary: '/Path-to-Your-App.app/Contents/MacOS/Atom'}}) // 여기에 사용중인 Electron 바이너리의 경로를 지정하세요.
binary: '/Path-to-Your-App.app/Contents/MacOS/Atom',
}
})
.forBrowser('electron') .forBrowser('electron')
.build(); .build();
@ -92,7 +95,10 @@ var options = {
port: 9515, // 연결할 크롬 드라이버 서버의 포트를 설정합니다. port: 9515, // 연결할 크롬 드라이버 서버의 포트를 설정합니다.
desiredCapabilities: { desiredCapabilities: {
browserName: 'chrome', browserName: 'chrome',
chromeOptions: {binary: '/Path-to-Your-App.app/Electron'} // Electron 바이너리의 위치 chromeOptions: {
binary: '/Path-to-Your-App/electron', // Electron 바이너리 경로
args: [/* cli arguments */] // 선택 사항, 'app=' + /path/to/your/app/
}
} }
}; };
@ -109,9 +115,12 @@ client
.end(); .end();
``` ```
## 작업환경 ## 작업 환경
따로 Electron을 다시 빌드하지 않는 경우 간단히 어플리케이션을 Electron의 리소스 디렉터리에 따로 Electron을 다시 빌드하지 않는 경우 간단히 어플리케이션을 Electron의 리소스 디렉터리에
[배치](application-distribution.md)하여 바로 테스트 할 수 있습니다. [배치](application-distribution.md)하여 바로 테스트 할 수 있습니다.
또한, Electron 바이너리의 명령줄 인수에 어플리케이션 폴더를 지정하는 방법으로 실행할 수도 있습니다.
이 방법을 사용하면 어플리케이션 폴더를 Electron의 `resource` 디렉터리로 복사하는 불필요한 과정을 생략할 수 있습니다.
[chrome-driver]: https://sites.google.com/a/chromium.org/chromedriver/ [chrome-driver]: https://sites.google.com/a/chromium.org/chromedriver/

View file

@ -31,32 +31,32 @@
### Modules for the Main Process: ### Modules for the Main Process:
* [app](api/app.md) * [app](api/app.md)
* [auto-updater](api/auto-updater.md) * [autoUpdater](api/auto-updater.md)
* [browser-window](api/browser-window.md) * [BrowserWindow](api/browser-window.md)
* [content-tracing](api/content-tracing.md) * [contentTracing](api/content-tracing.md)
* [dialog](api/dialog.md) * [dialog](api/dialog.md)
* [global-shortcut](api/global-shortcut.md) * [globalShortcut](api/global-shortcut.md)
* [ipc-main](api/ipc-main.md) * [ipcMain](api/ipc-main.md)
* [menu](api/menu.md) * [Menu](api/menu.md)
* [menu-item](api/menu-item.md) * [MenuItem](api/menu-item.md)
* [power-monitor](api/power-monitor.md) * [powerMonitor](api/power-monitor.md)
* [power-save-blocker](api/power-save-blocker.md) * [powerSaveBlocker](api/power-save-blocker.md)
* [protocol](api/protocol.md) * [protocol](api/protocol.md)
* [session](api/session.md) * [session](api/session.md)
* [web-contents](api/web-contents.md) * [webContents](api/web-contents.md)
* [tray](api/tray.md) * [Tray](api/tray.md)
### Modules for the Renderer Process (Web Page): ### Modules for the Renderer Process (Web Page):
* [ipc-renderer](api/ipc-renderer.md) * [ipcRenderer](api/ipc-renderer.md)
* [remote](api/remote.md) * [remote](api/remote.md)
* [web-frame](api/web-frame.md) * [webFrame](api/web-frame.md)
### Modules for Both Processes: ### Modules for Both Processes:
* [clipboard](api/clipboard.md) * [clipboard](api/clipboard.md)
* [crash-reporter](api/crash-reporter.md) * [crashReporter](api/crash-reporter.md)
* [native-image](api/native-image.md) * [nativeImage](api/native-image.md)
* [screen](api/screen.md) * [screen](api/screen.md)
* [shell](api/shell.md) * [shell](api/shell.md)

View file

@ -6,7 +6,7 @@ The following example shows how to quit the application when the last window is
closed: closed:
```javascript ```javascript
var app = require('app'); const app = require('electron').app;
app.on('window-all-closed', function() { app.on('window-all-closed', function() {
app.quit(); app.quit();
}); });
@ -238,9 +238,14 @@ You can request the following paths by the name:
* `userData` The directory for storing your app's configuration files, which by * `userData` The directory for storing your app's configuration files, which by
default it is the `appData` directory appended with your app's name. default it is the `appData` directory appended with your app's name.
* `temp` Temporary directory. * `temp` Temporary directory.
* `userDesktop` The current user's Desktop directory.
* `exe` The current executable file. * `exe` The current executable file.
* `module` The `libchromiumcontent` library. * `module` The `libchromiumcontent` library.
* `desktop` The current user's Desktop directory.
* `documents` Directory for a user's "My Documents".
* `downloads` Directory for a user's downloads.
* `music` Directory for a user's music.
* `pictures` Directory for a user's pictures.
* `videos` Directory for a user's videos.
### `app.setPath(name, path)` ### `app.setPath(name, path)`

View file

@ -67,7 +67,7 @@ Returns:
* `releaseNotes` String * `releaseNotes` String
* `releaseName` String * `releaseName` String
* `releaseDate` Date * `releaseDate` Date
* `updateUrl` String * `updateURL` String
Emitted when an update has been downloaded. Emitted when an update has been downloaded.
@ -77,7 +77,7 @@ On Windows only `releaseName` is available.
The `autoUpdater` object has the following methods: The `autoUpdater` object has the following methods:
### `autoUpdater.setFeedUrl(url)` ### `autoUpdater.setFeedURL(url)`
* `url` String * `url` String
@ -86,7 +86,7 @@ once it is set.
### `autoUpdater.checkForUpdates()` ### `autoUpdater.checkForUpdates()`
Asks the server whether there is an update. You must call `setFeedUrl` before Asks the server whether there is an update. You must call `setFeedURL` before
using this API. using this API.
### `autoUpdater.quitAndInstall()` ### `autoUpdater.quitAndInstall()`

View file

@ -4,14 +4,14 @@ The `BrowserWindow` class gives you the ability to create a browser window. For
example: example:
```javascript ```javascript
var BrowserWindow = require('browser-window'); const BrowserWindow = require('electron').BrowserWindow;
var win = new BrowserWindow({ width: 800, height: 600, show: false }); var win = new BrowserWindow({ width: 800, height: 600, show: false });
win.on('closed', function() { win.on('closed', function() {
win = null; win = null;
}); });
win.loadUrl('https://github.com'); win.loadURL('https://github.com');
win.show(); win.show();
``` ```
@ -291,11 +291,8 @@ Remove the DevTools extension whose name is `name`.
Objects created with `new BrowserWindow` have the following properties: Objects created with `new BrowserWindow` have the following properties:
```javascript ```javascript
var BrowserWindow = require('browser-window');
// In this example `win` is our instance // In this example `win` is our instance
var win = new BrowserWindow({ width: 800, height: 600 }); var win = new BrowserWindow({ width: 800, height: 600 });
``` ```
### `win.webContents` ### `win.webContents`
@ -316,14 +313,6 @@ Objects created with `new BrowserWindow` have the following instance methods:
**Note:** Some methods are only available on specific operating systems and are labeled as such. **Note:** Some methods are only available on specific operating systems and are labeled as such.
```javascript
var BrowserWindow = require('browser-window');
// In this example `win` is our instance
var win = new BrowserWindow({ width: 800, height: 600 });
```
### `win.destroy()` ### `win.destroy()`
Force closing the window, the `unload` and `beforeunload` event won't be emitted Force closing the window, the `unload` and `beforeunload` event won't be emitted
@ -624,9 +613,9 @@ Same as `webContents.print([options])`
Same as `webContents.printToPDF(options, callback)` Same as `webContents.printToPDF(options, callback)`
### `win.loadUrl(url[, options])` ### `win.loadURL(url[, options])`
Same as `webContents.loadUrl(url[, options])`. Same as `webContents.loadURL(url[, options])`.
### `win.reload()` ### `win.reload()`

View file

@ -6,7 +6,7 @@ them in your app's main script before the [ready][ready] event of [app][app]
module is emitted: module is emitted:
```javascript ```javascript
var app = require('app'); const app = require('electron').app;
app.commandLine.appendSwitch('remote-debugging-port', '8315'); app.commandLine.appendSwitch('remote-debugging-port', '8315');
app.commandLine.appendSwitch('host-rules', 'MAP * 127.0.0.1'); app.commandLine.appendSwitch('host-rules', 'MAP * 127.0.0.1');
@ -31,6 +31,15 @@ Disables the disk cache for HTTP requests.
Enables remote debugging over HTTP on the specified `port`. Enables remote debugging over HTTP on the specified `port`.
## --js-flags=`flags`
Specifies the flags passed to JS engine. It has to be passed when starting
Electron if you want to enable the `flags` in the main process.
```bash
$ electron --js-flags="--harmony_proxies --harmony_collections" your-app
```
## --proxy-server=`address:port` ## --proxy-server=`address:port`
Use a specified proxy server, which overrides the system setting. This switch Use a specified proxy server, which overrides the system setting. This switch

View file

@ -4,7 +4,7 @@ The `clipboard` module provides methods to perform copy and paste operations.
The following example shows how to write a string to the clipboard: The following example shows how to write a string to the clipboard:
```javascript ```javascript
var clipboard = require('clipboard'); const clipboard = require('electron').clipboard;
clipboard.writeText('Example String'); clipboard.writeText('Example String');
``` ```
@ -12,7 +12,6 @@ On X Window systems, there is also a selection clipboard. To manipulate it
you need to pass `selection` to each method: you need to pass `selection` to each method:
```javascript ```javascript
var clipboard = require('clipboard');
clipboard.writeText('Example String', 'selection'); clipboard.writeText('Example String', 'selection');
console.log(clipboard.readText('selection')); console.log(clipboard.readText('selection'));
``` ```
@ -82,7 +81,6 @@ Returns an array of supported formats for the clipboard `type`.
Returns whether the clipboard supports the format of specified `data`. Returns whether the clipboard supports the format of specified `data`.
```javascript ```javascript
var clipboard = require('clipboard');
console.log(clipboard.has('<p>selection</p>')); console.log(clipboard.has('<p>selection</p>'));
``` ```
@ -102,7 +100,6 @@ Reads `data` from the clipboard.
* `type` String (optional) * `type` String (optional)
```javascript ```javascript
var clipboard = require('clipboard');
clipboard.write({text: 'test', html: "<b>test</b>"}); clipboard.write({text: 'test', html: "<b>test</b>"});
``` ```
Writes `data` to the clipboard. Writes `data` to the clipboard.

View file

@ -6,9 +6,14 @@ so you need to open `chrome://tracing/` in a Chrome browser and load the
generated file to view the result. generated file to view the result.
```javascript ```javascript
var contentTracing = require('content-tracing'); const contentTracing = require('electron').contentTracing;
contentTracing.startRecording('*', contentTracing.DEFAULT_OPTIONS, function() { const options = {
categoryFilter: '*',
traceOptions: 'record-until-full,enable-sampling'
}
contentTracing.startRecording(options, function() {
console.log('Tracing started'); console.log('Tracing started');
setTimeout(function() { setTimeout(function() {

View file

@ -6,12 +6,12 @@ The following is an example of automatically submitting a crash report to a
remote server: remote server:
```javascript ```javascript
var crashReporter = require('crash-reporter'); const crashReporter = require('electron').crashReporter;
crashReporter.start({ crashReporter.start({
productName: 'YourName', productName: 'YourName',
companyName: 'YourCompany', companyName: 'YourCompany',
submitUrl: 'https://your-domain.com/url-to-submit', submitURL: 'https://your-domain.com/url-to-submit',
autoSubmit: true autoSubmit: true
}); });
``` ```
@ -26,7 +26,7 @@ The `crash-reporter` module has the following methods:
* `productName` String, default: Electron. * `productName` String, default: Electron.
* `companyName` String, default: GitHub, Inc. * `companyName` String, default: GitHub, Inc.
* `submitUrl` String, default: http://54.249.141.255:1127/post. * `submitURL` String, default: http://54.249.141.255:1127/post.
* URL that crash reports will be sent to as POST. * URL that crash reports will be sent to as POST.
* `autoSubmit` Boolean, default: `true`. * `autoSubmit` Boolean, default: `true`.
* Send the crash report without user interaction. * Send the crash report without user interaction.
@ -57,12 +57,12 @@ ID.
## crash-reporter Payload ## crash-reporter Payload
The crash reporter will send the following data to the `submitUrl` as `POST`: The crash reporter will send the following data to the `submitURL` as `POST`:
* `ver` String - The version of Electron. * `ver` String - The version of Electron.
* `platform` String - e.g. 'win32'. * `platform` String - e.g. 'win32'.
* `process_type` String - e.g. 'renderer'. * `process_type` String - e.g. 'renderer'.
* `guid` String - e.g. '5e1286fc-da97-479e-918b-6bfb0c3d1c72' * `guid` String - e.g. '5e1286fc-da97-479e-918b-6bfb0c3d1c72'
* `_version` String - The version in `package.json`. * `_version` String - The version in `package.json`.
* `_productName` String - The product name in the `crashReporter` `options` * `_productName` String - The product name in the `crashReporter` `options`
object. object.

View file

@ -8,7 +8,7 @@ An example of showing a dialog to select multiple files and directories:
```javascript ```javascript
var win = ...; // BrowserWindow in which to show the dialog var win = ...; // BrowserWindow in which to show the dialog
var dialog = require('dialog'); const dialog = require('electron').dialog;
console.log(dialog.showOpenDialog({ properties: [ 'openFile', 'openDirectory', 'multiSelections' ]})); console.log(dialog.showOpenDialog({ properties: [ 'openFile', 'openDirectory', 'multiSelections' ]}));
``` ```
@ -114,6 +114,6 @@ will be passed via `callback(response)`.
Displays a modal dialog that shows an error message. Displays a modal dialog that shows an error message.
This API can be called safely before the `ready` event the `app` module emits, This API can be called safely before the `ready` event the `app` module emits,
it is usually used to report errors in early stage of startup. If called it is usually used to report errors in early stage of startup. If called
before the app `ready`event on Linux, the message will be emitted to stderr, before the app `ready`event on Linux, the message will be emitted to stderr,
and no GUI dialog will appear. and no GUI dialog will appear.

View file

@ -66,7 +66,7 @@ Resumes the download that has been paused.
Cancels the download operation. Cancels the download operation.
### `downloadItem.getUrl()` ### `downloadItem.getURL()`
Returns a `String` represents the origin url where the item is downloaded from. Returns a `String` represents the origin url where the item is downloaded from.

View file

@ -9,7 +9,7 @@ To create a frameless window, you need to set `frame` to `false` in
```javascript ```javascript
var BrowserWindow = require('browser-window'); const BrowserWindow = require('electron').BrowserWindow;
var win = new BrowserWindow({ width: 800, height: 600, frame: false }); var win = new BrowserWindow({ width: 800, height: 600, frame: false });
``` ```
@ -23,8 +23,7 @@ the window controls ("traffic lights") for standard window actions.
You can do so by specifying the new `title-bar-style` option: You can do so by specifying the new `title-bar-style` option:
```javascript ```javascript
var BrowserWindow = require('browser-window'); var win = new BrowserWindow({ 'title-bar-style': 'hidden' });
var win = new BrowserWindow({ width: 800, height: 600, 'title-bar-style': 'hidden' });
``` ```
## Transparent window ## Transparent window

View file

@ -9,8 +9,9 @@ not have the keyboard focus. You should not use this module until the `ready`
event of the app module is emitted. event of the app module is emitted.
```javascript ```javascript
var app = require('app'); const electron = require('electron');
var globalShortcut = require('global-shortcut'); const app = electron.app;
const globalShortcut = electron.globalShortcut;
app.on('ready', function() { app.on('ready', function() {
// Register a 'ctrl+x' shortcut listener. // Register a 'ctrl+x' shortcut listener.

View file

@ -19,7 +19,7 @@ processes:
```javascript ```javascript
// In main process. // In main process.
var ipcMain = require('ipc-main'); const ipcMain = require('electron').ipcMain;
ipcMain.on('asynchronous-message', function(event, arg) { ipcMain.on('asynchronous-message', function(event, arg) {
console.log(arg); // prints "ping" console.log(arg); // prints "ping"
event.sender.send('asynchronous-reply', 'pong'); event.sender.send('asynchronous-reply', 'pong');
@ -33,7 +33,7 @@ ipcMain.on('synchronous-message', function(event, arg) {
```javascript ```javascript
// In renderer process (web page). // In renderer process (web page).
var ipcRenderer = require('ipc-renderer'); const ipcRenderer = require('electron').ipcRenderer;
console.log(ipcRenderer.sendSync('synchronous-message', 'ping')); // prints "pong" console.log(ipcRenderer.sendSync('synchronous-message', 'ping')); // prints "pong"
ipcRenderer.on('asynchronous-reply', function(event, arg) { ipcRenderer.on('asynchronous-reply', function(event, arg) {

View file

@ -16,9 +16,9 @@ the user right clicks the page:
```html ```html
<!-- index.html --> <!-- index.html -->
<script> <script>
var remote = require('remote'); const remote = require('electron').remote;
var Menu = remote.require('menu'); const Menu = remote.Menu;
var MenuItem = remote.require('menu-item'); const MenuItem = remote.MenuItem;
var menu = new Menu(); var menu = new Menu();
menu.append(new MenuItem({ label: 'MenuItem1', click: function() { console.log('item 1 clicked'); } })); menu.append(new MenuItem({ label: 'MenuItem1', click: function() { console.log('item 1 clicked'); } }));
@ -136,14 +136,14 @@ var template = [
submenu: [ submenu: [
{ {
label: 'Learn More', label: 'Learn More',
click: function() { require('shell').openExternal('http://electron.atom.io') } click: function() { require('electron').shell.openExternal('http://electron.atom.io') }
}, },
] ]
}, },
]; ];
if (process.platform == 'darwin') { if (process.platform == 'darwin') {
var name = require('app').getName(); var name = require('electron').app.getName();
template.unshift({ template.unshift({
label: name, label: name,
submenu: [ submenu: [

View file

@ -1,7 +1,7 @@
# NativeImage # nativeImage
In Electron, for the APIs that take images, you can pass either file paths or In Electron, for the APIs that take images, you can pass either file paths or
`NativeImage` instances. An empty image will be used when `null` is passed. `nativeImage` instances. An empty image will be used when `null` is passed.
For example, when creating a tray or setting a window's icon, you can pass an For example, when creating a tray or setting a window's icon, you can pass an
image file path as a `String`: image file path as a `String`:
@ -11,10 +11,9 @@ var appIcon = new Tray('/Users/somebody/images/icon.png');
var window = new BrowserWindow({icon: '/Users/somebody/images/window.png'}); var window = new BrowserWindow({icon: '/Users/somebody/images/window.png'});
``` ```
Or read the image from the clipboard which returns a `NativeImage`: Or read the image from the clipboard which returns a `nativeImage`:
```javascript ```javascript
var clipboard = require('clipboard');
var image = clipboard.readImage(); var image = clipboard.readImage();
var appIcon = new Tray(image); var appIcon = new Tray(image);
``` ```
@ -84,40 +83,40 @@ To mark an image as a template image, its filename should end with the word
## Methods ## Methods
The `NativeImage` class has the following methods: The `nativeImage` class has the following methods:
### `NativeImage.createEmpty()` ### `nativeImage.createEmpty()`
Creates an empty `NativeImage` instance. Creates an empty `nativeImage` instance.
### `NativeImage.createFromPath(path)` ### `nativeImage.createFromPath(path)`
* `path` String * `path` String
Creates a new `NativeImage` instance from a file located at `path`. Creates a new `nativeImage` instance from a file located at `path`.
### `NativeImage.createFromBuffer(buffer[, scaleFactor])` ### `nativeImage.createFromBuffer(buffer[, scaleFactor])`
* `buffer` [Buffer][buffer] * `buffer` [Buffer][buffer]
* `scaleFactor` Double (optional) * `scaleFactor` Double (optional)
Creates a new `NativeImage` instance from `buffer`. The default `scaleFactor` is Creates a new `nativeImage` instance from `buffer`. The default `scaleFactor` is
1.0. 1.0.
### `NativeImage.createFromDataUrl(dataUrl)` ### `nativeImage.createFromDataURL(dataURL)`
* `dataUrl` String * `dataURL` String
Creates a new `NativeImage` instance from `dataUrl`. Creates a new `nativeImage` instance from `dataURL`.
## Instance Methods ## Instance Methods
The following methods are available on instances of `nativeImage`: The following methods are available on instances of `nativeImage`:
```javascript ```javascript
var NativeImage = require('native-image'); const nativeImage = require('electron').nativeImage;
var image = NativeImage.createFromPath('/Users/somebody/images/icon.png'); var image = nativeImage.createFromPath('/Users/somebody/images/icon.png');
``` ```
### `image.toPng()` ### `image.toPng()`
@ -130,7 +129,7 @@ Returns a [Buffer][buffer] that contains the image's `PNG` encoded data.
Returns a [Buffer][buffer] that contains the image's `JPEG` encoded data. Returns a [Buffer][buffer] that contains the image's `JPEG` encoded data.
### `image.toDataUrl()` ### `image.toDataURL()`
Returns the data URL of the image. Returns the data URL of the image.

View file

@ -1,4 +1,4 @@
# power-monitor # powerMonitor
The `power-monitor` module is used to monitor power state changes. You can The `power-monitor` module is used to monitor power state changes. You can
only use it in the main process. You should not use this module until the `ready` only use it in the main process. You should not use this module until the `ready`
@ -7,10 +7,8 @@ event of the `app` module is emitted.
For example: For example:
```javascript ```javascript
var app = require('app');
app.on('ready', function() { app.on('ready', function() {
require('power-monitor').on('suspend', function() { require('electron').powerMonitor.on('suspend', function() {
console.log('The system is going to sleep'); console.log('The system is going to sleep');
}); });
}); });

View file

@ -1,13 +1,13 @@
# powerSaveBlocker # powerSaveBlocker
The `power-save-blocker` module is used to block the system from entering The `powerSaveBlocker` module is used to block the system from entering
low-power (sleep) mode and thus allowing the app to keep the system and screen low-power (sleep) mode and thus allowing the app to keep the system and screen
active. active.
For example: For example:
```javascript ```javascript
var powerSaveBlocker = require('power-save-blocker'); const powerSaveBlocker = require('electron').powerSaveBlocker;
var id = powerSaveBlocker.start('prevent-display-sleep'); var id = powerSaveBlocker.start('prevent-display-sleep');
console.log(powerSaveBlocker.isStarted(id)); console.log(powerSaveBlocker.isStarted(id));

View file

@ -7,11 +7,12 @@ An example of implementing a protocol that has the same effect as the
`file://` protocol: `file://` protocol:
```javascript ```javascript
var app = require('app'); const electron = require('electron');
var path = require('path'); const app = electron.app;
const path = require('path');
app.on('ready', function() { app.on('ready', function() {
var protocol = require('protocol'); var protocol = electron.protocol;
protocol.registerFileProtocol('atom', function(request, callback) { protocol.registerFileProtocol('atom', function(request, callback) {
var url = request.url.substr(7); var url = request.url.substr(7);
callback({path: path.normalize(__dirname + '/' + url)}); callback({path: path.normalize(__dirname + '/' + url)});

View file

@ -3,16 +3,20 @@
The `remote` module provides a simple way to do inter-process communication The `remote` module provides a simple way to do inter-process communication
(IPC) between the renderer process (web page) and the main process. (IPC) between the renderer process (web page) and the main process.
In Electron, GUI-related modules (such as `dialog`, `menu` etc.) are only available in the main process, not in the renderer process. In order to use them from the renderer process, the `ipc` module is necessary to send inter-process messages to the main process. With the `remote` module, you can invoke methods of the main process object without explicitly sending inter-process messages, similar to Java's [RMI](http://en.wikipedia.org/wiki/Java_remote_method_invocation). In Electron, GUI-related modules (such as `dialog`, `menu` etc.) are only
available in the main process, not in the renderer process. In order to use them
An example of creating a browser window from a renderer process: from the renderer process, the `ipc` module is necessary to send inter-process
messages to the main process. With the `remote` module, you can invoke methods
of the main process object without explicitly sending inter-process messages,
similar to Java's [RMI][rmi]. An example of creating a browser window from a
renderer process:
```javascript ```javascript
var remote = require('remote'); const remote = require('electron').remote;
var BrowserWindow = remote.require('browser-window'); const BrowserWindow = remote.BrowserWindow;
var win = new BrowserWindow({ width: 800, height: 600 }); var win = new BrowserWindow({ width: 800, height: 600 });
win.loadUrl('https://github.com'); win.loadURL('https://github.com');
``` ```
**Note:** for the reverse (access the renderer process from the main process), **Note:** for the reverse (access the renderer process from the main process),
@ -96,8 +100,6 @@ For example, the following code seems innocent at first glance. It installs a
callback for the `close` event on a remote object: callback for the `close` event on a remote object:
```javascript ```javascript
var remote = require('remote');
remote.getCurrentWindow().on('close', function() { remote.getCurrentWindow().on('close', function() {
// blabla... // blabla...
}); });
@ -116,6 +118,15 @@ passed to the main process. This involves cleaning up event handlers, or
ensuring the main process is explicitly told to deference callbacks that came ensuring the main process is explicitly told to deference callbacks that came
from a renderer process that is exiting. from a renderer process that is exiting.
## Accessing built-in modules in the main process
The built-in modules in the main process are added as getters in the `remote`
module, so you can use them directly like the `electron` module.
```javascript
const app = remote.app;
```
## Methods ## Methods
The `remote` module has the following methods: The `remote` module has the following methods:
@ -146,3 +157,5 @@ process.
Returns the `process` object in the main process. This is the same as Returns the `process` object in the main process. This is the same as
`remote.getGlobal('process')` but is cached. `remote.getGlobal('process')` but is cached.
[rmi]: http://en.wikipedia.org/wiki/Java_remote_method_invocation

Some files were not shown because too many files have changed in this diff Show more