Merge branch 'master' into jl-std-docs-2
This commit is contained in:
		
				commit
				
					
						f4783772c5
					
				
			
		
					 72 changed files with 118 additions and 15 deletions
				
			
		|  | @ -43,6 +43,12 @@ Guides and the API reference are located in the | ||||||
| [docs](https://github.com/atom/electron/tree/master/docs) directory. It also | [docs](https://github.com/atom/electron/tree/master/docs) directory. It also | ||||||
| contains documents describing how to build and contribute to Electron. | contains documents describing how to build and contribute to Electron. | ||||||
| 
 | 
 | ||||||
|  | ## Documentation Translations | ||||||
|  | 
 | ||||||
|  | - [Korean](https://github.com/atom/electron/tree/master/docs-translations/ko) | ||||||
|  | - [Japanese](https://github.com/atom/electron/tree/master/docs-translations/jp) | ||||||
|  | - [Spanish](https://github.com/atom/electron/tree/master/docs-translations/es) | ||||||
|  | 
 | ||||||
| ## Community | ## Community | ||||||
| 
 | 
 | ||||||
| There is an [`electron` category on the Atom forums](http://discuss.atom.io/category/electron) | There is an [`electron` category on the Atom forums](http://discuss.atom.io/category/electron) | ||||||
|  |  | ||||||
|  | @ -277,7 +277,10 @@ bool WebContents::IsPopupOrPanel(const content::WebContents* source) const { | ||||||
| void WebContents::HandleKeyboardEvent( | void WebContents::HandleKeyboardEvent( | ||||||
|     content::WebContents* source, |     content::WebContents* source, | ||||||
|     const content::NativeWebKeyboardEvent& event) { |     const content::NativeWebKeyboardEvent& event) { | ||||||
|   if (type_ == BROWSER_WINDOW) { |   if (event.windowsKeyCode == ui::VKEY_ESCAPE && is_html_fullscreen()) { | ||||||
|  |     // Escape exits tabbed fullscreen mode.
 | ||||||
|  |     ExitFullscreenModeForTab(source); | ||||||
|  |   } else if (type_ == BROWSER_WINDOW) { | ||||||
|     owner_window()->HandleKeyboardEvent(source, event); |     owner_window()->HandleKeyboardEvent(source, event); | ||||||
|   } else if (type_ == WEB_VIEW && guest_delegate_) { |   } else if (type_ == WEB_VIEW && guest_delegate_) { | ||||||
|     // Send the unhandled keyboard events back to the embedder.
 |     // Send the unhandled keyboard events back to the embedder.
 | ||||||
|  |  | ||||||
|  | @ -48,6 +48,8 @@ class CommonWebContentsDelegate | ||||||
| 
 | 
 | ||||||
|   NativeWindow* owner_window() const { return owner_window_.get(); } |   NativeWindow* owner_window() const { return owner_window_.get(); } | ||||||
| 
 | 
 | ||||||
|  |   bool is_html_fullscreen() const { return html_fullscreen_; } | ||||||
|  | 
 | ||||||
|  protected: |  protected: | ||||||
|   // content::WebContentsDelegate:
 |   // content::WebContentsDelegate:
 | ||||||
|   content::WebContents* OpenURLFromTab( |   content::WebContents* OpenURLFromTab( | ||||||
|  |  | ||||||
|  | @ -30,6 +30,10 @@ guestInstances = {} | ||||||
| embedderElementsMap = {} | embedderElementsMap = {} | ||||||
| reverseEmbedderElementsMap = {} | reverseEmbedderElementsMap = {} | ||||||
| 
 | 
 | ||||||
|  | # Moves the last element of array to the first one. | ||||||
|  | moveLastToFirst = (list) -> | ||||||
|  |   list.unshift list.pop() | ||||||
|  | 
 | ||||||
| # Generate guestInstanceId. | # Generate guestInstanceId. | ||||||
| getNextInstanceId = (webContents) -> | getNextInstanceId = (webContents) -> | ||||||
|   ++nextInstanceId |   ++nextInstanceId | ||||||
|  | @ -46,7 +50,13 @@ createGuest = (embedder, params) -> | ||||||
|   destroyEvents = ['destroyed', 'crashed', 'did-navigate-to-different-page'] |   destroyEvents = ['destroyed', 'crashed', 'did-navigate-to-different-page'] | ||||||
|   destroy = -> |   destroy = -> | ||||||
|     destroyGuest embedder, id if guestInstances[id]? |     destroyGuest embedder, id if guestInstances[id]? | ||||||
|   embedder.once event, destroy for event in destroyEvents |   for event in destroyEvents | ||||||
|  |     embedder.once event, destroy | ||||||
|  |     # Users might also listen to the crashed event, so We must ensure the guest | ||||||
|  |     # is destroyed before users' listener gets called. It is done by moving our | ||||||
|  |     # listener to the first one in queue. | ||||||
|  |     listeners = embedder._events[event] | ||||||
|  |     moveLastToFirst listeners if Array.isArray listeners | ||||||
|   guest.once 'destroyed', -> |   guest.once 'destroyed', -> | ||||||
|     embedder.removeListener event, destroy for event in destroyEvents |     embedder.removeListener event, destroy for event in destroyEvents | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -19,6 +19,9 @@ namespace { | ||||||
| // Makes sure that .jpg also shows .JPG.
 | // Makes sure that .jpg also shows .JPG.
 | ||||||
| gboolean FileFilterCaseInsensitive(const GtkFileFilterInfo* file_info, | gboolean FileFilterCaseInsensitive(const GtkFileFilterInfo* file_info, | ||||||
|                                    std::string* file_extension) { |                                    std::string* file_extension) { | ||||||
|  |   // Makes .* file extension matches all file types.
 | ||||||
|  |   if (*file_extension == ".*") | ||||||
|  |     return true; | ||||||
|   return EndsWith(file_info->filename, *file_extension, false); |   return EndsWith(file_info->filename, *file_extension, false); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -23,6 +23,12 @@ void SetAllowedFileTypes(NSSavePanel* dialog, const Filters& filters) { | ||||||
|   for (size_t i = 0; i < filters.size(); ++i) { |   for (size_t i = 0; i < filters.size(); ++i) { | ||||||
|     const Filter& filter = filters[i]; |     const Filter& filter = filters[i]; | ||||||
|     for (size_t j = 0; j < filter.second.size(); ++j) { |     for (size_t j = 0; j < filter.second.size(); ++j) { | ||||||
|  |       // If we meet a '*' file extension, we allow all the file types and no | ||||||
|  |       // need to set the specified file types. | ||||||
|  |       if (filter.second[j] == "*") { | ||||||
|  |         [dialog setAllowsOtherFileTypes:YES]; | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|       base::ScopedCFTypeRef<CFStringRef> ext_cf( |       base::ScopedCFTypeRef<CFStringRef> ext_cf( | ||||||
|           base::SysUTF8ToCFStringRef(filter.second[j])); |           base::SysUTF8ToCFStringRef(filter.second[j])); | ||||||
|       [file_type_set addObject:base::mac::CFToNSCast(ext_cf.get())]; |       [file_type_set addObject:base::mac::CFToNSCast(ext_cf.get())]; | ||||||
|  |  | ||||||
|  | @ -78,9 +78,9 @@ int ShowMessageBoxUTF16(HWND parent, | ||||||
|                         const base::string16& message, |                         const base::string16& message, | ||||||
|                         const base::string16& detail, |                         const base::string16& detail, | ||||||
|                         const gfx::ImageSkia& icon) { |                         const gfx::ImageSkia& icon) { | ||||||
|   TASKDIALOG_FLAGS flags = TDF_SIZE_TO_CONTENT;  // show all content.
 |   TASKDIALOG_FLAGS flags = | ||||||
|   if (cancel_id != 0) |       TDF_SIZE_TO_CONTENT |  // Show all content.
 | ||||||
|     flags |= TDF_ALLOW_DIALOG_CANCELLATION;  // allow dialog to be cancelled.
 |       TDF_ALLOW_DIALOG_CANCELLATION;  // Allow canceling the dialog.
 | ||||||
| 
 | 
 | ||||||
|   TASKDIALOGCONFIG config = { 0 }; |   TASKDIALOGCONFIG config = { 0 }; | ||||||
|   config.cbSize     = sizeof(config); |   config.cbSize     = sizeof(config); | ||||||
|  |  | ||||||
|  | @ -80,12 +80,15 @@ window.alert = (message, title='') -> | ||||||
|   buttons = ['OK'] |   buttons = ['OK'] | ||||||
|   message = message.toString() |   message = message.toString() | ||||||
|   dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons} |   dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons} | ||||||
|  |   # Alert should always return undefined. | ||||||
|  |   return | ||||||
| 
 | 
 | ||||||
| # And the confirm(). | # And the confirm(). | ||||||
| window.confirm = (message, title='') -> | window.confirm = (message, title='') -> | ||||||
|   dialog = remote.require 'dialog' |   dialog = remote.require 'dialog' | ||||||
|   buttons = ['OK', 'Cancel'] |   buttons = ['OK', 'Cancel'] | ||||||
|   not dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons} |   cancelId = 1 | ||||||
|  |   not dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons, cancelId} | ||||||
| 
 | 
 | ||||||
| # But we do not support prompt(). | # But we do not support prompt(). | ||||||
| window.prompt = -> | window.prompt = -> | ||||||
|  |  | ||||||
|  | @ -11,7 +11,9 @@ var dialog = require('dialog'); | ||||||
| console.log(dialog.showOpenDialog({ properties: [ 'openFile', 'openDirectory', 'multiSelections' ]})); | console.log(dialog.showOpenDialog({ properties: [ 'openFile', 'openDirectory', 'multiSelections' ]})); | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| **Note for OS X**: If you want to present dialogs as sheets, the only thing you have to do is provide a `BrowserWindow` reference in the `browserWindow` parameter. | **Note for OS X**: If you want to present dialogs as sheets, the only thing you | ||||||
|  | have to do is provide a `BrowserWindow` reference in the `browserWindow` | ||||||
|  | parameter. | ||||||
| 
 | 
 | ||||||
| ## dialog.showOpenDialog([browserWindow], [options], [callback]) | ## dialog.showOpenDialog([browserWindow], [options], [callback]) | ||||||
| 
 | 
 | ||||||
|  | @ -36,17 +38,22 @@ selected, an example is: | ||||||
|   filters: [ |   filters: [ | ||||||
|     { name: 'Images', extensions: ['jpg', 'png', 'gif'] }, |     { name: 'Images', extensions: ['jpg', 'png', 'gif'] }, | ||||||
|     { name: 'Movies', extensions: ['mkv', 'avi', 'mp4'] }, |     { name: 'Movies', extensions: ['mkv', 'avi', 'mp4'] }, | ||||||
|     { name: 'Custom File Type', extensions: ['as'] } |     { name: 'Custom File Type', extensions: ['as'] }, | ||||||
|  |     { name: 'All Files', extensions: ['*'] } | ||||||
|   ] |   ] | ||||||
| } | } | ||||||
| ``` | ``` | ||||||
|  | The `extensions` array should contain extensions without wildcards or dots (e.g. | ||||||
|  | `'png'` is good, `'.png'` and `'*.png'` are bad). To show all files, use the | ||||||
|  | `'*'` wildcard (no other wildcard is supported). | ||||||
| 
 | 
 | ||||||
| If a `callback` is passed, the API call would be asynchronous and the result | If a `callback` is passed, the API call would be asynchronous and the result | ||||||
| would be passed via `callback(filenames)` | would be passed via `callback(filenames)` | ||||||
| 
 | 
 | ||||||
| **Note:** On Windows and Linux, an open dialog can not be both a file selector | **Note:** On Windows and Linux, an open dialog can not be both a file selector | ||||||
| and a directory selector, so if you set `properties` to | and a directory selector, so if you set `properties` to | ||||||
| `['openFile', 'openDirectory']` on these platforms, a directory selector will be shown. | `['openFile', 'openDirectory']` on these platforms, a directory selector will be | ||||||
|  | shown. | ||||||
| 
 | 
 | ||||||
| ## dialog.showSaveDialog([browserWindow], [options], [callback]) | ## dialog.showSaveDialog([browserWindow], [options], [callback]) | ||||||
| 
 | 
 | ||||||
|  | @ -70,7 +77,9 @@ will be passed via `callback(filename)` | ||||||
| 
 | 
 | ||||||
| * `browserWindow` BrowserWindow | * `browserWindow` BrowserWindow | ||||||
| * `options` Object | * `options` Object | ||||||
|   * `type` String - Can be `"none"`, `"info"`, `"error"`, `"question"` or `"warning"`. On Windows, "question" displays the same icon as "info", unless if you set an icon using the "icon" option |   * `type` String - Can be `"none"`, `"info"`, `"error"`, `"question"` or | ||||||
|  |   `"warning"`. On Windows, "question" displays the same icon as "info", unless | ||||||
|  |   if you set an icon using the "icon" option | ||||||
|   * `buttons` Array - Array of texts for buttons |   * `buttons` Array - Array of texts for buttons | ||||||
|   * `title` String - Title of the message box, some platforms will not show it |   * `title` String - Title of the message box, some platforms will not show it | ||||||
|   * `message` String - Content of the message box |   * `message` String - Content of the message box | ||||||
|  |  | ||||||
|  | @ -8,6 +8,13 @@ script `script/cpplint.py` to check whether all files confirm. | ||||||
| 
 | 
 | ||||||
| The python's version we are using now is Python 2.7. | The python's version we are using now is Python 2.7. | ||||||
| 
 | 
 | ||||||
|  | The C++ code uses a lot of Chromium's abstractions and types, so it's  | ||||||
|  | recommended to get acquainted with them. A good place to start is  | ||||||
|  | Chromium's [Important Abstractions and Data Structures] | ||||||
|  | (https://www.chromium.org/developers/coding-style/important-abstractions-and-data-structures)  | ||||||
|  | document. The document mentions some special types, scoped types (that  | ||||||
|  | automatically release their memory when going out of scope), logging mechanisms etc. | ||||||
|  | 
 | ||||||
| ## CoffeeScript | ## CoffeeScript | ||||||
| 
 | 
 | ||||||
| For CoffeeScript, we follow GitHub's [Style | For CoffeeScript, we follow GitHub's [Style | ||||||
|  |  | ||||||
|  | @ -70,6 +70,53 @@ driver.wait(function() { | ||||||
| driver.quit(); | driver.quit(); | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
|  | ## Setting up with WebdriverIO | ||||||
|  | 
 | ||||||
|  | [WebdriverIO](http://webdriver.io/) provides a Node package for testing with web driver. | ||||||
|  | 
 | ||||||
|  | ### 1. Start chrome driver | ||||||
|  | 
 | ||||||
|  | First you need to download the `chromedriver` binary, and run it: | ||||||
|  | 
 | ||||||
|  | ```bash | ||||||
|  | $ chromedriver --url-base=/wd/hub --port=9515 | ||||||
|  | Starting ChromeDriver (v2.10.291558) on port 9515 | ||||||
|  | Only local connections are allowed. | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Remember the port number `9515`, which will be used later | ||||||
|  | 
 | ||||||
|  | ### 2. Install WebdriverIO | ||||||
|  | 
 | ||||||
|  | ```bash | ||||||
|  | $ npm install webdriverio | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ### 3. Connect to chrome driver | ||||||
|  | ```javascript | ||||||
|  | var webdriverio = require('webdriverio'); | ||||||
|  | var options = { | ||||||
|  |     host: "localhost", // Use localhost as chrome driver server  | ||||||
|  |     port: 9515,        // "9515" is the port opened by chrome driver. | ||||||
|  |     desiredCapabilities: { | ||||||
|  |         browserName: 'chrome', | ||||||
|  |         chromeOptions: {binary: '/Path-to-Your-App.app/Electron'} // Path to your Electron binary. | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | var client = webdriverio.remote(options); | ||||||
|  | 
 | ||||||
|  | client | ||||||
|  |     .init() | ||||||
|  |     .url('http://google.com') | ||||||
|  |     .setValue('#q', 'webdriverio') | ||||||
|  |     .click('#btnG') | ||||||
|  |     .getTitle().then(function(title) { | ||||||
|  |         console.log('Title was: ' + title); | ||||||
|  |     }) | ||||||
|  |     .end(); | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
| ## Workflow | ## Workflow | ||||||
| 
 | 
 | ||||||
| To test your application without rebuilding Electron, simply [place](https://github.com/atom/electron/blob/master/docs/tutorial/application-distribution.md) your app source into Electron's resource directory.  | To test your application without rebuilding Electron, simply [place](https://github.com/atom/electron/blob/master/docs/tutorial/application-distribution.md) your app source into Electron's resource directory.  | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| { | { | ||||||
|   "name": "electron", |   "name": "electron", | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "asar": "0.5.0", |     "asar": "0.7.x", | ||||||
|     "coffee-script": "^1.9.2", |     "coffee-script": "^1.9.2", | ||||||
|     "coffeelint": "^1.9.4", |     "coffeelint": "^1.9.4", | ||||||
|     "request": "*", |     "request": "*", | ||||||
|  |  | ||||||
|  | @ -5,6 +5,13 @@ remote = require 'remote' | ||||||
| 
 | 
 | ||||||
| BrowserWindow = remote.require 'browser-window' | BrowserWindow = remote.require 'browser-window' | ||||||
| 
 | 
 | ||||||
|  | comparePaths = (path1, path2) -> | ||||||
|  |   if process.platform is 'win32' | ||||||
|  |     # Paths in Windows are case insensitive. | ||||||
|  |     path1 = path1.toLowerCase() | ||||||
|  |     path2 = path2.toLowerCase() | ||||||
|  |   assert.equal path1, path2 | ||||||
|  | 
 | ||||||
| describe 'ipc module', -> | describe 'ipc module', -> | ||||||
|   fixtures = path.join __dirname, 'fixtures' |   fixtures = path.join __dirname, 'fixtures' | ||||||
| 
 | 
 | ||||||
|  | @ -19,8 +26,8 @@ describe 'ipc module', -> | ||||||
|       assert.equal a.id, 1127 |       assert.equal a.id, 1127 | ||||||
| 
 | 
 | ||||||
|     it 'should search module from the user app', -> |     it 'should search module from the user app', -> | ||||||
|       assert.equal path.normalize(remote.process.mainModule.filename), path.resolve(__dirname, 'static', 'main.js') |       comparePaths path.normalize(remote.process.mainModule.filename), path.resolve(__dirname, 'static', 'main.js') | ||||||
|       assert.equal path.normalize(remote.process.mainModule.paths[0]), path.resolve(__dirname, 'static', 'node_modules') |       comparePaths path.normalize(remote.process.mainModule.paths[0]), path.resolve(__dirname, 'static', 'node_modules') | ||||||
| 
 | 
 | ||||||
|   describe 'remote.createFunctionWithReturnValue', -> |   describe 'remote.createFunctionWithReturnValue', -> | ||||||
|     it 'should be called in browser synchronously', -> |     it 'should be called in browser synchronously', -> | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								vendor/brightray
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/brightray
									
										
									
									
										vendored
									
									
								
							|  | @ -1 +1 @@ | ||||||
| Subproject commit 939a7b814282a6433b8d7e3c9cfc74451360c07f | Subproject commit 5b2a73c68a986780e67eb2e738327d35c7c1c21e | ||||||
							
								
								
									
										2
									
								
								vendor/node
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/node
									
										
									
									
										vendored
									
									
								
							|  | @ -1 +1 @@ | ||||||
| Subproject commit 205b013ac86e5500678a791cd54f305580fa4f4b | Subproject commit b9b6dd9f3fc095e66a3b89d3efd50f7c576da2c8 | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jessica Lord
				Jessica Lord