Compare commits

..

133 Commits

Author SHA1 Message Date
John Kleinschmidt
311f7ac6bb Bump v2.0.2 2018-05-22 14:52:16 -04:00
trop[bot]
52a44facfd update locale documentation (#13027) 2018-05-21 15:07:46 -05:00
trop[bot]
5acb7a0226 Backport (2-0-x) - docs: Document missing quit events during shutdown (#13026)
* docs: Document missing events during shutdown

* docs: Better language
2018-05-21 12:52:18 -07:00
trop[bot]
afcf94a85c Add a tag to libchromiumcontent when a release is created. (#13025) 2018-05-21 13:35:56 -05:00
John Kleinschmidt
c42b468966 Merge pull request #13022 from trop-bot/2-0-x-bp-fix--menu.setapplicationmenu(null)-crash-on-linux-1526913387556
Backport (2-0-x) - fix: Menu.setApplicationMenu(null) crash on Linux
2018-05-21 11:06:36 -04:00
John Kleinschmidt
e0257acdf5 Merge pull request #13009 from ajmacd/ajm-libcc
Bump libcc ref to pick up patch file extension correction.
2018-05-21 11:05:34 -04:00
Jeremy Apthorp
b555434aa0 fix: Menu.setApplicationMenu(null) crash on Linux 2018-05-21 14:36:33 +00:00
trop[bot]
9574a4f472 Only expand maximum size constraint if there was a constraint originally (#13014) 2018-05-20 19:45:51 -07:00
Andrew MacDonald
2f167ce3d1 Bump libcc ref to pick up patch file extension correction. 2018-05-19 01:01:05 -07:00
John Kleinschmidt
8655d5e9ae Bump v2.0.1 2018-05-16 13:30:26 -04:00
John Kleinschmidt
2e06e0eccd Merge pull request #12964 from trop-bot/2-0-x-bp-fix--support-multiple-inherited-ubuntu-session-for-indicators-1526485540005
Backport (2-0-x) - fix: support multiple inherited ubuntu session for indicators
2018-05-16 12:14:46 -04:00
John Kleinschmidt
773f08ca43 Merge pull request #12963 from trop-bot/2-0-x-bp-fix-empty-description-when-only-one-extension-is-given-(getfiletypesfromaccepttype)-1526480331702
Backport (2-0-x) - Fix empty description when only one extension is given (GetFileTypesFromAcceptType)
2018-05-16 11:46:51 -04:00
Didier Roche
13850b9dff Fix linting error
Thx @MarshallOfSound
2018-05-16 15:45:46 +00:00
Didier Roche
1c57c76496 fix: more scalable code by factorizing appindicator support
- introduce a currentPlatformSupportsAppIndicator() function determining
  if app indicators are supported here.
- handle undefined process.env.XDG_CURRENT_DESKTOP
- added some comments to ensure that the intents are clear
Thanks MarshallOfSound
2018-05-16 15:45:46 +00:00
Didier Roche
e459b38c5d Support multiple inherited ubuntu session for indicators
Multiple sessions inherits the "ubuntu" base settings properties in ubuntu.
One of the most popular one is communitheme: the next ubuntu default theme
has its dedicated session, with thus duplicated indicators for dropbox.
Rather than a string comparison for ubuntu, only match a substring then.
XDG_CURRENT_DESKTOP can be of form: "communitheme:ubuntu:GNOME",
"ubuntu:GNOME", …
Fixes: #12843.
2018-05-16 15:45:46 +00:00
John Kleinschmidt
9796513b83 Merge pull request #12923 from electron/fix-12875-2-0-x
Allow frameless transparent windows to be sized smaller than 64x64 on Windows
2018-05-16 11:42:35 -04:00
Milan Burda
d3e5f430c7 Fix empty description when only one extension is given 2018-05-16 14:18:57 +00:00
John Kleinschmidt
df22eccfc1 Merge pull request #12946 from trop-bot/2-0-x-bp-make-security-warnings-tests-more-robust-1526401028749
Backport (2-0-x) - Make security-warnings tests more robust
2018-05-15 13:12:10 -04:00
Cheng Zhao
214c352f71 make security-warnings tests more robust 2018-05-15 16:17:14 +00:00
John Kleinschmidt
0070637b5a Fix typescript generation error (#12940) 2018-05-15 11:13:35 -05:00
Milan Burda
72b944f862 Fix contents.setSize(options) documentation in web-contents.md 2018-05-15 11:37:45 +02:00
Heilig Benedek
2fbb371689 Lock electron-typescript-definitions at 1.3.2 2018-05-15 04:05:13 +02:00
Heilig Benedek
e2e70e9b1e Match chromium's workaround when setting size of unresizable windows 2018-05-14 21:57:34 +02:00
Charles Kerr
324b769751 update command-line backlist switches (2.0.x) (#12806)
* update command-line backlist switches

Do a better job of finding edge cases, e.g. network_switch_list.h

**NB: This can't be tropped** because the list is dependent on the libcc version

* update list
2018-05-14 11:03:37 -05:00
John Kleinschmidt
e1d54d55be Merge pull request #12856 from trop-bot/2-0-x-bp-fix--listeners-out-of-limit-warning-1525756284370
Backport (2-0-x) - fix: listeners out of limit warning
2018-05-08 10:49:17 -04:00
biuuu
1d54032ba4 fix: listeners out of limit warning
When the Chrome Extension has too many content scripts (above default
10 counts), there will be a warning: possible EventEmitter memory leak
detected. 11 listeners added.
2018-05-08 05:11:30 +00:00
Andrew MacDonald
c6e4de16de Update 2-0-x libcc ref for electron/libchromiumcontent/#533. (#12785) 2018-05-07 09:29:40 -07:00
trop[bot]
f39cc1cc46 docs: fix the type information in in-app-purchase (#12824)
Method returns Boolean, Manually confirmed the
correctness by running `npm run create-api-json`.
2018-05-04 14:50:33 -07:00
trop[bot]
6af89eb260 don't filter out invisible menu separators (#12831) 2018-05-04 11:26:21 -07:00
trop[bot]
d33b71cc2d Backport (2-0-x) - show file filter name for accessory view of file dialog (#12779)
* Show file filter name for accessory view of file dialog

- Respect filters option of dialog.showOpenDialog() and
  dialog.showSaveDialog(). (#10335)
- Show "All Files" for <input> apart from "accept" attribute. (#11456)

* Fix memory leaks in file_dialog_mac.mm
2018-05-02 09:28:16 -05:00
trop[bot]
d0bbf3fb3c Fix context menu for sandbox devtools (#12731) 2018-05-01 17:53:58 -05:00
trop[bot]
289db66fee fix flaky security-warnings test (#12776) 2018-05-01 17:52:03 -05:00
John Kleinschmidt
6b90807cb8 Bump v2.0.0 2018-05-01 16:00:36 -04:00
John Kleinschmidt
cf4f078aca Merge pull request #12768 from electron/support-policy-2-0-x
Manually backport Support Policy docs from master
2018-05-01 15:55:03 -04:00
Charles Kerr
4eedd1455d Manually backport Support Policy docs from master 2018-05-01 14:49:08 -05:00
trop[bot]
9c167b63f2 Backport (2-0-x) - Add sccache option to bootstrap (#12753)
* Add sccache option to bootstrap

Couldn't see a CC wrapper style option for gyp so we inject the sccache commands directly into the generated ninja files.

* Use CC_wrapper

* Update toolchain.gypi

* s/sccache/cc_wrapper
2018-05-01 01:31:37 +10:00
John Kleinschmidt
d18ab0ca08 Bump v2.0.0-beta.8 2018-04-26 10:56:46 -04:00
trop[bot]
724cbc967c revert to more graceful template structure check (#12703) 2018-04-24 14:17:26 -04:00
trop[bot]
b9d589439f Backport (2-0-x) - Fix transparency (#12683)
* Fix transparent window capture. Transparency is preserved and not converted to black pixels anymore

* Add test to make sure aplha channel exists in captured image
2018-04-23 01:16:18 +10:00
trop[bot]
f37bc4a9d4 Backport (2-0-x) - Correct the default of allowRunningInsecureContent as per docs (#12629)
* Correct the default of allowRunningInsecureContent as per docs

* fix linting

* Update calls to match native_mate API change
2018-04-18 05:53:32 -07:00
Alexey Kuzmin
597c8964f6 Preload doesn't load in sandboxed render if preload path contains special chars (#12037) (#12643)
* Adding missing headers

* adding ut

* Removing the file path exists check

* fixing test

* exposing window.require in UT

(cherry picked from commit 2f4fd3324b)
2018-04-17 11:00:07 -05:00
trop[bot]
652f83fc88 Backport (2-0-x) - Fix event leak on reuse of touchbar item (#12624)
* fix event leak on reuse of touchbar item

* Clean up child touch bar item event listeners and escape item listeners
2018-04-15 11:26:56 -05:00
trop[bot]
d432038aab Use CircleCI for Mac builds (#12573) 2018-04-09 19:45:35 -05:00
trop[bot]
5d8f36c53c Check for devtools in BrowserWindow.getFocusedWindow() (#12554) 2018-04-06 12:45:11 -04:00
trop[bot]
85dfdd6665 Expose IsOffScreen method always to JS. (#12531) 2018-04-04 13:25:28 -05:00
electron
de428ebec0 Bump v2.0.0-beta.7 2018-04-03 12:54:17 -07:00
John Kleinschmidt
c6c49b9e4b Add native arm/arm64 mksnapshot for 2-0-x (#12524)
* Add logic to bundle native mksnapshot for arm/arm64

(cherry picked from commit 79eff95a39)

* Update to latest libchromiumcontent
2018-04-03 14:24:38 -05:00
John Kleinschmidt
98495fabfb Fix pushRelease for autorelease (#12523) 2018-04-03 14:14:25 -05:00
trop[bot]
06c33c7e56 WebFrame.setVisualZoomLevelLimits sets user-agent scale constraints (#12510)
Fixes #11216.
2018-04-03 07:50:37 -05:00
trop[bot]
33aad6ae11 Handle in-app-purchase less fatally on non-Darwin (#12512)
Fixes #12471

Right now it throws a new error when the file is even require()d, but this isn't ideal as there are cases where everything is mass-required, such as Spectron.

Instead, we should throw an error on non-Darwin environments only when the IAP methods are invoked.
2018-04-02 19:23:28 -05:00
Charles Kerr
6c00b37dd1 update libcc submodule reference to electron-2-0-x (#12448)
* update libcc submodule reference to electron-2-0-x

* remove MarkHighMemoryUsage api
2018-04-02 19:12:55 -05:00
trop[bot]
d209e59c30 re-enable null check against menu item accelerators (#12455) 2018-03-28 16:45:34 -05:00
trop[bot]
14f8a2a0e8 Backport (2-0-x) - update doc for setProgressBar (#12454)
* update doc for setProgressBar

The linter was unable to get `paused` as a possible value for `mode`

* update doc for setProgressBar

Addressing PR feedback
2018-03-28 11:35:40 +11:00
John Kleinschmidt
65e1252da0 Bump v2.0.0-beta.6 2018-03-27 16:10:49 -04:00
trop[bot]
2903d7608c Backport (2-0-x) - Fix nil tray title crash (#12356)
* Add check for title_ being nil

* remove print stub
2018-03-23 13:05:59 -05:00
John Kleinschmidt
0bc72961ab Merge pull request #12412 from electron/autorelease-fixes
Fixes for autorelease
2018-03-22 16:08:14 -04:00
John Kleinschmidt
b55a24c025 Fixes for autorelease
1. Allow passing in of branch
2. Validate release before trying to run release
3. Fix upload-index-json.py to allow use of release build.
2018-03-22 11:48:41 -04:00
trop[bot]
51bca764f7 Do not block main process for async dialog (#12407) 2018-03-22 08:46:15 -05:00
Shelley Vohr
35976a0a07 fix tray highlight in darkmode (#12398) 2018-03-22 13:59:50 +11:00
trop[bot]
283ab23524 Use the appname as the tray icon's default tooltip (#12393)
This makes an upstream DCHECK happy in AppIndicatorIcon::SetToolTip.
Empty tooltip strings are discouraged, as discussed in commit log
b6c510aa543193337041517c2d70113840189b06.

Fixes #12386.
2018-03-21 16:02:48 -04:00
John Kleinschmidt
2343f7c287 Bump v2.0.0-beta.5 2018-03-20 15:04:20 -04:00
Birunthan Mohanathas
8991ad31d8 Backport (2-0-x) - Update draggable regions when changing BrowserView (#12370)
* Store InspectableWebContents instead of InspectableWebContentsView in NativeBrowserView

* Rename system_drag_exclude_areas => drag_exclude_rects

* Use NSView convertRect:toView: for BrowserView DragRegionView positioning

* Make BrowserView DragRegionViews children of the WebContents view

Previously they were children of the `InspectableWebContentsView` view,
which caused this assertion to fail:

f993888424/brightray/browser/mac/bry_inspectable_web_contents_view.mm (L162)

* Update draggable regions when changing BrowserView

Fixes #12150.
2018-03-20 13:03:45 -05:00
trop[bot]
fae6167308 Backport (2-0-x) - Remove the race condition between new process creation and context release (#12361)
* Remove the race condition between new process creation and old process releasing remote context

Previously there was a race condition where the getId() method would return the new context ID even
though the release was for the old context.  This changes it to send the "initial" context ID with
the release message to ensure there is no race.

* fetch context ID from remote in sandbox mode
2018-03-20 18:11:39 +11:00
John Kleinschmidt
bd25a5f453 Merge pull request #12353 from trop-bot/2-0-x-bp-update-ci-to-use-node.js-8-1521472101213
Backport (2-0-x) - Update CI to use Node.js 8
2018-03-19 13:03:25 -04:00
John Kleinschmidt
c80021924e Update CI to use Node 8 2018-03-19 15:08:27 +00:00
trop[bot]
0cc4584352 Backport (2-0-x) - Check menu.popup options are an object (#12330)
* check menu.popup options are an object

* Add a spec for menu.popup options check

* remove stray .only
2018-03-17 19:46:48 +09:00
trop[bot]
706f0c436d Backport (2-0-x) - Better GTK+ Menu color support (#12331)
* Better GTK+ Menu color support

 * Fix 'invisible menu' issue (#12275)

 * Now updates menu text color when focus changes!

 * Better caching of colors when system theme changes

 * Removed all GTK+ deprecation warnings from menubar

* Don't highlight menu text on mouseover in GTK+

* Fix textColor declaration scope error

* Simplify FocusManager connection management a bit

* Make the linter happy

* Decouple MenuBar view recoloring from rebuilding

This way we don't need to rebuild the subview each time a recolor
is needed, e.g. when window focus changes or the system theme changes

* Don't iterate child views if we don't need to

* Move variable declaration outside of a loop

* More efficient iteration of MenuBar children

* Cleaner MenuButton bounds testing

* Fix oops

* Add a nullptr check in MenuBar::GetItemCount()

* Simplify iteration in MenuBar::RebuildChildren()

* Make the linter happy

* Fix signed-unsigned comparison

* Remove declarations of nonexistent methods

* Make SubmenuButton accessor const

* Cleaner accelerator iteration

* Windows fixes
2018-03-17 19:45:14 +09:00
Charles Kerr
663e1e059b net: change mime type deduction in Change URLRequestAsarJob (#12319) (#12333) 2018-03-17 19:28:37 +09:00
John Kleinschmidt
433aba34e6 Fix AttributeError: 'dict' object has no attribute 'required' (#12307)
(cherry picked from commit 71c3483f55)
2018-03-16 10:23:22 +09:00
trop[bot]
bd33e7198e 🔧 Fix security warning (#12313) 2018-03-16 07:22:36 +09:00
John Kleinschmidt
e1b19140e5 Bump v2.0.0-beta.4 2018-03-15 08:55:16 -04:00
trop[bot]
4632ade7ae Document BrowserView.{destroy,isDestroyed} (#12299) 2018-03-15 16:37:19 +09:00
trop[bot]
b32f332ce3 Backport (2-0-x) - Set appropriate defaults for webview options (#12292)
* Persist defaults to webPreferences object to JS land can read the inferred values instead of just user defined values

* Test inherited default propogation

* Refactor to remove coupling from fetching values and defaults

* Test description type

* Fix up tests
2018-03-15 15:06:40 +09:00
trop[bot]
6ff0d744ee Backport (2-0-x) - Fix require on network share path (#12287)
* first pass at server/network require fix

* refactor for clarity
2018-03-15 12:26:52 +09:00
John Kleinschmidt
37cbf5e4f1 Merge pull request #12280 from trop-bot/2-0-x-bp-switching-all-emails-to-@electronjs.org-domain-1521056557166
Backport (2-0-x) - Switching all emails to `@electronjs.org` domain
2018-03-14 16:33:10 -04:00
John Kleinschmidt
f48f486412 Merge pull request #12249 from electron/auto-release-updates
Auto release updates
2018-03-14 16:32:12 -04:00
Jacob Groundwater
018b676efd Change Contact Emails 2018-03-14 19:42:43 +00:00
John Kleinschmidt
c9e5d17950 Fix autogeneration of release notes 2018-03-14 09:22:25 -04:00
John Kleinschmidt
b1dd013425 Upgrade to node 8 2018-03-14 09:22:25 -04:00
John Kleinschmidt
7a91c5668f Skip prompting for version when running auto build 2018-03-14 09:22:24 -04:00
John Kleinschmidt
2f47b71211 Disable mips release builds
mips builds don't currently work for 2.0.0
2018-03-14 09:22:24 -04:00
Samuel Attard
e8a7cc576e fix remote setInterval flake (#12265) 2018-03-14 15:42:44 +09:00
Cheng Zhao
c00b1ac669 Update libcc to fix private API usage in mas build (#12264) 2018-03-14 15:06:42 +09:00
trop[bot]
c4bde8853f add missing report.length > 1 assertion (#12262) 2018-03-14 14:45:06 +09:00
trop[bot]
ab77b55a90 Backport (2-0-x) - Enable easy rebuild of native modules for unreleased electron (#12260)
* Enable easy rebuild of native modules for unreleased electron

Sometimes when developing locally (as I found this morning) you want to rebuild native modules
against an unreleased version of Electron (in this case local master).  This PR adds a simple
script to launch a local HTTP server that generates and hosts the required header and checksum
files to rebuild modules.  So far only tested on macOS but should work on all OS's

* Allow custom port

* clean up serve script

* make optionality more obvious
2018-03-14 13:34:54 +09:00
trop[bot]
05b0948dd0 Fixed passing of exception to the system crash handler (#12259) 2018-03-14 12:58:26 +09:00
trop[bot]
c9e2140bca Backport - fix: Ensure that getLastCrashReport() is actually the last crash report (#12255)
* 🔧 Sort crashes

* 🔧 Actually test the method

* 🔪 Cut typo

* 👷 Fancy test

* 👷 Tests, how do they work

* 🔧 Linter's gotta lint
2018-03-14 11:36:58 +09:00
Cheng Zhao
9843ce743e Merge pull request #12218 from electron/backport_double_preload_2_0_patch
browser: fix preload loading twice in 2.x
2018-03-14 10:27:42 +09:00
Robo
c846f677c9 browser: fix null pointer dereference with getWebPreferences api (#12245)
* add failing spec

* devtools webContents don't have associated webPreferences
2018-03-14 06:06:51 +09:00
John Kleinschmidt
643dd55e07 Merge pull request #12247 from trop-bot/2-0-x-bp-spec--isolate-sw-file-scheme-spec-storage-with-temp-partition-1520962317089
Backport - spec: isolate sw file scheme spec storage with temp partition
2018-03-13 14:33:07 -04:00
deepak1556
d2045b93b7 spec: isolate sw file scheme spec storage with temp partition 2018-03-13 17:32:04 +00:00
John Kleinschmidt
c22d53be5c Merge pull request #12239 from electron/update-libcc-2.x
update libcc ref for 2.x
2018-03-13 11:35:44 -04:00
trop[bot]
e9d28f9b14 Backport - Parent's visibility trumps inherited 'show' option (#12244)
* Parent's visibility trumps inherited 'show' option

* Add tests

* Remove unnecessary work when merging options

* Use idiomatic ES6 when merging options

* Apply further ES6 bikeshedding
2018-03-13 23:27:44 +09:00
deepak1556
7e53a4c72c update libcc ref for https://github.com/electron/libchromiumcontent/pull/476 2018-03-13 11:36:07 +09:00
trop-devel[bot]
515fbb6fc3 Backport - fix: Incorrect warnings in webviews (#12236)
* 🔧 Get correct webContents

* 🔧 Err, webPreferences
2018-03-13 11:34:32 +09:00
trop-devel[bot]
af4dfcf6fe Fix menubar toggle alt key detection on focus (#12235)
Reset alt keypress flag on window blur so switching window via
Alt+* window manager keybindings can't incedentally trigger
annoying menubar toggles
2018-03-13 11:25:55 +09:00
Charles Kerr
176abdbd80 Linux named notifications - 2-0-0 (#12229)
* Newer CI images (#12188)

* Bump electronbuilds/electron* versions

The linux-appname branch has been gathering dust for awhile.
Some of the versions in `master` are higher, and some of the
versions in `linux-appname` are higher to add libnotify.

This commit takes the higher of the two numbers in each case.

* Add libnotify to the Dockerfiles

* Linux named notifications (#12192)

* Set name & desktop-entry on Linux notifications

* DBusMock now honors verbose mode flag

* Disable DBus Notification tests on ia32

* Fix desktop-id notification edge case (#12216)

* Fix desktop-id notification edge case

* Extract-method platform_util::GetDesktopName()

This removes duplicated code from libnotify_notifications.cc
and atom/common/linux/application_info.cc.

* Check for empty case in GetDesktopName().

* Move GetDesktopName() to brightray::util

* Remove unnecessary changes in platform_util

* Add a brightray::platform_util namespace

* Bump CI
2018-03-13 11:13:34 +09:00
Charles Kerr
cda7b8ccc8 clean planned breaking changes for 3.0 (#12145) (#12222) 2018-03-12 16:09:58 +09:00
deepak1556
1a43ba50b6 move ipc from rvh to rfh 2018-03-12 14:30:42 +09:00
Cheng Zhao
1174fc0ab8 Skip client-certificate test for Linux (#12213) 2018-03-12 09:25:43 +09:00
John Kleinschmidt
3c5ba35d63 Bump v2.0.0-beta.3 2018-03-09 09:15:39 -05:00
Cheng Zhao
0f143fdba0 Merge pull request #12182 from electron/update-libcc-2-0-x
Update to latest libchromiumcontent for 2-0-x
2018-03-09 10:16:43 +09:00
John Kleinschmidt
99ae56b782 Add configurable mocha timeout
Adding an environment variable, MOCHA_TIMEOUT that can be set for slower CI platforms
2018-03-08 16:29:31 -05:00
Aleš Pergl
5471bc313f Use content origin in screen coordinates for calculating popup menu position (#12181) 2018-03-09 05:55:31 +09:00
John Kleinschmidt
b0077241ee Update to latest libchromiumcontent for 2-0-x 2018-03-08 15:12:29 -05:00
John Kleinschmidt
bb40bc4aca Add logic to support automatic releases (#12177) 2018-03-09 02:46:06 +09:00
John Kleinschmidt
76fb7ee87c Allow CI testing on arm64 hardware for 2-0-x (#12178)
* Allow CI building on arm64 hardware

* Use bundled freetype from Chromium

(cherry picked from commit 51f89048d6)
2018-03-09 02:21:55 +09:00
Alexey Kuzmin
bfc0e3f266 Merge pull request #12174 from electron/cp-2-0-x/12059
Merge pull request #12059 from electron/add-tabbedwindow-warning
2018-03-08 15:13:37 +01:00
Alexey Kuzmin
48e068997b More vibrancy fixes (#12157) (#12171)
* Only set title bar to transparent when vibrant with a custom titlebar
* Correctly set the transparent state of the GpuSwitcher so vibrancy works on reload
* Document case where using frame: false without custom titleBarStyle and vibrant

(cherry picked from commit 8c138e74be)
2018-03-08 08:51:36 -05:00
Alexey Kuzmin
f443974f3d Merge pull request #12043 from kaylieEB/fix-menu-item (#12170)
Fix context menu click callback

(cherry picked from commit cc608a3fb0)
2018-03-08 08:43:38 -05:00
shelley vohr
36505ae00e Merge pull request #12059 from electron/add-tabbedwindow-warning
add warning when addTabbedWindow is called on self

(cherry picked from commit dfa1dc43df)
2018-03-08 14:33:10 +01:00
Charles Kerr
b330ff8004 Removals come >=1 major release after deprecation. (#12164) 2018-03-08 11:18:36 +09:00
John Kleinschmidt
6cda9460ea Merge pull request #12161 from electron/backport-flake-fixes
Backport flake fixes (2-0-x)
2018-03-07 14:09:14 -05:00
Charles Kerr
2cac654974 Exit gracefully on linux (#12139)
* Fix timing issue in singleton fixture.

Singleton now sends the "we've started" message out only after it's
received a `'ready'` event from `app`. Previously it sent the message
out immediately, resulting in the parent test trying to manipulate it
before Singleton's event loop was fully bootstrapped.

* Check for graceful exits on Linux, too.

Rewrite the "exits gracefully on macos" spec to run on Linux too.

* Check for graceful exits everywhere.

* Tweak comment

* Better error logging in api-app-spec.js. (#12122)

In the 'exits gracefully' test for app.exit(exitCode),
print the relevant error information if the test fails.

* Run the exit-gracefully test on macOS and Linux.

Windows does not support sending signals, but Node.js offers some
emulation with process.kill(), and subprocess.kill(). Sending signal 0
can be used to test for the existence of a process. Sending SIGINT,
SIGTERM, and SIGKILL cause the unconditional termination of the target
process.

So, we'll need a different approach if we want to test this in win32.
2018-03-07 12:45:26 -05:00
shelley vohr
5a210f3d7a Merge pull request #12137 from electron/deprecate-getMenuBatHeight-2.0.x
Deprecate screen.getMenuBarHeight (2.0.x)
2018-03-06 07:38:53 -08:00
Alexey Kuzmin
4bb10c10e4 Merge pull request #12133 from electron/update-libcc
Update libchromiumcontent for 2-0-x
2018-03-06 12:51:58 +01:00
Shelley Vohr
c0076d9c52 remove screen.getMenuBarHeight spec 2018-03-05 21:00:55 -05:00
Shelley Vohr
95539c5b63 deprecate screen.getMenuBarHeight 2018-03-05 21:00:50 -05:00
John Kleinschmidt
4f8ca2f03a Update to latest libchromiumcontent
Update to get electron/libchromiumcontent#463 security fix
2018-03-05 15:12:02 -05:00
John Kleinschmidt
c9b92aebd3 Bump v2.0.0-beta.2 2018-03-05 13:14:27 -05:00
Cheng Zhao
6d3f60374e Merge pull request #12087 from electron/fix-dock-menu-gc-2-0-x
Fix crash when setting dock menu (2.0.x)
2018-03-02 08:39:03 +09:00
Cheng Zhao
8703298e9d spec: Test garbage collecting dock menu 2018-03-01 09:48:39 +09:00
Cheng Zhao
a42057aabd Fix dockMenu not being referenced in JavaScript 2018-03-01 09:48:39 +09:00
Cheng Zhao
bd2ab27c25 Merge pull request #12053 from electron/network-delegate-race
Fix network delegate race condition in 2-0-x
2018-02-27 08:47:20 +09:00
Cheng Zhao
1e6d7295cf Move the arguments instead of const referrencing
Safer and more efficient.
2018-02-26 09:34:49 -08:00
Cheng Zhao
1918da7c2e Remove the evil URLRequestContextGetter::network_delegate 2018-02-26 09:34:40 -08:00
Cheng Zhao
38345c7267 Fix race condition when getting network delegate 2018-02-26 09:34:32 -08:00
shelley vohr
c4742df1ee Merge pull request #12016 from electron/backport-release-updates
Backport fixes from running 2.0.0-beta.1 release to 2-0-x
2018-02-22 15:27:05 -05:00
John Kleinschmidt
5fc485043b Fixes from running 2.0.0-beta.1 release
This provides the following fixes:
1. Remove logic to delete release branch because that branch is no longer used.
2. Fix --validateRelease to not verifyShasums when release is in draft mode.

(cherry picked from commit fa6510a90c)
2018-02-22 11:26:30 -05:00
shelley vohr
967dcd3471 Merge pull request #12014 from electron/backport-version-fix
Fix deprecated API in tools/dump-version-info.js for 2-0-x
2018-02-22 09:28:52 -05:00
John Kleinschmidt
96f800552c Fix deprecated API in tools/dump-version-info.js 2018-02-22 09:00:37 -05:00
John Kleinschmidt
afcbb589b6 Bump v2.0.0-beta.1 2018-02-21 14:45:36 -05:00
John Kleinschmidt
4159103467 Use new release job 2018-02-21 14:41:18 -05:00
3330 changed files with 152148 additions and 256947 deletions

View File

@@ -1 +0,0 @@
config-staging

View File

@@ -1,76 +1,764 @@
version: 2.1
# Required for dynamic configuration
setup: true
# Orbs
orbs:
path-filtering: circleci/path-filtering@0.1.0
continuation: circleci/continuation@0.2.0
# All input parameters to pass to build config
parameters:
run-docs-only:
type: boolean
default: false
upload-to-storage:
type: string
default: '1'
run-build-linux:
type: boolean
default: false
run-build-mac:
type: boolean
default: false
run-linux-publish:
type: boolean
default: false
linux-publish-arch-limit:
type: enum
default: all
enum: ["all", "arm", "arm64", "x64", "ia32"]
run-macos-publish:
type: boolean
default: false
macos-publish-arch-limit:
type: enum
default: all
enum: ["all", "osx-x64", "osx-arm64", "mas-x64", "mas-arm64"]
version: 2
jobs:
generate-config:
electron-linux-arm:
docker:
- image: cimg/node:16.14
- image: electronbuilds/electron:0.0.7
environment:
TARGET_ARCH: arm
resource_class: 2xlarge
steps:
- checkout
- path-filtering/set-parameters:
base-revision: main
mapping: |
^((?!docs/).)*$ run-build-mac true
^((?!docs/).)*$ run-build-linux true
docs/.* run-docs-only true
^((?!docs/).)*$ run-docs-only false
- run:
name: Check for release
command: |
cd .circleci/config
yarn
export CIRCLECI_BINARY="$HOME/circleci"
curl -fLSs https://raw.githubusercontent.com/CircleCI-Public/circleci-cli/master/install.sh | DESTDIR=$CIRCLECI_BINARY bash
node build.js
name: Pack config.yml
- continuation/continue:
configuration_path: .circleci/config-staging/built.yml
parameters: /tmp/pipeline-parameters.json
if [ -n "${RUN_RELEASE_BUILD}" ]; then
echo 'release build triggered from api'
echo 'export ELECTRON_RELEASE=1 TRIGGERED_BY_API=1' >> $BASH_ENV
fi
- run:
name: Bootstrap
command: |
if [ "$ELECTRON_RELEASE" == "1" ]; then
echo 'Bootstrapping Electron for release build'
script/bootstrap.py --target_arch=$TARGET_ARCH
else
echo 'Bootstrapping Electron for debug build'
script/bootstrap.py --target_arch=$TARGET_ARCH --dev
fi
- run: npm run lint
- run:
name: Build
command: |
if [ "$ELECTRON_RELEASE" == "1" ]; then
echo 'Building Electron for release'
script/build.py -c R
else
echo 'Building Electron for debug'
script/build.py -c D
fi
- run:
name: Create distribution
command: |
if [ "$ELECTRON_RELEASE" == "1" ]; then
echo 'Creating Electron release distribution'
script/create-dist.py
else
echo 'Skipping create distribution because build is not for release'
fi
- run:
name: Upload distribution
command: |
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" != "1" ]; then
echo 'Uploading Electron release distribution to github releases'
script/upload.py
elif [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" == "1" ]; then
echo 'Uploading Electron release distribution to s3'
script/upload.py --upload_to_s3
else
echo 'Skipping upload distribution because build is not for release'
fi
- run:
name: Optionally finish release
shell: /bin/sh
command: |
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$AUTO_RELEASE" == "true" ]; then
echo 'Trying to finish release'
node script/release.js --validateRelease --automaticRelease
releaseExitCode=$?
if [ $releaseExitCode -eq 0 ]; then
echo 'Release is ready to go; releasing'
node script/release.js--automaticRelease
if [ $releaseExitCode -eq 0 ]; then
echo 'Release successful, now publishing to npm'
echo "//registry.npmjs.org/:_authToken=$ELECTRON_NPM_TOKEN" >> ~/.npmrc
npm run publish-to-npm
echo 'Release has been published to npm'
fi
else
echo 'Release is not complete, skipping publish for now'
fi
else
echo 'Skipping finishing release because build is not for release'
fi
- run:
name: Zip out directory
command: |
if [ "$ELECTRON_RELEASE" != "1" ]; then
zip -r electron.zip out/D
fi
- persist_to_workspace:
root: /home/builduser
paths:
- project/out
- store_artifacts:
path: electron.zip
electron-linux-arm-test:
machine: true
steps:
- attach_workspace:
at: /tmp/workspace
- checkout
- run:
name: Test in ARM docker container
command: |
if [ "$ELECTRON_RELEASE" != "1" ]; then
docker run --rm --privileged multiarch/qemu-user-static:register --reset
docker run -it \
--mount type=bind,source=/tmp/workspace,target=/tmp/workspace \
--rm electronbuilds/electronarm7:0.0.5 > version.txt
cat version.txt
if grep -q `script/get-version.py` version.txt; then
echo "Versions match"
else
echo "Versions do not match"
exit 1
fi
else
echo "Skipping test for release build"
fi
electron-linux-arm64:
docker:
- image: electronbuilds/electron:0.0.7
environment:
TARGET_ARCH: arm64
resource_class: 2xlarge
steps:
- checkout
- run:
name: Check for release
command: |
if [ -n "${RUN_RELEASE_BUILD}" ]; then
echo 'release build triggered from api'
echo 'export ELECTRON_RELEASE=1 TRIGGERED_BY_API=1' >> $BASH_ENV
fi
- run:
name: Bootstrap
command: |
if [ "$ELECTRON_RELEASE" == "1" ]; then
echo 'Bootstrapping Electron for release build'
script/bootstrap.py --target_arch=$TARGET_ARCH
else
echo 'Bootstrapping Electron for debug build'
script/bootstrap.py --target_arch=$TARGET_ARCH --dev
fi
- run: npm run lint
- run:
name: Build
command: |
if [ "$ELECTRON_RELEASE" == "1" ]; then
echo 'Building Electron for release'
script/build.py -c R
else
echo 'Building Electron for debug'
script/build.py -c D
fi
- run:
name: Create distribution
command: |
if [ "$ELECTRON_RELEASE" == "1" ]; then
echo 'Creating Electron release distribution'
script/create-dist.py
else
echo 'Skipping create distribution because build is not for release'
fi
- run:
name: Upload distribution
command: |
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" != "1" ]; then
echo 'Uploading Electron release distribution to github releases'
script/upload.py
elif [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" == "1" ]; then
echo 'Uploading Electron release distribution to s3'
script/upload.py --upload_to_s3
else
echo 'Skipping upload distribution because build is not for release'
fi
- run:
name: Optionally finish release
shell: /bin/sh
command: |
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$AUTO_RELEASE" == "true" ]; then
echo 'Trying to finish release'
node script/release.js --validateRelease --automaticRelease
releaseExitCode=$?
if [ $releaseExitCode -eq 0 ]; then
echo 'Release is ready to go; releasing'
node script/release.js--automaticRelease
if [ $releaseExitCode -eq 0 ]; then
echo 'Release successful, now publishing to npm'
echo "//registry.npmjs.org/:_authToken=$ELECTRON_NPM_TOKEN" >> ~/.npmrc
npm run publish-to-npm
echo 'Release has been published to npm'
fi
else
echo 'Release is not complete, skipping publish for now'
fi
else
echo 'Skipping finishing release because build is not for release'
fi
- run:
name: Zip out directory
command: |
if [ "$ELECTRON_RELEASE" != "1" ]; then
zip -r electron.zip out/D
fi
- persist_to_workspace:
root: /home/builduser
paths:
- project/out
- store_artifacts:
path: electron.zip
electron-linux-arm64-test:
machine: true
steps:
- attach_workspace:
at: /tmp/workspace
- checkout
- run:
name: Test in ARM64 docker container
command: |
if [ "$ELECTRON_RELEASE" != "1" ]; then
docker run --rm --privileged multiarch/qemu-user-static:register --reset
docker run -it \
--mount type=bind,source=/tmp/workspace,target=/tmp/workspace \
--rm electronbuilds/electronarm64:0.0.6 > version.txt
cat version.txt
if grep -q `script/get-version.py` version.txt; then
echo "Versions match"
else
echo "Versions do not match"
exit 1
fi
else
echo "Skipping test for release build"
fi
electron-linux-ia32:
docker:
- image: electronbuilds/electron:0.0.7
environment:
TARGET_ARCH: ia32
DISPLAY: ':99.0'
resource_class: xlarge
steps:
- checkout
- run:
name: Setup for headless testing
command: sh -e /etc/init.d/xvfb start
- run:
name: Check for release
command: |
if [ -n "${RUN_RELEASE_BUILD}" ]; then
echo 'release build triggered from api'
echo 'export ELECTRON_RELEASE=1 TRIGGERED_BY_API=1' >> $BASH_ENV
fi
- run:
name: Bootstrap
command: |
if [ "$ELECTRON_RELEASE" == "1" ]; then
echo 'Bootstrapping Electron for release build'
script/bootstrap.py --target_arch=$TARGET_ARCH
else
echo 'Bootstrapping Electron for debug build'
script/bootstrap.py --target_arch=$TARGET_ARCH --dev
fi
- run: npm run lint
- run:
name: Build
command: |
if [ "$ELECTRON_RELEASE" == "1" ]; then
echo 'Building Electron for release'
script/build.py -c R
else
echo 'Building Electron for debug'
script/build.py -c D
fi
- run:
name: Create distribution
command: |
if [ "$ELECTRON_RELEASE" == "1" ]; then
echo 'Creating Electron release distribution'
script/create-dist.py
else
echo 'Skipping create distribution because build is not for release'
fi
- run:
name: Upload distribution
command: |
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" != "1" ]; then
echo 'Uploading Electron release distribution to github releases'
script/upload.py
elif [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" == "1" ]; then
echo 'Uploading Electron release distribution to s3'
script/upload.py --upload_to_s3
else
echo 'Skipping upload distribution because build is not for release'
fi
- run:
name: Optionally finish release
shell: /bin/sh
command: |
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$AUTO_RELEASE" == "true" ]; then
echo 'Trying to finish release'
node script/release.js --validateRelease --automaticRelease
releaseExitCode=$?
if [ $releaseExitCode -eq 0 ]; then
echo 'Release is ready to go; releasing'
node script/release.js--automaticRelease
if [ $releaseExitCode -eq 0 ]; then
echo 'Release successful, now publishing to npm'
echo "//registry.npmjs.org/:_authToken=$ELECTRON_NPM_TOKEN" >> ~/.npmrc
npm run publish-to-npm
echo 'Release has been published to npm'
fi
else
echo 'Release is not complete, skipping publish for now'
fi
else
echo 'Skipping finishing release because build is not for release'
fi
- run:
name: Test
environment:
MOCHA_FILE: junit/test-results.xml
MOCHA_REPORTER: mocha-junit-reporter
command: |
if [ "$ELECTRON_RELEASE" != "1" ]; then
echo 'Testing Electron debug build'
out/D/electron --version
mkdir junit
script/test.py --ci --rebuild_native_modules
else
echo 'Skipping testing on release build'
fi
- run:
name: Verify FFmpeg
command: |
if [ "$ELECTRON_RELEASE" != "1" ]; then
echo 'Verifying ffmpeg on debug build'
script/verify-ffmpeg.py
else
echo 'Skipping verify ffmpeg on release build'
fi
electron-linux-mips64el:
docker:
- image: electronbuilds/electron:0.0.7
environment:
TARGET_ARCH: mips64el
resource_class: xlarge
steps:
- checkout
- run:
name: Check for release
command: |
if [ -n "${RUN_RELEASE_BUILD}" ]; then
echo 'release build triggered from api'
echo 'export ELECTRON_RELEASE=1 TRIGGERED_BY_API=1' >> $BASH_ENV
fi
- run:
name: Bootstrap
command: |
if [ "$ELECTRON_RELEASE" == "1" ]; then
echo 'Bootstrapping Electron for release build'
script/bootstrap.py --target_arch=$TARGET_ARCH
else
echo 'Bootstrapping Electron for debug build'
script/bootstrap.py --target_arch=$TARGET_ARCH --dev
fi
- run: npm run lint
- run:
name: Build
command: |
if [ "$ELECTRON_RELEASE" == "1" ]; then
echo 'Building Electron for release'
script/build.py -c R
else
echo 'Building Electron for debug'
script/build.py -c D
fi
- run:
name: Create distribution
command: |
if [ "$ELECTRON_RELEASE" == "1" ]; then
echo 'Creating Electron release distribution'
script/create-dist.py
else
echo 'Skipping create distribution because build is not for release'
fi
- run:
name: Upload distribution
command: |
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" != "1" ]; then
echo 'Uploading Electron release distribution to github releases'
script/upload.py
elif [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" == "1" ]; then
echo 'Uploading Electron release distribution to s3'
script/upload.py --upload_to_s3
else
echo 'Skipping upload distribution because build is not for release'
fi
- run:
name: Optionally finish release
shell: /bin/sh
command: |
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$AUTO_RELEASE" == "true" ]; then
echo 'Trying to finish release'
node script/release.js --validateRelease --automaticRelease
releaseExitCode=$?
if [ $releaseExitCode -eq 0 ]; then
echo 'Release is ready to go; releasing'
node script/release.js--automaticRelease
if [ $releaseExitCode -eq 0 ]; then
echo 'Release successful, now publishing to npm'
echo "//registry.npmjs.org/:_authToken=$ELECTRON_NPM_TOKEN" >> ~/.npmrc
npm run publish-to-npm
echo 'Release has been published to npm'
fi
else
echo 'Release is not complete, skipping publish for now'
fi
else
echo 'Skipping finishing release because build is not for release'
fi
electron-linux-x64:
docker:
- image: electronbuilds/electron:0.0.7
environment:
TARGET_ARCH: x64
DISPLAY: ':99.0'
resource_class: xlarge
steps:
- checkout
- run:
name: Setup for headless testing
command: sh -e /etc/init.d/xvfb start
- run:
name: Check for release
command: |
if [ -n "${RUN_RELEASE_BUILD}" ]; then
echo 'release build triggered from api'
echo 'export ELECTRON_RELEASE=1 TRIGGERED_BY_API=1' >> $BASH_ENV
fi
- run:
name: Bootstrap
command: |
if [ "$ELECTRON_RELEASE" == "1" ]; then
echo 'Bootstrapping Electron for release build'
script/bootstrap.py --target_arch=$TARGET_ARCH
else
echo 'Bootstrapping Electron for debug build'
script/bootstrap.py --target_arch=$TARGET_ARCH --dev
fi
- run: npm run lint
- run:
name: Build
command: |
if [ "$ELECTRON_RELEASE" == "1" ]; then
echo 'Building Electron for release'
script/build.py -c R
else
echo 'Building Electron for debug'
script/build.py -c D
fi
- run:
name: Create distribution
command: |
if [ "$ELECTRON_RELEASE" == "1" ]; then
echo 'Creating Electron release distribution'
script/create-dist.py
else
echo 'Skipping create distribution because build is not for release'
fi
- run:
name: Upload distribution
command: |
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" != "1" ]; then
echo 'Uploading Electron release distribution to github releases'
script/upload.py
elif [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" == "1" ]; then
echo 'Uploading Electron release distribution to s3'
script/upload.py --upload_to_s3
else
echo 'Skipping upload distribution because build is not for release'
fi
- run:
name: Optionally finish release
shell: /bin/sh
command: |
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$AUTO_RELEASE" == "true" ]; then
echo 'Trying to finish release'
node script/release.js --validateRelease --automaticRelease
releaseExitCode=$?
if [ $releaseExitCode -eq 0 ]; then
echo 'Release is ready to go; releasing'
node script/release.js--automaticRelease
if [ $releaseExitCode -eq 0 ]; then
echo 'Release successful, now publishing to npm'
echo "//registry.npmjs.org/:_authToken=$ELECTRON_NPM_TOKEN" >> ~/.npmrc
npm run publish-to-npm
echo 'Release has been published to npm'
fi
else
echo 'Release is not complete, skipping publish for now'
fi
else
echo 'Skipping finishing release because build is not for release'
fi
- run:
name: Test
environment:
MOCHA_FILE: junit/test-results.xml
MOCHA_REPORTER: mocha-junit-reporter
command: |
if [ "$ELECTRON_RELEASE" != "1" ]; then
echo 'Testing Electron debug build'
mkdir junit
script/test.py --ci --rebuild_native_modules
else
echo 'Skipping testing on release build'
fi
- run:
name: Verify FFmpeg
command: |
if [ "$ELECTRON_RELEASE" != "1" ]; then
echo 'Verifying ffmpeg on debug build'
script/verify-ffmpeg.py
else
echo 'Skipping verify ffmpeg on release build'
fi
- run:
name: Generate Typescript Definitions
command: npm run create-typescript-definitions
- store_test_results:
path: junit
- store_artifacts:
path: junit
- store_artifacts:
path: out/electron.d.ts
- store_artifacts:
path: out/electron-api.json
electron-osx-x64:
environment:
TARGET_ARCH: x64
macos:
xcode: "9.0"
resource_class: xlarge
steps:
- checkout
- run:
name: Reclaim disk space
command: |
df -h
sudo rm -rf /Library/Developer/CoreSimulator
df -h
sysctl -n hw.ncpu
- run:
name: Check for release
command: |
if [ -n "${RUN_RELEASE_BUILD}" ]; then
echo 'release build triggered from api'
echo 'export ELECTRON_RELEASE=1 TRIGGERED_BY_API=1' >> $BASH_ENV
fi
- run:
name: Bootstrap
command: |
if [ "$ELECTRON_RELEASE" == "1" ]; then
echo 'Bootstrapping Electron for release build'
script/bootstrap.py --target_arch=$TARGET_ARCH
else
echo 'Bootstrapping Electron for debug build'
script/bootstrap.py --target_arch=$TARGET_ARCH --dev
fi
- run: npm run lint
- run:
name: Build
command: |
if [ "$ELECTRON_RELEASE" == "1" ]; then
echo 'Building Electron for release'
script/build.py -c R
else
echo 'Building Electron for debug'
script/build.py -c D
fi
- run:
name: Create distribution
command: |
if [ "$ELECTRON_RELEASE" == "1" ]; then
echo 'Creating Electron release distribution'
script/create-dist.py
else
echo 'Skipping create distribution because build is not for release'
fi
- run:
name: Upload distribution
command: |
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" != "1" ]; then
echo 'Uploading Electron release distribution to github releases'
script/upload.py
elif [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" == "1" ]; then
echo 'Uploading Electron release distribution to s3'
script/upload.py --upload_to_s3
else
echo 'Skipping upload distribution because build is not for release'
fi
- run:
name: Test
environment:
MOCHA_FILE: junit/test-results.xml
MOCHA_REPORTER: mocha-junit-reporter
command: |
if [ "$ELECTRON_RELEASE" != "1" ]; then
echo 'Testing Electron debug build'
mkdir junit
script/test.py --ci --rebuild_native_modules
else
echo 'Skipping testing on release build'
fi
- run:
name: Verify FFmpeg
command: |
if [ "$ELECTRON_RELEASE" != "1" ]; then
echo 'Verifying ffmpeg on debug build'
script/verify-ffmpeg.py
else
echo 'Skipping verify ffmpeg on release build'
fi
- run:
name: Generate Typescript Definitions
command: npm run create-typescript-definitions
- store_test_results:
path: junit
- store_artifacts:
path: junit
- store_artifacts:
path: out/electron.d.ts
- store_artifacts:
path: out/electron-api.json
electron-mas-x64:
environment:
TARGET_ARCH: x64
MAS_BUILD: 1
macos:
xcode: "9.0"
resource_class: xlarge
steps:
- checkout
- run:
name: Reclaim disk space
command: |
df -h
sudo rm -rf /Library/Developer/CoreSimulator
df -h
sysctl -n hw.ncpu
- run:
name: Check for release
command: |
if [ -n "${RUN_RELEASE_BUILD}" ]; then
echo 'release build triggered from api'
echo 'export ELECTRON_RELEASE=1 TRIGGERED_BY_API=1' >> $BASH_ENV
fi
- run:
name: Bootstrap
command: |
if [ "$ELECTRON_RELEASE" == "1" ]; then
echo 'Bootstrapping Electron for release build'
script/bootstrap.py --target_arch=$TARGET_ARCH
else
echo 'Bootstrapping Electron for debug build'
script/bootstrap.py --target_arch=$TARGET_ARCH --dev
fi
- run: npm run lint
- run:
name: Build
command: |
if [ "$ELECTRON_RELEASE" == "1" ]; then
echo 'Building Electron for release'
script/build.py -c R
else
echo 'Building Electron for debug'
script/build.py -c D
fi
- run:
name: Create distribution
command: |
if [ "$ELECTRON_RELEASE" == "1" ]; then
echo 'Creating Electron release distribution'
script/create-dist.py
else
echo 'Skipping create distribution because build is not for release'
fi
- run:
name: Upload distribution
command: |
if [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" != "1" ]; then
echo 'Uploading Electron release distribution to github releases'
script/upload.py
elif [ "$ELECTRON_RELEASE" == "1" ] && [ "$TRIGGERED_BY_API" == "1" ]; then
echo 'Uploading Electron release distribution to s3'
script/upload.py --upload_to_s3
else
echo 'Skipping upload distribution because build is not for release'
fi
- run:
name: Test
environment:
MOCHA_FILE: junit/test-results.xml
MOCHA_REPORTER: mocha-junit-reporter
command: |
if [ "$ELECTRON_RELEASE" != "1" ]; then
echo 'Testing Electron debug build'
mkdir junit
script/test.py --ci --rebuild_native_modules
else
echo 'Skipping testing on release build'
fi
- run:
name: Verify FFmpeg
command: |
if [ "$ELECTRON_RELEASE" != "1" ]; then
echo 'Verifying ffmpeg on debug build'
script/verify-ffmpeg.py
else
echo 'Skipping verify ffmpeg on release build'
fi
- run:
name: Generate Typescript Definitions
command: npm run create-typescript-definitions
- store_test_results:
path: junit
- store_artifacts:
path: junit
- store_artifacts:
path: out/electron.d.ts
- store_artifacts:
path: out/electron-api.json
# Initial setup workflow
workflows:
setup:
version: 2
build-arm:
jobs:
- generate-config
- electron-linux-arm
- electron-linux-arm-test:
requires:
- electron-linux-arm
build-arm64:
jobs:
- electron-linux-arm64
- electron-linux-arm64-test:
requires:
- electron-linux-arm64
build-ia32:
jobs:
- electron-linux-ia32
build-x64:
jobs:
- electron-linux-x64
build-osx-x64:
jobs:
- electron-osx-x64
build-mas-x64:
jobs:
- electron-mas-x64

File diff suppressed because it is too large Load Diff

View File

@@ -1,34 +0,0 @@
const cp = require('child_process');
const fs = require('fs-extra');
const path = require('path');
const yaml = require('js-yaml');
const STAGING_DIR = path.resolve(__dirname, '..', 'config-staging');
function copyAndExpand(dir = './') {
const absDir = path.resolve(__dirname, dir);
const targetDir = path.resolve(STAGING_DIR, dir);
if (!fs.existsSync(targetDir)) {
fs.mkdirSync(targetDir);
}
for (const file of fs.readdirSync(absDir)) {
if (!file.endsWith('.yml')) {
if (fs.statSync(path.resolve(absDir, file)).isDirectory()) {
copyAndExpand(path.join(dir, file));
}
continue;
}
fs.writeFileSync(path.resolve(targetDir, file), yaml.dump(yaml.load(fs.readFileSync(path.resolve(absDir, file), 'utf8')), {
noRefs: true,
}));
}
}
if (fs.pathExists(STAGING_DIR)) fs.removeSync(STAGING_DIR);
copyAndExpand();
const output = cp.spawnSync(process.env.CIRCLECI_BINARY || 'circleci', ['config', 'pack', STAGING_DIR]);
fs.writeFileSync(path.resolve(STAGING_DIR, 'built.yml'), output.stdout.toString());

View File

@@ -1,51 +0,0 @@
executor:
name: linux-docker
size: medium
steps:
- checkout:
path: src/electron
- run:
name: Setup third_party Depot Tools
command: |
# "depot_tools" has to be checkout into "//third_party/depot_tools" so pylint.py can a "pylintrc" file.
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git src/third_party/depot_tools
echo 'export PATH="$PATH:'"$PWD"'/src/third_party/depot_tools"' >> $BASH_ENV
- run:
name: Download GN Binary
command: |
chromium_revision="$(grep -A1 chromium_version src/electron/DEPS | tr -d '\n' | cut -d\' -f4)"
gn_version="$(curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/DEPS?format=TEXT" | base64 -d | grep gn_version | head -n1 | cut -d\' -f4)"
cipd ensure -ensure-file - -root . \<<-CIPD
\$ServiceURL https://chrome-infra-packages.appspot.com/
@Subdir src/buildtools/linux64
gn/gn/linux-amd64 $gn_version
CIPD
echo 'export CHROMIUM_BUILDTOOLS_PATH="'"$PWD"'/src/buildtools"' >> $BASH_ENV
- run:
name: Download clang-format Binary
command: |
chromium_revision="$(grep -A1 chromium_version src/electron/DEPS | tr -d '\n' | cut -d\' -f4)"
sha1_path='buildtools/linux64/clang-format.sha1'
curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/${sha1_path}?format=TEXT" | base64 -d > "src/${sha1_path}"
download_from_google_storage.py --no_resume --no_auth --bucket chromium-clang-format -s "src/${sha1_path}"
- run:
name: Run Lint
command: |
# gn.py tries to find a gclient root folder starting from the current dir.
# When it fails and returns "None" path, the whole script fails. Let's "fix" it.
touch .gclient
# Another option would be to checkout "buildtools" inside the Electron checkout,
# but then we would lint its contents (at least gn format), and it doesn't pass it.
cd src/electron
node script/yarn install --frozen-lockfile
node script/yarn lint
- run:
name: Run Script Typechecker
command: |
cd src/electron
node script/yarn tsc -p tsconfig.script.json

View File

@@ -1,10 +0,0 @@
{
"name": "@electron/circleci-config",
"version": "0.0.0",
"private": true,
"license": "MIT",
"dependencies": {
"fs-extra": "^10.1.0",
"js-yaml": "^4.1.0"
}
}

View File

@@ -1,43 +0,0 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
argparse@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
fs-extra@^10.1.0:
version "10.1.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf"
integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==
dependencies:
graceful-fs "^4.2.0"
jsonfile "^6.0.1"
universalify "^2.0.0"
graceful-fs@^4.1.6, graceful-fs@^4.2.0:
version "4.2.10"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
js-yaml@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
dependencies:
argparse "^2.0.1"
jsonfile@^6.0.1:
version "6.1.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
dependencies:
universalify "^2.0.0"
optionalDependencies:
graceful-fs "^4.1.6"
universalify@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==

View File

@@ -1,7 +0,0 @@
#!/bin/bash
set -e
mkdir -p ~/.ssh
echo "|1|B3r+7aO0/x90IdefihIjxIoJrrk=|OJddGDfhbuLFc1bUyy84hhIw57M= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
|1|rGlEvW55DtzNZp+pzw9gvyOyKi4=|LLWr+7qlkAlw3YGGVfLHHxB/kR0= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==" >> ~/.ssh/known_hosts

View File

@@ -1,59 +0,0 @@
# Electron Dev on Codespaces
Welcome to the Codespaces Electron Developer Environment.
## Quick Start
Upon creation of your codespace you should have [build tools](https://github.com/electron/build-tools) installed and an initialized gclient checkout of Electron. In order to build electron you'll need to run the following commands.
```bash
e sync -vv
e build
```
The initial sync will take approximately ~30 minutes and the build will take ~8 minutes. Incremental syncs and incremental builds are substantially quicker.
## Directory Structure
Codespaces doesn't lean very well into gclient based checkouts, the directory structure is slightly strange. There are two locations for the `electron` checkout that both map to the same files under the hood.
```graphql
# Primary gclient checkout container
/workspaces/gclient/*
src/* - # Chromium checkout
electron - # Electron checkout
# Symlinked Electron checkout (identical to the above)
/workspaces/electron
```
## Goma
If you are a maintainer [with Goma access](../docs/development/goma.md) it should be automatically configured and authenticated when you spin up a new codespaces instance. You can validate this by checking `e d goma_auth info` or by checking that your build-tools configuration has a goma mode of `cluster`.
## Running Electron
You can run Electron in a few ways. If you just want to see if it launches:
```bash
# Enter an interactive JS prompt headlessly
xvfb-run e start -i
```
But if you want to actually see Electron you will need to use the built-in VNC capability. If you click "Ports" in codespaces and then open the `VNC web client` forwarded port you should see a web based VNC portal in your browser. When you are asked for a password use `builduser`.
Once in the VNC UI you can open `Applications -> System -> XTerm` which will open a VNC based terminal app and then you can run `e start` like normal and Electron will open in your VNC session.
## Running Tests
You run tests via build-tools and `xvfb`.
```bash
# Run all tests
xvfb-run e test
# Run the main process tests
xvfb-run e test --runners=main
# Run the old remote tests
xvfb-run e test --runners=remote
```

View File

@@ -1,43 +0,0 @@
{
"dockerComposeFile": "docker-compose.yml",
"service": "buildtools",
"onCreateCommand": ".devcontainer/on-create-command.sh",
"workspaceFolder": "/workspaces/gclient/src/electron",
"extensions": [
"joeleinbinder.mojom-language",
"rafaelmaiolla.diff",
"surajbarkale.ninja",
"ms-vscode.cpptools",
"mutantdino.resourcemonitor",
"dbaeumer.vscode-eslint",
"shakram02.bash-beautify",
"marshallofsound.gnls-electron"
],
"settings": {
"[gn]": {
"editor.formatOnSave": true
},
"editor.tabSize": 2,
"bashBeautify.tabSize": 2
},
"forwardPorts": [8088, 6080, 5901],
"portsAttributes": {
"8088": {
"label": "Goma Control Panel",
"onAutoForward": "silent"
},
"6080": {
"label": "VNC web client (noVNC)",
"onAutoForward": "silent"
},
"5901": {
"label": "VNC TCP port",
"onAutoForward": "silent"
}
},
"hostRequirements": {
"storage": "32gb",
"cpus": 8
},
"remoteUser": "builduser"
}

View File

@@ -1,19 +0,0 @@
version: '3'
services:
buildtools:
image: ghcr.io/electron/devcontainer:27db4a3e3512bfd2e47f58cea69922da0835f1d9
volumes:
- ..:/workspaces/gclient/src/electron:cached
- /var/run/docker.sock:/var/run/docker.sock
command: /bin/sh -c "while sleep 1000; do :; done"
user: builduser
cap_add:
- SYS_PTRACE
security_opt:
- seccomp:unconfined

View File

@@ -1,74 +0,0 @@
#!/bin/bash
set -eo pipefail
buildtools=$HOME/.electron_build_tools
gclient_root=/workspaces/gclient
buildtools_configs=/workspaces/buildtools-configs
export PATH="$PATH:$buildtools/src"
# Create the persisted buildtools config folder
mkdir -p $buildtools_configs
rm -f $buildtools/configs
ln -s $buildtools_configs $buildtools/configs
# Write the gclient config if it does not already exist
if [ ! -f $gclient_root/.gclient ]; then
echo "solutions = [
{ \"name\" : \"src/electron\",
\"url\" : \"https://github.com/electron/electron\",
\"deps_file\" : \"DEPS\",
\"managed\" : False,
\"custom_deps\" : {
},
\"custom_vars\": {},
},
]
" >$gclient_root/.gclient
fi
# Write the default buildtools config file if it does
# not already exist
if [ ! -f $buildtools/configs/evm.testing.json ]; then
write_config() {
echo "
{
\"root\": \"/workspaces/gclient\",
\"goma\": \"$1\",
\"gen\": {
\"args\": [
\"import(\\\"//electron/build/args/testing.gn\\\")\",
\"import(\\\"/home/builduser/.electron_build_tools/third_party/goma.gn\\\")\"
],
\"out\": \"Testing\"
},
\"env\": {
\"CHROMIUM_BUILDTOOLS_PATH\": \"/workspaces/gclient/src/buildtools\",
\"GIT_CACHE_PATH\": \"/workspaces/gclient/.git-cache\"
},
\"remotes\": {
\"electron\": {
\"origin\": \"https://github.com/electron/electron.git\"
}
}
}
" >$buildtools/configs/evm.testing.json
}
# Start out as cache only
write_config cache-only
e use testing
# Attempt to auth to the goma service via codespaces tokens
# if it works we can use the goma cluster
export NOTGOMA_CODESPACES_TOKEN=$GITHUB_TOKEN
if e d goma_auth login; then
write_config cluster
fi
else
# Even if the config file existed we still need to re-auth with the goma
# cluster
NOTGOMA_CODESPACES_TOKEN=$GITHUB_TOKEN e d goma_auth login || true
fi

View File

@@ -1,2 +1,3 @@
*
!tools/xvfb-init.sh
!tools/run-electron.sh

View File

@@ -1,6 +0,0 @@
# These env vars are only necessary for creating Electron releases.
# See docs/development/releasing.md
APPVEYOR_CLOUD_TOKEN=
CIRCLE_TOKEN=
ELECTRON_GITHUB_TOKEN=

View File

@@ -1,54 +0,0 @@
{
"root": true,
"extends": "standard",
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"env": {
"browser": true
},
"rules": {
"semi": ["error", "always"],
"no-var": "error",
"no-unused-vars": "off",
"no-global-assign": "off",
"guard-for-in": "error",
"@typescript-eslint/no-unused-vars": ["error", {
"vars": "all",
"args": "after-used",
"ignoreRestSiblings": true
}],
"prefer-const": ["error", {
"destructuring": "all"
}],
"standard/no-callback-literal": "off",
"node/no-deprecated-api": "off"
},
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
"overrides": [
{
"files": "*.js",
"rules": {
"@typescript-eslint/no-unused-vars": "off"
}
},
{
"files": "*.ts",
"rules": {
"no-undef": "off",
"no-redeclare": "off",
"@typescript-eslint/no-redeclare": ["error"],
"no-use-before-define": "off"
}
},
{
"files": "*.d.ts",
"rules": {
"no-useless-constructor": "off",
"@typescript-eslint/no-unused-vars": "off"
}
}
]
}

View File

@@ -1,5 +0,0 @@
# Atom --> Electron rename
d9321f4df751fa32813fab1b6387bbd61bd681d0
34c4c8d5088fa183f56baea28809de6f2a427e02
# Enable JS Semicolons
5d657dece4102e5e5304d42e8004b6ad64c0fcda

14
.gitattributes vendored
View File

@@ -1,14 +0,0 @@
# `git apply` and friends don't understand CRLF, even on windows. Force those
# files to be checked out with LF endings even if core.autocrlf is true.
*.patch text eol=lf
patches/**/.patches merge=union
# Source code and markdown files should always use LF as line ending.
*.cc text eol=lf
*.mm text eol=lf
*.h text eol=lf
*.js text eol=lf
*.ts text eol=lf
*.py text eol=lf
*.ps1 text eol=lf
*.md text eol=lf

26
.github/CODEOWNERS vendored
View File

@@ -3,17 +3,19 @@
# https://help.github.com/articles/about-codeowners
# https://git-scm.com/docs/gitignore
# Upgrades WG
/patches/ @electron/patch-owners
DEPS @electron/wg-upgrades
# Everything that falls through the cracks:
* @electron/reviewers
# Releases WG
/npm/ @electron/wg-releases
/script/release @electron/wg-releases
# filename patterns
*browser_view* @electron/browserview
*notification* @electron/notifications
*pdf* @electron/printing
*printing* @electron/printing
*updater* @electron/updater
# Security WG
/lib/browser/devtools.ts @electron/wg-security
/lib/browser/guest-view-manager.ts @electron/wg-security
/lib/browser/guest-window-proxy.ts @electron/wg-security
/lib/browser/rpc-server.ts @electron/wg-security
/lib/renderer/security-warnings.ts @electron/wg-security
# directories
/.github/ @electron/hubbers
/default_app/ @electron/docs
/docs/ @electron/docs
/docs-translations/ @electron/i18n
/npm/ @electron/hubbers

35
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,35 @@
<!--
Thanks for opening an issue! A few things to keep in mind:
- The issue tracker is only for bugs and feature requests.
- Before reporting a bug, please try reproducing your issue against
the latest version of Electron.
- If you need general advice, join our Slack: http://atom-slack.herokuapp.com
-->
* Electron version:
* Operating system:
### Expected behavior
<!-- What do you think should happen? -->
### Actual behavior
<!-- What actually happens? -->
### How to reproduce
<!--
Your best chance of getting this bug looked at quickly is to provide a REPOSITORY that can be cloned and run.
You can fork https://github.com/electron/electron-quick-start and include a link to the branch with your changes.
If you provide a URL, please list the commands required to clone/setup/run your repo e.g.
$ git clone $YOUR_URL -b $BRANCH
$ npm install
$ npm start || electron .
-->

View File

@@ -1,80 +0,0 @@
name: Bug Report
description: Report an Electron bug
title: "[Bug]: "
labels: "bug :beetle:"
body:
- type: checkboxes
attributes:
label: Preflight Checklist
description: Please ensure you've completed all of the following.
options:
- label: I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/main/CONTRIBUTING.md) for this project.
required: true
- label: I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md) that this project adheres to.
required: true
- label: I have searched the [issue tracker](https://www.github.com/electron/electron/issues) for a bug report that matches the one I want to file, without success.
required: true
- type: input
attributes:
label: Electron Version
description: |
What version of Electron are you using?
Note: Please only report issues for [currently supported versions of Electron](https://www.electronjs.org/docs/latest/tutorial/support#currently-supported-versions).
placeholder: 17.0.0
validations:
required: true
- type: dropdown
attributes:
label: What operating system are you using?
options:
- Windows
- macOS
- Ubuntu
- Other Linux
- Other (specify below)
validations:
required: true
- type: input
attributes:
label: Operating System Version
description: What operating system version are you using? On Windows, click Start button > Settings > System > About. On macOS, click the Apple Menu > About This Mac. On Linux, use lsb_release or uname -a.
placeholder: "e.g. Windows 10 version 1909, macOS Catalina 10.15.7, or Ubuntu 20.04"
validations:
required: true
- type: dropdown
attributes:
label: What arch are you using?
options:
- x64
- ia32
- arm64 (including Apple Silicon)
- Other (specify below)
validations:
required: true
- type: input
attributes:
label: Last Known Working Electron version
description: What is the last version of Electron this worked in, if applicable?
placeholder: 16.0.0
- type: textarea
attributes:
label: Expected Behavior
description: A clear and concise description of what you expected to happen.
validations:
required: true
- type: textarea
attributes:
label: Actual Behavior
description: A clear description of what actually happens.
validations:
required: true
- type: input
attributes:
label: Testcase Gist URL
description: If you can reproduce the issue in a standalone test case, please use [Electron Fiddle](https://github.com/electron/fiddle) to create one and to publish it as a [GitHub gist](https://gist.github.com) and put the gist URL here. This is **the best way** to ensure this issue is triaged quickly.
placeholder: https://gist.github.com/...
- type: textarea
attributes:
label: Additional Information
description: If your problem needs further explanation, or if the issue you're seeing cannot be reproduced in a gist, please add more information here.

View File

@@ -1,40 +0,0 @@
name: Feature Request
description: Suggest an idea for Electron
title: "[Feature Request]: "
labels: "enhancement :sparkles:"
body:
- type: checkboxes
attributes:
label: Preflight Checklist
description: Please ensure you've completed all of the following.
options:
- label: I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/main/CONTRIBUTING.md) for this project.
required: true
- label: I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md) that this project adheres to.
required: true
- label: I have searched the [issue tracker](https://www.github.com/electron/electron/issues) for a feature request that matches the one I want to file, without success.
required: true
- type: textarea
attributes:
label: Problem Description
description: Please add a clear and concise description of the problem you are seeking to solve with this feature request.
validations:
required: true
- type: textarea
attributes:
label: Proposed Solution
description: Describe the solution you'd like in a clear and concise manner.
validations:
required: true
- type: textarea
attributes:
label: Alternatives Considered
description: A clear and concise description of any alternative solutions or features you've considered.
validations:
required: true
- type: textarea
attributes:
label: Additional Information
description: Add any other context about the problem here.
validations:
required: false

View File

@@ -1,30 +0,0 @@
name: Report Mac App Store Private API Rejection
description: Your app was rejected from the Mac App Store for using private API's
title: "[MAS Rejection]: "
body:
- type: checkboxes
attributes:
label: Preflight Checklist
description: Please ensure you've completed all of the following.
options:
- label: I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/main/CONTRIBUTING.md) for this project.
required: true
- label: I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md) that this project adheres to.
required: true
- type: input
attributes:
label: Electron Version
description: What version of Electron are you using?
placeholder: 12.0.0
validations:
required: true
- type: textarea
attributes:
label: Rejection Email
description: Paste the contents of your rejection email here, censoring any private information such as app names.
validations:
required: true
- type: textarea
attributes:
label: Additional Information
description: Add any other context about the problem here.

View File

@@ -1,20 +1,8 @@
#### Description of Change
<!--
Thank you for your Pull Request. Please provide a description above and review
the requirements below.
Contributors guide: https://github.com/electron/electron/blob/main/CONTRIBUTING.md
-->
Bug fixes and new features should include tests and possibly benchmarks.
#### Checklist
<!-- Remove items that do not apply. For completed items, change [ ] to [x]. -->
- [ ] PR description included and stakeholders cc'd
- [ ] `npm test` passes
- [ ] tests are [changed or added](https://github.com/electron/electron/blob/main/docs/development/testing.md)
- [ ] relevant documentation is changed or added
- [ ] [PR release notes](https://github.com/electron/clerk/blob/master/README.md) describe the change in a way relevant to app developers, and are [capitalized, punctuated, and past tense](https://github.com/electron/clerk/blob/master/README.md#examples).
#### Release Notes
Notes: <!-- Please add a one-line description for app developers to read in the release notes, or 'none' if no notes relevant to app developers. Examples and help on special cases: https://github.com/electron/clerk/blob/master/README.md#examples -->
Contributors guide: https://github.com/electron/electron/blob/master/CONTRIBUTING.md
-->

40
.github/config.yml vendored
View File

@@ -1,23 +1,25 @@
# Configuration for new-issue-welcome - https://github.com/behaviorbot/new-issue-welcome
# Comment to be posted to on first time issues
newIssueWelcomeComment: |
👋 Thanks for opening your first issue here! If you're reporting a 🐞 bug, please make sure you include steps to reproduce it. We get a lot of issues on this repo, so please be patient and we will get back to you as soon as we can.
To help make it easier for us to investigate your issue, please follow the [contributing guidelines](https://github.com/electron/electron/blob/master/CONTRIBUTING.md#submitting-issues).
# Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome
# Comment to be posted to on PRs from first time contributors in your repository
newPRWelcomeComment: |
💖 Thanks for opening this pull request! 💖
We use [semantic commit messages](https://github.com/electron/electron/blob/main/docs/development/pull-requests.md#commit-message-guidelines) to streamline the release process. Before your pull request can be merged, you should **update your pull request title** to start with a semantic prefix.
![typing cat](https://user-images.githubusercontent.com/2289/36400158-2c7c589e-1584-11e8-81c7-bd34fd3c392b.gif)
Examples of commit messages with semantic prefixes:
- `fix: don't overwrite prevent_default if default wasn't prevented`
- `feat: add app.isPackaged() method`
- `docs: app.isDefaultProtocolClient is now available on Linux`
Things that will help get your PR across the finish line:
- Follow the JavaScript, C++, and Python [coding style](https://github.com/electron/electron/blob/main/docs/development/coding-style.md).
Here is a list of things that will help get it across the finish line:
- Follow the JavaScript, C++, and Python [coding style](https://github.com/electron/electron/blob/master/docs/development/coding-style.md).
- Run `npm run lint` locally to catch formatting errors earlier.
- Document any user-facing changes you've made following the [documentation styleguide](https://github.com/electron/electron/blob/main/docs/styleguide.md).
- Document any user-facing changes you've made following the [documentation styleguide](https://github.com/electron/electron/blob/master/docs/styleguide.md).
- Include tests when adding/changing behavior.
- Include screenshots and animated GIFs whenever possible.
We get a lot of pull requests on this repo, so please be patient and we will get back to you as soon as we can.
# Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge
@@ -26,16 +28,4 @@ newPRWelcomeComment: |
firstPRMergeComment: >
Congrats on merging your first pull request! 🎉🎉🎉
# Users authorized to run manual trop backports
authorizedUsers:
- alexeykuzmin
- ckerr
- codebytere
- deepak1556
- jkleinsc
- loc
- MarshallOfSound
- miniak
- mlaurencin
- nornagon
- zcbenz
# It is recommend to include as many gifs and emojis as possible

31
.github/stale.yml vendored
View File

@@ -1,14 +1,25 @@
daysUntilStale: 90
daysUntilClose: 30
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 45
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- discussion
- security 🔒
- "enhancement :sparkles:"
- fixme/bug
- fixme/crash
- fixme/regression
- fixme/security
- blocked
- blocking-stable
- needs-review
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale. **If this issue is still affecting you, please leave any comment** (for example, "bump"), and we'll keep it open. If you have any new additional information—in particular, if this is still reproducible in the [latest version of Electron](https://www.electronjs.org/releases/stable) or in the [beta](https://www.electronjs.org/releases/beta)—please include it with your comment!
This issue has been automatically marked as stale because it has not had
recent activity and is not currently prioritized. It will be closed
in a week if no further activity occurs :)
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: >
This issue has been closed as it was considered stale, this issue will not be
monitored. If this is a bug and you can reproduce this issue on a [supported
version of Electron](https://www.electronjs.org/docs/latest/tutorial/electron-timelines#timeline) please open a new issue and ensure a repro is provided.
If you still think this issue is relevant, please ping a maintainer or
leave a comment!

View File

@@ -1,24 +0,0 @@
name: Issue Labeled
on:
issues:
types: [labeled]
jobs:
issue-labeled:
runs-on: ubuntu-latest
steps:
- name: blocked/need-repro
if: github.event.label.name == 'blocked/need-repro'
uses: actions-cool/issues-helper@dad28fdb88da5f082c04659b7373d85790f9b135 # v3.3.0
with:
actions: 'create-comment'
body: |
Hello @${{ github.event.issue.user.login }}. Thanks for reporting this and helping to make Electron better!
Would it be possible for you to make a standalone testcase with only the code necessary to reproduce the issue? For example, [Electron Fiddle](https://www.electronjs.org/fiddle) is a great tool for making small test cases and makes it easy to publish your test case to a [gist](https://gist.github.com) that Electron maintainers can use.
Stand-alone test cases make fixing issues go more smoothly: it ensure everyone's looking at the same issue, it removes all unnecessary variables from the equation, and it can also provide the basis for automated regression tests.
Now adding the `blocked/need-repro` label for this reason. After you make a test case, please link to it in a followup comment. This issue will be closed in 10 days if the above is not addressed.

View File

@@ -1,33 +0,0 @@
name: Trigger Major Release Dependency Updates
on:
release:
types: [published]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jobs:
trigger_chromedriver:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag: v3
- name: Trigger New chromedriver Release
run: |
if [[ ${{ github.event.release.tag_name }} =~ ^v\d+\.\d+\.\d+$ ]]; then
gh api /repos/:owner/chromedriver/actions/workflows/release.yml/dispatches --input - <<< '{"ref":"main","inputs":{"version":"${{ github.event.release.tag_name }}"}}'
else
echo "Not releasing for version ${{ github.event.release.tag_name }}"
fi
trigger_mksnapshot:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag: v3
- name: Trigger New mksnapshot Release
run: |
if [[ ${{ github.event.release.tag_name }} =~ ^v\d+\.\d+\.\d+$ ]]; then
gh api /repos/:owner/mksnapshot/actions/workflows/release.yml/dispatches --input - <<< '{"ref":"main","inputs":{"version":"${{ github.event.release.tag_name }}"}}'
else
echo "Not releasing for version ${{ github.event.release.tag_name }}"
fi

View File

@@ -1,26 +0,0 @@
name: "Check Semantic Commit"
on:
pull_request_target:
types:
- opened
- edited
- synchronize
permissions:
contents: read
jobs:
main:
permissions:
pull-requests: read # for amannn/action-semantic-pull-request to analyze PRs
statuses: write # for amannn/action-semantic-pull-request to mark status of analyzed PR
name: Validate PR Title
runs-on: ubuntu-latest
steps:
- name: semantic-pull-request
uses: amannn/action-semantic-pull-request@v4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
validateSingleCommit: false

View File

@@ -1,62 +0,0 @@
name: Update AppVeyor Image
# Run chron daily Mon-Fri
on:
schedule:
- cron: '0 8 * * 1-5' # runs 8:00 every business day (see https://crontab.guru)
permissions:
contents: write
pull-requests: write
jobs:
bake-appveyor-image:
name: Bake AppVeyor Image
permissions:
contents: write
pull-requests: write # to create a new PR with updated Appveyor images
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
with:
fetch-depth: 0
- name: Yarn install
run: |
node script/yarn.js install --frozen-lockfile
- name: Set Repo for Commit
run: git config --global --add safe.directory $GITHUB_WORKSPACE
- name: Check AppVeyor Image
env:
APPVEYOR_TOKEN: ${{ secrets.APPVEYOR_TOKEN }}
run: |
node ./script/prepare-appveyor
if [ -f ./image_version.txt ]; then
echo "APPVEYOR_IMAGE_VERSION="$(cat image_version.txt)"" >> $GITHUB_ENV
rm image_version.txt
fi
- name: (Optionally) Update Appveyor Image
if: ${{ env.APPVEYOR_IMAGE_VERSION }}
uses: mikefarah/yq@1c7dc0e88aad311c89889bc5ce5d8f96931a1bd0 # v4.27.2
with:
cmd: yq '.image = "${{ env.APPVEYOR_IMAGE_VERSION }}"' "appveyor.yml" > "appveyor2.yml"
- name: (Optionally) Generate Commit Diff
if: ${{ env.APPVEYOR_IMAGE_VERSION }}
run: |
diff -w -B appveyor.yml appveyor2.yml > appveyor.diff || true
patch -f appveyor.yml < appveyor.diff
rm appveyor2.yml appveyor.diff
- name: (Optionally) Commit and Pull Request
if: ${{ env.APPVEYOR_IMAGE_VERSION }}
uses: peter-evans/create-pull-request@2b011faafdcbc9ceb11414d64d0573f37c774b04 # v4.2.3
with:
token: ${{ secrets.ACTIONS_GITHUB_TOKEN }}
commit-message: 'build: update appveyor image to latest version'
committer: GitHub <noreply@github.com>
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
signoff: false
branch: bump-appveyor-image
delete-branch: true
title: 'build: update appveyor image to latest version'
body: |
This PR updates appveyor.yml to the latest baked image, ${{ env.APPVEYOR_IMAGE_VERSION }}.

64
.gitignore vendored
View File

@@ -16,41 +16,35 @@
*.vcxproj.user
*.xcodeproj
/.idea/
/brightray/brightray.opensdf
/brightray/brightray.sdf
/brightray/brightray.sln
/brightray/brightray.suo
/brightray/brightray.v12.suo
/brightray/brightray.vcxproj*
/brightray/brightray.xcodeproj/
/build/
/dist/
/external_binaries/
/out/
/vendor/.gclient
/vendor/debian_jessie_amd64-sysroot/
/vendor/debian_jessie_arm-sysroot/
/vendor/debian_jessie_arm64-sysroot/
/vendor/debian_jessie_i386-sysroot/
/vendor/debian_jessie_mips64-sysroot/
/vendor/debian_wheezy_amd64-sysroot/
/vendor/debian_wheezy_arm-sysroot/
/vendor/debian_wheezy_i386-sysroot/
/vendor/gcc-4.8.3-d197-n64-loongson/
/vendor/readme-gcc483-loongson.txt
/vendor/download/
/vendor/llvm-build/
/vendor/llvm/
/vendor/npm/
/vendor/python_26/
/vendor/native_mksnapshot
/vendor/LICENSES.chromium.html
node_modules/
SHASUMS256.txt
**/package-lock.json
compile_commands.json
.envrc
# npm package
/npm/dist
/npm/path.txt
/npm/checksums.json
.npmrc
# Generated API definitions
electron-api.json
electron.d.ts
# Spec hash calculation
spec/.hash
# Eslint Cache
.eslintcache*
# Generated native addon files
/spec/fixtures/native-addon/echo/build/
# If someone runs tsc this is where stuff will end up
ts-gen
# Used to accelerate CI builds
.depshash
.depshash-target
# Used to accelerate builds after sync
patches/mtime-cache.json
spec/fixtures/logo.png
**/package-lock.json

30
.gitmodules vendored Normal file
View File

@@ -0,0 +1,30 @@
[submodule "vendor/node"]
path = vendor/node
url = https://github.com/electron/node.git
[submodule "vendor/depot_tools"]
path = vendor/depot_tools
url = https://chromium.googlesource.com/chromium/tools/depot_tools.git
[submodule "vendor/breakpad"]
path = vendor/breakpad
url = https://github.com/electron/chromium-breakpad.git
[submodule "vendor/native_mate"]
path = vendor/native_mate
url = https://github.com/electron/native-mate.git
[submodule "vendor/crashpad"]
path = vendor/crashpad
url = https://github.com/electron/crashpad.git
[submodule "vendor/requests"]
path = vendor/requests
url = https://github.com/kennethreitz/requests
[submodule "vendor/boto"]
path = vendor/boto
url = https://github.com/boto/boto.git
[submodule "vendor/pdf_viewer"]
path = vendor/pdf_viewer
url = https://github.com/electron/pdf-viewer.git
[submodule "vendor/gyp"]
path = vendor/gyp
url = https://github.com/electron/gyp
[submodule "vendor/libchromiumcontent"]
path = vendor/libchromiumcontent
url = https://github.com/electron/libchromiumcontent

View File

@@ -1,4 +0,0 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npm run precommit

View File

@@ -1,4 +0,0 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npm run prepack

View File

@@ -1,6 +0,0 @@
{
"default": false,
"no-trailing-spaces": {
"br_spaces": 0
}
}

View File

@@ -1,27 +0,0 @@
{
"commands-show-output": false,
"first-line-h1": false,
"header-increment": false,
"line-length": {
"code_blocks": false,
"tables": false,
"stern": true,
"line_length": -1
},
"no-bare-urls": false,
"no-blanks-blockquote": false,
"no-duplicate-header": {
"allow_different_nesting": true
},
"no-emphasis-as-header": false,
"no-hard-tabs": {
"code_blocks": false
},
"no-space-in-emphasis": false,
"no-trailing-punctuation": false,
"no-trailing-spaces": {
"br_spaces": 0
},
"single-h1": false,
"no-inline-html": false
}

1
.node-version Normal file
View File

@@ -0,0 +1 @@
v8.2.1

1
.nvmrc
View File

@@ -1 +0,0 @@
16

34
.travis.yml Normal file
View File

@@ -0,0 +1,34 @@
git:
depth: 10
notifications:
email: false
before_install:
- export BOTO_CONFIG=/dev/null
language: node_js
node_js:
- "4"
os:
- linux
- osx
env:
- TARGET_ARCH=x64
osx_image: xcode7.3
matrix:
include:
- os: linux
env: TARGET_ARCH=arm
- os: linux
env: TARGET_ARCH=ia32
- os: linux
env: TARGET_ARCH=arm64
allow_failures:
- os: osx
script: './script/cibuild'
branches:
only:
- master

1565
BUILD.gn

File diff suppressed because it is too large Load Diff

View File

@@ -1,135 +1,46 @@
# Code of Conduct
# Contributor Covenant Code of Conduct:
As a member project of the OpenJS Foundation, Electron uses [Contributor Covenant v2.0](https://contributor-covenant.org/version/2/0/code_of_conduct) as their code of conduct. The full text is included [below](#contributor-covenant-code-of-conduct) in English, and translations are available from the Contributor Covenant organisation:
## Our Pledge
* [contributor-covenant.org/translations](https://www.contributor-covenant.org/translations)
* [github.com/ContributorCovenant](https://github.com/ContributorCovenant/contributor_covenant/tree/release/content/version/2/0)
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Contributor Covenant Code of Conduct
## Our Standards
### Our Pledge
Examples of behavior that contributes to creating a positive environment include:
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
Examples of unacceptable behavior by participants include:
### Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
### Enforcement Responsibilities
## Our Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
### Scope
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
### Enforcement
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
[coc@electronjs.org](mailto:coc@electronjs.org).
All complaints will be reviewed and investigated promptly and fairly.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [coc@electronjs.org](mailto:coc@electronjs.org). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
### Enforcement Guidelines
## Attribution
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
This Code of Conduct is adapted from the [Contributor-Covenant][homepage], version 1.4, available at [https://contributor-covenant.org/version/1/4][version]
#### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
#### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
#### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
#### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
### Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
[homepage]: https://contributor-covenant.org
[version]: https://contributor-covenant.org/version/1/4/

View File

@@ -20,23 +20,13 @@ Issues are created [here](https://github.com/electron/electron/issues/new).
* [Triaging a Bug Report](https://electronjs.org/docs/development/issues#triaging-a-bug-report)
* [Resolving a Bug Report](https://electronjs.org/docs/development/issues#resolving-a-bug-report)
### Issue Closure
Bug reports will be closed if the issue has been inactive and the latest affected version no longer receives support. At the moment, Electron maintains its three latest major versions, with a new major version being released every 8 weeks. (For more information on Electron's release cadence, see [this blog post](https://electronjs.org/blog/8-week-cadence).)
_If an issue has been closed and you still feel it's relevant, feel free to ping a maintainer or add a comment!_
### Languages
We accept issues in *any* language.
When an issue is posted in a language besides English, it is acceptable and encouraged to post an English-translated copy as a reply.
Anyone may post the translated reply.
In most cases, a quick pass through translation software is sufficient.
Having the original text _as well as_ the translation can help mitigate translation errors.
Responses to posted issues may or may not be in the original language.
**Please note** that using non-English as an attempt to circumvent our [Code of Conduct](https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md) will be an immediate, and possibly indefinite, ban from the project.
### Issue Maintenance and Closure
* If an issue is inactive for 45 days (no activity of any kind), it will be
marked for closure with `stale`.
* If after this label is applied, no further activity occurs in the next 7 days,
the issue will be closed.
* If an issue has been closed and you still feel it's relevant, feel free to
ping a maintainer or add a comment!
## [Pull Requests](https://electronjs.org/docs/development/pull-requests)
@@ -47,24 +37,20 @@ dependencies, and tools contained in the `electron/electron` repository.
* [Step 1: Fork](https://electronjs.org/docs/development/pull-requests#step-1-fork)
* [Step 2: Build](https://electronjs.org/docs/development/pull-requests#step-2-build)
* [Step 3: Branch](https://electronjs.org/docs/development/pull-requests#step-3-branch)
* [Making Changes](https://electronjs.org/docs/development/pull-requests#making-changes)
* [The Process of Making Changes](https://electronjs.org/docs/development/pull-requests#the-process-of-making-changes)
* [Step 4: Code](https://electronjs.org/docs/development/pull-requests#step-4-code)
* [Step 5: Commit](https://electronjs.org/docs/development/pull-requests#step-5-commit)
* [Commit message guidelines](https://electronjs.org/docs/development/pull-requests#commit-message-guidelines)
* [Step 6: Rebase](https://electronjs.org/docs/development/pull-requests#step-6-rebase)
* [Step 7: Test](https://electronjs.org/docs/development/pull-requests#step-7-test)
* [Step 8: Push](https://electronjs.org/docs/development/pull-requests#step-8-push)
* [Step 9: Opening the Pull Request](https://electronjs.org/docs/development/pull-requests#step-9-opening-the-pull-request)
* [Step 10: Discuss and Update](https://electronjs.org/docs/development/pull-requests#step-10-discuss-and-update)
* [Step 8: Opening the Pull Request](https://electronjs.org/docs/development/pull-requests#step-8-opening-the-pull-request)
* [Step 9: Discuss and Update](#step-9-discuss-and-update)
* [Approval and Request Changes Workflow](https://electronjs.org/docs/development/pull-requests#approval-and-request-changes-workflow)
* [Step 11: Landing](https://electronjs.org/docs/development/pull-requests#step-11-landing)
* [Step 10: Landing](https://electronjs.org/docs/development/pull-requests#step-10-landing)
* [Continuous Integration Testing](https://electronjs.org/docs/development/pull-requests#continuous-integration-testing)
## Style Guides
See [Coding Style](https://electronjs.org/docs/development/coding-style) for information about which standards Electron adheres to in different parts of its codebase.
## Further Reading
For more in-depth guides on developing Electron, see
[/docs/development](/docs/development/README.md)

153
DEPS
View File

@@ -1,153 +0,0 @@
gclient_gn_args_from = 'src'
vars = {
'chromium_version':
'108.0.5359.215',
'node_version':
'v16.17.1',
'nan_version':
'16fa32231e2ccd89d2804b3f765319128b20c4ac',
'squirrel.mac_version':
'0e5d146ba13101a1302d59ea6e6e0b3cace4ae38',
'pyyaml_version': '3.12',
'chromium_git': 'https://chromium.googlesource.com',
'electron_git': 'https://github.com/electron',
'nodejs_git': 'https://github.com/nodejs',
'yaml_git': 'https://github.com/yaml',
'squirrel_git': 'https://github.com/Squirrel',
# KEEP IN SYNC WITH utils.js FILE
'yarn_version': '1.15.2',
# To be able to build clean Chromium from sources.
'apply_patches': True,
# To use an mtime cache for patched files to speed up builds.
'use_mtime_cache': True,
# To allow in-house builds to checkout those manually.
'checkout_chromium': True,
'checkout_node': True,
'checkout_nan': True,
'checkout_pgo_profiles': True,
# It's only needed to parse the native tests configurations.
'checkout_pyyaml': False,
'use_rts': False,
'mac_xcode_version': 'default',
'generate_location_tags': False,
# To allow running hooks without parsing the DEPS tree
'process_deps': True,
'checkout_nacl':
False,
'checkout_libaom':
True,
'checkout_oculus_sdk':
False,
'checkout_openxr':
False,
'build_with_chromium':
True,
'checkout_android':
False,
'checkout_android_native_support':
False,
'checkout_google_benchmark':
False,
'checkout_clang_tidy':
True,
}
deps = {
'src': {
'url': (Var("chromium_git")) + '/chromium/src.git@' + (Var("chromium_version")),
'condition': 'checkout_chromium and process_deps',
},
'src/third_party/nan': {
'url': (Var("nodejs_git")) + '/nan.git@' + (Var("nan_version")),
'condition': 'checkout_nan and process_deps',
},
'src/third_party/electron_node': {
'url': (Var("nodejs_git")) + '/node.git@' + (Var("node_version")),
'condition': 'checkout_node and process_deps',
},
'src/third_party/pyyaml': {
'url': (Var("yaml_git")) + '/pyyaml.git@' + (Var("pyyaml_version")),
'condition': 'checkout_pyyaml and process_deps',
},
'src/third_party/squirrel.mac': {
'url': Var("squirrel_git") + '/Squirrel.Mac.git@' + Var("squirrel.mac_version"),
'condition': 'process_deps',
},
'src/third_party/squirrel.mac/vendor/ReactiveObjC': {
'url': 'https://github.com/ReactiveCocoa/ReactiveObjC.git@74ab5baccc6f7202c8ac69a8d1e152c29dc1ea76',
'condition': 'process_deps'
},
'src/third_party/squirrel.mac/vendor/Mantle': {
'url': 'https://github.com/Mantle/Mantle.git@78d3966b3c331292ea29ec38661b25df0a245948',
'condition': 'process_deps',
}
}
pre_deps_hooks = [
{
'name': 'generate_mtime_cache',
'condition': '(checkout_chromium and apply_patches and use_mtime_cache) and process_deps',
'pattern': 'src/electron',
'action': [
'python3',
'src/electron/script/patches-mtime-cache.py',
'generate',
'--cache-file',
'src/electron/patches/mtime-cache.json',
'--patches-config',
'src/electron/patches/config.json',
],
},
]
hooks = [
{
'name': 'patch_chromium',
'condition': '(checkout_chromium and apply_patches) and process_deps',
'pattern': 'src/electron',
'action': [
'python3',
'src/electron/script/apply_all_patches.py',
'src/electron/patches/config.json',
],
},
{
'name': 'apply_mtime_cache',
'condition': '(checkout_chromium and apply_patches and use_mtime_cache) and process_deps',
'pattern': 'src/electron',
'action': [
'python3',
'src/electron/script/patches-mtime-cache.py',
'apply',
'--cache-file',
'src/electron/patches/mtime-cache.json',
],
},
{
'name': 'electron_npm_deps',
'pattern': 'src/electron/package.json',
'action': [
'python3',
'-c',
'import os, subprocess; os.chdir(os.path.join("src", "electron")); subprocess.check_call(["python3", "script/lib/npx.py", "yarn@' + (Var("yarn_version")) + '", "install", "--frozen-lockfile"]);',
],
},
]
recursedeps = [
'src',
'src/third_party/squirrel.mac',
]

24
Dockerfile Normal file
View File

@@ -0,0 +1,24 @@
FROM electronbuilds/libchromiumcontent:0.0.4
USER root
# Set up HOME directory
ENV HOME=/home
RUN chmod a+rwx /home
# Install node.js
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash -
RUN apt-get update && apt-get install -y nodejs
# Install wget used by crash reporter
RUN apt-get install -y wget
# Install python-dbusmock
RUN apt-get install -y python-dbusmock
# Install libnotify
RUN apt-get install -y libnotify-bin
# Add xvfb init script
ADD tools/xvfb-init.sh /etc/init.d/xvfb
RUN chmod a+x /etc/init.d/xvfb

35
Dockerfile.arm64 Normal file
View File

@@ -0,0 +1,35 @@
FROM multiarch/debian-debootstrap:arm64-jessie
RUN apt-get update && apt-get install -y\
bison \
build-essential \
clang \
curl \
gperf \
libasound2 \
libasound2-dev \
libcap-dev \
libcups2-dev \
libdbus-1-dev \
libgconf-2-4 \
libgconf2-dev \
libgnome-keyring-dev \
libgtk-3-0 \
libgtk-3-dev \
libnotify-bin \
libnotify-dev \
libnss3 \
libnss3-dev \
libx11-xcb-dev \
libxss1 \
libxtst-dev \
libxtst6 \
python-dbusmock \
wget \
xvfb
ADD tools/xvfb-init.sh /etc/init.d/xvfb
RUN chmod a+x /etc/init.d/xvfb
ADD tools/run-electron.sh /run-electron.sh
RUN chmod a+x /run-electron.sh
CMD sh /run-electron.sh

63
Dockerfile.arm64v8 Normal file
View File

@@ -0,0 +1,63 @@
FROM arm64v8/ubuntu:16.04
RUN groupadd --gid 1000 builduser \
&& useradd --uid 1000 --gid builduser --shell /bin/bash --create-home builduser
RUN groupadd --gid 114 jenkins \
&& useradd --uid 110 --gid jenkins --shell /bin/bash --create-home jenkins
# Set up TEMP directory
ENV TEMP=/tmp
RUN chmod a+rwx /tmp
RUN apt-get update && apt-get install -y\
bison \
build-essential \
clang \
curl \
gperf \
git \
libasound2 \
libasound2-dev \
libcap-dev \
libcups2-dev \
libdbus-1-dev \
libgconf-2-4 \
libgconf2-dev \
libgnome-keyring-dev \
libgtk2.0-0 \
libgtk2.0-dev \
libgtk-3-0 \
libgtk-3-dev \
libnotify-dev \
libnss3 \
libnss3-dev \
libx11-xcb-dev \
libxss1 \
libxtst-dev \
libxtst6 \
lsb-release \
locales \
ninja \
python-setuptools \
python-pip \
python-dbusmock \
wget \
xvfb
# Install node.js
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash -
RUN apt-get update && apt-get install -y nodejs
# Install crcmod
RUN pip install -U crcmod
ADD tools/xvfb-init.sh /etc/init.d/xvfb
RUN chmod a+x /etc/init.d/xvfb
# Install ninja in /usr/local
RUN cd /usr/local && git clone https://github.com/martine/ninja.git -b v1.5.3
RUN cd /usr/local/ninja && ./configure.py --bootstrap
USER builduser
WORKDIR /home/builduser

36
Dockerfile.armv7 Normal file
View File

@@ -0,0 +1,36 @@
FROM multiarch/debian-debootstrap:armhf-jessie
RUN apt-get update && apt-get install -y\
bison \
build-essential \
clang \
curl \
gperf \
libasound2 \
libasound2-dev \
libcap-dev \
libcups2-dev \
libdbus-1-dev \
libgconf-2-4 \
libgconf2-dev \
libgnome-keyring-dev \
libgtk-3-0 \
libgtk-3-dev \
libnotify-bin \
libnotify-dev \
libnss3 \
libnss3-dev \
libx11-xcb-dev \
libxss1 \
libxtst-dev \
libxtst6 \
python-dbusmock \
git \
wget \
xvfb
ADD tools/xvfb-init.sh /etc/init.d/xvfb
RUN chmod a+x /etc/init.d/xvfb
ADD tools/run-electron.sh /run-electron.sh
RUN chmod a+x /run-electron.sh
CMD sh /run-electron.sh

23
Dockerfile.circleci Normal file
View File

@@ -0,0 +1,23 @@
FROM electronbuilds/libchromiumcontent:0.0.4
USER root
# Install node.js
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash -
RUN apt-get update && apt-get install -y nodejs
# Install wget used by crash reporter
RUN apt-get install -y wget
# Install python-dbusmock
RUN apt-get install -y python-dbusmock
# Install libnotify
RUN apt-get install -y libnotify-bin
# Add xvfb init script
ADD tools/xvfb-init.sh /etc/init.d/xvfb
RUN chmod a+x /etc/init.d/xvfb
USER builduser
WORKDIR /home/builduser

48
Jenkinsfile vendored Normal file
View File

@@ -0,0 +1,48 @@
pipeline {
agent none
stages {
stage('Build') {
parallel {
stage('electron-osx-x64') {
agent {
label 'osx'
}
steps {
timeout(60) {
sh 'script/bootstrap.py --target_arch=x64 --dev'
sh 'npm run lint'
sh 'script/build.py -c D'
sh 'script/test.py --ci --rebuild_native_modules'
}
}
post {
always {
cleanWs()
}
}
}
stage('electron-mas-x64') {
agent {
label 'osx'
}
environment {
MAS_BUILD = '1'
}
steps {
timeout(60) {
sh 'script/bootstrap.py --target_arch=x64 --dev'
sh 'npm run lint'
sh 'script/build.py -c D'
sh 'script/test.py --ci --rebuild_native_modules'
}
}
post {
always {
cleanWs()
}
}
}
}
}
}
}

36
Jenkinsfile.arm64 Normal file
View File

@@ -0,0 +1,36 @@
pipeline {
agent {
docker {
image 'electronbuilds/arm64v8:0.0.2'
args '--privileged'
}
}
environment {
TARGET_ARCH='arm64'
DISPLAY=':99.0'
MOCHA_TIMEOUT='60000'
}
stages {
stage('Bootstrap') {
steps {
sh 'script/bootstrap.py -v --dev --target_arch=$TARGET_ARCH'
}
}
stage('Build') {
steps {
sh 'script/build.py -c D --ninja-path /usr/local/ninja/ninja'
}
}
stage('Test') {
steps {
sh '/etc/init.d/xvfb start'
sh 'script/test.py --ci'
}
}
}
post {
always {
cleanWs()
}
}
}

View File

@@ -1,5 +1,4 @@
Copyright (c) Electron contributors
Copyright (c) 2013-2020 GitHub Inc.
Copyright (c) 2013-2018 GitHub Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

View File

@@ -1,22 +1,25 @@
[![Electron Logo](https://electronjs.org/images/electron-logo.svg)](https://electronjs.org)
[![CircleCI Build Status](https://circleci.com/gh/electron/electron/tree/main.svg?style=shield)](https://circleci.com/gh/electron/electron/tree/main)
[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/4lggi9dpjc1qob7k/branch/main?svg=true)](https://ci.appveyor.com/project/electron-bot/electron-ljo26/branch/main)
[![Electron Discord Invite](https://img.shields.io/discord/745037351163527189?color=%237289DA&label=chat&logo=discord&logoColor=white)](https://discord.gg/electronjs)
:memo: Available Translations: 🇨🇳 🇧🇷 🇪🇸 🇯🇵 🇷🇺 🇫🇷 🇺🇸 🇩🇪.
View these docs in other languages on our [Crowdin](https://crowdin.com/project/electron) project.
[![CircleCI Build Status](https://circleci.com/gh/electron/electron/tree/master.svg?style=shield)](https://circleci.com/gh/electron/electron/tree/master)
[![AppVeyor Build Status](https://windows-ci.electronjs.org/api/projects/status/nilyf07hcef14dvj/branch/master?svg=true)](https://windows-ci.electronjs.org/project/AppVeyor/electron/branch/master)
[![Jenkins Build Status](https://mac-ci.electronjs.org/buildStatus/icon?job=Electron%20org/electron/master)](https://mac-ci.electronjs.org/blue/organizations/jenkins/Electron%20org%2Felectron/activity?branch=master)
[![devDependency Status](https://david-dm.org/electron/electron/dev-status.svg)](https://david-dm.org/electron/electron?type=dev)
[![Join the Electron Community on Slack](https://atom-slack.herokuapp.com/badge.svg)](https://atom-slack.herokuapp.com/)
:memo: Available Translations: 🇨🇳 🇹🇼 🇧🇷 🇪🇸 🇰🇷 🇯🇵 🇷🇺 🇫🇷 🇹🇭 🇳🇱 🇹🇷 🇮🇩 🇺🇦 🇨🇿 🇮🇹.
View these docs in other languages at [electron/electron-i18n](https://github.com/electron/electron-i18n/tree/master/content/).
The Electron framework lets you write cross-platform desktop applications
using JavaScript, HTML and CSS. It is based on [Node.js](https://nodejs.org/) and
[Chromium](https://www.chromium.org) and is used by the [Atom
editor](https://github.com/atom/atom) and many other [apps](https://electronjs.org/apps).
Follow [@electronjs](https://twitter.com/electronjs) on Twitter for important
Follow [@ElectronJS](https://twitter.com/electronjs) on Twitter for important
announcements.
This project adheres to the Contributor Covenant
[code of conduct](https://github.com/electron/electron/tree/main/CODE_OF_CONDUCT.md).
[code of conduct](https://github.com/electron/electron/tree/master/CODE_OF_CONDUCT.md).
By participating, you are expected to uphold this code. Please report unacceptable
behavior to [coc@electronjs.org](mailto:coc@electronjs.org).
@@ -27,32 +30,19 @@ The preferred method is to install Electron as a development dependency in your
app:
```sh
npm install electron --save-dev
npm install electron --save-dev --save-exact
```
For more installation options and troubleshooting tips, see
[installation](docs/tutorial/installation.md). For info on how to manage Electron versions in your apps, see
The `--save-exact` flag is recommended as Electron does not follow semantic
versioning. For info on how to manage Electron versions in your apps, see
[Electron versioning](docs/tutorial/electron-versioning.md).
## Platform support
For more installation options and troubleshooting tips, see
[installation](docs/tutorial/installation.md).
Each Electron release provides binaries for macOS, Windows, and Linux.
## Quick start
* macOS (High Sierra and up): Electron provides 64-bit Intel and ARM binaries for macOS. Apple Silicon support was added in Electron 11.
* Windows (Windows 7 and up): Electron provides `ia32` (`x86`), `x64` (`amd64`), and `arm64` binaries for Windows. Windows on ARM support was added in Electron 5.0.8.
* Linux: The prebuilt binaries of Electron are built on Ubuntu 20.04. They have also been verified to work on:
* Ubuntu 14.04 and newer
* Fedora 24 and newer
* Debian 8 and newer
## Quick start & Electron Fiddle
Use [`Electron Fiddle`](https://github.com/electron/fiddle)
to build, run, and package small Electron experiments, to see code examples for all of Electron's APIs, and
to try out different versions of Electron. It's designed to make the start of your journey with
Electron easier.
Alternatively, clone and run the
Clone and run the
[electron/electron-quick-start](https://github.com/electron/electron-quick-start)
repository to see a minimal Electron app in action:
@@ -65,10 +55,12 @@ npm start
## Resources for learning Electron
* [electronjs.org/docs](https://electronjs.org/docs) - All of Electron's documentation
* [electron/fiddle](https://github.com/electron/fiddle) - A tool to build, run, and package small Electron experiments
* [electron/electron-quick-start](https://github.com/electron/electron-quick-start) - A very basic starter Electron app
* [electronjs.org/community#boilerplates](https://electronjs.org/community#boilerplates) - Sample starter apps created by the community
- [electronjs.org/docs](https://electronjs.org/docs) - all of Electron's documentation
- [electron/electron-quick-start](https://github.com/electron/electron-quick-start) - a very basic starter Electron app
- [electronjs.org/community#boilerplates](https://electronjs.org/community#boilerplates) - sample starter apps created by the community
- [electron/simple-samples](https://github.com/electron/simple-samples) - small applications with ideas for taking them further
- [electron/electron-api-demos](https://github.com/electron/electron-api-demos) - an Electron app that teaches you how to use Electron
- [hokein/electron-sample-apps](https://github.com/hokein/electron-sample-apps) - small demo apps for the various Electron APIs
## Programmatic usage
@@ -89,27 +81,19 @@ const child = proc.spawn(electron)
### Mirrors
* [China](https://npmmirror.com/mirrors/electron/)
- [China](https://npm.taobao.org/mirrors/electron)
See the [Advanced Installation Instructions](https://www.electronjs.org/docs/latest/tutorial/installation#mirror) to learn how to use a custom mirror.
## Documentation Translations
## Documentation translations
We crowdsource translations for our documentation via [Crowdin](https://crowdin.com/project/electron).
We currently accept translations for Chinese (Simplified), French, German, Japanese, Portuguese,
Russian, and Spanish.
## Contributing
If you are interested in reporting/fixing issues and contributing directly to the code base, please see [CONTRIBUTING.md](CONTRIBUTING.md) for more information on what we're looking for and how to get started.
Find documentation translations in [electron/electron-i18n](https://github.com/electron/electron-i18n).
## Community
Info on reporting bugs, getting help, finding third-party tools and sample apps,
and more can be found on the [Community page](https://www.electronjs.org/community).
and more can be found in the [support document](docs/tutorial/support.md#finding-support).
## License
[MIT](https://github.com/electron/electron/blob/main/LICENSE)
[MIT](https://github.com/electron/electron/blob/master/LICENSE)
When using Electron logos, make sure to follow [OpenJS Foundation Trademark Policy](https://openjsf.org/wp-content/uploads/sites/84/2021/01/OpenJS-Foundation-Trademark-Policy-2021-01-12.docx.pdf).
When using the Electron or other GitHub logos, be sure to follow the [GitHub logo guidelines](https://github.com/logos).

View File

@@ -6,12 +6,7 @@ To report a security issue, email [security@electronjs.org](mailto:security@elec
The Electron team will send a response indicating the next steps in handling your report. After the initial reply to your report, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance.
Report security bugs in third-party modules to the person or team maintaining the module. You can also report a vulnerability through the [npm contact form](https://www.npmjs.com/support) by selecting "I'm reporting a security vulnerability".
## The Electron Security Notification Process
For context on Electron's security notification process, please see the [Notifications](https://github.com/electron/governance/blob/main/wg-security/membership-and-notifications.md#notifications) section of the Security WG's [Membership and Notifications](https://github.com/electron/governance/blob/main/wg-security/membership-and-notifications.md) Governance document.
Report security bugs in third-party modules to the person or team maintaining the module. You can also report a vulnerability through the [Node Security Project](https://nodesecurity.io/report).
## Learning More About Security
To learn more about securing an Electron application, please see the [security tutorial](docs/tutorial/security.md).

View File

@@ -1,108 +0,0 @@
# The config is used to bake appveyor images, not for running CI jobs.
# The config expects the following environment variables to be set:
# - "APPVEYOR_BAKE_IMAGE" e.g. 'electron-99.0.4767.0'. Name of the image to be baked.
# Typically named after the Chromium version on which the image is built.
# This can be set dynamically in the prepare-appveyor script.
version: 1.0.{build}
build_cloud: electronhq-16-core
image: e-111.0.5560.0-node18
environment:
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
ELECTRON_OUT_DIR: Default
ELECTRON_ENABLE_STACK_DUMPING: 1
MOCHA_REPORTER: mocha-multi-reporters
MOCHA_MULTI_REPORTERS: mocha-appveyor-reporter, tap
GOMA_FALLBACK_ON_AUTH_FAILURE: true
DEPOT_TOOLS_WIN_TOOLCHAIN: 0
PYTHONIOENCODING: UTF-8
# The following lines are needed when baking from a completely new image (eg MicrosoftWindowsServer:WindowsServer:2019-Datacenter:latest via image: base-windows-server2019)
# init:
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
# - appveyor version
# - ps: $ErrorActionPreference = 'Stop'
# - ps: 'Write-Host "OS Build: $((Get-CimInstance Win32_OperatingSystem).BuildNumber)"'
# clone_folder: '%USERPROFILE%\image-bake-scripts'
# clone_script:
# - ps: Invoke-WebRequest "https://github.com/appveyor/build-images/archive/1f90d94e74c8243c909a09b994e527584dfcb838.zip" -OutFile "$env:temp\scripts.zip"
# - ps: Expand-Archive -Path "$env:temp\scripts.zip" -DestinationPath "$env:temp\scripts" -Force
# - ps: Copy-Item -Path "$env:temp\scripts\build-images-1f90d94e74c8243c909a09b994e527584dfcb838\scripts\Windows\*" -Destination $env:APPVEYOR_BUILD_FOLDER -Recurse
build_script:
# The following lines are needed when baking from a completely new image (eg MicrosoftWindowsServer:WindowsServer:2019-Datacenter:latest via image: base-windows-server2019)
# - ps: .\init_server.ps1
# - ps: .\extend_system_volume.ps1
# # Restart VM
# - ps: Start-Sleep -s 5; Restart-Computer
# - ps: Start-Sleep -s 5
# - appveyor version
# - ps: .\install_path_utils.ps1
# - ps: .\install_powershell_core.ps1
# - ps: .\install_powershell_get.ps1
# - ps: .\install_7zip.ps1
# - ps: .\install_chocolatey.ps1
# - ps: .\install_webpi.ps1
# - ps: .\install_nuget.ps1
# - ps: .\install_pstools.ps1
# - ps: .\install_git.ps1
# - ps: .\install_git_lfs.ps1
# # Restart VM
# - ps: Start-Sleep -s 5; Restart-Computer
# - ps: Start-Sleep -s 5
# END LINES FOR COMPLETELY NEW IMAGE
- git config --global core.longpaths true
- ps: >-
if (-not (Test-Path -Path C:\projects\src)) {
New-Item -Path C:\projects\src -ItemType Directory
}
- cd C:\projects\
- git clone -q --branch=%APPVEYOR_REPO_BRANCH% https://github.com/electron/electron.git C:\projects\src\electron
- git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
- ps: $env:PATH="$pwd\depot_tools;$env:PATH"
- update_depot_tools.bat
# Uncomment the following line if windows deps change
# - src\electron\script\setup-win-for-dev.bat
- >-
gclient config
--name "src\electron"
--unmanaged
%GCLIENT_EXTRA_ARGS%
"https://github.com/electron/electron"
- ps: cd src\electron
- ps: node script\generate-deps-hash.js
- ps: $depshash = Get-Content .\.depshash -Raw
- ps: Copy-Item -path .\.depshash -destination ..\.depshash
- ps: cd ..\..
- gclient sync --with_branch_heads --with_tags --nohooks
- ps: regsvr32 /s "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\DIA SDK\bin\amd64\msdia140.dll"
# The following lines are needed when baking from a completely new image (eg MicrosoftWindowsServer:WindowsServer:2019-Datacenter:latest via image: base-windows-server2019)
# # Restart VM
# - ps: Start-Sleep -s 5; Restart-Computer
# - ps: Start-Sleep -s 5
# - cd %USERPROFILE%\image-bake-scripts
# - appveyor version
# - ps: .\optimize_dotnet_runtime.ps1
# - ps: .\disable_windows_background_services.ps1
# - ps: .\enforce_windows_firewall.ps1
# - ps: .\cleanup_windows.ps1
# END LINES FOR COMPLETELY NEW IMAGE
on_image_bake:
- ps: >-
echo "Baking image: $env:APPVEYOR_BAKE_IMAGE at dir $PWD"
- ps: Remove-Item -Recurse -Force C:\projects\depot_tools
- ps: Remove-Item -Recurse -Force C:\projects\src\electron
# Uncomment these lines and set APPVEYOR_RDP_PASSWORD in project settings to enable RDP after bake is done
# # on_finish:
# - ps: >-
# $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))

View File

@@ -1,279 +0,0 @@
# NOTE IF CHANGING THIS FILE, ALSO APPLY THE CHANGE TO appveyor.yml
# IF APPLICABLE!!!!
#
#
# The config expects the following environment variables to be set:
# - "GN_CONFIG" Build type. One of {'testing', 'release'}.
# - "GN_EXTRA_ARGS" Additional gn arguments for a build config,
# e.g. 'target_cpu="x86"' to build for a 32bit platform.
# https://gn.googlesource.com/gn/+/master/docs/reference.md#target_cpu
# Don't forget to set up "NPM_CONFIG_ARCH" and "TARGET_ARCH" accordingly
# if you pass a custom value for 'target_cpu'.
# - "ELECTRON_RELEASE" Set it to '1' upload binaries on success.
# - "NPM_CONFIG_ARCH" E.g. 'x86'. Is used to build native Node.js modules.
# Must match 'target_cpu' passed to "GN_EXTRA_ARGS" and "TARGET_ARCH" value.
# - "TARGET_ARCH" Choose from {'ia32', 'x64', 'arm', 'arm64', 'mips64el'}.
# Is used in some publishing scripts, but does NOT affect the Electron binary.
# Must match 'target_cpu' passed to "GN_EXTRA_ARGS" and "NPM_CONFIG_ARCH" value.
# - "UPLOAD_TO_STORAGE" Set it to '1' upload a release to the Azure bucket.
# Otherwise the release will be uploaded to the GitHub Releases.
# (The value is only checked if "ELECTRON_RELEASE" is defined.)
#
# The publishing scripts expect access tokens to be defined as env vars,
# but those are not covered here.
#
# AppVeyor docs on variables:
# https://www.appveyor.com/docs/environment-variables/
# https://www.appveyor.com/docs/build-configuration/#secure-variables
# https://www.appveyor.com/docs/build-configuration/#custom-environment-variables
version: 1.0.{build}
build_cloud: electronhq-16-core
image: e-108.0.5359.215
environment:
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
ELECTRON_OUT_DIR: Default
ELECTRON_ENABLE_STACK_DUMPING: 1
ELECTRON_ALSO_LOG_TO_STDERR: 1
MOCHA_REPORTER: mocha-multi-reporters
MOCHA_MULTI_REPORTERS: mocha-appveyor-reporter, tap
GOMA_FALLBACK_ON_AUTH_FAILURE: true
DEPOT_TOOLS_WIN_TOOLCHAIN: 0
PYTHONIOENCODING: UTF-8
matrix:
- job_name: Build Arm on X64 Windows
- job_name: Test On Windows On Arm Hardware
job_depends_on: Build Arm on X64 Windows
APPVEYOR_BUILD_WORKER_IMAGE: base-woa
APPVEYOR_BUILD_WORKER_CLOUD: electronhq-woa
clone_folder: C:\projects\src\electron
skip_branch_with_pr: true
# the first failed job cancels other jobs and fails entire build
matrix:
fast_finish: true
for:
- matrix:
only:
- job_name: Build Arm on X64 Windows
build_script:
- ps: |
node script/yarn.js install --frozen-lockfile
node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER --prBranch=$env:APPVEYOR_REPO_BRANCH
if ($LASTEXITCODE -eq 0) {
Write-warning "Skipping build for doc only change"; Exit-AppveyorBuild
}
$global:LASTEXITCODE = 0
- cd ..
- ps: Write-Host "Building $env:GN_CONFIG build"
- git config --global core.longpaths true
- ps: >-
if (Test-Path -Path "$pwd\depot_tools") {
Remove-Item -Recurse -Force $pwd\depot_tools
}
- ps: >-
if (Test-Path -Path "$pwd\build-tools") {
Remove-Item -Recurse -Force $pwd\build-tools
}
- git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
- ps: $env:PATH="$pwd\depot_tools;$env:PATH"
- ps: >-
if (Test-Path -Path "$pwd\src\electron") {
Remove-Item -Recurse -Force $pwd\src\electron
}
- ps: >-
if (Test-Path 'env:RAW_GOMA_AUTH') {
$env:GOMA_OAUTH2_CONFIG_FILE = "$pwd\.goma_oauth2_config"
$env:RAW_GOMA_AUTH | Set-Content $env:GOMA_OAUTH2_CONFIG_FILE
}
- git clone https://github.com/electron/build-tools.git
- cd build-tools
- npm install
- mkdir third_party
- ps: >-
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
- ps: $env:GN_GOMA_FILE = node -e "console.log(require('./src/utils/goma.js').gnFilePath)"
- ps: $env:LOCAL_GOMA_DIR = node -e "console.log(require('./src/utils/goma.js').dir)"
- cd ..\..
- ps: .\src\electron\script\start-goma.ps1 -gomaDir $env:LOCAL_GOMA_DIR
- ps: >-
if (Test-Path 'env:RAW_GOMA_AUTH') {
$goma_login = python $env:LOCAL_GOMA_DIR\goma_auth.py info
if ($goma_login -eq 'Login as Fermi Planck') {
Write-warning "Goma authentication is correct";
} else {
Write-warning "WARNING!!!!!! Goma authentication is incorrect; please update Goma auth token.";
$host.SetShouldExit(1)
}
}
- ps: $env:CHROMIUM_BUILDTOOLS_PATH="$pwd\src\buildtools"
- ps: >-
if ($env:GN_CONFIG -ne 'release') {
$env:NINJA_STATUS="[%r processes, %f/%t @ %o/s : %es] "
}
- gclient config --name "src\electron" --unmanaged %GCLIENT_EXTRA_ARGS% "https://github.com/electron/electron"
# Patches are applied in the image bake. Check depshash to see if patches have changed.
- ps: $env:RUN_GCLIENT_SYNC="false"
- ps: $depshash_baked = Get-Content .\src\.depshash -Raw
- ps: cd src\electron
- ps: node script\generate-deps-hash.js
- ps: $depshash = Get-Content .\.depshash -Raw
- ps: cd ..\..
- ps: >-
if ($depshash_baked -ne $depshash) {
$env:RUN_GCLIENT_SYNC="true"
}
- if "%RUN_GCLIENT_SYNC%"=="true" ( gclient sync --with_branch_heads --with_tags ) else ( gclient runhooks )
- cd src
- ps: $env:PATH="$pwd\third_party\ninja;$env:PATH"
- set BUILD_CONFIG_PATH=//electron/build/args/%GN_CONFIG%.gn
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") import(\"%GN_GOMA_FILE%\") %GN_EXTRA_ARGS% "
- gn check out/Default //electron:electron_lib
- gn check out/Default //electron:electron_app
- gn check out/Default //electron/shell/common/api:mojo
- if DEFINED GN_GOMA_FILE (ninja -j 300 -C out/Default electron:electron_app) else (ninja -C out/Default electron:electron_app)
- if "%GN_CONFIG%"=="testing" ( python C:\depot_tools\post_build_ninja_summary.py -C out\Default )
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") %GN_EXTRA_ARGS%"
- ninja -C out/ffmpeg electron:electron_ffmpeg_zip
- ninja -C out/Default electron:electron_dist_zip
- ninja -C out/Default shell_browser_ui_unittests
- gn desc out/Default v8:run_mksnapshot_default args > out/Default/default_mksnapshot_args
# Remove unused args from mksnapshot_args
- ps: >-
Get-Content out/Default/default_mksnapshot_args | Where-Object { -not $_.Contains('--turbo-profiling-input') -And -not $_.Contains('builtins-pgo') } | Set-Content out/Default/mksnapshot_args
- ninja -C out/Default electron:electron_mksnapshot_zip
- cd out\Default
- 7z a mksnapshot.zip mksnapshot_args gen\v8\embedded.S
- cd ..\..
- ninja -C out/Default electron:hunspell_dictionaries_zip
- ninja -C out/Default electron:electron_chromedriver_zip
- ninja -C out/Default third_party/electron_node:headers
- python %LOCAL_GOMA_DIR%\goma_ctl.py stat
- ps: >-
Get-CimInstance -Namespace root\cimv2 -Class Win32_product | Select vendor, description, @{l='install_location';e='InstallLocation'}, @{l='install_date';e='InstallDate'}, @{l='install_date_2';e='InstallDate2'}, caption, version, name, @{l='sku_number';e='SKUNumber'} | ConvertTo-Json | Out-File -Encoding utf8 -FilePath .\installed_software.json
- python3 electron/build/profile_toolchain.py --output-json=out/Default/windows_toolchain_profile.json
- 7z a node_headers.zip out\Default\gen\node_headers
- ps: >-
if ($env:GN_CONFIG -eq 'release') {
# Needed for msdia140.dll on 64-bit windows
$env:Path += ";$pwd\third_party\llvm-build\Release+Asserts\bin"
ninja -C out/Default electron:electron_symbols
}
- ps: >-
if ($env:GN_CONFIG -eq 'release') {
python3 electron\script\zip-symbols.py
appveyor-retry appveyor PushArtifact out/Default/symbols.zip
} else {
# It's useful to have pdb files when debugging testing builds that are
# built on CI.
7z a pdb.zip out\Default\*.pdb
}
- python3 electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.win.%TARGET_ARCH%.manifest
deploy_script:
- cd electron
- ps: >-
if (Test-Path Env:\ELECTRON_RELEASE) {
if (Test-Path Env:\UPLOAD_TO_STORAGE) {
Write-Output "Uploading Electron release distribution to azure"
& python3 script\release\uploaders\upload.py --verbose --upload_to_storage
} else {
Write-Output "Uploading Electron release distribution to github releases"
& python3 script\release\uploaders\upload.py --verbose
}
}
on_finish:
# Uncomment this lines to enable RDP
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
- cd C:\projects\src
- if exist out\Default\windows_toolchain_profile.json ( appveyor-retry appveyor PushArtifact out\Default\windows_toolchain_profile.json )
- if exist out\Default\dist.zip (appveyor-retry appveyor PushArtifact out\Default\dist.zip)
- if exist out\Default\shell_browser_ui_unittests.exe (appveyor-retry appveyor PushArtifact out\Default\shell_browser_ui_unittests.exe)
- if exist out\Default\chromedriver.zip (appveyor-retry appveyor PushArtifact out\Default\chromedriver.zip)
- if exist out\ffmpeg\ffmpeg.zip (appveyor-retry appveyor PushArtifact out\ffmpeg\ffmpeg.zip)
- if exist node_headers.zip (appveyor-retry appveyor PushArtifact node_headers.zip)
- if exist out\Default\mksnapshot.zip (appveyor-retry appveyor PushArtifact out\Default\mksnapshot.zip)
- if exist out\Default\hunspell_dictionaries.zip (appveyor-retry appveyor PushArtifact out\Default\hunspell_dictionaries.zip)
- if exist out\Default\electron.lib (appveyor-retry appveyor PushArtifact out\Default\electron.lib)
- ps: >-
if ((Test-Path "pdb.zip") -And ($env:GN_CONFIG -ne 'release')) {
appveyor-retry appveyor PushArtifact pdb.zip
}
- matrix:
only:
- job_name: Test On Windows On Arm Hardware
environment:
IGNORE_YARN_INSTALL_ERROR: 1
ELECTRON_TEST_RESULTS_DIR: junit
MOCHA_MULTI_REPORTERS: 'mocha-junit-reporter, tap'
MOCHA_REPORTER: mocha-multi-reporters
ELECTRON_SKIP_NATIVE_MODULE_TESTS: true
build_script:
- ps: |
node script/yarn.js install --frozen-lockfile
node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER --prBranch=$env:APPVEYOR_REPO_BRANCH
if ($LASTEXITCODE -eq 0) {
Write-warning "Skipping build for doc only change"; Exit-AppveyorBuild
}
$global:LASTEXITCODE = 0
- cd ..
- mkdir out\Default
- cd ..
- ps: |
# Download build artifacts
$apiUrl = 'https://ci.appveyor.com/api'
$build_info = Invoke-RestMethod -Method Get -Uri "$apiUrl/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/builds/$env:APPVEYOR_BUILD_ID"
$artifacts_to_download = @('dist.zip','ffmpeg.zip','node_headers.zip','pdb.zip','electron.lib')
foreach ($job in $build_info.build.jobs) {
if ($job.name -eq "Build Arm on X64 Windows") {
$jobId = $job.jobId
foreach($artifact_name in $artifacts_to_download) {
if ($artifact_name -eq 'shell_browser_ui_unittests.exe' -Or $artifact_name -eq 'electron.lib') {
$outfile = "src\out\Default\$artifact_name"
} else {
$outfile = $artifact_name
}
Invoke-RestMethod -Method Get -Uri "$apiUrl/buildjobs/$jobId/artifacts/$artifact_name" -OutFile $outfile
}
}
}
- ps: |
$out_default_zips = @('dist.zip','pdb.zip')
foreach($zip_name in $out_default_zips) {
7z x -y -osrc\out\Default $zip_name
}
- ps: 7z x -y -osrc\out\ffmpeg ffmpeg.zip
- ps: 7z x -y -osrc node_headers.zip
test_script:
# Workaround for https://github.com/appveyor/ci/issues/2420
- set "PATH=%PATH%;C:\Program Files\Git\mingw64\libexec\git-core"
- ps: |
cd src
New-Item .\out\Default\gen\node_headers\Release -Type directory
Copy-Item -path .\out\Default\electron.lib -destination .\out\Default\gen\node_headers\Release\node.lib
- set npm_config_nodedir=%cd%\out\Default\gen\node_headers
- set npm_config_arch=arm64
- cd electron
# Explicitly set npm_config_arch because the .env doesn't persist
- ps: >-
if ($env:TARGET_ARCH -eq 'ia32') {
$env:npm_config_arch = "ia32"
}
- echo Running main test suite & node script/yarn test --runners=main --enable-logging --disable-features=CalculateNativeWinOcclusion
- cd ..
- echo Verifying non proprietary ffmpeg & python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg
on_finish:
# Uncomment these lines to enable RDP
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
- if exist electron\electron.log ( appveyor-retry appveyor PushArtifact electron\electron.log )

View File

@@ -1,279 +0,0 @@
# NOTE IF CHANGING THIS FILE, ALSO APPLY THE CHANGE TO appveyor-woa.yml
# IF APPLICABLE!!!!
#
#
# The config expects the following environment variables to be set:
# - "GN_CONFIG" Build type. One of {'testing', 'release'}.
# - "GN_EXTRA_ARGS" Additional gn arguments for a build config,
# e.g. 'target_cpu="x86"' to build for a 32bit platform.
# https://gn.googlesource.com/gn/+/master/docs/reference.md#target_cpu
# Don't forget to set up "NPM_CONFIG_ARCH" and "TARGET_ARCH" accordingly
# if you pass a custom value for 'target_cpu'.
# - "ELECTRON_RELEASE" Set it to '1' upload binaries on success.
# - "NPM_CONFIG_ARCH" E.g. 'x86'. Is used to build native Node.js modules.
# Must match 'target_cpu' passed to "GN_EXTRA_ARGS" and "TARGET_ARCH" value.
# - "TARGET_ARCH" Choose from {'ia32', 'x64', 'arm', 'arm64', 'mips64el'}.
# Is used in some publishing scripts, but does NOT affect the Electron binary.
# Must match 'target_cpu' passed to "GN_EXTRA_ARGS" and "NPM_CONFIG_ARCH" value.
# - "UPLOAD_TO_STORAGE" Set it to '1' upload a release to the Azure bucket.
# Otherwise the release will be uploaded to the GitHub Releases.
# (The value is only checked if "ELECTRON_RELEASE" is defined.)
#
# The publishing scripts expect access tokens to be defined as env vars,
# but those are not covered here.
#
# AppVeyor docs on variables:
# https://www.appveyor.com/docs/environment-variables/
# https://www.appveyor.com/docs/build-configuration/#secure-variables
# https://www.appveyor.com/docs/build-configuration/#custom-environment-variables
version: 1.0.{build}
build_cloud: electronhq-16-core
image: e-108.0.5359.215-node18
environment:
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
ELECTRON_OUT_DIR: Default
ELECTRON_ENABLE_STACK_DUMPING: 1
ELECTRON_ALSO_LOG_TO_STDERR: 1
MOCHA_REPORTER: mocha-multi-reporters
MOCHA_MULTI_REPORTERS: mocha-appveyor-reporter, tap
GOMA_FALLBACK_ON_AUTH_FAILURE: true
DEPOT_TOOLS_WIN_TOOLCHAIN: 0
PYTHONIOENCODING: UTF-8
matrix:
- job_name: Build
- job_name: Test
job_depends_on: Build
clone_folder: C:\projects\src\electron
skip_branch_with_pr: true
# the first failed job cancels other jobs and fails entire build
matrix:
fast_finish: true
for:
- matrix:
only:
- job_name: Build
build_script:
- ps: |
node script/yarn.js install --frozen-lockfile
node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER --prBranch=$env:APPVEYOR_REPO_BRANCH
if ($LASTEXITCODE -eq 0) {
Write-warning "Skipping build for doc only change"; Exit-AppveyorBuild
}
$global:LASTEXITCODE = 0
- cd ..
- ps: Write-Host "Building $env:GN_CONFIG build"
- git config --global core.longpaths true
- ps: >-
if (Test-Path -Path "$pwd\depot_tools") {
Remove-Item -Recurse -Force $pwd\depot_tools
}
- ps: >-
if (Test-Path -Path "$pwd\build-tools") {
Remove-Item -Recurse -Force $pwd\build-tools
}
- git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
- ps: $env:PATH="$pwd\depot_tools;$env:PATH"
- ps: >-
if (Test-Path -Path "$pwd\src\electron") {
Remove-Item -Recurse -Force $pwd\src\electron
}
- ps: >-
if (Test-Path 'env:RAW_GOMA_AUTH') {
$env:GOMA_OAUTH2_CONFIG_FILE = "$pwd\.goma_oauth2_config"
$env:RAW_GOMA_AUTH | Set-Content $env:GOMA_OAUTH2_CONFIG_FILE
}
- git clone https://github.com/electron/build-tools.git
- cd build-tools
- npm install
- mkdir third_party
- ps: >-
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
- ps: $env:GN_GOMA_FILE = node -e "console.log(require('./src/utils/goma.js').gnFilePath)"
- ps: $env:LOCAL_GOMA_DIR = node -e "console.log(require('./src/utils/goma.js').dir)"
- cd ..\..
- ps: .\src\electron\script\start-goma.ps1 -gomaDir $env:LOCAL_GOMA_DIR
- ps: >-
if (Test-Path 'env:RAW_GOMA_AUTH') {
$goma_login = python $env:LOCAL_GOMA_DIR\goma_auth.py info
if ($goma_login -eq 'Login as Fermi Planck') {
Write-warning "Goma authentication is correct";
} else {
Write-warning "WARNING!!!!!! Goma authentication is incorrect; please update Goma auth token.";
$host.SetShouldExit(1)
}
}
- ps: $env:CHROMIUM_BUILDTOOLS_PATH="$pwd\src\buildtools"
- ps: >-
if ($env:GN_CONFIG -ne 'release') {
$env:NINJA_STATUS="[%r processes, %f/%t @ %o/s : %es] "
}
- gclient config --name "src\electron" --unmanaged %GCLIENT_EXTRA_ARGS% "https://github.com/electron/electron"
# Patches are applied in the image bake. Check depshash to see if patches have changed.
- ps: $env:RUN_GCLIENT_SYNC="false"
- ps: $depshash_baked = Get-Content .\src\.depshash -Raw
- ps: cd src\electron
- ps: node script\generate-deps-hash.js
- ps: $depshash = Get-Content .\.depshash -Raw
- ps: cd ..\..
- ps: >-
if ($depshash_baked -ne $depshash) {
$env:RUN_GCLIENT_SYNC="true"
}
- if "%RUN_GCLIENT_SYNC%"=="true" ( gclient sync --with_branch_heads --with_tags ) else ( gclient runhooks )
- cd src
- ps: $env:PATH="$pwd\third_party\ninja;$env:PATH"
- set BUILD_CONFIG_PATH=//electron/build/args/%GN_CONFIG%.gn
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") import(\"%GN_GOMA_FILE%\") %GN_EXTRA_ARGS% "
- gn check out/Default //electron:electron_lib
- gn check out/Default //electron:electron_app
- gn check out/Default //electron/shell/common/api:mojo
- if DEFINED GN_GOMA_FILE (ninja -j 300 -C out/Default electron:electron_app) else (ninja -C out/Default electron:electron_app)
- if "%GN_CONFIG%"=="testing" ( python C:\depot_tools\post_build_ninja_summary.py -C out\Default )
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") %GN_EXTRA_ARGS%"
- ninja -C out/ffmpeg electron:electron_ffmpeg_zip
- ninja -C out/Default electron:electron_dist_zip
- ninja -C out/Default shell_browser_ui_unittests
- gn desc out/Default v8:run_mksnapshot_default args > out/Default/default_mksnapshot_args
# Remove unused args from mksnapshot_args
- ps: >-
Get-Content out/Default/default_mksnapshot_args | Where-Object { -not $_.Contains('--turbo-profiling-input') -And -not $_.Contains('builtins-pgo') } | Set-Content out/Default/mksnapshot_args
- ninja -C out/Default electron:electron_mksnapshot_zip
- cd out\Default
- 7z a mksnapshot.zip mksnapshot_args gen\v8\embedded.S
- cd ..\..
- ninja -C out/Default electron:hunspell_dictionaries_zip
- ninja -C out/Default electron:electron_chromedriver_zip
- ninja -C out/Default third_party/electron_node:headers
- python %LOCAL_GOMA_DIR%\goma_ctl.py stat
- ps: >-
Get-CimInstance -Namespace root\cimv2 -Class Win32_product | Select vendor, description, @{l='install_location';e='InstallLocation'}, @{l='install_date';e='InstallDate'}, @{l='install_date_2';e='InstallDate2'}, caption, version, name, @{l='sku_number';e='SKUNumber'} | ConvertTo-Json | Out-File -Encoding utf8 -FilePath .\installed_software.json
- python3 electron/build/profile_toolchain.py --output-json=out/Default/windows_toolchain_profile.json
- 7z a node_headers.zip out\Default\gen\node_headers
- ps: >-
if ($env:GN_CONFIG -eq 'release') {
# Needed for msdia140.dll on 64-bit windows
$env:Path += ";$pwd\third_party\llvm-build\Release+Asserts\bin"
ninja -C out/Default electron:electron_symbols
}
- ps: >-
if ($env:GN_CONFIG -eq 'release') {
python3 electron\script\zip-symbols.py
appveyor-retry appveyor PushArtifact out/Default/symbols.zip
} else {
# It's useful to have pdb files when debugging testing builds that are
# built on CI.
7z a pdb.zip out\Default\*.pdb
}
- python3 electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.win.%TARGET_ARCH%.manifest
deploy_script:
- cd electron
- ps: >-
if (Test-Path Env:\ELECTRON_RELEASE) {
if (Test-Path Env:\UPLOAD_TO_STORAGE) {
Write-Output "Uploading Electron release distribution to azure"
& python3 script\release\uploaders\upload.py --verbose --upload_to_storage
} else {
Write-Output "Uploading Electron release distribution to github releases"
& python3 script\release\uploaders\upload.py --verbose
}
}
on_finish:
# Uncomment this lines to enable RDP
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
- cd C:\projects\src
- if exist out\Default\windows_toolchain_profile.json ( appveyor-retry appveyor PushArtifact out\Default\windows_toolchain_profile.json )
- if exist out\Default\dist.zip (appveyor-retry appveyor PushArtifact out\Default\dist.zip)
- if exist out\Default\shell_browser_ui_unittests.exe (appveyor-retry appveyor PushArtifact out\Default\shell_browser_ui_unittests.exe)
- if exist out\Default\chromedriver.zip (appveyor-retry appveyor PushArtifact out\Default\chromedriver.zip)
- if exist out\ffmpeg\ffmpeg.zip (appveyor-retry appveyor PushArtifact out\ffmpeg\ffmpeg.zip)
- if exist node_headers.zip (appveyor-retry appveyor PushArtifact node_headers.zip)
- if exist out\Default\mksnapshot.zip (appveyor-retry appveyor PushArtifact out\Default\mksnapshot.zip)
- if exist out\Default\hunspell_dictionaries.zip (appveyor-retry appveyor PushArtifact out\Default\hunspell_dictionaries.zip)
- if exist out\Default\electron.lib (appveyor-retry appveyor PushArtifact out\Default\electron.lib)
- ps: >-
if ((Test-Path "pdb.zip") -And ($env:GN_CONFIG -ne 'release')) {
appveyor-retry appveyor PushArtifact pdb.zip
}
- matrix:
only:
- job_name: Test
init:
- ps: |
if ($env:RUN_TESTS -ne 'true') {
Write-warning "Skipping tests for $env:APPVEYOR_PROJECT_NAME"; Exit-AppveyorBuild
}
build_script:
- ps: |
node script/yarn.js install --frozen-lockfile
node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER --prBranch=$env:APPVEYOR_REPO_BRANCH
if ($LASTEXITCODE -eq 0) {
Write-warning "Skipping build for doc only change"; Exit-AppveyorBuild
}
$global:LASTEXITCODE = 0
- cd ..
- mkdir out\Default
- cd ..
- ps: |
# Download build artifacts
$apiUrl = 'https://ci.appveyor.com/api'
$build_info = Invoke-RestMethod -Method Get -Uri "$apiUrl/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/builds/$env:APPVEYOR_BUILD_ID"
$artifacts_to_download = @('dist.zip','shell_browser_ui_unittests.exe','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib')
foreach ($job in $build_info.build.jobs) {
if ($job.name -eq "Build") {
$jobId = $job.jobId
foreach($artifact_name in $artifacts_to_download) {
if ($artifact_name -eq 'shell_browser_ui_unittests.exe' -Or $artifact_name -eq 'electron.lib') {
$outfile = "src\out\Default\$artifact_name"
} else {
$outfile = $artifact_name
}
Invoke-RestMethod -Method Get -Uri "$apiUrl/buildjobs/$jobId/artifacts/$artifact_name" -OutFile $outfile
}
}
}
- ps: |
$out_default_zips = @('dist.zip','chromedriver.zip','mksnapshot.zip')
foreach($zip_name in $out_default_zips) {
7z x -y -osrc\out\Default $zip_name
}
- ps: 7z x -y -osrc\out\ffmpeg ffmpeg.zip
- ps: 7z x -y -osrc node_headers.zip
test_script:
# Workaround for https://github.com/appveyor/ci/issues/2420
- set "PATH=%PATH%;C:\Program Files\Git\mingw64\libexec\git-core"
- ps: |
cd src
New-Item .\out\Default\gen\node_headers\Release -Type directory
Copy-Item -path .\out\Default\electron.lib -destination .\out\Default\gen\node_headers\Release\node.lib
- cd electron
# Explicitly set npm_config_arch because the .env doesn't persist
- ps: >-
if ($env:TARGET_ARCH -eq 'ia32') {
$env:npm_config_arch = "ia32"
}
- echo Running main test suite & node script/yarn test -- --trace-uncaught --runners=main --enable-logging=file --log-file=%cd%\electron.log
- echo Running native test suite & node script/yarn test -- --trace-uncaught --runners=native --enable-logging=file --log-file=%cd%\electron.log
- cd ..
- echo Verifying non proprietary ffmpeg & python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg
- echo "About to verify mksnapshot"
- echo Verifying mksnapshot & python electron\script\verify-mksnapshot.py --build-dir out\Default --source-root %cd%
- echo "Done verifying mksnapshot"
- echo Verifying chromedriver & python electron\script\verify-chromedriver.py --build-dir out\Default --source-root %cd%
- echo "Done verifying chromedriver"
on_finish:
# Uncomment these lines to enable RDP
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
- if exist electron\electron.log ( appveyor-retry appveyor PushArtifact electron\electron.log )

1
atom/CPPLINT.cfg Normal file
View File

@@ -0,0 +1 @@
filter=+build/include_alpha

View File

@@ -0,0 +1,225 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/app/atom_content_client.h"
#include <string>
#include <vector>
#include "atom/common/atom_constants.h"
#include "atom/common/atom_version.h"
#include "atom/common/chrome_version.h"
#include "atom/common/options_switches.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/pepper_plugin_info.h"
#include "content/public/common/user_agent.h"
#include "pdf/pdf.h"
#include "ppapi/shared_impl/ppapi_permissions.h"
#include "third_party/widevine/cdm/stub/widevine_cdm_version.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/url_constants.h"
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS)
#include "chrome/common/widevine_cdm_constants.h"
#endif
namespace atom {
namespace {
content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path,
const std::string& version) {
content::PepperPluginInfo plugin;
plugin.is_out_of_process = true;
plugin.name = content::kFlashPluginName;
plugin.path = path;
plugin.permissions = ppapi::PERMISSION_ALL_BITS;
std::vector<std::string> flash_version_numbers = base::SplitString(
version, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
if (flash_version_numbers.empty())
flash_version_numbers.push_back("11");
// |SplitString()| puts in an empty string given an empty string. :(
else if (flash_version_numbers[0].empty())
flash_version_numbers[0] = "11";
if (flash_version_numbers.size() < 2)
flash_version_numbers.push_back("2");
if (flash_version_numbers.size() < 3)
flash_version_numbers.push_back("999");
if (flash_version_numbers.size() < 4)
flash_version_numbers.push_back("999");
// E.g., "Shockwave Flash 10.2 r154":
plugin.description = plugin.name + " " + flash_version_numbers[0] + "." +
flash_version_numbers[1] + " r" + flash_version_numbers[2];
plugin.version = base::JoinString(flash_version_numbers, ".");
content::WebPluginMimeType swf_mime_type(
content::kFlashPluginSwfMimeType,
content::kFlashPluginSwfExtension,
content::kFlashPluginSwfDescription);
plugin.mime_types.push_back(swf_mime_type);
content::WebPluginMimeType spl_mime_type(
content::kFlashPluginSplMimeType,
content::kFlashPluginSplExtension,
content::kFlashPluginSplDescription);
plugin.mime_types.push_back(spl_mime_type);
return plugin;
}
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS)
content::PepperPluginInfo CreateWidevineCdmInfo(const base::FilePath& path,
const std::string& version) {
content::PepperPluginInfo widevine_cdm;
widevine_cdm.is_out_of_process = true;
widevine_cdm.path = path;
widevine_cdm.name = kWidevineCdmDisplayName;
widevine_cdm.description = kWidevineCdmDescription +
std::string(" (version: ") +
version + ")";
widevine_cdm.version = version;
content::WebPluginMimeType widevine_cdm_mime_type(
kWidevineCdmPluginMimeType,
kWidevineCdmPluginExtension,
kWidevineCdmPluginMimeTypeDescription);
// Add the supported codecs as if they came from the component manifest.
std::vector<std::string> codecs;
codecs.push_back(kCdmSupportedCodecVp8);
codecs.push_back(kCdmSupportedCodecVp9);
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
codecs.push_back(kCdmSupportedCodecAvc1);
#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
std::string codec_string = base::JoinString(
codecs, std::string(1, kCdmSupportedCodecsValueDelimiter));
widevine_cdm_mime_type.additional_param_names.push_back(
base::ASCIIToUTF16(kCdmSupportedCodecsParamName));
widevine_cdm_mime_type.additional_param_values.push_back(
base::ASCIIToUTF16(codec_string));
widevine_cdm.mime_types.push_back(widevine_cdm_mime_type);
widevine_cdm.permissions = kWidevineCdmPluginPermissions;
return widevine_cdm;
}
#endif
void ComputeBuiltInPlugins(std::vector<content::PepperPluginInfo>* plugins) {
content::PepperPluginInfo pdf_info;
pdf_info.is_internal = true;
pdf_info.is_out_of_process = true;
pdf_info.name = "Chromium PDF Viewer";
pdf_info.description = "Portable Document Format";
pdf_info.path = base::FilePath::FromUTF8Unsafe(kPdfPluginPath);
content::WebPluginMimeType pdf_mime_type(kPdfPluginMimeType, "pdf",
"Portable Document Format");
pdf_info.mime_types.push_back(pdf_mime_type);
pdf_info.internal_entry_points.get_interface = chrome_pdf::PPP_GetInterface;
pdf_info.internal_entry_points.initialize_module =
chrome_pdf::PPP_InitializeModule;
pdf_info.internal_entry_points.shutdown_module =
chrome_pdf::PPP_ShutdownModule;
pdf_info.permissions = ppapi::PERMISSION_PRIVATE | ppapi::PERMISSION_DEV;
plugins->push_back(pdf_info);
}
void ConvertStringWithSeparatorToVector(std::vector<std::string>* vec,
const char* separator,
const char* cmd_switch) {
auto command_line = base::CommandLine::ForCurrentProcess();
auto string_with_separator = command_line->GetSwitchValueASCII(cmd_switch);
if (!string_with_separator.empty())
*vec = base::SplitString(string_with_separator, separator,
base::TRIM_WHITESPACE,
base::SPLIT_WANT_NONEMPTY);
}
} // namespace
void AddPepperFlashFromCommandLine(
std::vector<content::PepperPluginInfo>* plugins) {
auto command_line = base::CommandLine::ForCurrentProcess();
base::FilePath flash_path = command_line->GetSwitchValuePath(
switches::kPpapiFlashPath);
if (flash_path.empty())
return;
auto flash_version = command_line->GetSwitchValueASCII(
switches::kPpapiFlashVersion);
plugins->push_back(CreatePepperFlashInfo(flash_path, flash_version));
}
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS)
void AddWidevineCdmFromCommandLine(
std::vector<content::PepperPluginInfo>* plugins) {
auto command_line = base::CommandLine::ForCurrentProcess();
base::FilePath widevine_cdm_path = command_line->GetSwitchValuePath(
switches::kWidevineCdmPath);
if (widevine_cdm_path.empty())
return;
if (!base::PathExists(widevine_cdm_path))
return;
auto widevine_cdm_version = command_line->GetSwitchValueASCII(
switches::kWidevineCdmVersion);
if (widevine_cdm_version.empty())
return;
plugins->push_back(CreateWidevineCdmInfo(widevine_cdm_path,
widevine_cdm_version));
}
#endif
AtomContentClient::AtomContentClient() {
}
AtomContentClient::~AtomContentClient() {
}
std::string AtomContentClient::GetProduct() const {
return "Chrome/" CHROME_VERSION_STRING;
}
std::string AtomContentClient::GetUserAgent() const {
return content::BuildUserAgentFromProduct(
"Chrome/" CHROME_VERSION_STRING " "
ATOM_PRODUCT_NAME "/" ATOM_VERSION_STRING);
}
base::string16 AtomContentClient::GetLocalizedString(int message_id) const {
return l10n_util::GetStringUTF16(message_id);
}
void AtomContentClient::AddAdditionalSchemes(Schemes* schemes) {
schemes->standard_schemes.push_back("chrome-extension");
std::vector<std::string> splited;
ConvertStringWithSeparatorToVector(&splited, ",",
switches::kRegisterServiceWorkerSchemes);
for (const std::string& scheme : splited)
schemes->service_worker_schemes.push_back(scheme);
schemes->service_worker_schemes.push_back(url::kFileScheme);
ConvertStringWithSeparatorToVector(&splited, ",", switches::kSecureSchemes);
for (const std::string& scheme : splited)
schemes->secure_schemes.push_back(scheme);
}
void AtomContentClient::AddPepperPlugins(
std::vector<content::PepperPluginInfo>* plugins) {
AddPepperFlashFromCommandLine(plugins);
#if defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS)
AddWidevineCdmFromCommandLine(plugins);
#endif
ComputeBuiltInPlugins(plugins);
}
} // namespace atom

View File

@@ -0,0 +1,36 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_APP_ATOM_CONTENT_CLIENT_H_
#define ATOM_APP_ATOM_CONTENT_CLIENT_H_
#include <set>
#include <string>
#include <vector>
#include "brightray/common/content_client.h"
namespace atom {
class AtomContentClient : public brightray::ContentClient {
public:
AtomContentClient();
virtual ~AtomContentClient();
protected:
// content::ContentClient:
std::string GetProduct() const override;
std::string GetUserAgent() const override;
base::string16 GetLocalizedString(int message_id) const override;
void AddAdditionalSchemes(Schemes* schemes) override;
void AddPepperPlugins(
std::vector<content::PepperPluginInfo>* plugins) override;
private:
DISALLOW_COPY_AND_ASSIGN(AtomContentClient);
};
} // namespace atom
#endif // ATOM_APP_ATOM_CONTENT_CLIENT_H_

View File

@@ -0,0 +1,20 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_APP_ATOM_LIBRARY_MAIN_H_
#define ATOM_APP_ATOM_LIBRARY_MAIN_H_
#include "build/build_config.h"
#if defined(OS_MACOSX)
extern "C" {
__attribute__((visibility("default")))
int AtomMain(int argc, char* argv[]);
__attribute__((visibility("default")))
int AtomInitializeICUandStartNode(int argc, char *argv[]);
}
#endif // OS_MACOSX
#endif // ATOM_APP_ATOM_LIBRARY_MAIN_H_

View File

@@ -0,0 +1,38 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/app/atom_library_main.h"
#include "atom/app/atom_main_delegate.h"
#include "atom/app/node_main.h"
#include "atom/common/atom_command_line.h"
#include "base/at_exit.h"
#include "base/i18n/icu_util.h"
#include "base/mac/bundle_locations.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#include "brightray/common/mac/main_application_bundle.h"
#include "content/public/app/content_main.h"
#if defined(OS_MACOSX)
int AtomMain(int argc, char* argv[]) {
atom::AtomMainDelegate delegate;
content::ContentMainParams params(&delegate);
params.argc = argc;
params.argv = const_cast<const char**>(argv);
atom::AtomCommandLine::Init(argc, argv);
return content::ContentMain(params);
}
int AtomInitializeICUandStartNode(int argc, char *argv[]) {
base::AtExitManager atexit_manager;
base::mac::ScopedNSAutoreleasePool pool;
base::mac::SetOverrideFrameworkBundlePath(
brightray::MainApplicationBundlePath()
.Append("Contents")
.Append("Frameworks")
.Append(ATOM_PRODUCT_NAME " Framework.framework"));
base::i18n::InitializeICU();
return atom::NodeMain(argc, argv);
}
#endif // OS_MACOSX

View File

@@ -0,0 +1,11 @@
#import <Cocoa/Cocoa.h>
int main(int argc, char* argv[]) {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSArray* pathComponents = [[[NSBundle mainBundle] bundlePath] pathComponents];
pathComponents = [pathComponents subarrayWithRange:NSMakeRange(0, [pathComponents count] - 4)];
NSString* path = [NSString pathWithComponents:pathComponents];
[[NSWorkspace sharedWorkspace] launchApplication:path];
[pool drain];
return 0;
}

187
atom/app/atom_main.cc Normal file
View File

@@ -0,0 +1,187 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/app/atom_main.h"
#include <cstdlib>
#include <vector>
#if defined(OS_WIN)
#include <windows.h> // windows.h must be included first
#include <atlbase.h> // ensures that ATL statics like `_AtlWinModule` are initialized (it's an issue in static debug build)
#include <shellapi.h>
#include <shellscalingapi.h>
#include <tchar.h>
#include "atom/app/atom_main_delegate.h"
#include "atom/app/command_line_args.h"
#include "atom/common/crash_reporter/win/crash_service_main.h"
#include "base/environment.h"
#include "base/process/launch.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/windows_version.h"
#include "content/public/app/sandbox_helper_win.h"
#include "sandbox/win/src/sandbox_types.h"
#elif defined(OS_LINUX) // defined(OS_WIN)
#include "atom/app/atom_main_delegate.h" // NOLINT
#include "content/public/app/content_main.h"
#else // defined(OS_LINUX)
#include "atom/app/atom_library_main.h"
#endif // defined(OS_MACOSX)
#include "atom/app/node_main.h"
#include "atom/common/atom_command_line.h"
#include "base/at_exit.h"
#include "base/i18n/icu_util.h"
namespace {
#ifdef ENABLE_RUN_AS_NODE
const auto kRunAsNode = "ELECTRON_RUN_AS_NODE";
#endif
bool IsEnvSet(const char* name) {
#if defined(OS_WIN)
size_t required_size;
getenv_s(&required_size, nullptr, 0, name);
return required_size != 0;
#else
char* indicator = getenv(name);
return indicator && indicator[0] != '\0';
#endif
}
} // namespace
#if defined(OS_WIN)
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
struct Arguments {
int argc = 0;
wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
~Arguments() { LocalFree(argv); }
} arguments;
if (!arguments.argv)
return -1;
#ifdef _DEBUG
// Don't display assert dialog boxes in CI test runs
static const auto kCI = "ELECTRON_CI";
bool is_ci = IsEnvSet(kCI);
if (!is_ci) {
for (int i = 0; i < arguments.argc; ++i) {
if (!_wcsicmp(arguments.argv[i], L"--ci")) {
is_ci = true;
_putenv_s(kCI, "1"); // set flag for child processes
break;
}
}
}
if (is_ci) {
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
_set_error_mode(_OUT_TO_STDERR);
}
#endif
#ifdef ENABLE_RUN_AS_NODE
bool run_as_node = IsEnvSet(kRunAsNode);
#else
bool run_as_node = false;
#endif
// Make sure the output is printed to console.
if (run_as_node || !IsEnvSet("ELECTRON_NO_ATTACH_CONSOLE"))
base::RouteStdioToConsole(false);
#ifndef DEBUG
// Chromium has its own TLS subsystem which supports automatic destruction
// of thread-local data, and also depends on memory allocation routines
// provided by the CRT. The problem is that the auto-destruction mechanism
// uses a hidden feature of the OS loader which calls a callback on thread
// exit, but only after all loaded DLLs have been detached. Since the CRT is
// also a DLL, it happens that by the time Chromium's `OnThreadExit` function
// is called, the heap functions, though still in memory, no longer perform
// their duties, and when Chromium calls `free` on its buffer, it triggers
// an access violation error.
// We work around this problem by invoking Chromium's `OnThreadExit` in time
// from within the CRT's atexit facility, ensuring the heap functions are
// still active. The second invocation from the OS loader will be a no-op.
extern void NTAPI OnThreadExit(PVOID module, DWORD reason, PVOID reserved);
atexit([]() {
OnThreadExit(nullptr, DLL_THREAD_DETACH, nullptr);
});
#endif
#ifdef ENABLE_RUN_AS_NODE
if (run_as_node) {
std::vector<char*> argv(arguments.argc);
std::transform(
arguments.argv, arguments.argv + arguments.argc, argv.begin(),
[](auto& a) { return _strdup(base::WideToUTF8(a).c_str()); });
base::AtExitManager atexit_manager;
base::i18n::InitializeICU();
auto ret = atom::NodeMain(argv.size(), argv.data());
std::for_each(argv.begin(), argv.end(), free);
return ret;
}
#endif
if (IsEnvSet("ELECTRON_INTERNAL_CRASH_SERVICE")) {
return crash_service::Main(cmd);
}
if (!atom::CheckCommandLineArguments(arguments.argc, arguments.argv))
return -1;
sandbox::SandboxInterfaceInfo sandbox_info = {0};
content::InitializeSandboxInfo(&sandbox_info);
atom::AtomMainDelegate delegate;
content::ContentMainParams params(&delegate);
params.instance = instance;
params.sandbox_info = &sandbox_info;
atom::AtomCommandLine::Init(arguments.argc, arguments.argv);
return content::ContentMain(params);
}
#elif defined(OS_LINUX) // defined(OS_WIN)
int main(int argc, char* argv[]) {
#ifdef ENABLE_RUN_AS_NODE
if (IsEnvSet(kRunAsNode)) {
base::i18n::InitializeICU();
base::AtExitManager atexit_manager;
return atom::NodeMain(argc, argv);
}
#endif
atom::AtomMainDelegate delegate;
content::ContentMainParams params(&delegate);
params.argc = argc;
params.argv = const_cast<const char**>(argv);
atom::AtomCommandLine::Init(argc, argv);
return content::ContentMain(params);
}
#else // defined(OS_LINUX)
int main(int argc, char* argv[]) {
#ifdef ENABLE_RUN_AS_NODE
if (IsEnvSet(kRunAsNode)) {
return AtomInitializeICUandStartNode(argc, argv);
}
#endif
return AtomMain(argc, argv);
}
#endif // defined(OS_MACOSX)

10
atom/app/atom_main.h Normal file
View File

@@ -0,0 +1,10 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_APP_ATOM_MAIN_H_
#define ATOM_APP_ATOM_MAIN_H_
#include "content/public/app/content_main.h"
#endif // ATOM_APP_ATOM_MAIN_H_

View File

@@ -0,0 +1,208 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/app/atom_main_delegate.h"
#include <iostream>
#include <string>
#include "atom/app/atom_content_client.h"
#include "atom/browser/atom_browser_client.h"
#include "atom/browser/relauncher.h"
#include "atom/common/google_api_key.h"
#include "atom/common/options_switches.h"
#include "atom/renderer/atom_renderer_client.h"
#include "atom/renderer/atom_sandboxed_renderer_client.h"
#include "atom/utility/atom_content_utility_client.h"
#include "base/command_line.h"
#include "base/debug/stack_trace.h"
#include "base/environment.h"
#include "base/logging.h"
#include "chrome/common/chrome_paths.h"
#include "content/public/common/content_switches.h"
#include "ipc/ipc_features.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
#define IPC_MESSAGE_MACROS_LOG_ENABLED
#include "content/public/common/content_ipc_logging.h"
#define IPC_LOG_TABLE_ADD_ENTRY(msg_id, logger) \
content::RegisterIPCLogger(msg_id, logger)
#include "atom/common/common_message_generator.h"
#endif
namespace atom {
namespace {
const char* kRelauncherProcess = "relauncher";
bool IsBrowserProcess(base::CommandLine* cmd) {
std::string process_type = cmd->GetSwitchValueASCII(::switches::kProcessType);
return process_type.empty();
}
#if defined(OS_WIN)
void InvalidParameterHandler(const wchar_t*, const wchar_t*, const wchar_t*,
unsigned int, uintptr_t) {
// noop.
}
#endif
} // namespace
AtomMainDelegate::AtomMainDelegate() {
}
AtomMainDelegate::~AtomMainDelegate() {
}
bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
auto command_line = base::CommandLine::ForCurrentProcess();
logging::LoggingSettings settings;
#if defined(OS_WIN)
// On Windows the terminal returns immediately, so we add a new line to
// prevent output in the same line as the prompt.
if (IsBrowserProcess(command_line))
std::wcout << std::endl;
#if defined(DEBUG)
// Print logging to debug.log on Windows
settings.logging_dest = logging::LOG_TO_ALL;
settings.log_file = L"debug.log";
settings.lock_log = logging::LOCK_LOG_FILE;
settings.delete_old = logging::DELETE_OLD_LOG_FILE;
#else
settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
#endif // defined(DEBUG)
#else // defined(OS_WIN)
settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
#endif // !defined(OS_WIN)
// Only enable logging when --enable-logging is specified.
std::unique_ptr<base::Environment> env(base::Environment::Create());
if (!command_line->HasSwitch(::switches::kEnableLogging) &&
!env->HasVar("ELECTRON_ENABLE_LOGGING")) {
settings.logging_dest = logging::LOG_NONE;
logging::SetMinLogLevel(logging::LOG_NUM_SEVERITIES);
}
logging::InitLogging(settings);
// Logging with pid and timestamp.
logging::SetLogItems(true, false, true, false);
// Enable convient stack printing.
#if defined(DEBUG) && defined(OS_LINUX)
bool enable_stack_dumping = true;
#else
bool enable_stack_dumping = env->HasVar("ELECTRON_ENABLE_STACK_DUMPING");
#endif
if (enable_stack_dumping)
base::debug::EnableInProcessStackDumping();
chrome::RegisterPathProvider();
#if defined(OS_MACOSX)
SetUpBundleOverrides();
#endif
#if defined(OS_WIN)
// Ignore invalid parameter errors.
_set_invalid_parameter_handler(InvalidParameterHandler);
// Disable the ActiveVerifier, which is used by Chrome to track possible
// bugs, but no use in Electron.
base::win::DisableHandleVerifier();
#endif
return brightray::MainDelegate::BasicStartupComplete(exit_code);
}
void AtomMainDelegate::PreSandboxStartup() {
brightray::MainDelegate::PreSandboxStartup();
// Set google API key.
std::unique_ptr<base::Environment> env(base::Environment::Create());
if (!env->HasVar("GOOGLE_API_KEY"))
env->SetVar("GOOGLE_API_KEY", GOOGLEAPIS_API_KEY);
auto command_line = base::CommandLine::ForCurrentProcess();
std::string process_type = command_line->GetSwitchValueASCII(
::switches::kProcessType);
// Only append arguments for browser process.
if (!IsBrowserProcess(command_line))
return;
if (!command_line->HasSwitch(switches::kEnableMixedSandbox)) {
if (command_line->HasSwitch(switches::kEnableSandbox)) {
// Disable setuid sandbox since it is not longer required on
// linux(namespace sandbox is available on most distros).
command_line->AppendSwitch(::switches::kDisableSetuidSandbox);
} else {
// Disable renderer sandbox for most of node's functions.
command_line->AppendSwitch(::switches::kNoSandbox);
}
}
// Allow file:// URIs to read other file:// URIs by default.
command_line->AppendSwitch(::switches::kAllowFileAccessFromFiles);
#if defined(OS_MACOSX)
// Enable AVFoundation.
command_line->AppendSwitch("enable-avfoundation");
#endif
}
content::ContentBrowserClient* AtomMainDelegate::CreateContentBrowserClient() {
browser_client_.reset(new AtomBrowserClient);
return browser_client_.get();
}
content::ContentRendererClient*
AtomMainDelegate::CreateContentRendererClient() {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableSandbox) ||
!base::CommandLine::ForCurrentProcess()->HasSwitch(
::switches::kNoSandbox)) {
renderer_client_.reset(new AtomSandboxedRendererClient);
} else {
renderer_client_.reset(new AtomRendererClient);
}
return renderer_client_.get();
}
content::ContentUtilityClient* AtomMainDelegate::CreateContentUtilityClient() {
utility_client_.reset(new AtomContentUtilityClient);
return utility_client_.get();
}
int AtomMainDelegate::RunProcess(
const std::string& process_type,
const content::MainFunctionParams& main_function_params) {
if (process_type == kRelauncherProcess)
return relauncher::RelauncherMain(main_function_params);
else
return -1;
}
#if defined(OS_MACOSX)
bool AtomMainDelegate::ShouldSendMachPort(const std::string& process_type) {
return process_type != kRelauncherProcess;
}
bool AtomMainDelegate::DelaySandboxInitialization(
const std::string& process_type) {
return process_type == kRelauncherProcess;
}
#endif
std::unique_ptr<brightray::ContentClient>
AtomMainDelegate::CreateContentClient() {
return std::unique_ptr<brightray::ContentClient>(new AtomContentClient);
}
} // namespace atom

View File

@@ -0,0 +1,56 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_APP_ATOM_MAIN_DELEGATE_H_
#define ATOM_APP_ATOM_MAIN_DELEGATE_H_
#include <string>
#include "brightray/common/content_client.h"
#include "brightray/common/main_delegate.h"
namespace atom {
class AtomMainDelegate : public brightray::MainDelegate {
public:
AtomMainDelegate();
~AtomMainDelegate();
protected:
// content::ContentMainDelegate:
bool BasicStartupComplete(int* exit_code) override;
void PreSandboxStartup() override;
content::ContentBrowserClient* CreateContentBrowserClient() override;
content::ContentRendererClient* CreateContentRendererClient() override;
content::ContentUtilityClient* CreateContentUtilityClient() override;
int RunProcess(
const std::string& process_type,
const content::MainFunctionParams& main_function_params) override;
#if defined(OS_MACOSX)
bool ShouldSendMachPort(const std::string& process_type) override;
bool DelaySandboxInitialization(const std::string& process_type) override;
#endif
// brightray::MainDelegate:
std::unique_ptr<brightray::ContentClient> CreateContentClient() override;
#if defined(OS_MACOSX)
void OverrideChildProcessPath() override;
void OverrideFrameworkBundlePath() override;
#endif
private:
#if defined(OS_MACOSX)
void SetUpBundleOverrides();
#endif
std::unique_ptr<content::ContentBrowserClient> browser_client_;
std::unique_ptr<content::ContentRendererClient> renderer_client_;
std::unique_ptr<content::ContentUtilityClient> utility_client_;
DISALLOW_COPY_AND_ASSIGN(AtomMainDelegate);
};
} // namespace atom
#endif // ATOM_APP_ATOM_MAIN_DELEGATE_H_

View File

@@ -0,0 +1,65 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/app/atom_main_delegate.h"
#include "base/mac/bundle_locations.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/mac/foundation_util.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#include "base/path_service.h"
#include "base/strings/sys_string_conversions.h"
#include "brightray/common/application_info.h"
#include "brightray/common/mac/main_application_bundle.h"
#include "content/public/common/content_paths.h"
namespace atom {
namespace {
base::FilePath GetFrameworksPath() {
return brightray::MainApplicationBundlePath().Append("Contents")
.Append("Frameworks");
}
base::FilePath GetHelperAppPath(const base::FilePath& frameworks_path,
const std::string& name) {
return frameworks_path.Append(name + " Helper.app")
.Append("Contents")
.Append("MacOS")
.Append(name + " Helper");
}
} // namespace
void AtomMainDelegate::OverrideFrameworkBundlePath() {
base::mac::SetOverrideFrameworkBundlePath(
GetFrameworksPath().Append(ATOM_PRODUCT_NAME " Framework.framework"));
}
void AtomMainDelegate::OverrideChildProcessPath() {
base::FilePath frameworks_path = GetFrameworksPath();
base::FilePath helper_path = GetHelperAppPath(frameworks_path,
ATOM_PRODUCT_NAME);
if (!base::PathExists(helper_path))
helper_path = GetHelperAppPath(frameworks_path,
brightray::GetApplicationName());
if (!base::PathExists(helper_path))
LOG(FATAL) << "Unable to find helper app";
PathService::Override(content::CHILD_PROCESS_EXE, helper_path);
}
void AtomMainDelegate::SetUpBundleOverrides() {
base::mac::ScopedNSAutoreleasePool pool;
NSBundle* bundle = brightray::MainApplicationBundle();
std::string base_bundle_id =
base::SysNSStringToUTF8([bundle bundleIdentifier]);
NSString* team_id = [bundle objectForInfoDictionaryKey:@"ElectronTeamID"];
if (team_id)
base_bundle_id = base::SysNSStringToUTF8(team_id) + "." + base_bundle_id;
base::mac::SetBaseBundleID(base_bundle_id.c_str());
}
} // namespace atom

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,17 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_APP_COMMAND_LINE_ARGS_H_
#define ATOM_APP_COMMAND_LINE_ARGS_H_
#include "base/command_line.h"
namespace atom {
bool CheckCommandLineArguments(int argc, base::CommandLine::CharType** argv);
} // namespace atom
#endif // ATOM_APP_COMMAND_LINE_ARGS_H_

113
atom/app/node_main.cc Normal file
View File

@@ -0,0 +1,113 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifdef ENABLE_RUN_AS_NODE
#include "atom/app/node_main.h"
#include "atom/app/uv_task_runner.h"
#include "atom/browser/javascript_environment.h"
#include "atom/browser/node_debugger.h"
#include "atom/common/api/atom_bindings.h"
#include "atom/common/crash_reporter/crash_reporter.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/task_scheduler/task_scheduler.h"
#include "base/threading/thread_task_runner_handle.h"
#include "gin/array_buffer.h"
#include "gin/public/isolate_holder.h"
#include "gin/v8_initializer.h"
#include "native_mate/dictionary.h"
#include "atom/common/node_includes.h"
namespace atom {
int NodeMain(int argc, char *argv[]) {
base::CommandLine::Init(argc, argv);
int exit_code = 1;
{
// Feed gin::PerIsolateData with a task runner.
argv = uv_setup_args(argc, argv);
uv_loop_t* loop = uv_default_loop();
scoped_refptr<UvTaskRunner> uv_task_runner(new UvTaskRunner(loop));
base::ThreadTaskRunnerHandle handle(uv_task_runner);
// Initialize feature list.
std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
feature_list->InitializeFromCommandLine("", "");
base::FeatureList::SetInstance(std::move(feature_list));
gin::V8Initializer::LoadV8Snapshot();
gin::V8Initializer::LoadV8Natives();
// V8 requires a task scheduler apparently
base::TaskScheduler::CreateAndStartWithDefaultParams("Electron");
// Initialize gin::IsolateHolder.
JavascriptEnvironment gin_env;
int exec_argc;
const char** exec_argv;
node::Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);
node::IsolateData isolate_data(gin_env.isolate(), loop);
node::Environment* env = node::CreateEnvironment(
&isolate_data, gin_env.context(), argc, argv,
exec_argc, exec_argv);
// Enable support for v8 inspector.
NodeDebugger node_debugger(env);
node_debugger.Start(gin_env.platform());
mate::Dictionary process(gin_env.isolate(), env->process_object());
#if defined(OS_WIN)
process.SetMethod("log", &AtomBindings::Log);
#endif
process.SetMethod("crash", &AtomBindings::Crash);
// Setup process.crashReporter.start in child node processes
auto reporter = mate::Dictionary::CreateEmpty(gin_env.isolate());
reporter.SetMethod("start", &crash_reporter::CrashReporter::StartInstance);
process.Set("crashReporter", reporter);
node::LoadEnvironment(env);
bool more;
do {
more = uv_run(env->event_loop(), UV_RUN_ONCE);
if (more == false) {
node::EmitBeforeExit(env);
// Emit `beforeExit` if the loop became alive either after emitting
// event, or after running some callbacks.
more = uv_loop_alive(env->event_loop());
if (uv_run(env->event_loop(), UV_RUN_NOWAIT) != 0)
more = true;
}
} while (more == true);
exit_code = node::EmitExit(env);
node::RunAtExit(env);
node::FreeEnvironment(env);
}
// According to "src/gin/shell/gin_main.cc":
//
// gin::IsolateHolder waits for tasks running in TaskScheduler in its
// destructor and thus must be destroyed before TaskScheduler starts skipping
// CONTINUE_ON_SHUTDOWN tasks.
base::TaskScheduler::GetInstance()->Shutdown();
v8::V8::Dispose();
return exit_code;
}
} // namespace atom
#endif // ENABLE_RUN_AS_NODE

18
atom/app/node_main.h Normal file
View File

@@ -0,0 +1,18 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_APP_NODE_MAIN_H_
#define ATOM_APP_NODE_MAIN_H_
#ifdef ENABLE_RUN_AS_NODE
namespace atom {
int NodeMain(int argc, char *argv[]);
} // namespace atom
#endif // ENABLE_RUN_AS_NODE
#endif // ATOM_APP_NODE_MAIN_H_

View File

@@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>${ELECTRON_BUNDLE_ID}</string>
<string>${ATOM_BUNDLE_ID}</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>

View File

@@ -0,0 +1,62 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include <utility>
#include "atom/app/uv_task_runner.h"
#include "base/stl_util.h"
namespace atom {
UvTaskRunner::UvTaskRunner(uv_loop_t* loop) : loop_(loop) {
}
UvTaskRunner::~UvTaskRunner() {
for (auto& iter : tasks_) {
uv_unref(reinterpret_cast<uv_handle_t*>(iter.first));
delete iter.first;
}
}
bool UvTaskRunner::PostDelayedTask(const tracked_objects::Location& from_here,
base::OnceClosure task,
base::TimeDelta delay) {
auto* timer = new uv_timer_t;
timer->data = this;
uv_timer_init(loop_, timer);
uv_timer_start(timer, UvTaskRunner::OnTimeout, delay.InMilliseconds(), 0);
tasks_[timer] = std::move(task);
return true;
}
bool UvTaskRunner::RunsTasksInCurrentSequence() const {
return true;
}
bool UvTaskRunner::PostNonNestableDelayedTask(
const tracked_objects::Location& from_here,
base::OnceClosure task,
base::TimeDelta delay) {
return PostDelayedTask(from_here, std::move(task), delay);
}
// static
void UvTaskRunner::OnTimeout(uv_timer_t* timer) {
UvTaskRunner* self = static_cast<UvTaskRunner*>(timer->data);
if (!ContainsKey(self->tasks_, timer))
return;
std::move(self->tasks_[timer]).Run();
self->tasks_.erase(timer);
uv_timer_stop(timer);
uv_close(reinterpret_cast<uv_handle_t*>(timer), UvTaskRunner::OnClose);
}
// static
void UvTaskRunner::OnClose(uv_handle_t* handle) {
delete reinterpret_cast<uv_timer_t*>(handle);
}
} // namespace atom

45
atom/app/uv_task_runner.h Normal file
View File

@@ -0,0 +1,45 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_APP_UV_TASK_RUNNER_H_
#define ATOM_APP_UV_TASK_RUNNER_H_
#include <map>
#include "base/callback.h"
#include "base/single_thread_task_runner.h"
#include "vendor/node/deps/uv/include/uv.h"
namespace atom {
// TaskRunner implementation that posts tasks into libuv's default loop.
class UvTaskRunner : public base::SingleThreadTaskRunner {
public:
explicit UvTaskRunner(uv_loop_t* loop);
~UvTaskRunner() override;
// base::SingleThreadTaskRunner:
bool PostDelayedTask(const tracked_objects::Location& from_here,
base::OnceClosure task,
base::TimeDelta delay) override;
bool RunsTasksInCurrentSequence() const override;
bool PostNonNestableDelayedTask(
const tracked_objects::Location& from_here,
base::OnceClosure task,
base::TimeDelta delay) override;
private:
static void OnTimeout(uv_timer_t* timer);
static void OnClose(uv_handle_t* handle);
uv_loop_t* loop_;
std::map<uv_timer_t*, base::OnceClosure> tasks_;
DISALLOW_COPY_AND_ASSIGN(UvTaskRunner);
};
} // namespace atom
#endif // ATOM_APP_UV_TASK_RUNNER_H_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,248 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_API_ATOM_API_APP_H_
#define ATOM_BROWSER_API_ATOM_API_APP_H_
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "atom/browser/api/event_emitter.h"
#include "atom/browser/atom_browser_client.h"
#include "atom/browser/browser.h"
#include "atom/browser/browser_observer.h"
#include "atom/common/native_mate_converters/callback.h"
#include "base/process/process_iterator.h"
#include "base/task/cancelable_task_tracker.h"
#include "chrome/browser/icon_manager.h"
#include "chrome/browser/process_singleton.h"
#include "content/public/browser/browser_child_process_observer.h"
#include "content/public/browser/gpu_data_manager_observer.h"
#include "content/public/browser/render_process_host.h"
#include "native_mate/dictionary.h"
#include "native_mate/handle.h"
#include "net/base/completion_callback.h"
#include "net/ssl/client_cert_identity.h"
#if defined(USE_NSS_CERTS)
#include "chrome/browser/certificate_manager_model.h"
#endif
namespace base {
class FilePath;
}
namespace mate {
class Arguments;
} // namespace mate
namespace atom {
#if defined(OS_WIN)
enum class JumpListResult : int;
#endif
struct ProcessMetric {
int type;
base::ProcessId pid;
std::unique_ptr<base::ProcessMetrics> metrics;
ProcessMetric(int type,
base::ProcessId pid,
std::unique_ptr<base::ProcessMetrics> metrics) {
this->type = type;
this->pid = pid;
this->metrics = std::move(metrics);
}
};
namespace api {
class App : public AtomBrowserClient::Delegate,
public mate::EventEmitter<App>,
public BrowserObserver,
public content::GpuDataManagerObserver,
public content::BrowserChildProcessObserver {
public:
using FileIconCallback = base::Callback<void(v8::Local<v8::Value>,
const gfx::Image&)>;
static mate::Handle<App> Create(v8::Isolate* isolate);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
#if defined(USE_NSS_CERTS)
void OnCertificateManagerModelCreated(
std::unique_ptr<base::DictionaryValue> options,
const net::CompletionCallback& callback,
std::unique_ptr<CertificateManagerModel> model);
#endif
base::FilePath GetAppPath() const;
void RenderProcessReady(content::RenderProcessHost* host);
void RenderProcessDisconnected(base::ProcessId host_pid);
void PreMainMessageLoopRun();
protected:
explicit App(v8::Isolate* isolate);
~App() override;
// BrowserObserver:
void OnBeforeQuit(bool* prevent_default) override;
void OnWillQuit(bool* prevent_default) override;
void OnWindowAllClosed() override;
void OnQuit() override;
void OnOpenFile(bool* prevent_default, const std::string& file_path) override;
void OnOpenURL(const std::string& url) override;
void OnActivate(bool has_visible_windows) override;
void OnWillFinishLaunching() override;
void OnFinishLaunching(const base::DictionaryValue& launch_info) override;
void OnLogin(LoginHandler* login_handler,
const base::DictionaryValue& request_details) override;
void OnAccessibilitySupportChanged() override;
void OnPreMainMessageLoopRun() override;
#if defined(OS_MACOSX)
void OnWillContinueUserActivity(
bool* prevent_default,
const std::string& type) override;
void OnDidFailToContinueUserActivity(
const std::string& type,
const std::string& error) override;
void OnContinueUserActivity(
bool* prevent_default,
const std::string& type,
const base::DictionaryValue& user_info) override;
void OnUserActivityWasContinued(
const std::string& type,
const base::DictionaryValue& user_info) override;
void OnUpdateUserActivityState(
bool* prevent_default,
const std::string& type,
const base::DictionaryValue& user_info) override;
void OnNewWindowForTab() override;
#endif
// content::ContentBrowserClient:
void AllowCertificateError(
content::WebContents* web_contents,
int cert_error,
const net::SSLInfo& ssl_info,
const GURL& request_url,
content::ResourceType resource_type,
bool overridable,
bool strict_enforcement,
bool expired_previous_decision,
const base::Callback<void(content::CertificateRequestResultType)>&
callback) override;
void SelectClientCertificate(
content::WebContents* web_contents,
net::SSLCertRequestInfo* cert_request_info,
net::ClientCertIdentityList client_certs,
std::unique_ptr<content::ClientCertificateDelegate> delegate) override;
bool CanCreateWindow(content::RenderFrameHost* opener,
const GURL& opener_url,
const GURL& opener_top_level_frame_url,
const GURL& source_origin,
content::mojom::WindowContainerType container_type,
const GURL& target_url,
const content::Referrer& referrer,
const std::string& frame_name,
WindowOpenDisposition disposition,
const blink::mojom::WindowFeatures& features,
const std::vector<std::string>& additional_features,
const scoped_refptr<content::ResourceRequestBody>& body,
bool user_gesture,
bool opener_suppressed,
bool* no_javascript_access) override;
// content::GpuDataManagerObserver:
void OnGpuProcessCrashed(base::TerminationStatus status) override;
// content::BrowserChildProcessObserver:
void BrowserChildProcessLaunchedAndConnected(
const content::ChildProcessData& data) override;
void BrowserChildProcessHostDisconnected(
const content::ChildProcessData& data) override;
void BrowserChildProcessCrashed(
const content::ChildProcessData& data, int exit_code) override;
void BrowserChildProcessKilled(
const content::ChildProcessData& data, int exit_code) override;
private:
void SetAppPath(const base::FilePath& app_path);
void ChildProcessLaunched(int process_type, base::ProcessHandle handle);
void ChildProcessDisconnected(base::ProcessId pid);
// Get/Set the pre-defined path in PathService.
base::FilePath GetPath(mate::Arguments* args, const std::string& name);
void SetPath(mate::Arguments* args,
const std::string& name,
const base::FilePath& path);
void SetDesktopName(const std::string& desktop_name);
std::string GetLocale();
bool MakeSingleInstance(
const ProcessSingleton::NotificationCallback& callback);
void ReleaseSingleInstance();
bool Relaunch(mate::Arguments* args);
void DisableHardwareAcceleration(mate::Arguments* args);
void DisableDomainBlockingFor3DAPIs(mate::Arguments* args);
bool IsAccessibilitySupportEnabled();
void SetAccessibilitySupportEnabled(bool enabled);
Browser::LoginItemSettings GetLoginItemSettings(mate::Arguments* args);
#if defined(USE_NSS_CERTS)
void ImportCertificate(const base::DictionaryValue& options,
const net::CompletionCallback& callback);
#endif
void GetFileIcon(const base::FilePath& path,
mate::Arguments* args);
std::vector<mate::Dictionary> GetAppMetrics(v8::Isolate* isolate);
v8::Local<v8::Value> GetGPUFeatureStatus(v8::Isolate* isolate);
void EnableMixedSandbox(mate::Arguments* args);
#if defined(OS_MACOSX)
bool MoveToApplicationsFolder(mate::Arguments* args);
bool IsInApplicationsFolder();
#endif
#if defined(MAS_BUILD)
base::Callback<void()> StartAccessingSecurityScopedResource(
mate::Arguments* args);
#endif
#if defined(OS_WIN)
// Get the current Jump List settings.
v8::Local<v8::Value> GetJumpListSettings();
// Set or remove a custom Jump List for the application.
JumpListResult SetJumpList(v8::Local<v8::Value> val, mate::Arguments* args);
#endif // defined(OS_WIN)
std::unique_ptr<ProcessSingleton> process_singleton_;
#if defined(USE_NSS_CERTS)
std::unique_ptr<CertificateManagerModel> certificate_manager_model_;
#endif
// Tracks tasks requesting file icons.
base::CancelableTaskTracker cancelable_task_tracker_;
base::FilePath app_path_;
using ProcessMetricMap =
std::unordered_map<base::ProcessId,
std::unique_ptr<atom::ProcessMetric>>;
ProcessMetricMap app_metrics_;
DISALLOW_COPY_AND_ASSIGN(App);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_APP_H_

View File

@@ -0,0 +1,59 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_app.h"
#import <Cocoa/Cocoa.h>
#include "base/strings/sys_string_conversions.h"
namespace atom {
namespace api {
// Callback passed to js which will stop accessing the given bookmark.
void OnStopAccessingSecurityScopedResource(NSURL* bookmarkUrl) {
[bookmarkUrl stopAccessingSecurityScopedResource];
[bookmarkUrl release];
}
// Get base64 encoded NSData, create a bookmark for it and start accessing it.
base::Callback<void ()> App::StartAccessingSecurityScopedResource(mate::Arguments* args) {
std::string data;
args->GetNext(&data);
NSString *base64str = base::SysUTF8ToNSString(data);
NSData *bookmarkData = [[NSData alloc] initWithBase64EncodedString: base64str options: 0];
// Create bookmarkUrl from NSData.
BOOL isStale = false;
NSError *error = nil;
NSURL *bookmarkUrl = [NSURL URLByResolvingBookmarkData: bookmarkData
options: NSURLBookmarkResolutionWithSecurityScope
relativeToURL: nil
bookmarkDataIsStale: &isStale
error: &error];
if (error != nil) {
NSString *err = [NSString stringWithFormat: @"NSError: %@ %@", error, [error userInfo]];
args->ThrowError(base::SysNSStringToUTF8(err));
}
if (isStale) {
args->ThrowError("bookmarkDataIsStale - try recreating the bookmark");
}
if (error == nil && isStale == false) {
[bookmarkUrl startAccessingSecurityScopedResource];
}
// Stop the NSURL from being GC'd.
[bookmarkUrl retain];
// Return a js callback which will close the bookmark.
return base::Bind(&OnStopAccessingSecurityScopedResource, bookmarkUrl);
}
} // namespace atom
} // namespace api

View File

@@ -0,0 +1,153 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_auto_updater.h"
#include "atom/browser/browser.h"
#include "atom/browser/native_window.h"
#include "atom/browser/window_list.h"
#include "atom/common/api/event_emitter_caller.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/node_includes.h"
#include "base/time/time.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
namespace mate {
template<>
struct Converter<base::Time> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const base::Time& val) {
v8::MaybeLocal<v8::Value> date = v8::Date::New(
isolate->GetCurrentContext(), val.ToJsTime());
if (date.IsEmpty())
return v8::Null(isolate);
else
return date.ToLocalChecked();
}
};
} // namespace mate
namespace atom {
namespace api {
AutoUpdater::AutoUpdater(v8::Isolate* isolate) {
auto_updater::AutoUpdater::SetDelegate(this);
Init(isolate);
}
AutoUpdater::~AutoUpdater() {
auto_updater::AutoUpdater::SetDelegate(nullptr);
}
void AutoUpdater::OnError(const std::string& message) {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
auto error = v8::Exception::Error(mate::StringToV8(isolate(), message));
mate::EmitEvent(
isolate(),
GetWrapper(),
"error",
error->ToObject(isolate()->GetCurrentContext()).ToLocalChecked(),
// Message is also emitted to keep compatibility with old code.
message);
}
void AutoUpdater::OnError(const std::string& message,
const int code, const std::string& domain) {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
auto error = v8::Exception::Error(mate::StringToV8(isolate(), message));
auto errorObject = error->ToObject(
isolate()->GetCurrentContext()).ToLocalChecked();
// add two new params for better error handling
errorObject->Set(mate::StringToV8(isolate(), "code"),
v8::Integer::New(isolate(), code));
errorObject->Set(mate::StringToV8(isolate(), "domain"),
mate::StringToV8(isolate(), domain));
mate::EmitEvent(isolate(), GetWrapper(), "error", errorObject, message);
}
void AutoUpdater::OnCheckingForUpdate() {
Emit("checking-for-update");
}
void AutoUpdater::OnUpdateAvailable() {
Emit("update-available");
}
void AutoUpdater::OnUpdateNotAvailable() {
Emit("update-not-available");
}
void AutoUpdater::OnUpdateDownloaded(const std::string& release_notes,
const std::string& release_name,
const base::Time& release_date,
const std::string& url) {
Emit("update-downloaded", release_notes, release_name, release_date, url,
// Keep compatibility with old APIs.
base::Bind(&AutoUpdater::QuitAndInstall, base::Unretained(this)));
}
void AutoUpdater::OnWindowAllClosed() {
QuitAndInstall();
}
void AutoUpdater::SetFeedURL(mate::Arguments* args) {
auto_updater::AutoUpdater::SetFeedURL(args);
}
void AutoUpdater::QuitAndInstall() {
// If we don't have any window then quitAndInstall immediately.
if (WindowList::IsEmpty()) {
auto_updater::AutoUpdater::QuitAndInstall();
return;
}
// Otherwise do the restart after all windows have been closed.
WindowList::AddObserver(this);
WindowList::CloseAllWindows();
}
// static
mate::Handle<AutoUpdater> AutoUpdater::Create(v8::Isolate* isolate) {
return mate::CreateHandle(isolate, new AutoUpdater(isolate));
}
// static
void AutoUpdater::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "AutoUpdater"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("checkForUpdates", &auto_updater::AutoUpdater::CheckForUpdates)
.SetMethod("getFeedURL", &auto_updater::AutoUpdater::GetFeedURL)
.SetMethod("setFeedURL", &AutoUpdater::SetFeedURL)
.SetMethod("quitAndInstall", &AutoUpdater::QuitAndInstall);
}
} // namespace api
} // namespace atom
namespace {
using atom::api::AutoUpdater;
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
dict.Set("autoUpdater", AutoUpdater::Create(isolate));
dict.Set("AutoUpdater", AutoUpdater::GetConstructor(isolate)->GetFunction());
}
} // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_auto_updater, Initialize)

View File

@@ -0,0 +1,60 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_API_ATOM_API_AUTO_UPDATER_H_
#define ATOM_BROWSER_API_ATOM_API_AUTO_UPDATER_H_
#include <string>
#include "atom/browser/api/event_emitter.h"
#include "atom/browser/auto_updater.h"
#include "atom/browser/window_list_observer.h"
#include "native_mate/arguments.h"
#include "native_mate/handle.h"
namespace atom {
namespace api {
class AutoUpdater : public mate::EventEmitter<AutoUpdater>,
public auto_updater::Delegate,
public WindowListObserver {
public:
static mate::Handle<AutoUpdater> Create(v8::Isolate* isolate);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
protected:
explicit AutoUpdater(v8::Isolate* isolate);
~AutoUpdater() override;
// Delegate implementations.
void OnError(const std::string& error) override;
void OnError(const std::string& message, const int code,
const std::string& domain);
void OnCheckingForUpdate() override;
void OnUpdateAvailable() override;
void OnUpdateNotAvailable() override;
void OnUpdateDownloaded(const std::string& release_notes,
const std::string& release_name,
const base::Time& release_date,
const std::string& update_url) override;
// WindowListObserver:
void OnWindowAllClosed() override;
private:
std::string GetFeedURL();
void SetFeedURL(mate::Arguments* args);
void QuitAndInstall();
DISALLOW_COPY_AND_ASSIGN(AutoUpdater);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_AUTO_UPDATER_H_

View File

@@ -0,0 +1,165 @@
// Copyright (c) 2017 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_browser_view.h"
#include "atom/browser/api/atom_api_web_contents.h"
#include "atom/browser/browser.h"
#include "atom/browser/native_browser_view.h"
#include "atom/common/color_util.h"
#include "atom/common/native_mate_converters/gfx_converter.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "atom/common/node_includes.h"
#include "atom/common/options_switches.h"
#include "native_mate/constructor.h"
#include "native_mate/dictionary.h"
#include "ui/gfx/geometry/rect.h"
namespace mate {
template <>
struct Converter<atom::AutoResizeFlags> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
atom::AutoResizeFlags* auto_resize_flags) {
mate::Dictionary params;
if (!ConvertFromV8(isolate, val, &params)) {
return false;
}
uint8_t flags = 0;
bool width = false;
if (params.Get("width", &width) && width) {
flags |= atom::kAutoResizeWidth;
}
bool height = false;
if (params.Get("height", &height) && height) {
flags |= atom::kAutoResizeHeight;
}
*auto_resize_flags = static_cast<atom::AutoResizeFlags>(flags);
return true;
}
};
} // namespace mate
namespace atom {
namespace api {
BrowserView::BrowserView(v8::Isolate* isolate,
v8::Local<v8::Object> wrapper,
const mate::Dictionary& options)
: api_web_contents_(nullptr) {
Init(isolate, wrapper, options);
}
void BrowserView::Init(v8::Isolate* isolate,
v8::Local<v8::Object> wrapper,
const mate::Dictionary& options) {
mate::Dictionary web_preferences = mate::Dictionary::CreateEmpty(isolate);
options.Get(options::kWebPreferences, &web_preferences);
web_preferences.Set("isBrowserView", true);
mate::Handle<class WebContents> web_contents =
WebContents::Create(isolate, web_preferences);
web_contents_.Reset(isolate, web_contents.ToV8());
api_web_contents_ = web_contents.get();
view_.reset(
NativeBrowserView::Create(api_web_contents_->managed_web_contents()));
InitWith(isolate, wrapper);
}
BrowserView::~BrowserView() {
api_web_contents_->DestroyWebContents(true /* async */);
}
// static
mate::WrappableBase* BrowserView::New(mate::Arguments* args) {
if (!Browser::Get()->is_ready()) {
args->ThrowError("Cannot create BrowserView before app is ready");
return nullptr;
}
if (args->Length() > 1) {
args->ThrowError("Too many arguments");
return nullptr;
}
mate::Dictionary options;
if (!(args->Length() == 1 && args->GetNext(&options))) {
options = mate::Dictionary::CreateEmpty(args->isolate());
}
return new BrowserView(args->isolate(), args->GetThis(), options);
}
int32_t BrowserView::ID() const {
return weak_map_id();
}
void BrowserView::SetAutoResize(AutoResizeFlags flags) {
view_->SetAutoResizeFlags(flags);
}
void BrowserView::SetBounds(const gfx::Rect& bounds) {
view_->SetBounds(bounds);
}
void BrowserView::SetBackgroundColor(const std::string& color_name) {
view_->SetBackgroundColor(ParseHexColor(color_name));
}
v8::Local<v8::Value> BrowserView::GetWebContents() {
if (web_contents_.IsEmpty()) {
return v8::Null(isolate());
}
return v8::Local<v8::Value>::New(isolate(), web_contents_);
}
// static
void BrowserView::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "BrowserView"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.MakeDestroyable()
.SetMethod("setAutoResize", &BrowserView::SetAutoResize)
.SetMethod("setBounds", &BrowserView::SetBounds)
.SetMethod("setBackgroundColor", &BrowserView::SetBackgroundColor)
.SetProperty("webContents", &BrowserView::GetWebContents)
.SetProperty("id", &BrowserView::ID);
}
} // namespace api
} // namespace atom
namespace {
using atom::api::BrowserView;
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
v8::Isolate* isolate = context->GetIsolate();
BrowserView::SetConstructor(isolate, base::Bind(&BrowserView::New));
mate::Dictionary browser_view(
isolate, BrowserView::GetConstructor(isolate)->GetFunction());
browser_view.SetMethod("fromId",
&mate::TrackableObject<BrowserView>::FromWeakMapID);
browser_view.SetMethod("getAllViews",
&mate::TrackableObject<BrowserView>::GetAll);
mate::Dictionary dict(isolate, exports);
dict.Set("BrowserView", browser_view);
}
} // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_browser_view, Initialize)

View File

@@ -0,0 +1,73 @@
// Copyright (c) 2017 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_API_ATOM_API_BROWSER_VIEW_H_
#define ATOM_BROWSER_API_ATOM_API_BROWSER_VIEW_H_
#include <memory>
#include <string>
#include "atom/browser/api/trackable_object.h"
#include "atom/browser/native_browser_view.h"
#include "native_mate/handle.h"
namespace gfx {
class Rect;
}
namespace mate {
class Arguments;
class Dictionary;
} // namespace mate
namespace atom {
class NativeBrowserView;
namespace api {
class WebContents;
class BrowserView : public mate::TrackableObject<BrowserView> {
public:
static mate::WrappableBase* New(mate::Arguments* args);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
WebContents* web_contents() const { return api_web_contents_; }
NativeBrowserView* view() const { return view_.get(); }
int32_t ID() const;
protected:
BrowserView(v8::Isolate* isolate,
v8::Local<v8::Object> wrapper,
const mate::Dictionary& options);
~BrowserView() override;
private:
void Init(v8::Isolate* isolate,
v8::Local<v8::Object> wrapper,
const mate::Dictionary& options);
void SetAutoResize(AutoResizeFlags flags);
void SetBounds(const gfx::Rect& bounds);
void SetBackgroundColor(const std::string& color_name);
v8::Local<v8::Value> GetWebContents();
v8::Global<v8::Value> web_contents_;
class WebContents* api_web_contents_;
std::unique_ptr<NativeBrowserView> view_;
DISALLOW_COPY_AND_ASSIGN(BrowserView);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_BROWSER_VIEW_H_

View File

@@ -0,0 +1,76 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include <set>
#include <string>
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "base/bind.h"
#include "base/files/file_util.h"
#include "content/public/browser/tracing_controller.h"
#include "native_mate/dictionary.h"
#include "atom/common/node_includes.h"
using content::TracingController;
namespace mate {
template<>
struct Converter<base::trace_event::TraceConfig> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
base::trace_event::TraceConfig* out) {
Dictionary options;
if (!ConvertFromV8(isolate, val, &options))
return false;
std::string category_filter, trace_options;
if (!options.Get("categoryFilter", &category_filter) ||
!options.Get("traceOptions", &trace_options))
return false;
*out = base::trace_event::TraceConfig(category_filter, trace_options);
return true;
}
};
} // namespace mate
namespace {
using CompletionCallback = base::Callback<void(const base::FilePath&)>;
scoped_refptr<TracingController::TraceDataSink> GetTraceDataSink(
const base::FilePath& path, const CompletionCallback& callback) {
base::FilePath result_file_path = path;
if (result_file_path.empty() && !base::CreateTemporaryFile(&result_file_path))
LOG(ERROR) << "Creating temporary file failed";
return TracingController::CreateFileSink(result_file_path,
base::Bind(callback,
result_file_path));
}
void StopRecording(const base::FilePath& path,
const CompletionCallback& callback) {
TracingController::GetInstance()->StopTracing(
GetTraceDataSink(path, callback));
}
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
auto controller = base::Unretained(TracingController::GetInstance());
mate::Dictionary dict(context->GetIsolate(), exports);
dict.SetMethod("getCategories", base::Bind(
&TracingController::GetCategories, controller));
dict.SetMethod("startRecording", base::Bind(
&TracingController::StartTracing, controller));
dict.SetMethod("stopRecording", &StopRecording);
dict.SetMethod("getTraceBufferUsage", base::Bind(
&TracingController::GetTraceBufferUsage, controller));
}
} // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_content_tracing, Initialize)

View File

@@ -0,0 +1,313 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_cookies.h"
#include "atom/browser/atom_browser_context.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/gurl_converter.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "base/time/time.h"
#include "base/values.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "net/cookies/cookie_monster.h"
#include "net/cookies/cookie_store.h"
#include "net/cookies/cookie_util.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
using atom::AtomCookieDelegate;
using content::BrowserThread;
namespace mate {
template<>
struct Converter<atom::api::Cookies::Error> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
atom::api::Cookies::Error val) {
if (val == atom::api::Cookies::SUCCESS)
return v8::Null(isolate);
else
return v8::Exception::Error(StringToV8(isolate, "Setting cookie failed"));
}
};
template<>
struct Converter<net::CanonicalCookie> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const net::CanonicalCookie& val) {
mate::Dictionary dict(isolate, v8::Object::New(isolate));
dict.Set("name", val.Name());
dict.Set("value", val.Value());
dict.Set("domain", val.Domain());
dict.Set("hostOnly", net::cookie_util::DomainIsHostOnly(val.Domain()));
dict.Set("path", val.Path());
dict.Set("secure", val.IsSecure());
dict.Set("httpOnly", val.IsHttpOnly());
dict.Set("session", !val.IsPersistent());
if (val.IsPersistent())
dict.Set("expirationDate", val.ExpiryDate().ToDoubleT());
return dict.GetHandle();
}
};
template<>
struct Converter<net::CookieStore::ChangeCause> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const net::CookieStore::ChangeCause& val) {
switch (val) {
case net::CookieStore::ChangeCause::INSERTED:
case net::CookieStore::ChangeCause::EXPLICIT:
case net::CookieStore::ChangeCause::EXPLICIT_DELETE_BETWEEN:
case net::CookieStore::ChangeCause::EXPLICIT_DELETE_PREDICATE:
case net::CookieStore::ChangeCause::EXPLICIT_DELETE_SINGLE:
case net::CookieStore::ChangeCause::EXPLICIT_DELETE_CANONICAL:
return mate::StringToV8(isolate, "explicit");
case net::CookieStore::ChangeCause::OVERWRITE:
return mate::StringToV8(isolate, "overwrite");
case net::CookieStore::ChangeCause::EXPIRED:
return mate::StringToV8(isolate, "expired");
case net::CookieStore::ChangeCause::EVICTED:
return mate::StringToV8(isolate, "evicted");
case net::CookieStore::ChangeCause::EXPIRED_OVERWRITE:
return mate::StringToV8(isolate, "expired-overwrite");
default:
return mate::StringToV8(isolate, "unknown");
}
}
};
} // namespace mate
namespace atom {
namespace api {
namespace {
// Returns whether |domain| matches |filter|.
bool MatchesDomain(std::string filter, const std::string& domain) {
// Add a leading '.' character to the filter domain if it doesn't exist.
if (net::cookie_util::DomainIsHostOnly(filter))
filter.insert(0, ".");
std::string sub_domain(domain);
// Strip any leading '.' character from the input cookie domain.
if (!net::cookie_util::DomainIsHostOnly(sub_domain))
sub_domain = sub_domain.substr(1);
// Now check whether the domain argument is a subdomain of the filter domain.
for (sub_domain.insert(0, "."); sub_domain.length() >= filter.length();) {
if (sub_domain == filter)
return true;
const size_t next_dot = sub_domain.find('.', 1); // Skip over leading dot.
sub_domain.erase(0, next_dot);
}
return false;
}
// Returns whether |cookie| matches |filter|.
bool MatchesCookie(const base::DictionaryValue* filter,
const net::CanonicalCookie& cookie) {
std::string str;
bool b;
if (filter->GetString("name", &str) && str != cookie.Name())
return false;
if (filter->GetString("path", &str) && str != cookie.Path())
return false;
if (filter->GetString("domain", &str) && !MatchesDomain(str, cookie.Domain()))
return false;
if (filter->GetBoolean("secure", &b) && b != cookie.IsSecure())
return false;
if (filter->GetBoolean("session", &b) && b != !cookie.IsPersistent())
return false;
return true;
}
// Helper to returns the CookieStore.
inline net::CookieStore* GetCookieStore(
scoped_refptr<net::URLRequestContextGetter> getter) {
return getter->GetURLRequestContext()->cookie_store();
}
// Run |callback| on UI thread.
void RunCallbackInUI(const base::Closure& callback) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
}
// Remove cookies from |list| not matching |filter|, and pass it to |callback|.
void FilterCookies(std::unique_ptr<base::DictionaryValue> filter,
const Cookies::GetCallback& callback,
const net::CookieList& list) {
net::CookieList result;
for (const auto& cookie : list) {
if (MatchesCookie(filter.get(), cookie))
result.push_back(cookie);
}
RunCallbackInUI(base::Bind(callback, Cookies::SUCCESS, result));
}
// Receives cookies matching |filter| in IO thread.
void GetCookiesOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
std::unique_ptr<base::DictionaryValue> filter,
const Cookies::GetCallback& callback) {
std::string url;
filter->GetString("url", &url);
auto filtered_callback =
base::Bind(FilterCookies, base::Passed(&filter), callback);
// Empty url will match all url cookies.
if (url.empty())
GetCookieStore(getter)->GetAllCookiesAsync(filtered_callback);
else
GetCookieStore(getter)->GetAllCookiesForURLAsync(GURL(url),
filtered_callback);
}
// Removes cookie with |url| and |name| in IO thread.
void RemoveCookieOnIOThread(scoped_refptr<net::URLRequestContextGetter> getter,
const GURL& url, const std::string& name,
const base::Closure& callback) {
GetCookieStore(getter)->DeleteCookieAsync(
url, name, base::Bind(RunCallbackInUI, callback));
}
// Callback of SetCookie.
void OnSetCookie(const Cookies::SetCallback& callback, bool success) {
RunCallbackInUI(
base::Bind(callback, success ? Cookies::SUCCESS : Cookies::FAILED));
}
// Flushes cookie store in IO thread.
void FlushCookieStoreOnIOThread(
scoped_refptr<net::URLRequestContextGetter> getter,
const base::Closure& callback) {
GetCookieStore(getter)->FlushStore(base::Bind(RunCallbackInUI, callback));
}
// Sets cookie with |details| in IO thread.
void SetCookieOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
std::unique_ptr<base::DictionaryValue> details,
const Cookies::SetCallback& callback) {
std::string url, name, value, domain, path;
bool secure = false;
bool http_only = false;
double creation_date;
double expiration_date;
double last_access_date;
details->GetString("url", &url);
details->GetString("name", &name);
details->GetString("value", &value);
details->GetString("domain", &domain);
details->GetString("path", &path);
details->GetBoolean("secure", &secure);
details->GetBoolean("httpOnly", &http_only);
base::Time creation_time;
if (details->GetDouble("creationDate", &creation_date)) {
creation_time = (creation_date == 0) ?
base::Time::UnixEpoch() :
base::Time::FromDoubleT(creation_date);
}
base::Time expiration_time;
if (details->GetDouble("expirationDate", &expiration_date)) {
expiration_time = (expiration_date == 0) ?
base::Time::UnixEpoch() :
base::Time::FromDoubleT(expiration_date);
}
base::Time last_access_time;
if (details->GetDouble("lastAccessDate", &last_access_date)) {
last_access_time = (last_access_date == 0) ?
base::Time::UnixEpoch() :
base::Time::FromDoubleT(last_access_date);
}
GetCookieStore(getter)->SetCookieWithDetailsAsync(
GURL(url), name, value, domain, path, creation_time,
expiration_time, last_access_time, secure, http_only,
net::CookieSameSite::DEFAULT_MODE, net::COOKIE_PRIORITY_DEFAULT,
base::Bind(OnSetCookie, callback));
}
} // namespace
Cookies::Cookies(v8::Isolate* isolate,
AtomBrowserContext* browser_context)
: request_context_getter_(browser_context->url_request_context_getter()),
cookie_delegate_(browser_context->cookie_delegate()) {
Init(isolate);
cookie_delegate_->AddObserver(this);
}
Cookies::~Cookies() {
cookie_delegate_->RemoveObserver(this);
}
void Cookies::Get(const base::DictionaryValue& filter,
const GetCallback& callback) {
std::unique_ptr<base::DictionaryValue> copied(filter.CreateDeepCopy());
auto getter = make_scoped_refptr(request_context_getter_);
content::BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(GetCookiesOnIO, getter, Passed(&copied), callback));
}
void Cookies::Remove(const GURL& url, const std::string& name,
const base::Closure& callback) {
auto getter = make_scoped_refptr(request_context_getter_);
content::BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(RemoveCookieOnIOThread, getter, url, name, callback));
}
void Cookies::Set(const base::DictionaryValue& details,
const SetCallback& callback) {
std::unique_ptr<base::DictionaryValue> copied(details.CreateDeepCopy());
auto getter = make_scoped_refptr(request_context_getter_);
content::BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(SetCookieOnIO, getter, Passed(&copied), callback));
}
void Cookies::FlushStore(const base::Closure& callback) {
auto getter = make_scoped_refptr(request_context_getter_);
content::BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(FlushCookieStoreOnIOThread, getter, callback));
}
void Cookies::OnCookieChanged(const net::CanonicalCookie& cookie,
bool removed,
net::CookieStore::ChangeCause cause) {
Emit("changed", cookie, cause, removed);
}
// static
mate::Handle<Cookies> Cookies::Create(
v8::Isolate* isolate,
AtomBrowserContext* browser_context) {
return mate::CreateHandle(isolate, new Cookies(isolate, browser_context));
}
// static
void Cookies::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "Cookies"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("get", &Cookies::Get)
.SetMethod("remove", &Cookies::Remove)
.SetMethod("set", &Cookies::Set)
.SetMethod("flushStore", &Cookies::FlushStore);
}
} // namespace api
} // namespace atom

View File

@@ -0,0 +1,74 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_API_ATOM_API_COOKIES_H_
#define ATOM_BROWSER_API_ATOM_API_COOKIES_H_
#include <string>
#include "atom/browser/api/trackable_object.h"
#include "atom/browser/net/atom_cookie_delegate.h"
#include "base/callback.h"
#include "native_mate/handle.h"
#include "net/cookies/canonical_cookie.h"
namespace base {
class DictionaryValue;
}
namespace net {
class URLRequestContextGetter;
}
namespace atom {
class AtomBrowserContext;
namespace api {
class Cookies : public mate::TrackableObject<Cookies>,
public AtomCookieDelegate::Observer {
public:
enum Error {
SUCCESS,
FAILED,
};
using GetCallback = base::Callback<void(Error, const net::CookieList&)>;
using SetCallback = base::Callback<void(Error)>;
static mate::Handle<Cookies> Create(v8::Isolate* isolate,
AtomBrowserContext* browser_context);
// mate::TrackableObject:
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
protected:
Cookies(v8::Isolate* isolate, AtomBrowserContext* browser_context);
~Cookies() override;
void Get(const base::DictionaryValue& filter, const GetCallback& callback);
void Remove(const GURL& url, const std::string& name,
const base::Closure& callback);
void Set(const base::DictionaryValue& details, const SetCallback& callback);
void FlushStore(const base::Closure& callback);
// AtomCookieDelegate::Observer:
void OnCookieChanged(const net::CanonicalCookie& cookie,
bool removed,
net::CookieStore::ChangeCause cause) override;
private:
net::URLRequestContextGetter* request_context_getter_;
scoped_refptr<AtomCookieDelegate> cookie_delegate_;
DISALLOW_COPY_AND_ASSIGN(Cookies);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_COOKIES_H_

View File

@@ -0,0 +1,181 @@
// Copyright (c) 2016 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_debugger.h"
#include <string>
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/memory/ptr_util.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/web_contents.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "atom/common/node_includes.h"
using content::DevToolsAgentHost;
namespace atom {
namespace api {
Debugger::Debugger(v8::Isolate* isolate, content::WebContents* web_contents)
: web_contents_(web_contents),
previous_request_id_(0) {
Init(isolate);
}
Debugger::~Debugger() {
}
void Debugger::AgentHostClosed(DevToolsAgentHost* agent_host,
bool replaced_with_another_client) {
std::string detach_reason = "target closed";
if (replaced_with_another_client)
detach_reason = "replaced with devtools";
Emit("detach", detach_reason);
}
void Debugger::DispatchProtocolMessage(DevToolsAgentHost* agent_host,
const std::string& message) {
DCHECK(agent_host == agent_host_.get());
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
std::unique_ptr<base::Value> parsed_message = base::JSONReader::Read(message);
if (!parsed_message || !parsed_message->is_dict())
return;
base::DictionaryValue* dict =
static_cast<base::DictionaryValue*>(parsed_message.get());
int id;
if (!dict->GetInteger("id", &id)) {
std::string method;
if (!dict->GetString("method", &method))
return;
base::DictionaryValue* params_value = nullptr;
base::DictionaryValue params;
if (dict->GetDictionary("params", &params_value))
params.Swap(params_value);
Emit("message", method, params);
} else {
auto send_command_callback = pending_requests_[id];
pending_requests_.erase(id);
if (send_command_callback.is_null())
return;
base::DictionaryValue* error_body = nullptr;
base::DictionaryValue error;
if (dict->GetDictionary("error", &error_body))
error.Swap(error_body);
base::DictionaryValue* result_body = nullptr;
base::DictionaryValue result;
if (dict->GetDictionary("result", &result_body))
result.Swap(result_body);
send_command_callback.Run(error, result);
}
}
void Debugger::Attach(mate::Arguments* args) {
std::string protocol_version;
args->GetNext(&protocol_version);
if (!protocol_version.empty() &&
!DevToolsAgentHost::IsSupportedProtocolVersion(protocol_version)) {
args->ThrowError("Requested protocol version is not supported");
return;
}
agent_host_ = DevToolsAgentHost::GetOrCreateFor(web_contents_);
if (!agent_host_.get()) {
args->ThrowError("No target available");
return;
}
if (agent_host_->IsAttached()) {
args->ThrowError("Another debugger is already attached to this target");
return;
}
agent_host_->AttachClient(this);
}
bool Debugger::IsAttached() {
return agent_host_.get() ? agent_host_->IsAttached() : false;
}
void Debugger::Detach() {
if (!agent_host_.get())
return;
agent_host_->DetachClient(this);
AgentHostClosed(agent_host_.get(), false);
agent_host_ = nullptr;
}
void Debugger::SendCommand(mate::Arguments* args) {
if (!agent_host_.get())
return;
std::string method;
if (!args->GetNext(&method)) {
args->ThrowError();
return;
}
base::DictionaryValue command_params;
args->GetNext(&command_params);
SendCommandCallback callback;
args->GetNext(&callback);
base::DictionaryValue request;
int request_id = ++previous_request_id_;
pending_requests_[request_id] = callback;
request.SetInteger("id", request_id);
request.SetString("method", method);
if (!command_params.empty())
request.Set("params", base::WrapUnique(command_params.DeepCopy()));
std::string json_args;
base::JSONWriter::Write(request, &json_args);
agent_host_->DispatchProtocolMessage(this, json_args);
}
// static
mate::Handle<Debugger> Debugger::Create(
v8::Isolate* isolate,
content::WebContents* web_contents) {
return mate::CreateHandle(isolate, new Debugger(isolate, web_contents));
}
// static
void Debugger::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "Debugger"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("attach", &Debugger::Attach)
.SetMethod("isAttached", &Debugger::IsAttached)
.SetMethod("detach", &Debugger::Detach)
.SetMethod("sendCommand", &Debugger::SendCommand);
}
} // namespace api
} // namespace atom
namespace {
using atom::api::Debugger;
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary(isolate, exports)
.Set("Debugger", Debugger::GetConstructor(isolate)->GetFunction());
}
} // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_debugger, Initialize);

View File

@@ -0,0 +1,75 @@
// Copyright (c) 2016 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_API_ATOM_API_DEBUGGER_H_
#define ATOM_BROWSER_API_ATOM_API_DEBUGGER_H_
#include <map>
#include <string>
#include "atom/browser/api/trackable_object.h"
#include "base/callback.h"
#include "base/values.h"
#include "content/public/browser/devtools_agent_host_client.h"
#include "native_mate/handle.h"
namespace content {
class DevToolsAgentHost;
class WebContents;
}
namespace mate {
class Arguments;
}
namespace atom {
namespace api {
class Debugger: public mate::TrackableObject<Debugger>,
public content::DevToolsAgentHostClient {
public:
using SendCommandCallback =
base::Callback<void(const base::DictionaryValue&,
const base::DictionaryValue&)>;
static mate::Handle<Debugger> Create(
v8::Isolate* isolate, content::WebContents* web_contents);
// mate::TrackableObject:
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
protected:
Debugger(v8::Isolate* isolate, content::WebContents* web_contents);
~Debugger() override;
// content::DevToolsAgentHostClient:
void AgentHostClosed(content::DevToolsAgentHost* agent_host,
bool replaced_with_another_client) override;
void DispatchProtocolMessage(content::DevToolsAgentHost* agent_host,
const std::string& message) override;
private:
using PendingRequestMap = std::map<int, SendCommandCallback>;
void Attach(mate::Arguments* args);
bool IsAttached();
void Detach();
void SendCommand(mate::Arguments* args);
content::WebContents* web_contents_; // Weak Reference.
scoped_refptr<content::DevToolsAgentHost> agent_host_;
PendingRequestMap pending_requests_;
int previous_request_id_;
DISALLOW_COPY_AND_ASSIGN(Debugger);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_DEBUGGER_H_

View File

@@ -0,0 +1,117 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_desktop_capturer.h"
using base::PlatformThreadRef;
#include "atom/common/api/atom_api_native_image.h"
#include "atom/common/native_mate_converters/gfx_converter.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/media/desktop_media_list.h"
#include "content/public/browser/desktop_capture.h"
#include "native_mate/dictionary.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
#include "atom/common/node_includes.h"
namespace mate {
template<>
struct Converter<DesktopMediaList::Source> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const DesktopMediaList::Source& source) {
mate::Dictionary dict(isolate, v8::Object::New(isolate));
content::DesktopMediaID id = source.id;
dict.Set("name", base::UTF16ToUTF8(source.name));
dict.Set("id", id.ToString());
dict.Set(
"thumbnail",
atom::api::NativeImage::Create(isolate, gfx::Image(source.thumbnail)));
return ConvertToV8(isolate, dict);
}
};
} // namespace mate
namespace atom {
namespace api {
DesktopCapturer::DesktopCapturer(v8::Isolate* isolate) {
Init(isolate);
}
DesktopCapturer::~DesktopCapturer() {
}
void DesktopCapturer::StartHandling(bool capture_window,
bool capture_screen,
const gfx::Size& thumbnail_size) {
webrtc::DesktopCaptureOptions options =
content::CreateDesktopCaptureOptions();
std::unique_ptr<webrtc::DesktopCapturer> screen_capturer(
capture_screen ? webrtc::DesktopCapturer::CreateScreenCapturer(options)
: nullptr);
std::unique_ptr<webrtc::DesktopCapturer> window_capturer(
capture_window ? webrtc::DesktopCapturer::CreateWindowCapturer(options)
: nullptr);
media_list_.reset(new NativeDesktopMediaList(
std::move(screen_capturer), std::move(window_capturer)));
media_list_->SetThumbnailSize(thumbnail_size);
media_list_->StartUpdating(this);
}
void DesktopCapturer::OnSourceAdded(int index) {
}
void DesktopCapturer::OnSourceRemoved(int index) {
}
void DesktopCapturer::OnSourceMoved(int old_index, int new_index) {
}
void DesktopCapturer::OnSourceNameChanged(int index) {
}
void DesktopCapturer::OnSourceThumbnailChanged(int index) {
}
bool DesktopCapturer::OnRefreshFinished() {
Emit("finished", media_list_->GetSources());
return false;
}
// static
mate::Handle<DesktopCapturer> DesktopCapturer::Create(v8::Isolate* isolate) {
return mate::CreateHandle(isolate, new DesktopCapturer(isolate));
}
// static
void DesktopCapturer::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "DesktopCapturer"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("startHandling", &DesktopCapturer::StartHandling);
}
} // namespace api
} // namespace atom
namespace {
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
dict.Set("desktopCapturer", atom::api::DesktopCapturer::Create(isolate));
}
} // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_desktop_capturer, Initialize);

View File

@@ -0,0 +1,51 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_API_ATOM_API_DESKTOP_CAPTURER_H_
#define ATOM_BROWSER_API_ATOM_API_DESKTOP_CAPTURER_H_
#include "atom/browser/api/event_emitter.h"
#include "chrome/browser/media/desktop_media_list_observer.h"
#include "chrome/browser/media/native_desktop_media_list.h"
#include "native_mate/handle.h"
namespace atom {
namespace api {
class DesktopCapturer: public mate::EventEmitter<DesktopCapturer>,
public DesktopMediaListObserver {
public:
static mate::Handle<DesktopCapturer> Create(v8::Isolate* isolate);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
void StartHandling(bool capture_window,
bool capture_screen,
const gfx::Size& thumbnail_size);
protected:
explicit DesktopCapturer(v8::Isolate* isolate);
~DesktopCapturer() override;
// DesktopMediaListObserver overrides.
void OnSourceAdded(int index) override;
void OnSourceRemoved(int index) override;
void OnSourceMoved(int old_index, int new_index) override;
void OnSourceNameChanged(int index) override;
void OnSourceThumbnailChanged(int index) override;
bool OnRefreshFinished() override;
private:
std::unique_ptr<DesktopMediaList> media_list_;
DISALLOW_COPY_AND_ASSIGN(DesktopCapturer);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_DESKTOP_CAPTURER_H_

View File

@@ -0,0 +1,143 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include <string>
#include <utility>
#include <vector>
#include "atom/browser/api/atom_api_window.h"
#include "atom/browser/native_window.h"
#include "atom/browser/ui/certificate_trust.h"
#include "atom/browser/ui/file_dialog.h"
#include "atom/browser/ui/message_box.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "atom/common/native_mate_converters/image_converter.h"
#include "atom/common/native_mate_converters/net_converter.h"
#include "native_mate/dictionary.h"
#include "atom/common/node_includes.h"
namespace mate {
template<>
struct Converter<file_dialog::Filter> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
file_dialog::Filter* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
if (!dict.Get("name", &(out->first)))
return false;
if (!dict.Get("extensions", &(out->second)))
return false;
return true;
}
};
template<>
struct Converter<file_dialog::DialogSettings> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
file_dialog::DialogSettings* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
dict.Get("window", &(out->parent_window));
dict.Get("title", &(out->title));
dict.Get("message", &(out->message));
dict.Get("buttonLabel", &(out->button_label));
dict.Get("nameFieldLabel", &(out->name_field_label));
dict.Get("defaultPath", &(out->default_path));
dict.Get("filters", &(out->filters));
dict.Get("properties", &(out->properties));
dict.Get("showsTagField", &(out->shows_tag_field));
#if defined(MAS_BUILD)
dict.Get("securityScopedBookmarks", &(out->security_scoped_bookmarks));
#endif
return true;
}
};
} // namespace mate
namespace {
void ShowMessageBox(int type,
const std::vector<std::string>& buttons,
int default_id,
int cancel_id,
int options,
const std::string& title,
const std::string& message,
const std::string& detail,
const std::string& checkbox_label,
bool checkbox_checked,
const gfx::ImageSkia& icon,
atom::NativeWindow* window,
mate::Arguments* args) {
v8::Local<v8::Value> peek = args->PeekNext();
atom::MessageBoxCallback callback;
if (mate::Converter<atom::MessageBoxCallback>::FromV8(args->isolate(),
peek,
&callback)) {
atom::ShowMessageBox(window, static_cast<atom::MessageBoxType>(type),
buttons, default_id, cancel_id, options, title,
message, detail, checkbox_label, checkbox_checked,
icon, callback);
} else {
int chosen = atom::ShowMessageBox(
window, static_cast<atom::MessageBoxType>(type), buttons, default_id,
cancel_id, options, title, message, detail, icon);
args->Return(chosen);
}
}
void ShowOpenDialog(const file_dialog::DialogSettings& settings,
mate::Arguments* args) {
v8::Local<v8::Value> peek = args->PeekNext();
file_dialog::OpenDialogCallback callback;
if (mate::Converter<file_dialog::OpenDialogCallback>::FromV8(args->isolate(),
peek,
&callback)) {
file_dialog::ShowOpenDialog(settings, callback);
} else {
std::vector<base::FilePath> paths;
if (file_dialog::ShowOpenDialog(settings, &paths))
args->Return(paths);
}
}
void ShowSaveDialog(const file_dialog::DialogSettings& settings,
mate::Arguments* args) {
v8::Local<v8::Value> peek = args->PeekNext();
file_dialog::SaveDialogCallback callback;
if (mate::Converter<file_dialog::SaveDialogCallback>::FromV8(args->isolate(),
peek,
&callback)) {
file_dialog::ShowSaveDialog(settings, callback);
} else {
base::FilePath path;
if (file_dialog::ShowSaveDialog(settings, &path))
args->Return(path);
}
}
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
mate::Dictionary dict(context->GetIsolate(), exports);
dict.SetMethod("showMessageBox", &ShowMessageBox);
dict.SetMethod("showErrorBox", &atom::ShowErrorBox);
dict.SetMethod("showOpenDialog", &ShowOpenDialog);
dict.SetMethod("showSaveDialog", &ShowSaveDialog);
#if defined(OS_MACOSX) || defined(OS_WIN)
dict.SetMethod("showCertificateTrustDialog",
&certificate_trust::ShowCertificateTrust);
#endif
}
} // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_dialog, Initialize)

View File

@@ -0,0 +1,239 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_download_item.h"
#include <map>
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "atom/common/native_mate_converters/gurl_converter.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "native_mate/dictionary.h"
#include "net/base/filename_util.h"
#include "atom/common/node_includes.h"
namespace mate {
template<>
struct Converter<content::DownloadItem::DownloadState> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
content::DownloadItem::DownloadState state) {
std::string download_state;
switch (state) {
case content::DownloadItem::IN_PROGRESS:
download_state = "progressing";
break;
case content::DownloadItem::COMPLETE:
download_state = "completed";
break;
case content::DownloadItem::CANCELLED:
download_state = "cancelled";
break;
case content::DownloadItem::INTERRUPTED:
download_state = "interrupted";
break;
default:
break;
}
return ConvertToV8(isolate, download_state);
}
};
} // namespace mate
namespace atom {
namespace api {
namespace {
std::map<uint32_t, v8::Global<v8::Object>> g_download_item_objects;
} // namespace
DownloadItem::DownloadItem(v8::Isolate* isolate,
content::DownloadItem* download_item)
: download_item_(download_item) {
download_item_->AddObserver(this);
Init(isolate);
AttachAsUserData(download_item);
}
DownloadItem::~DownloadItem() {
if (download_item_) {
// Destroyed by either garbage collection or destroy().
download_item_->RemoveObserver(this);
download_item_->Remove();
}
// Remove from the global map.
g_download_item_objects.erase(weak_map_id());
}
void DownloadItem::OnDownloadUpdated(content::DownloadItem* item) {
if (download_item_->IsDone()) {
Emit("done", item->GetState());
// Destroy the item once item is downloaded.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, GetDestroyClosure());
} else {
Emit("updated", item->GetState());
}
}
void DownloadItem::OnDownloadDestroyed(content::DownloadItem* download_item) {
download_item_ = nullptr;
// Destroy the native class immediately when downloadItem is destroyed.
delete this;
}
void DownloadItem::Pause() {
download_item_->Pause();
}
bool DownloadItem::IsPaused() const {
return download_item_->IsPaused();
}
void DownloadItem::Resume() {
download_item_->Resume();
}
bool DownloadItem::CanResume() const {
return download_item_->CanResume();
}
void DownloadItem::Cancel() {
download_item_->Cancel(true);
}
int64_t DownloadItem::GetReceivedBytes() const {
return download_item_->GetReceivedBytes();
}
int64_t DownloadItem::GetTotalBytes() const {
return download_item_->GetTotalBytes();
}
std::string DownloadItem::GetMimeType() const {
return download_item_->GetMimeType();
}
bool DownloadItem::HasUserGesture() const {
return download_item_->HasUserGesture();
}
std::string DownloadItem::GetFilename() const {
return base::UTF16ToUTF8(net::GenerateFileName(GetURL(),
GetContentDisposition(),
std::string(),
download_item_->GetSuggestedFilename(),
GetMimeType(),
"download").LossyDisplayName());
}
std::string DownloadItem::GetContentDisposition() const {
return download_item_->GetContentDisposition();
}
const GURL& DownloadItem::GetURL() const {
return download_item_->GetURL();
}
const std::vector<GURL>& DownloadItem::GetURLChain() const {
return download_item_->GetUrlChain();
}
content::DownloadItem::DownloadState DownloadItem::GetState() const {
return download_item_->GetState();
}
bool DownloadItem::IsDone() const {
return download_item_->IsDone();
}
void DownloadItem::SetSavePath(const base::FilePath& path) {
save_path_ = path;
}
base::FilePath DownloadItem::GetSavePath() const {
return save_path_;
}
std::string DownloadItem::GetLastModifiedTime() const {
return download_item_->GetLastModifiedTime();
}
std::string DownloadItem::GetETag() const {
return download_item_->GetETag();
}
double DownloadItem::GetStartTime() const {
return download_item_->GetStartTime().ToDoubleT();
}
// static
void DownloadItem::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "DownloadItem"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.MakeDestroyable()
.SetMethod("pause", &DownloadItem::Pause)
.SetMethod("isPaused", &DownloadItem::IsPaused)
.SetMethod("resume", &DownloadItem::Resume)
.SetMethod("canResume", &DownloadItem::CanResume)
.SetMethod("cancel", &DownloadItem::Cancel)
.SetMethod("getReceivedBytes", &DownloadItem::GetReceivedBytes)
.SetMethod("getTotalBytes", &DownloadItem::GetTotalBytes)
.SetMethod("getMimeType", &DownloadItem::GetMimeType)
.SetMethod("hasUserGesture", &DownloadItem::HasUserGesture)
.SetMethod("getFilename", &DownloadItem::GetFilename)
.SetMethod("getContentDisposition", &DownloadItem::GetContentDisposition)
.SetMethod("getURL", &DownloadItem::GetURL)
.SetMethod("getURLChain", &DownloadItem::GetURLChain)
.SetMethod("getState", &DownloadItem::GetState)
.SetMethod("isDone", &DownloadItem::IsDone)
.SetMethod("setSavePath", &DownloadItem::SetSavePath)
.SetMethod("getSavePath", &DownloadItem::GetSavePath)
.SetMethod("getLastModifiedTime", &DownloadItem::GetLastModifiedTime)
.SetMethod("getETag", &DownloadItem::GetETag)
.SetMethod("getStartTime", &DownloadItem::GetStartTime);
}
// static
mate::Handle<DownloadItem> DownloadItem::Create(
v8::Isolate* isolate, content::DownloadItem* item) {
auto existing = TrackableObject::FromWrappedClass(isolate, item);
if (existing)
return mate::CreateHandle(isolate, static_cast<DownloadItem*>(existing));
auto handle = mate::CreateHandle(isolate, new DownloadItem(isolate, item));
// Reference this object in case it got garbage collected.
g_download_item_objects[handle->weak_map_id()] =
v8::Global<v8::Object>(isolate, handle.ToV8());
return handle;
}
} // namespace api
} // namespace atom
namespace {
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary(isolate, exports)
.Set("DownloadItem",
atom::api::DownloadItem::GetConstructor(isolate)->GetFunction());
}
} // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_download_item, Initialize);

View File

@@ -0,0 +1,70 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_API_ATOM_API_DOWNLOAD_ITEM_H_
#define ATOM_BROWSER_API_ATOM_API_DOWNLOAD_ITEM_H_
#include <string>
#include <vector>
#include "atom/browser/api/trackable_object.h"
#include "base/files/file_path.h"
#include "content/public/browser/download_item.h"
#include "native_mate/handle.h"
#include "url/gurl.h"
namespace atom {
namespace api {
class DownloadItem : public mate::TrackableObject<DownloadItem>,
public content::DownloadItem::Observer {
public:
static mate::Handle<DownloadItem> Create(v8::Isolate* isolate,
content::DownloadItem* item);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
void Pause();
bool IsPaused() const;
void Resume();
bool CanResume() const;
void Cancel();
int64_t GetReceivedBytes() const;
int64_t GetTotalBytes() const;
std::string GetMimeType() const;
bool HasUserGesture() const;
std::string GetFilename() const;
std::string GetContentDisposition() const;
const GURL& GetURL() const;
const std::vector<GURL>& GetURLChain() const;
content::DownloadItem::DownloadState GetState() const;
bool IsDone() const;
void SetSavePath(const base::FilePath& path);
base::FilePath GetSavePath() const;
std::string GetLastModifiedTime() const;
std::string GetETag() const;
double GetStartTime() const;
protected:
DownloadItem(v8::Isolate* isolate, content::DownloadItem* download_item);
~DownloadItem();
// Override content::DownloadItem::Observer methods
void OnDownloadUpdated(content::DownloadItem* download) override;
void OnDownloadDestroyed(content::DownloadItem* download) override;
private:
base::FilePath save_path_;
content::DownloadItem* download_item_;
DISALLOW_COPY_AND_ASSIGN(DownloadItem);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_DOWNLOAD_ITEM_H_

View File

@@ -0,0 +1,101 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_global_shortcut.h"
#include <string>
#include "atom/common/native_mate_converters/accelerator_converter.h"
#include "atom/common/native_mate_converters/callback.h"
#include "base/stl_util.h"
#include "native_mate/dictionary.h"
#include "atom/common/node_includes.h"
using extensions::GlobalShortcutListener;
namespace atom {
namespace api {
GlobalShortcut::GlobalShortcut(v8::Isolate* isolate) {
Init(isolate);
}
GlobalShortcut::~GlobalShortcut() {
UnregisterAll();
}
void GlobalShortcut::OnKeyPressed(const ui::Accelerator& accelerator) {
if (accelerator_callback_map_.find(accelerator) ==
accelerator_callback_map_.end()) {
// This should never occur, because if it does, GlobalGlobalShortcutListener
// notifes us with wrong accelerator.
NOTREACHED();
return;
}
accelerator_callback_map_[accelerator].Run();
}
bool GlobalShortcut::Register(const ui::Accelerator& accelerator,
const base::Closure& callback) {
if (!GlobalShortcutListener::GetInstance()->RegisterAccelerator(
accelerator, this)) {
return false;
}
accelerator_callback_map_[accelerator] = callback;
return true;
}
void GlobalShortcut::Unregister(const ui::Accelerator& accelerator) {
if (!ContainsKey(accelerator_callback_map_, accelerator))
return;
accelerator_callback_map_.erase(accelerator);
GlobalShortcutListener::GetInstance()->UnregisterAccelerator(
accelerator, this);
}
bool GlobalShortcut::IsRegistered(const ui::Accelerator& accelerator) {
return ContainsKey(accelerator_callback_map_, accelerator);
}
void GlobalShortcut::UnregisterAll() {
accelerator_callback_map_.clear();
GlobalShortcutListener::GetInstance()->UnregisterAccelerators(this);
}
// static
mate::Handle<GlobalShortcut> GlobalShortcut::Create(v8::Isolate* isolate) {
return mate::CreateHandle(isolate, new GlobalShortcut(isolate));
}
// static
void GlobalShortcut::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "GlobalShortcut"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("register", &GlobalShortcut::Register)
.SetMethod("isRegistered", &GlobalShortcut::IsRegistered)
.SetMethod("unregister", &GlobalShortcut::Unregister)
.SetMethod("unregisterAll", &GlobalShortcut::UnregisterAll);
}
} // namespace api
} // namespace atom
namespace {
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
dict.Set("globalShortcut", atom::api::GlobalShortcut::Create(isolate));
}
} // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_global_shortcut, Initialize)

View File

@@ -0,0 +1,54 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_API_ATOM_API_GLOBAL_SHORTCUT_H_
#define ATOM_BROWSER_API_ATOM_API_GLOBAL_SHORTCUT_H_
#include <map>
#include <string>
#include "atom/browser/api/trackable_object.h"
#include "base/callback.h"
#include "chrome/browser/extensions/global_shortcut_listener.h"
#include "native_mate/handle.h"
#include "ui/base/accelerators/accelerator.h"
namespace atom {
namespace api {
class GlobalShortcut : public extensions::GlobalShortcutListener::Observer,
public mate::TrackableObject<GlobalShortcut> {
public:
static mate::Handle<GlobalShortcut> Create(v8::Isolate* isolate);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
protected:
explicit GlobalShortcut(v8::Isolate* isolate);
~GlobalShortcut() override;
private:
typedef std::map<ui::Accelerator, base::Closure> AcceleratorCallbackMap;
bool Register(const ui::Accelerator& accelerator,
const base::Closure& callback);
bool IsRegistered(const ui::Accelerator& accelerator);
void Unregister(const ui::Accelerator& accelerator);
void UnregisterAll();
// GlobalShortcutListener::Observer implementation.
void OnKeyPressed(const ui::Accelerator& accelerator) override;
AcceleratorCallbackMap accelerator_callback_map_;
DISALLOW_COPY_AND_ASSIGN(GlobalShortcut);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_GLOBAL_SHORTCUT_H_

View File

@@ -0,0 +1,115 @@
// Copyright (c) 2017 Amaplex Software, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_in_app_purchase.h"
#include <string>
#include <utility>
#include <vector>
#include "atom/common/native_mate_converters/callback.h"
#include "native_mate/dictionary.h"
#include "atom/common/node_includes.h"
namespace mate {
template <>
struct Converter<in_app_purchase::Payment> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const in_app_purchase::Payment& payment) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
dict.SetHidden("simple", true);
dict.Set("productIdentifier", payment.productIdentifier);
dict.Set("quantity", payment.quantity);
return dict.GetHandle();
}
};
template <>
struct Converter<in_app_purchase::Transaction> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const in_app_purchase::Transaction& val) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
dict.SetHidden("simple", true);
dict.Set("transactionIdentifier", val.transactionIdentifier);
dict.Set("transactionDate", val.transactionDate);
dict.Set("originalTransactionIdentifier",
val.originalTransactionIdentifier);
dict.Set("transactionState", val.transactionState);
dict.Set("errorCode", val.errorCode);
dict.Set("errorMessage", val.errorMessage);
dict.Set("payment", val.payment);
return dict.GetHandle();
}
};
} // namespace mate
namespace atom {
namespace api {
#if defined(OS_MACOSX)
// static
mate::Handle<InAppPurchase> InAppPurchase::Create(v8::Isolate* isolate) {
return mate::CreateHandle(isolate, new InAppPurchase(isolate));
}
// static
void InAppPurchase::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "InAppPurchase"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("canMakePayments", &in_app_purchase::CanMakePayments)
.SetMethod("getReceiptURL", &in_app_purchase::GetReceiptURL)
.SetMethod("purchaseProduct", &InAppPurchase::PurchaseProduct);
}
InAppPurchase::InAppPurchase(v8::Isolate* isolate) {
Init(isolate);
}
InAppPurchase::~InAppPurchase() {
}
void InAppPurchase::PurchaseProduct(const std::string& product_id,
mate::Arguments* args) {
int quantity = 1;
in_app_purchase::InAppPurchaseCallback callback;
args->GetNext(&quantity);
args->GetNext(&callback);
in_app_purchase::PurchaseProduct(product_id, quantity, callback);
}
void InAppPurchase::OnTransactionsUpdated(
const std::vector<in_app_purchase::Transaction>& transactions) {
Emit("transactions-updated", transactions);
}
#endif
} // namespace api
} // namespace atom
namespace {
using atom::api::InAppPurchase;
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
#if defined(OS_MACOSX)
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
dict.Set("inAppPurchase", InAppPurchase::Create(isolate));
dict.Set("InAppPurchase",
InAppPurchase::GetConstructor(isolate)->GetFunction());
#endif
}
} // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_in_app_purchase, Initialize)

View File

@@ -0,0 +1,46 @@
// Copyright (c) 2017 Amaplex Software, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_API_ATOM_API_IN_APP_PURCHASE_H_
#define ATOM_BROWSER_API_ATOM_API_IN_APP_PURCHASE_H_
#include <string>
#include <vector>
#include "atom/browser/api/event_emitter.h"
#include "atom/browser/mac/in_app_purchase.h"
#include "atom/browser/mac/in_app_purchase_observer.h"
#include "native_mate/handle.h"
namespace atom {
namespace api {
class InAppPurchase: public mate::EventEmitter<InAppPurchase>,
public in_app_purchase::TransactionObserver {
public:
static mate::Handle<InAppPurchase> Create(v8::Isolate* isolate);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
protected:
explicit InAppPurchase(v8::Isolate* isolate);
~InAppPurchase() override;
void PurchaseProduct(const std::string& product_id, mate::Arguments* args);
// TransactionObserver:
void OnTransactionsUpdated(
const std::vector<in_app_purchase::Transaction>& transactions) override;
private:
DISALLOW_COPY_AND_ASSIGN(InAppPurchase);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_IN_APP_PURCHASE_H_

View File

@@ -0,0 +1,231 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_menu.h"
#include "atom/browser/native_window.h"
#include "atom/common/native_mate_converters/accelerator_converter.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/image_converter.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "native_mate/constructor.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "atom/common/node_includes.h"
namespace atom {
namespace api {
Menu::Menu(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
: model_(new AtomMenuModel(this)),
parent_(nullptr) {
InitWith(isolate, wrapper);
model_->AddObserver(this);
}
Menu::~Menu() {
if (model_) {
model_->RemoveObserver(this);
}
}
void Menu::AfterInit(v8::Isolate* isolate) {
mate::Dictionary wrappable(isolate, GetWrapper());
mate::Dictionary delegate;
if (!wrappable.Get("delegate", &delegate))
return;
delegate.Get("isCommandIdChecked", &is_checked_);
delegate.Get("isCommandIdEnabled", &is_enabled_);
delegate.Get("isCommandIdVisible", &is_visible_);
delegate.Get("getAcceleratorForCommandId", &get_accelerator_);
delegate.Get("executeCommand", &execute_command_);
delegate.Get("menuWillShow", &menu_will_show_);
}
bool Menu::IsCommandIdChecked(int command_id) const {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
return is_checked_.Run(GetWrapper(), command_id);
}
bool Menu::IsCommandIdEnabled(int command_id) const {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
return is_enabled_.Run(GetWrapper(), command_id);
}
bool Menu::IsCommandIdVisible(int command_id) const {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
return is_visible_.Run(GetWrapper(), command_id);
}
bool Menu::GetAcceleratorForCommandIdWithParams(
int command_id,
bool use_default_accelerator,
ui::Accelerator* accelerator) const {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
v8::Local<v8::Value> val = get_accelerator_.Run(
GetWrapper(), command_id, use_default_accelerator);
return mate::ConvertFromV8(isolate(), val, accelerator);
}
void Menu::ExecuteCommand(int command_id, int flags) {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
execute_command_.Run(
GetWrapper(),
mate::internal::CreateEventFromFlags(isolate(), flags),
command_id);
}
void Menu::MenuWillShow(ui::SimpleMenuModel* source) {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
menu_will_show_.Run(GetWrapper());
}
void Menu::InsertItemAt(
int index, int command_id, const base::string16& label) {
model_->InsertItemAt(index, command_id, label);
}
void Menu::InsertSeparatorAt(int index) {
model_->InsertSeparatorAt(index, ui::NORMAL_SEPARATOR);
}
void Menu::InsertCheckItemAt(int index,
int command_id,
const base::string16& label) {
model_->InsertCheckItemAt(index, command_id, label);
}
void Menu::InsertRadioItemAt(int index,
int command_id,
const base::string16& label,
int group_id) {
model_->InsertRadioItemAt(index, command_id, label, group_id);
}
void Menu::InsertSubMenuAt(int index,
int command_id,
const base::string16& label,
Menu* menu) {
menu->parent_ = this;
model_->InsertSubMenuAt(index, command_id, label, menu->model_.get());
}
void Menu::SetIcon(int index, const gfx::Image& image) {
model_->SetIcon(index, image);
}
void Menu::SetSublabel(int index, const base::string16& sublabel) {
model_->SetSublabel(index, sublabel);
}
void Menu::SetRole(int index, const base::string16& role) {
model_->SetRole(index, role);
}
void Menu::Clear() {
model_->Clear();
}
int Menu::GetIndexOfCommandId(int command_id) {
return model_->GetIndexOfCommandId(command_id);
}
int Menu::GetItemCount() const {
return model_->GetItemCount();
}
int Menu::GetCommandIdAt(int index) const {
return model_->GetCommandIdAt(index);
}
base::string16 Menu::GetLabelAt(int index) const {
return model_->GetLabelAt(index);
}
base::string16 Menu::GetSublabelAt(int index) const {
return model_->GetSublabelAt(index);
}
bool Menu::IsItemCheckedAt(int index) const {
return model_->IsItemCheckedAt(index);
}
bool Menu::IsEnabledAt(int index) const {
return model_->IsEnabledAt(index);
}
bool Menu::IsVisibleAt(int index) const {
return model_->IsVisibleAt(index);
}
void Menu::OnMenuWillClose() {
Emit("menu-will-close");
}
void Menu::OnMenuWillShow() {
Emit("menu-will-show");
}
// static
void Menu::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "Menu"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.MakeDestroyable()
.SetMethod("insertItem", &Menu::InsertItemAt)
.SetMethod("insertCheckItem", &Menu::InsertCheckItemAt)
.SetMethod("insertRadioItem", &Menu::InsertRadioItemAt)
.SetMethod("insertSeparator", &Menu::InsertSeparatorAt)
.SetMethod("insertSubMenu", &Menu::InsertSubMenuAt)
.SetMethod("setIcon", &Menu::SetIcon)
.SetMethod("setSublabel", &Menu::SetSublabel)
.SetMethod("setRole", &Menu::SetRole)
.SetMethod("clear", &Menu::Clear)
.SetMethod("getIndexOfCommandId", &Menu::GetIndexOfCommandId)
.SetMethod("getItemCount", &Menu::GetItemCount)
.SetMethod("getCommandIdAt", &Menu::GetCommandIdAt)
.SetMethod("getLabelAt", &Menu::GetLabelAt)
.SetMethod("getSublabelAt", &Menu::GetSublabelAt)
.SetMethod("isItemCheckedAt", &Menu::IsItemCheckedAt)
.SetMethod("isEnabledAt", &Menu::IsEnabledAt)
.SetMethod("isVisibleAt", &Menu::IsVisibleAt)
.SetMethod("popupAt", &Menu::PopupAt)
.SetMethod("closePopupAt", &Menu::ClosePopupAt);
}
} // namespace api
} // namespace atom
namespace {
using atom::api::Menu;
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate();
Menu::SetConstructor(isolate, base::Bind(&Menu::New));
mate::Dictionary dict(isolate, exports);
dict.Set("Menu", Menu::GetConstructor(isolate)->GetFunction());
#if defined(OS_MACOSX)
dict.SetMethod("setApplicationMenu", &Menu::SetApplicationMenu);
dict.SetMethod("sendActionToFirstResponder",
&Menu::SendActionToFirstResponder);
#endif
}
} // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_menu, Initialize)

View File

@@ -0,0 +1,135 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_API_ATOM_API_MENU_H_
#define ATOM_BROWSER_API_ATOM_API_MENU_H_
#include <memory>
#include <string>
#include "atom/browser/api/atom_api_window.h"
#include "atom/browser/api/trackable_object.h"
#include "atom/browser/ui/atom_menu_model.h"
#include "base/callback.h"
namespace atom {
namespace api {
class Menu : public mate::TrackableObject<Menu>,
public AtomMenuModel::Delegate,
public AtomMenuModel::Observer {
public:
static mate::WrappableBase* New(mate::Arguments* args);
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
#if defined(OS_MACOSX)
// Set the global menubar.
static void SetApplicationMenu(Menu* menu);
// Fake sending an action from the application menu.
static void SendActionToFirstResponder(const std::string& action);
#endif
AtomMenuModel* model() const { return model_.get(); }
protected:
Menu(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
~Menu() override;
// mate::Wrappable:
void AfterInit(v8::Isolate* isolate) override;
// ui::SimpleMenuModel::Delegate:
bool IsCommandIdChecked(int command_id) const override;
bool IsCommandIdEnabled(int command_id) const override;
bool IsCommandIdVisible(int command_id) const override;
bool GetAcceleratorForCommandIdWithParams(
int command_id,
bool use_default_accelerator,
ui::Accelerator* accelerator) const override;
void ExecuteCommand(int command_id, int event_flags) override;
void MenuWillShow(ui::SimpleMenuModel* source) override;
virtual void PopupAt(Window* window, int x, int y, int positioning_item,
const base::Closure& callback) = 0;
virtual void ClosePopupAt(int32_t window_id) = 0;
std::unique_ptr<AtomMenuModel> model_;
Menu* parent_;
// Observable:
void OnMenuWillClose() override;
void OnMenuWillShow() override;
private:
void InsertItemAt(int index, int command_id, const base::string16& label);
void InsertSeparatorAt(int index);
void InsertCheckItemAt(int index,
int command_id,
const base::string16& label);
void InsertRadioItemAt(int index,
int command_id,
const base::string16& label,
int group_id);
void InsertSubMenuAt(int index,
int command_id,
const base::string16& label,
Menu* menu);
void SetIcon(int index, const gfx::Image& image);
void SetSublabel(int index, const base::string16& sublabel);
void SetRole(int index, const base::string16& role);
void Clear();
int GetIndexOfCommandId(int command_id);
int GetItemCount() const;
int GetCommandIdAt(int index) const;
base::string16 GetLabelAt(int index) const;
base::string16 GetSublabelAt(int index) const;
bool IsItemCheckedAt(int index) const;
bool IsEnabledAt(int index) const;
bool IsVisibleAt(int index) const;
// Stored delegate methods.
base::Callback<bool(v8::Local<v8::Value>, int)> is_checked_;
base::Callback<bool(v8::Local<v8::Value>, int)> is_enabled_;
base::Callback<bool(v8::Local<v8::Value>, int)> is_visible_;
base::Callback<v8::Local<v8::Value>(v8::Local<v8::Value>, int, bool)>
get_accelerator_;
base::Callback<void(v8::Local<v8::Value>, v8::Local<v8::Value>, int)>
execute_command_;
base::Callback<void(v8::Local<v8::Value>)> menu_will_show_;
DISALLOW_COPY_AND_ASSIGN(Menu);
};
} // namespace api
} // namespace atom
namespace mate {
template<>
struct Converter<atom::AtomMenuModel*> {
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
atom::AtomMenuModel** out) {
// null would be tranfered to NULL.
if (val->IsNull()) {
*out = nullptr;
return true;
}
atom::api::Menu* menu;
if (!Converter<atom::api::Menu*>::FromV8(isolate, val, &menu))
return false;
*out = menu->model();
return true;
}
};
} // namespace mate
#endif // ATOM_BROWSER_API_ATOM_API_MENU_H_

View File

@@ -0,0 +1,54 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_API_ATOM_API_MENU_MAC_H_
#define ATOM_BROWSER_API_ATOM_API_MENU_MAC_H_
#include "atom/browser/api/atom_api_menu.h"
#include <map>
#include <string>
#import "atom/browser/ui/cocoa/atom_menu_controller.h"
using base::scoped_nsobject;
namespace atom {
namespace api {
class MenuMac : public Menu {
protected:
MenuMac(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
void PopupAt(Window* window, int x, int y, int positioning_item,
const base::Closure& callback) override;
void PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
int32_t window_id,
int x,
int y,
int positioning_item,
base::Closure callback);
void ClosePopupAt(int32_t window_id) override;
private:
friend class Menu;
void OnClosed(int32_t window_id, base::Closure callback);
scoped_nsobject<AtomMenuController> menu_controller_;
// window ID -> open context menu
std::map<int32_t, scoped_nsobject<AtomMenuController>> popup_controllers_;
base::WeakPtrFactory<MenuMac> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(MenuMac);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_MENU_MAC_H_

View File

@@ -0,0 +1,157 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#import "atom/browser/api/atom_api_menu_mac.h"
#include "atom/browser/native_window.h"
#include "atom/browser/unresponsive_suppressor.h"
#include "base/mac/scoped_sending_event.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/sys_string_conversions.h"
#include "brightray/browser/inspectable_web_contents.h"
#include "brightray/browser/inspectable_web_contents_view.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "atom/common/node_includes.h"
using content::BrowserThread;
namespace atom {
namespace api {
MenuMac::MenuMac(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
: Menu(isolate, wrapper),
weak_factory_(this) {
}
void MenuMac::PopupAt(Window* window, int x, int y, int positioning_item,
const base::Closure& callback) {
NativeWindow* native_window = window->window();
if (!native_window)
return;
auto popup = base::Bind(&MenuMac::PopupOnUI, weak_factory_.GetWeakPtr(),
native_window->GetWeakPtr(), window->ID(), x, y,
positioning_item, callback);
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, popup);
}
void MenuMac::PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
int32_t window_id,
int x,
int y,
int positioning_item,
base::Closure callback) {
if (!native_window)
return;
brightray::InspectableWebContents* web_contents =
native_window->inspectable_web_contents();
if (!web_contents)
return;
auto close_callback = base::Bind(
&MenuMac::OnClosed, weak_factory_.GetWeakPtr(), window_id, callback);
popup_controllers_[window_id] = base::scoped_nsobject<AtomMenuController>(
[[AtomMenuController alloc] initWithModel:model()
useDefaultAccelerator:NO]);
NSMenu* menu = [popup_controllers_[window_id] menu];
NSView* view = web_contents->GetView()->GetNativeView();
// Which menu item to show.
NSMenuItem* item = nil;
if (positioning_item < [menu numberOfItems] && positioning_item >= 0)
item = [menu itemAtIndex:positioning_item];
// (-1, -1) means showing on mouse location.
NSPoint position;
if (x == -1 || y == -1) {
NSWindow* nswindow = native_window->GetNativeWindow();
position = [view convertPoint:[nswindow mouseLocationOutsideOfEventStream]
fromView:nil];
} else {
position = NSMakePoint(x, [view frame].size.height - y);
}
// If no preferred item is specified, try to show all of the menu items.
if (!positioning_item) {
CGFloat windowBottom = CGRectGetMinY([view window].frame);
CGFloat lowestMenuPoint = windowBottom + position.y - [menu size].height;
CGFloat screenBottom = CGRectGetMinY([view window].screen.frame);
CGFloat distanceFromBottom = lowestMenuPoint - screenBottom;
if (distanceFromBottom < 0)
position.y = position.y - distanceFromBottom + 4;
}
// Place the menu left of cursor if it is overflowing off right of screen.
CGFloat windowLeft = CGRectGetMinX([view window].frame);
CGFloat rightmostMenuPoint = windowLeft + position.x + [menu size].width;
CGFloat screenRight = CGRectGetMaxX([view window].screen.frame);
if (rightmostMenuPoint > screenRight)
position.x = position.x - [menu size].width;
[popup_controllers_[window_id] setCloseCallback:close_callback];
// Make sure events can be pumped while the menu is up.
base::MessageLoop::ScopedNestableTaskAllower allow(
base::MessageLoop::current());
// One of the events that could be pumped is |window.close()|.
// User-initiated event-tracking loops protect against this by
// setting flags in -[CrApplication sendEvent:], but since
// web-content menus are initiated by IPC message the setup has to
// be done manually.
base::mac::ScopedSendingEvent sendingEventScoper;
// Don't emit unresponsive event when showing menu.
atom::UnresponsiveSuppressor suppressor;
[menu popUpMenuPositioningItem:item atLocation:position inView:view];
}
void MenuMac::ClosePopupAt(int32_t window_id) {
auto controller = popup_controllers_.find(window_id);
if (controller != popup_controllers_.end()) {
// Close the controller for the window.
[controller->second cancel];
} else if (window_id == -1) {
// Or just close all opened controllers.
for (auto it = popup_controllers_.begin();
it != popup_controllers_.end();) {
// The iterator is invalidated after the call.
[(it++)->second cancel];
}
}
}
void MenuMac::OnClosed(int32_t window_id, base::Closure callback) {
popup_controllers_.erase(window_id);
callback.Run();
}
// static
void Menu::SetApplicationMenu(Menu* base_menu) {
MenuMac* menu = static_cast<MenuMac*>(base_menu);
base::scoped_nsobject<AtomMenuController> menu_controller(
[[AtomMenuController alloc] initWithModel:menu->model_.get()
useDefaultAccelerator:YES]);
[NSApp setMainMenu:[menu_controller menu]];
// Ensure the menu_controller_ is destroyed after main menu is set.
menu_controller.swap(menu->menu_controller_);
}
// static
void Menu::SendActionToFirstResponder(const std::string& action) {
SEL selector = NSSelectorFromString(base::SysUTF8ToNSString(action));
[NSApp sendAction:selector to:nil from:[NSApp mainMenu]];
}
// static
mate::WrappableBase* Menu::New(mate::Arguments* args) {
return new MenuMac(args->isolate(), args->GetThis());
}
} // namespace api
} // namespace atom

View File

@@ -0,0 +1,84 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_menu_views.h"
#include "atom/browser/native_window_views.h"
#include "atom/browser/unresponsive_suppressor.h"
#include "brightray/browser/inspectable_web_contents.h"
#include "brightray/browser/inspectable_web_contents_view.h"
#include "ui/display/screen.h"
using views::MenuRunner;
namespace atom {
namespace api {
MenuViews::MenuViews(v8::Isolate* isolate, v8::Local<v8::Object> wrapper)
: Menu(isolate, wrapper),
weak_factory_(this) {
}
void MenuViews::PopupAt(Window* window, int x, int y, int positioning_item,
const base::Closure& callback) {
auto* native_window = static_cast<NativeWindowViews*>(window->window());
if (!native_window)
return;
// (-1, -1) means showing on mouse location.
gfx::Point location;
if (x == -1 || y == -1) {
location = display::Screen::GetScreen()->GetCursorScreenPoint();
} else {
gfx::Point origin = native_window->GetContentBounds().origin();
location = gfx::Point(origin.x() + x, origin.y() + y);
}
int flags = MenuRunner::CONTEXT_MENU | MenuRunner::HAS_MNEMONICS;
// Don't emit unresponsive event when showing menu.
atom::UnresponsiveSuppressor suppressor;
// Show the menu.
int32_t window_id = window->ID();
auto close_callback = base::Bind(
&MenuViews::OnClosed, weak_factory_.GetWeakPtr(), window_id, callback);
menu_runners_[window_id] = std::unique_ptr<MenuRunner>(new MenuRunner(
model(), flags, close_callback));
menu_runners_[window_id]->RunMenuAt(
native_window->widget(),
NULL,
gfx::Rect(location, gfx::Size()),
views::MENU_ANCHOR_TOPLEFT,
ui::MENU_SOURCE_MOUSE);
}
void MenuViews::ClosePopupAt(int32_t window_id) {
auto runner = menu_runners_.find(window_id);
if (runner != menu_runners_.end()) {
// Close the runner for the window.
runner->second->Cancel();
} else if (window_id == -1) {
// Or just close all opened runners.
for (auto it = menu_runners_.begin(); it != menu_runners_.end();) {
// The iterator is invalidated after the call.
(it++)->second->Cancel();
}
}
}
void MenuViews::OnClosed(int32_t window_id, base::Closure callback) {
menu_runners_.erase(window_id);
callback.Run();
}
// static
mate::WrappableBase* Menu::New(mate::Arguments* args) {
return new MenuViews(args->isolate(), args->GetThis());
}
} // namespace api
} // namespace atom

View File

@@ -0,0 +1,43 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_API_ATOM_API_MENU_VIEWS_H_
#define ATOM_BROWSER_API_ATOM_API_MENU_VIEWS_H_
#include <map>
#include "atom/browser/api/atom_api_menu.h"
#include "base/memory/weak_ptr.h"
#include "ui/display/screen.h"
#include "ui/views/controls/menu/menu_runner.h"
namespace atom {
namespace api {
class MenuViews : public Menu {
public:
MenuViews(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);
protected:
void PopupAt(Window* window, int x, int y, int positioning_item,
const base::Closure& callback) override;
void ClosePopupAt(int32_t window_id) override;
private:
void OnClosed(int32_t window_id, base::Closure callback);
// window ID -> open context menu
std::map<int32_t, std::unique_ptr<views::MenuRunner>> menu_runners_;
base::WeakPtrFactory<MenuViews> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(MenuViews);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_MENU_VIEWS_H_

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