Compare commits

..

288 Commits

Author SHA1 Message Date
Cheng Zhao
dadd34249a Bump v0.29.0 2015-07-03 16:45:56 +08:00
Cheng Zhao
173babc18b Merge pull request #2111 from atom/upload-in-ci
Create Release distributions in CI machine
2015-07-03 16:42:05 +08:00
Cheng Zhao
64c0e0dfdc Only creates Release build when ELECTRON_RELEASE is set 2015-07-03 16:31:33 +08:00
Cheng Zhao
bdbb994c72 Fix pylint warning 2015-07-03 15:31:55 +08:00
Cheng Zhao
ffb1732607 Delete the original file before uploading in CI 2015-07-03 15:26:54 +08:00
Cheng Zhao
02f3d7a25e Just ignore all OSError for rm_rf 2015-07-03 15:07:11 +08:00
Cheng Zhao
518ec36511 WindowsError is undefined on POSIX 2015-07-03 14:54:32 +08:00
Cheng Zhao
12233d704b Use better tag and title 2015-07-03 14:49:29 +08:00
Cheng Zhao
2717556a92 WindowsError is a subclass of OSError 2015-07-03 14:46:26 +08:00
Cheng Zhao
7288581393 Fix path to requests library 2015-07-03 14:43:58 +08:00
Cheng Zhao
f87a4b9a04 One failing rm should not block others 2015-07-03 14:40:32 +08:00
Cheng Zhao
b30709f133 No need to clean after cibuild 2015-07-03 14:36:45 +08:00
Cheng Zhao
20e9abe26a Don't check build version in CI 2015-07-03 14:30:59 +08:00
Cheng Zhao
89b22db618 Build the python requests library 2015-07-03 14:23:42 +08:00
Cheng Zhao
e95ee4775e Ignore Windows errors in clean.py 2015-07-03 13:59:02 +08:00
Cheng Zhao
f5ae3111ba Fix calling clean.py 2015-07-03 13:54:29 +08:00
Cheng Zhao
6b7d3a070a Clean before and after cibuild
Our CI machine is out of disk space
2015-07-03 13:52:13 +08:00
Cheng Zhao
e4530e6e32 Don't force redownloading some assets 2015-07-03 13:46:26 +08:00
Cheng Zhao
1212e45a6e Fix pylint warning 2015-07-03 13:45:29 +08:00
Cheng Zhao
82153eb75f Upload dist to Releases 2015-07-03 13:43:20 +08:00
Cheng Zhao
f99cd4d05a Try doing release in CI 2015-07-03 12:08:14 +08:00
Cheng Zhao
a720e52568 Set DISPLAY in CI machine 2015-07-03 12:04:27 +08:00
Cheng Zhao
83ee7a464d Avoid using the old gyp lib in system 2015-07-03 11:59:34 +08:00
Cheng Zhao
8e5a434560 Suppress window operations in CI 2015-07-03 11:40:20 +08:00
Cheng Zhao
8f06bd6f3e Merge pull request #2107 from atom/win-ci
Build in Windows CI
2015-07-03 11:28:16 +08:00
Cheng Zhao
fe877da61f Do debug build on Windows CI for non-release 2015-07-03 11:17:58 +08:00
Cheng Zhao
a1bb0d4d66 Don't call register_required_dll for now 2015-07-03 11:10:23 +08:00
Cheng Zhao
a6073113a1 No need to remove node_modules 2015-07-03 11:04:57 +08:00
Cheng Zhao
7d2866f3a7 Do not run tests in Windows CI 2015-07-03 10:35:40 +08:00
Cheng Zhao
52ba6a25df Create release dist when ELECTRON_RELEASE is set 2015-07-03 10:17:20 +08:00
Cheng Zhao
25e15869ec Force using VS2013 for building 2015-07-03 10:01:44 +08:00
Cheng Zhao
b3c76f3904 Only define mac_framework_dirs on Mac 2015-07-03 09:49:55 +08:00
Cheng Zhao
8de9c75caf Don't define source_root on Windows 2015-07-03 09:46:35 +08:00
Cheng Zhao
33109a2718 Ignore npm install errors when running in CI 2015-07-03 09:43:09 +08:00
Cheng Zhao
cab1b75c41 Use npm@2.12.1
See https://github.com/npm/npm/issues/8702.
2015-07-03 09:35:16 +08:00
Cheng Zhao
1e9af82bf6 Install npm before cleaning node_modules 2015-07-02 22:45:26 +08:00
Cheng Zhao
ddaf005c2b Fix calling npm on win32 2015-07-02 22:35:41 +08:00
Cheng Zhao
558a612d37 Install latest npm in CI 2015-07-02 22:34:05 +08:00
Cheng Zhao
5ccc909f2f Merge pull request #2094 from atom/arm
Add arm build
2015-07-02 16:04:37 +08:00
Cheng Zhao
a367934b95 docs: Cross compilation 2015-07-02 15:55:21 +08:00
Cheng Zhao
2078e5736e Don't upload arm version of mksnapshot too 2015-07-02 07:26:53 +00:00
Cheng Zhao
f0eac9d828 Don't upload arm version of chromedriver 2015-07-02 07:25:17 +00:00
Cheng Zhao
8110f2f221 Call correct strip for arm target 2015-07-02 07:19:39 +00:00
Cheng Zhao
c76d87719d Build dump_syms for host arch 2015-07-02 07:10:05 +00:00
Cheng Zhao
9bdefa6f1f Use clang's integrated as
The system as is throwing error when compiling atom_api_web_contents.cc:
/tmp/xxx.s: Assembler messages:
/tmp/xxx.s:23559: Internal error!
Assertion failure in get_line_subseg at ../../gas/dwarf2dbg.c line 262.
2015-07-02 06:31:10 +00:00
Cheng Zhao
b261c5f87c Libraries on host side is needed to make pkg-config work 2015-07-02 05:27:12 +00:00
Cheng Zhao
f569617d24 Clean up the libraries to install 2015-07-02 05:19:53 +00:00
Cheng Zhao
88b71b9633 Only run tests for x64 target 2015-07-02 05:18:05 +00:00
Cheng Zhao
f2daeb9d70 Build ia32 target with sysroot 2015-07-02 05:07:56 +00:00
Cheng Zhao
6088af623e Install ia32 build dependencies 2015-07-02 04:47:43 +00:00
Cheng Zhao
57262dd5ef Install arm build dependencies 2015-07-02 04:42:36 +00:00
Cheng Zhao
2de5ae9991 Add build matrix for arm and ia32 2015-07-02 03:13:18 +00:00
Cheng Zhao
3a094e9802 Use prebuild clang to build node modules 2015-07-02 02:56:56 +00:00
Cheng Zhao
62a5159e72 Don't install ubuntu test toolchain 2015-07-02 01:27:33 +00:00
Cheng Zhao
7b955fe829 Update libchromiumcontent to get arm build 2015-07-02 01:09:53 +00:00
Cheng Zhao
14bc544d89 Use our custom debian sysroot image 2015-07-02 00:47:14 +00:00
Cheng Zhao
a04bfbbc4b Never send email notifications
It is anonnying.
2015-07-02 00:46:10 +00:00
Kevin Sawicki
69ef175ac5 Merge pull request #2083 from johnhaley81/patch-1
Fix `window.open` with wrong name
2015-07-01 09:12:02 -07:00
Kevin Sawicki
cbac7179fd Merge pull request #2087 from shainnif/patch-1
Update build-instructions-windows.md
2015-07-01 09:07:55 -07:00
Kevin Sawicki
d6e25af59a Merge pull request #2095 from atom/fix-page-key-error
Fix the wrong reverse `pageup` and `pagedown` keys.
2015-07-01 09:07:33 -07:00
Haojian Wu
c01a79de6b Fix the wrong reverse pageup and pagedown keys. 2015-07-01 21:24:51 +08:00
Cheng Zhao
4214b62551 Set sysroot for arm build 2015-07-01 09:54:27 +00:00
Cheng Zhao
88eb5283a0 Download debian arm sysroot image 2015-07-01 09:22:40 +00:00
Cheng Zhao
af05f5b329 Add function to get host_arch 2015-07-01 09:17:44 +00:00
Cheng Zhao
1b3a8435e5 Define chromeos 2015-07-01 08:59:17 +00:00
Cheng Zhao
432bab3107 Only allow building on 64bit machine 2015-07-01 16:51:06 +08:00
Cheng Zhao
e15b05603d Merge pull request #2092 from atom/download-clang
Use downloaded clang binaries for building
2015-07-01 16:43:13 +08:00
Cheng Zhao
b1db947def Fix compilation errors due to compiler change 2015-07-01 07:56:29 +00:00
Cheng Zhao
3d88d56965 Support cross-compiling 2015-07-01 07:47:21 +00:00
Cheng Zhao
fdf7452ba9 Use downloaded clang for building 2015-07-01 14:44:45 +08:00
Cheng Zhao
bceac2ab7f Download prebuilt clang 2015-07-01 14:27:15 +08:00
Shaine Ismail
11cfe20395 Update build-instructions-windows.md
Very very very minor typo
2015-06-30 13:00:20 +01:00
Kevin Sawicki
dbb6723dfa Remove extra newline 2015-06-29 16:47:36 -07:00
Kevin Sawicki
ee3ac608cf Add slack back to README 2015-06-29 16:46:22 -07:00
John Haley
565a500320 Fix window.open with wrong name
When calling `window.open` the newly created window would have the name of the last option in the `features` argument as the title. I think it's supposed to be pointed to `frameName`.
2015-06-29 10:32:27 -07:00
Cheng Zhao
ebfbbc0801 Don't override user's menu in default_app
Close #2068.
2015-06-29 13:11:53 +08:00
Cheng Zhao
b508346ed8 Merge pull request #2077 from atom/iojs-latest
Update to io.js v2.3.1
2015-06-29 12:41:38 +08:00
Cheng Zhao
04de1aa51d Update to io.js v2.3.1 2015-06-29 12:18:50 +08:00
Cheng Zhao
1e514620b5 Remove window from window list before notifying closed event 2015-06-27 17:11:36 +08:00
Kevin Sawicki
4b4654ec71 Merge pull request #2066 from atom/doc-type-error
📝 Fix a type error.
2015-06-26 08:24:33 -06:00
Cheng Zhao
a79fcac047 Merge pull request #2063 from darwin/missing-overrides
Missing overrides
2015-06-26 21:49:57 +08:00
Cheng Zhao
572d4c5687 Merge pull request #2060 from geelen/patch-1
electron-installer not atom-shell-installer
2015-06-26 21:26:15 +08:00
Antonin Hildebrand
a8d58ea448 Missing overrides
ninja compilation failed for me under OS X 10.11
2015-06-26 11:43:39 +02:00
Glen Maddern
19daed9479 electron-installer not atom-shell-installer
<3
2015-06-26 14:17:52 +10:00
Cheng Zhao
637b642837 Fix building on Windows 2015-06-26 12:04:15 +08:00
Cheng Zhao
e6f3c4c22b Merge pull request #2002 from atom/app-commands-win32
Windows App Commands
2015-06-26 11:43:08 +08:00
Cheng Zhao
b5ff77ef0d Small cleanups 2015-06-26 11:20:12 +08:00
Cheng Zhao
bff66caaa6 Only convert command ID on Windows 2015-06-26 11:16:50 +08:00
Cheng Zhao
aa20f75335 Clean up ResolveProxyHelper
Since the ResolveProxyHelper is deleted after the callback is called,
there is no need to use weak reference.
2015-06-26 11:04:12 +08:00
Cheng Zhao
143a5e1178 Merge pull request #2054 from deepak1556/proxy_patch
session: using storageparttion to retrieve requestcontext
2015-06-26 10:54:47 +08:00
Cheng Zhao
a96ff85005 Clean up code in AtomBrowserClient 2015-06-26 10:53:37 +08:00
Haojian Wu
80e02d945c 📝 Fix a type error. 2015-06-26 10:47:50 +08:00
Cheng Zhao
edf60b8529 spec: Remove grabage console.log 2015-06-26 10:47:36 +08:00
Cheng Zhao
7fd60294f9 Merge pull request #2057 from atom/app-gpu-crash
Move gpu-crashed event to app
2015-06-26 10:47:04 +08:00
Cheng Zhao
a3ec50437d Rename event name to gpu-process-crashed 2015-06-26 10:34:38 +08:00
Cheng Zhao
5b5393e82b docs: gpu-crashed is moved to app 2015-06-26 10:34:13 +08:00
Cheng Zhao
ffd9c743de Move gpu-crashed event to app 2015-06-26 10:33:52 +08:00
Cheng Zhao
09c2317ae6 Merge pull request #1941 from deepak1556/certificate_api_patch
app: event to pass client certificate data
2015-06-26 10:31:18 +08:00
Paul Betts
58efb3c018 I forget cpplint every time 2015-06-25 15:09:25 -06:00
Paul Betts
528e0f3efb Revert submodule change 2015-06-25 11:31:32 -06:00
Paul Betts
2a2158e0e3 📝 consistency 2015-06-25 11:29:58 -06:00
Paul Betts
cde7c6a4ef Move app commands to strings 2015-06-25 11:29:57 -06:00
Paul Betts
210417b428 cpplint see me rollin', he hatin' 2015-06-25 11:29:28 -06:00
Paul Betts
1509aca788 Invisible character tyranny 2015-06-25 11:29:27 -06:00
Paul Betts
b98154431c 📝 app commands 2015-06-25 11:29:25 -06:00
Paul Betts
55a8862374 Add appcommand to files 2015-06-25 11:29:24 -06:00
Paul Betts
c2290ad058 Add enum for media keys on Win32 2015-06-25 11:29:23 -06:00
Paul Betts
cec6895e67 Emit the message as an event 2015-06-25 11:29:22 -06:00
Paul Betts
794f89abf5 In our widget delegate, signal our Observer 2015-06-25 11:29:21 -06:00
Paul Betts
37d18d512b Create a method to signal our Observer method 2015-06-25 11:29:21 -06:00
Paul Betts
d98cece115 Create a new method for NativeWindowObserver for AppCommands 2015-06-25 11:29:20 -06:00
deepak1556
0fbd908fb6 app: event to pass client certificate data 2015-06-25 21:29:21 +05:30
deepak1556
c15a9e7d5c session: using storageparttion to retrieve requestcontext 2015-06-25 19:55:57 +05:30
Cheng Zhao
1418fdbc02 Merge pull request #2051 from atom/detach-web-contents
Decouple WebContents from NativeWindow
2015-06-25 15:11:40 +08:00
Cheng Zhao
9f52b11761 Remove NativeWindow::GetWebContents 2015-06-25 14:54:00 +08:00
Cheng Zhao
01dc0f973c Remove inspectable_web_contents_ 2015-06-25 14:32:38 +08:00
Cheng Zhao
b2a8678c47 Move BrowserPluginGuestDelegate to a separate class 2015-06-25 14:28:13 +08:00
Cheng Zhao
9974a238c2 Fix the order of function definitions 2015-06-25 13:29:30 +08:00
Cheng Zhao
62c44ee47b Rename CloseWebContents to RequestToClosePage 2015-06-25 13:27:51 +08:00
Cheng Zhao
e41b0d4d2c Remove NativeWindow::ActivateContents 2015-06-25 13:18:36 +08:00
Cheng Zhao
eb370ba22a Allowing destroying a closed window 2015-06-25 13:08:11 +08:00
Cheng Zhao
afa9f30aac Add InspectableWebContentsViewDelegate 2015-06-25 12:30:04 +08:00
Cheng Zhao
2ea2413752 Set sender in EventEmitter.emit 2015-06-25 11:16:42 +08:00
Cheng Zhao
fb5fe7a714 Decouple WebContentsDelegate from NativeWindow 2015-06-25 11:07:23 +08:00
Cheng Zhao
5236b0c067 Don't create WebContents in NativeWindow 2015-06-25 09:47:57 +08:00
Cheng Zhao
081a4597e9 Pass isGuest when creating WebContents 2015-06-24 23:29:32 +08:00
Cheng Zhao
4b61683cdf Store NativeWindow in weak ptr 2015-06-24 22:29:44 +08:00
Cheng Zhao
19ca011735 Discard is_guest_, use type_ instead 2015-06-24 22:23:38 +08:00
Cheng Zhao
2bfa9da82e Store NativeWindow's weak ptr in WebContents 2015-06-24 22:14:46 +08:00
Cheng Zhao
2532318bee Add type for WebContents 2015-06-24 21:44:27 +08:00
Cheng Zhao
87f44c42df Handle close cancel in BeforeUnloadDialogCancelled 2015-06-24 21:28:36 +08:00
Cheng Zhao
b822a83bc2 Remove usages of NotificationObserver 2015-06-24 20:16:51 +08:00
Cheng Zhao
7d05a12ee9 Remove ActivateContents and DeactivateContents 2015-06-24 20:10:07 +08:00
Cheng Zhao
bd4d6dcda2 Merge pull request #2046 from atom/id-weak-map
Track native JS objects in C++
2015-06-24 20:01:42 +08:00
Cheng Zhao
9b9108f789 Remove JS override of setMenu 2015-06-24 19:51:11 +08:00
Cheng Zhao
f198148c79 Always initailize webContents in BrowserWindow 2015-06-24 19:04:08 +08:00
Cheng Zhao
8c83dfe918 Remove usages of JS IDWeakMap in browser-window 2015-06-24 19:01:44 +08:00
Cheng Zhao
f93d50c380 Merge pull request #2025 from atom/power-save-blocker-api
Power save blocker API
2015-06-24 18:53:10 +08:00
Cheng Zhao
cc8b22b5ff Make each class only have one weak map 2015-06-24 17:58:12 +08:00
Cheng Zhao
28d1fb8cad Add Values() method for IDWeakMap 2015-06-24 16:54:20 +08:00
Cheng Zhao
5e62b5975b Move "id" and "fromId" to C++ 2015-06-24 16:37:48 +08:00
Cheng Zhao
c2f14e6053 Initialize defaultSession after app is ready 2015-06-24 16:14:49 +08:00
Cheng Zhao
0ebd4d04ad Make Session trackable 2015-06-24 15:39:05 +08:00
Cheng Zhao
1023b67d59 Make sure each C++ WebContents has only one JS WebContents 2015-06-24 15:22:11 +08:00
Cheng Zhao
552a12d2ee Enable storing TrackableObject in other C++ class 2015-06-24 14:49:08 +08:00
Cheng Zhao
7f0658efa7 Add mate::TrackableObject 2015-06-24 14:36:05 +08:00
Cheng Zhao
15f350edcb Don't make IDWeakMap public API 2015-06-24 13:38:55 +08:00
Cheng Zhao
d02413de00 Make the JS IDWeakMap a thin wrapper of C++ IDWeakMap 2015-06-24 13:35:39 +08:00
Cheng Zhao
cd93b9412c Add C++ version of IDWeakMap 2015-06-24 13:22:09 +08:00
Haojian Wu
13784e6551 More updates: use string instead of integer to identify blocker type. 2015-06-24 13:06:39 +08:00
Cheng Zhao
b8cf9a2788 Merge pull request #2043 from atom/default-session
Add app.defaultSession
2015-06-24 12:25:06 +08:00
Cheng Zhao
09a6e37a09 Keep compatibility with app.resolveProxy 2015-06-24 12:01:19 +08:00
Cheng Zhao
ea69e91e49 Move resolveProxy From app to session 2015-06-24 11:59:11 +08:00
Cheng Zhao
ab6ed823d1 Merge pull request #2027 from deepak1556/devtools_file_save_patch
devtools: writing to filesystem in FILE thread
2015-06-24 10:45:22 +08:00
Cheng Zhao
33c2768a77 Add app.defaultSession 2015-06-23 23:40:41 +08:00
deepak1556
1f3a73e802 devtools: write to file in FILE thread 2015-06-23 20:58:56 +05:30
Cheng Zhao
4359eb4472 mac: Set NSHighResolutionCapable in Info.plist, close #2020 2015-06-23 23:02:49 +08:00
Cheng Zhao
3b762fddfb Merge pull request #2039 from atom/cleanup-web-contents-js
Some cleanup of WebContents and BrowserWindow code
2015-06-23 22:57:08 +08:00
Cheng Zhao
93fb70b62f Merge pull request #2030 from deepak1556/file_download_patch
browser: creating download manager delegate to handle downloads
2015-06-23 22:39:12 +08:00
Cheng Zhao
6d9ca4f52b Clean up coffee files 2015-06-23 22:11:59 +08:00
Cheng Zhao
77dbec305f Emit ATOM_BROWSER_RELEASE_RENDER_VIEW in C++ 2015-06-23 21:27:50 +08:00
deepak1556
8f429bc25a browser: creating download manager delegate to handle downloads 2015-06-23 17:54:07 +05:30
Cheng Zhao
42e21d15bf Remove all calls to node::MakeCallback
node::MakeCallback is doing too much for us, avoid calling it.
2015-06-23 20:14:03 +08:00
Cheng Zhao
78459b913b Add EmitEvent function to replace node::MakeCallback 2015-06-23 19:46:37 +08:00
Cheng Zhao
197a9b4165 Remove calls to v8::Isolate::GetCurrent
It is generally a bad thing to do since we might have multiple Isolates.
2015-06-23 17:22:14 +08:00
Cheng Zhao
1f97cee7c9 Fix release render view with wrong ID 2015-06-23 16:43:55 +08:00
Cheng Zhao
015ef3e014 Omit extra transfer of new-window event 2015-06-23 16:34:22 +08:00
Cheng Zhao
2d65c3bcd0 Clean up SetAllowTransparency 2015-06-23 16:19:12 +08:00
Cheng Zhao
52789ab96f Implement getId in C++ 2015-06-23 16:16:10 +08:00
Cheng Zhao
89c7028ed1 Don't include routing ID in WebContents's ID 2015-06-23 16:09:34 +08:00
Cheng Zhao
b3905e867e Bump v0.28.3 2015-06-23 14:22:17 +08:00
Cheng Zhao
aba517d4fd Merge pull request #2014 from atom/enable-zygote
Use zygote process on Linux
2015-06-23 13:34:40 +08:00
Cheng Zhao
4f6e70a75c Merge pull request #2034 from hongrich/internalModuleReadFile-asar-unpack
Update internalModuleReadFile to support unpacked asar files
2015-06-23 12:38:02 +08:00
Cheng Zhao
7b542b88f0 Merge pull request #2028 from preco21/master
Translate docs to korean (Re PR)
2015-06-23 11:12:23 +08:00
Cheng Zhao
3519dd96ee Merge pull request #2019 from atom/pdf-api-doc
Add usage sample code of printToPDF API.
2015-06-23 10:20:46 +08:00
Cheng Zhao
1ce86b6dfc win: Fix building, close #2018 2015-06-23 10:18:43 +08:00
Cheng Zhao
19963bfcd1 Merge pull request #1981 from atom/cookies-api
Implement Cookies api
2015-06-23 10:04:42 +08:00
Cheng Zhao
2fca10ac98 Merge pull request #2009 from deepak1556/webview_patch
override: set window.opener to null for webview
2015-06-23 10:03:40 +08:00
Rich Hong
f51103f44a Update internalModuleReadFile to support unpacked asar files
Add tests for reading unpacked files using both fs.readFileSync and
internalModuleReadFile
2015-06-22 19:38:47 -04:00
Kevin Sawicki
339496a361 Merge pull request #2024 from atom/dev-tools-doc
📝 Add missing BrowserWindow.isDevToolsOpened method.
2015-06-22 08:49:40 -07:00
Plusb Preco
30dfd54575 First translation
Translate docs to korean
2015-06-22 14:06:06 +09:00
Haojian Wu
532f75fcab Update PowerSaveBlocker APIs design. 2015-06-22 12:08:09 +08:00
Haojian Wu
7ee2a703d9 📝 Add powerSaveBlocker APIs doc. 2015-06-21 21:14:49 +08:00
Haojian Wu
7c5afdd388 Add PowerSaveBlocker APIs. 2015-06-21 21:14:14 +08:00
Haojian Wu
f73e1f9188 📝 Add missing BrowserWindow.isDevToolsOpened method. 2015-06-21 10:56:40 +08:00
Haojian Wu
d50db378d7 Add usage sample code of printToPDF API. 2015-06-20 15:18:21 +08:00
Haojian Wu
db23d1165c Update cookies spec. 2015-06-20 10:42:18 +08:00
Haojian Wu
bafbee805c Fix more code styles. 2015-06-20 10:41:40 +08:00
Cheng Zhao
ef59f4f243 Move headers to atom/common 2015-06-19 23:11:53 +08:00
Cheng Zhao
83fe340b98 Make process.argv work with zygote 2015-06-19 22:56:10 +08:00
Cheng Zhao
b4f90c8c81 Update libchromiumcontent to enable zygote process 2015-06-19 22:01:32 +08:00
Cheng Zhao
a1cbd11b5b Only append --register-standard-schemes when needed 2015-06-19 21:53:29 +08:00
Cheng Zhao
befdfceada Merge pull request #1998 from deepak1556/process_patch
process: add hang method
2015-06-19 16:21:29 +08:00
Cheng Zhao
49e1316f7f Merge pull request #1970 from deepak1556/scheme_patch
protocol: api to register custom schemes to standard schemes
2015-06-19 16:16:46 +08:00
Haojian Wu
c164da5a38 Make cookie aligns to Chrome's. 2015-06-19 14:18:22 +08:00
Haojian Wu
969916442f Use webContents BrowserContext.
Also fix some code styles.
2015-06-19 13:57:54 +08:00
Haojian Wu
99bfc9b7f5 Move cookies APIs to webContents.session.cookies namespace. 2015-06-19 10:30:08 +08:00
Haojian Wu
245dc01e33 Add cookies spec. 2015-06-19 10:29:18 +08:00
Haojian Wu
4818e76ad9 📝 add cookies doc. 2015-06-19 10:29:18 +08:00
Haojian Wu
98adcac5df Move set status code into error. 2015-06-19 10:29:17 +08:00
Haojian Wu
19e96cc212 Fix cpplint. 2015-06-19 10:29:17 +08:00
Haojian Wu
cfffe39151 Add cookies.set API. 2015-06-19 10:29:17 +08:00
Haojian Wu
0dfd00f664 Add cookies.remove API. 2015-06-19 10:29:17 +08:00
Haojian Wu
dbbc2f19f4 Implement cookies.get API. 2015-06-19 10:29:17 +08:00
deepak1556
cb1d9f60ec override: set window.opener to null for webview 2015-06-18 21:14:45 +05:30
Cheng Zhao
db2042f561 Merge pull request #2004 from atom/remove-global-browser-context
Remove global browser context
2015-06-18 18:25:42 +08:00
Cheng Zhao
91f3b3955a Remove AtomBrowserContext::Get 2015-06-18 17:19:29 +08:00
Cheng Zhao
923296b4ee Use the BrowserContext from protocol 2015-06-18 17:18:11 +08:00
Cheng Zhao
e209312459 Replace a few calls to AtomBrowserMainParts::Get.
These calls replies on global BrowserContext, we can just make them use
the future default BrowserContext.
2015-06-18 17:01:23 +08:00
Cheng Zhao
b47fae7393 Make api::Protocol per-context 2015-06-18 16:59:03 +08:00
deepak1556
8e05fe3350 process: add hang method 2015-06-18 14:14:29 +05:30
Cheng Zhao
e6341ceaaa Move BrowserProcess to BrowserMainParts 2015-06-18 16:34:02 +08:00
Cheng Zhao
0120be5b8c Don't rely on real focus/blur events in tests
It is super unreliable.
2015-06-18 16:31:55 +08:00
Cheng Zhao
19436358fb win: Fix setContentSize changing window position
Close #1934.
2015-06-18 16:17:13 +08:00
Cheng Zhao
2cb1aa6639 Merge pull request #1997 from deepak1556/api_app_patch
app: adding focus/blur events
2015-06-18 15:55:59 +08:00
deepak1556
2f36f5ca78 app: adding browser-window-focus/blur events 2015-06-18 11:29:08 +05:30
Cheng Zhao
25a7bcef82 Bump v0.28.2 2015-06-18 13:15:13 +08:00
Cheng Zhao
c8eaaaea83 mac: Use NSFileManager::resultingItemURL for moving file to trash
This allows the deleted file to be restored, fixes #2001.
2015-06-18 13:09:02 +08:00
Cheng Zhao
beb2853bbf Update how to rebrand from source, close #1999 2015-06-18 12:59:13 +08:00
Cheng Zhao
f76b60f295 Update brightray 2015-06-18 12:42:02 +08:00
deepak1556
663a48ee38 protocol: api to register custom schemes to standard schemes 2015-06-17 14:43:04 +05:30
Cheng Zhao
db8ffe1dc7 Handle ".." in asar path, fix #1982 2015-06-17 15:52:49 +08:00
Cheng Zhao
ad59393641 Update brightray, close #1025 2015-06-17 12:38:36 +08:00
Cheng Zhao
a751f4c689 Merge pull request #1835 from hokein/pdf-api
Add `BrowserWindow.printToPDF` API Implementation
2015-06-17 12:22:56 +08:00
Cheng Zhao
b3e9d35667 Merge pull request #1995 from atom/request-http-job
Implement protocol.RequestHttpJob
2015-06-17 12:00:26 +08:00
Cheng Zhao
c2aa7d538f Fix cpplint warnings 2015-06-17 11:34:47 +08:00
Cheng Zhao
1d41903779 docs: protocol.RequestHttpJob 2015-06-17 11:32:39 +08:00
Cheng Zhao
92f3371118 Use |request|'s headers if possible 2015-06-17 11:30:31 +08:00
Cheng Zhao
543c4d5597 Allow setting referrer 2015-06-17 11:22:02 +08:00
Cheng Zhao
e07f5cd53f Use |request|'s method if |method| is not specified 2015-06-17 11:11:13 +08:00
Cheng Zhao
66c4c7e77b Clear pending_buffer_ at correct time 2015-06-17 11:04:15 +08:00
Cheng Zhao
274854876c Allow setting method for RequestHttpJob 2015-06-17 10:57:26 +08:00
Cheng Zhao
81db8e098e Don't need buffer for piping data 2015-06-17 10:19:58 +08:00
Cheng Zhao
af05f26a5f Make URLRequestFetchJob actually work 2015-06-17 09:31:33 +08:00
Paul Betts
0b35d97821 Merge pull request #1994 from atom/paulcbetts-patch-1
Note that setPressedImage only has an effect on OS X
2015-06-16 18:18:14 -07:00
Paul Betts
8a56ab3947 Note that setPressedImage only has an effect on OS X 2015-06-16 18:17:51 -07:00
Haojian Wu
82b1607c1e 📝 Add missing printToPDF API in webview. 2015-06-16 20:17:58 +08:00
Haojian Wu
16348fc895 Copy pdf data on IO thread to avoid causing main process hangs. 2015-06-16 20:08:30 +08:00
Haojian Wu
1eba552a8d Also Expose printToPDF to BrowserWindow. 2015-06-16 20:08:30 +08:00
Haojian Wu
47eac062f6 Expose Print API to webContents and webView.
Also move the print implementation from window to webContents.
2015-06-16 20:08:30 +08:00
Haojian Wu
57580e00f9 Fix code style. 2015-06-16 20:07:45 +08:00
Haojian Wu
93bbc6c810 Simplify the pdf-data handled code. 2015-06-16 20:07:45 +08:00
Haojian Wu
894f9c0cb0 Don't use duprecated node buffer api, fix build error on OS X. 2015-06-16 20:07:44 +08:00
Haojian Wu
f22662ffb2 📝 Update docs. 2015-06-16 20:07:44 +08:00
Haojian Wu
559eb20e7f Fixing type: printBackgrounds => printBackground 2015-06-16 20:07:44 +08:00
Haojian Wu
ccbe554ec0 Make callback aligns node.js style. 2015-06-16 20:07:44 +08:00
Haojian Wu
93243ef223 Remove some unused IPC messages. 2015-06-16 20:07:44 +08:00
Haojian Wu
47439cd77c Fix a type error. 2015-06-16 20:07:44 +08:00
Haojian Wu
ac62871645 Return node::Buffer as a printToPDF callback result. 2015-06-16 20:07:44 +08:00
Haojian Wu
ab40da3f31 Add silent and savePath options. 2015-06-16 20:07:43 +08:00
Haojian Wu
6e099af5fe Move PDF printing setting in JS part. 2015-06-16 20:07:43 +08:00
Haojian Wu
c0a6cb69bf Move printToPDF API to WebContents.
Also expose in webview.
2015-06-16 20:06:52 +08:00
Haojian Wu
2597ded985 Cleanup. 2015-06-16 20:02:25 +08:00
Haojian Wu
10da361db1 Fix a type error in checking function options. 2015-06-16 20:02:25 +08:00
Haojian Wu
36fa4da252 Fix Linux compilation error. 2015-06-16 20:02:25 +08:00
Haojian Wu
68005f9ad4 Fix OS X compilation error. 2015-06-16 20:02:25 +08:00
Haojian Wu
bf5d448e37 📝 Add BrowserWindow.printToPDF API docs. 2015-06-16 20:02:24 +08:00
Haojian Wu
600077996c Fix a landscape option error. 2015-06-16 20:02:24 +08:00
Haojian Wu
cef177abc4 Add preview failed error. 2015-06-16 20:02:24 +08:00
Haojian Wu
8572ccb807 Add callback function in printToPDF API. 2015-06-16 20:02:24 +08:00
Haojian Wu
ce8bbb689c Add options to custom print settings in printToPDF API. 2015-06-16 20:02:24 +08:00
Haojian Wu
9cf9229308 Write PDF file in FILE thread. 2015-06-16 20:02:23 +08:00
Haojian Wu
7ffa7042b1 Add printToPDF Implementation. 2015-06-16 20:02:23 +08:00
Haojian Wu
b360f7d86a Add printToPDF API skeleton. 2015-06-16 20:02:23 +08:00
Cheng Zhao
44f8bfc550 Don't leak URLFetcher 2015-06-16 17:09:25 +08:00
Cheng Zhao
bd704dd8aa Merge pull request #1979 from deepak1556/remote_args_patch
remote: handle circular reference in wrapArgs
2015-06-16 16:40:06 +08:00
Cheng Zhao
7b3fc14023 docs: --ignore-connections-limit 2015-06-16 16:13:46 +08:00
deepak1556
193f95a888 remote: handle circular reference in wrapArgs 2015-06-16 13:43:30 +05:30
Cheng Zhao
b03f44df10 Update brightray for #1960 2015-06-16 16:04:03 +08:00
Cheng Zhao
bf9af4d45b Merge pull request #1980 from magicae/set-audio-mute
webContents: add setAudioMuted to webContents
2015-06-16 14:46:31 +08:00
Cheng Zhao
8181e9a0ef Update brightray for #1941 2015-06-16 13:38:21 +08:00
Cheng Zhao
d9db657b43 Merge pull request #1967 from j13z/patch-1
Add minor grammar fixes
2015-06-16 10:30:06 +08:00
Cheng Zhao
e96119fc32 s/liste/listen 2015-06-16 10:08:32 +08:00
Magica
8aa559fe51 Add setAudioMuted to webContents 2015-06-15 21:40:49 +08:00
deepak1556
a5e2f8e79e protocol: adding requestHttpJob method 2015-06-15 03:20:45 +05:30
Johannes Schmitz
2b3a80ecda Add minor grammar fixes 2015-06-13 16:58:18 +02:00
Benjamin Pasero
7da3e84369 Update app.md to document how open-file is emitted
On Mac, open-file is also emitted when the application is not yet running.
2015-06-12 12:37:53 +02:00
Cheng Zhao
8b8a6aea74 Bump v0.28.1 2015-06-12 16:26:51 +08:00
Cheng Zhao
16e224bb86 Don't set browser_handles_all_top_level_requests
POST requests currently can not be handled on browser side.

Fix #1945.
2015-06-12 16:26:04 +08:00
Cheng Zhao
459d389e03 Merge pull request #1951 from sotayamashita/translate/quick-start-jp.md
Translate quick-start.md into Japanese.
2015-06-12 15:49:21 +08:00
Cheng Zhao
8e4581a3c0 Merge pull request #1932 from samueleaton/master
adds example for "before using methods"
2015-06-12 15:07:17 +08:00
Cheng Zhao
c97c3fb9a1 Use LSGetApplicationForURL to search for app
It costs less.
2015-06-12 13:54:42 +08:00
Cheng Zhao
7ce8156691 Merge branch 'master' of https://github.com/mattotodd/electron into mattotodd-master 2015-06-12 13:49:51 +08:00
Sota Yamashita
0e6a70c556 Tranlsate quick-start-jp.md: status first
Translate: quick-start-jp.md

Fix bug

Tranlsate the world web

Change the method

Translate tutorial/quick-start-jp.md

Translate docs

Translate

Translate quick-start
2015-06-12 14:44:47 +09:00
Sam Eaton
b68d559329 Merge branch 'master' of https://github.com/atom/electron 2015-06-11 07:13:45 -06:00
eaton11
d367af3fa4 Merge branch 'master' of https://github.com/atom/electron 2015-06-10 19:28:14 -06:00
Sam Eaton
549ec51bce adds 'before using methods' example
The document does not inform that the webview element has to be loaded
before using the element's methods. It is not clear.
2015-06-10 19:24:36 -06:00
msullivan
b4674923c9 return bool on shell.openExternal 2015-06-10 11:06:22 -04:00
162 changed files with 7543 additions and 1316 deletions

4
.gitignore vendored
View File

@@ -4,8 +4,12 @@
/external_binaries/
/out/
/vendor/brightray/vendor/download/
/vendor/debian_wheezy_arm-sysroot/
/vendor/debian_wheezy_i386-sysroot/
/vendor/python_26/
/vendor/npm/
/vendor/llvm/
/vendor/llvm-build/
/vendor/.gclient
node_modules/
*.xcodeproj

3
.gitmodules vendored
View File

@@ -16,3 +16,6 @@
[submodule "vendor/crashpad"]
path = vendor/crashpad
url = https://github.com/atom/crashpad.git
[submodule "vendor/requests"]
path = vendor/requests
url = https://github.com/kennethreitz/requests

View File

@@ -1,15 +1,21 @@
git:
depth: 10
notifications:
email: false
language: cpp
compiler: clang
os:
- linux
- osx
env:
- TARGET_ARCH=x64
notifications:
email:
on_success: never
on_failure: change
matrix:
include:
- os: linux
env: TARGET_ARCH=arm
- os: linux
env: TARGET_ARCH=ia32
script: './script/cibuild'
git:
depth: 10

43
README-ko.md Normal file
View File

@@ -0,0 +1,43 @@
[![Electron Logo](http://electron.atom.io/images/electron-logo.svg)](http://electron.atom.io/)
[![Build Status](https://travis-ci.org/atom/electron.svg?branch=master)](https://travis-ci.org/atom/electron)
[![devDependency Status](https://david-dm.org/atom/electron/dev-status.svg)](https://david-dm.org/atom/electron#info=devDependencies)
### [Electron](https://github.com/atom/electron/) 한국어 참조문서
:zap: *이전까지 Atom Shell로 알려져 있었습니다* :zap:
Electron은 JavaScript, HTML 그리고 CSS를 이용하여 Cross-Platform 데스크톱 어플리케이션을 개발할 수 있도록 해주는 프레임워크입니다. 이 프레임워크는 [io.js](http://iojs.org) 와
[Chromium](http://www.chromium.org) 을 기반으로 만들어 졌으며 [Atom Editor](https://github.com/atom/atom) 에 사용되고 있습니다.
Electron에 대한 중요한 알림을 받으려면 Twitter에서 [@ElectronJS](https://twitter.com/electronjs)를 Follow하세요.
## 다운로드
Linux, Windows, Mac용으로 미리 빌드된 Electron 바이너리와 디버그 심볼이 준비되어 있습니다. [releases](https://github.com/atom/electron/releases) 페이지에서 받아 볼 수 있습니다.
또한 [`npm`](https://docs.npmjs.com/)을 이용하여 미리 빌드된 Electron 바이너리를 받을 수 있습니다:
```sh
# $PATH에 `electron`을 등록하고 전역에 설치합니다.
npm install electron-prebuilt -g
# 개발용 dependency로 설치합니다.
npm install electron-prebuilt --save-dev
```
### 미러
- [China](https://npm.taobao.org/mirrors/electron)
## 참조문서
[docs](https://github.com/preco21/electron/tree/master/docs) 에 프레임워크 사용 가이드와 API 레퍼런스가 있습니다.
또한, Electron을 빌드 하는 방법과 프로젝트에 기여하는 방법 문서에 포함되어 있으니 참고바랍니다.
## 커뮤니티
[Atom 포럼내의 `electron` 카테고리](http://discuss.atom.io/category/electron) 와 Freenode `#atom-shell` 채팅채널이 있습니다.
[awesome-electron](https://github.com/sindresorhus/awesome-electron) 에 커뮤니티가 운영중인 유용한 예제 앱과 툴, 리소스가 있으니 한번 탐색해 보시기 바랍니다.

View File

@@ -2,6 +2,7 @@
[![Build Status](https://travis-ci.org/atom/electron.svg?branch=master)](https://travis-ci.org/atom/electron)
[![devDependency Status](https://david-dm.org/atom/electron/dev-status.svg)](https://david-dm.org/atom/electron#info=devDependencies)
[![Join the Electron Community on Slack](http://atom-slack.herokuapp.com/badge.svg)](http://atom-slack.herokuapp.com/)
:zap: *formerly known as Atom Shell* :zap:

View File

@@ -4,9 +4,7 @@
'product_name%': 'Electron',
'company_name%': 'GitHub, Inc',
'company_abbr%': 'github',
'version%': '0.28.0',
'atom_source_root': '<!(["python", "tools/atom_source_root.py"])',
'version%': '0.29.0',
},
'includes': [
'filenames.gypi',
@@ -17,8 +15,12 @@
'ATOM_PRODUCT_NAME="<(product_name)"',
'ATOM_PROJECT_NAME="<(project_name)"',
],
'mac_framework_dirs': [
'<(atom_source_root)/external_binaries',
'conditions': [
['OS=="mac"', {
'mac_framework_dirs': [
'<(source_root)/external_binaries',
],
}],
],
},
'targets': [
@@ -45,7 +47,6 @@
'dependencies': [
'<(project_name)_framework',
'<(project_name)_helper',
'vendor/breakpad/breakpad.gyp:dump_syms',
],
'xcode_settings': {
'ATOM_BUNDLE_ID': 'com.<(company_abbr).<(project_name)',
@@ -157,6 +158,10 @@
]
},
],
}, {
'dependencies': [
'vendor/breakpad/breakpad.gyp:dump_syms#host',
],
}], # OS=="win"
['OS=="linux"', {
'copies': [

View File

@@ -75,6 +75,16 @@ std::string AtomContentClient::GetProduct() const {
void AtomContentClient::AddAdditionalSchemes(
std::vector<std::string>* standard_schemes,
std::vector<std::string>* savable_schemes) {
auto command_line = base::CommandLine::ForCurrentProcess();
auto custom_schemes = command_line->GetSwitchValueASCII(
switches::kRegisterStandardSchemes);
if (!custom_schemes.empty()) {
std::vector<std::string> schemes;
base::SplitString(custom_schemes, ',', &schemes);
standard_schemes->insert(standard_schemes->end(),
schemes.begin(),
schemes.end());
}
standard_schemes->push_back("chrome-extension");
}

View File

@@ -4,9 +4,9 @@
#include "atom/app/atom_library_main.h"
#include "atom/app/atom_main_args.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"

View File

@@ -3,7 +3,6 @@
// found in the LICENSE file.
#include "atom/app/atom_main.h"
#include "atom/app/atom_main_args.h"
#include <stdlib.h>
#include <string.h>
@@ -33,6 +32,7 @@
#endif // defined(OS_MACOSX)
#include "atom/app/node_main.h"
#include "atom/common/atom_command_line.h"
#include "base/i18n/icu_util.h"
#if defined(OS_WIN)

View File

@@ -12,22 +12,23 @@
#endif
#include "atom/browser/api/atom_api_menu.h"
#include "atom/browser/api/atom_api_session.h"
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/browser/browser.h"
#include "atom/browser/api/atom_api_web_contents.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "atom/common/native_mate_converters/gurl_converter.h"
#include "base/command_line.h"
#include "base/environment.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "brightray/browser/brightray_paths.h"
#include "content/public/browser/client_certificate_delegate.h"
#include "content/public/browser/gpu_data_manager.h"
#include "native_mate/callback.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "net/base/load_flags.h"
#include "net/proxy/proxy_service.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "net/ssl/ssl_cert_request_info.h"
#if defined(OS_WIN)
#include "base/strings/utf_string_conversions.h"
@@ -60,6 +61,21 @@ struct Converter<Browser::UserTask> {
};
#endif
template<>
struct Converter<scoped_refptr<net::X509Certificate>> {
static v8::Local<v8::Value> ToV8(
v8::Isolate* isolate,
const scoped_refptr<net::X509Certificate>& val) {
mate::Dictionary dict(isolate, v8::Object::New(isolate));
std::string encoded_data;
net::X509Certificate::GetPEMEncoded(
val->os_cert_handle(), &encoded_data);
dict.Set("data", encoded_data);
dict.Set("issuerName", val->issuer().GetDisplayName());
return dict.GetHandle();
}
};
} // namespace mate
@@ -93,50 +109,39 @@ int GetPathConstant(const std::string& name) {
return -1;
}
class ResolveProxyHelper {
public:
ResolveProxyHelper(const GURL& url, App::ResolveProxyCallback callback)
: callback_(callback) {
net::ProxyService* proxy_service = AtomBrowserContext::Get()->
url_request_context_getter()->GetURLRequestContext()->proxy_service();
// Start the request.
int result = proxy_service->ResolveProxy(
url, net::LOAD_NORMAL, &proxy_info_,
base::Bind(&ResolveProxyHelper::OnResolveProxyCompleted,
base::Unretained(this)),
&pac_req_, nullptr, net::BoundNetLog());
// Completed synchronously.
if (result != net::ERR_IO_PENDING)
OnResolveProxyCompleted(result);
void OnClientCertificateSelected(
v8::Isolate* isolate,
std::shared_ptr<content::ClientCertificateDelegate> delegate,
mate::Arguments* args) {
v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
mate::Dictionary cert_data;
if (!(args->Length() == 1 && args->GetNext(&cert_data))) {
args->ThrowError();
return;
}
void OnResolveProxyCompleted(int result) {
std::string proxy;
if (result == net::OK)
proxy = proxy_info_.ToPacString();
callback_.Run(proxy);
std::string encoded_data;
cert_data.Get("data", &encoded_data);
delete this;
}
auto certs =
net::X509Certificate::CreateCertificateListFromBytes(
encoded_data.data(), encoded_data.size(),
net::X509Certificate::FORMAT_AUTO);
private:
App::ResolveProxyCallback callback_;
net::ProxyInfo proxy_info_;
net::ProxyService::PacRequest* pac_req_;
DISALLOW_COPY_AND_ASSIGN(ResolveProxyHelper);
};
delegate->ContinueWithCertificate(certs[0].get());
}
} // namespace
App::App() {
Browser::Get()->AddObserver(this);
content::GpuDataManager::GetInstance()->AddObserver(this);
}
App::~App() {
Browser::Get()->RemoveObserver(this);
content::GpuDataManager::GetInstance()->RemoveObserver(this);
}
void App::OnBeforeQuit(bool* prevent_default) {
@@ -172,9 +177,42 @@ void App::OnWillFinishLaunching() {
}
void App::OnFinishLaunching() {
// Create the defaultSession.
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
auto browser_context = static_cast<AtomBrowserContext*>(
AtomBrowserMainParts::Get()->browser_context());
auto handle = Session::CreateFrom(isolate(), browser_context);
default_session_.Reset(isolate(), handle.ToV8());
Emit("ready");
}
void App::OnSelectCertificate(
content::WebContents* web_contents,
net::SSLCertRequestInfo* cert_request_info,
scoped_ptr<content::ClientCertificateDelegate> delegate) {
std::shared_ptr<content::ClientCertificateDelegate>
shared_delegate(delegate.release());
bool prevent_default =
Emit("select-certificate",
api::WebContents::CreateFrom(isolate(), web_contents),
cert_request_info->host_and_port.ToString(),
cert_request_info->client_certs,
base::Bind(&OnClientCertificateSelected,
isolate(),
shared_delegate));
// Default to first certificate from the platform store.
if (!prevent_default)
shared_delegate->ContinueWithCertificate(
cert_request_info->client_certs[0].get());
}
void App::OnGpuProcessCrashed(base::TerminationStatus exit_code) {
Emit("gpu-process-crashed");
}
base::FilePath App::GetPath(mate::Arguments* args, const std::string& name) {
bool succeed = false;
base::FilePath path;
@@ -197,10 +235,6 @@ void App::SetPath(mate::Arguments* args,
args->ThrowError("Failed to set path");
}
void App::ResolveProxy(const GURL& url, ResolveProxyCallback callback) {
new ResolveProxyHelper(url, callback);
}
void App::SetDesktopName(const std::string& desktop_name) {
#if defined(OS_LINUX)
scoped_ptr<base::Environment> env(base::Environment::Create());
@@ -215,6 +249,13 @@ void App::SetAppUserModelId(const std::string& app_id) {
#endif
}
v8::Local<v8::Value> App::DefaultSession(v8::Isolate* isolate) {
if (default_session_.IsEmpty())
return v8::Null(isolate);
else
return v8::Local<v8::Value>::New(isolate, default_session_);
}
mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
auto browser = base::Unretained(Browser::Get());
@@ -236,9 +277,9 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder(
#endif
.SetMethod("setPath", &App::SetPath)
.SetMethod("getPath", &App::GetPath)
.SetMethod("resolveProxy", &App::ResolveProxy)
.SetMethod("setDesktopName", &App::SetDesktopName)
.SetMethod("setAppUserModelId", &App::SetAppUserModelId);
.SetMethod("setAppUserModelId", &App::SetAppUserModelId)
.SetProperty("defaultSession", &App::DefaultSession);
}
// static

View File

@@ -9,11 +9,9 @@
#include "atom/browser/api/event_emitter.h"
#include "atom/browser/browser_observer.h"
#include "base/callback.h"
#include "content/public/browser/gpu_data_manager_observer.h"
#include "native_mate/handle.h"
class GURL;
namespace base {
class FilePath;
}
@@ -27,10 +25,9 @@ namespace atom {
namespace api {
class App : public mate::EventEmitter,
public BrowserObserver {
public BrowserObserver,
public content::GpuDataManagerObserver {
public:
typedef base::Callback<void(std::string)> ResolveProxyCallback;
static mate::Handle<App> Create(v8::Isolate* isolate);
protected:
@@ -47,6 +44,13 @@ class App : public mate::EventEmitter,
void OnActivateWithNoOpenWindows() override;
void OnWillFinishLaunching() override;
void OnFinishLaunching() override;
void OnSelectCertificate(
content::WebContents* web_contents,
net::SSLCertRequestInfo* cert_request_info,
scoped_ptr<content::ClientCertificateDelegate> delegate) override;
// content::GpuDataManagerObserver:
void OnGpuProcessCrashed(base::TerminationStatus exit_code) override;
// mate::Wrappable:
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
@@ -59,9 +63,11 @@ class App : public mate::EventEmitter,
const std::string& name,
const base::FilePath& path);
void ResolveProxy(const GURL& url, ResolveProxyCallback callback);
void SetDesktopName(const std::string& desktop_name);
void SetAppUserModelId(const std::string& app_id);
v8::Local<v8::Value> DefaultSession(v8::Isolate* isolate);
v8::Global<v8::Value> default_session_;
DISALLOW_COPY_AND_ASSIGN(App);
};

View File

@@ -0,0 +1,349 @@
// 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/common/native_mate_converters/gurl_converter.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "base/bind.h"
#include "base/time/time.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "native_mate/callback.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"
#include "atom/common/node_includes.h"
using atom::api::Cookies;
using content::BrowserThread;
namespace {
bool GetCookieListFromStore(
net::CookieStore* cookie_store,
const std::string& url,
const net::CookieMonster::GetCookieListCallback& callback) {
DCHECK(cookie_store);
GURL gurl(url);
net::CookieMonster* monster = cookie_store->GetCookieMonster();
// Empty url will match all url cookies.
if (url.empty()) {
monster->GetAllCookiesAsync(callback);
return true;
}
if (!gurl.is_valid())
return false;
monster->GetAllCookiesForURLAsync(gurl, callback);
return true;
}
void RunGetCookiesCallbackOnUIThread(v8::Isolate* isolate,
const std::string& error_message,
const net::CookieList& cookie_list,
const Cookies::CookiesCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
if (!error_message.empty()) {
v8::Local<v8::Value> error = mate::ConvertToV8(isolate, error_message);
callback.Run(error, v8::Null(isolate));
return;
}
callback.Run(v8::Null(isolate), mate::ConvertToV8(isolate, cookie_list));
}
void RunRemoveCookiesCallbackOnUIThread(
v8::Isolate* isolate,
const std::string& error_message,
const Cookies::CookiesCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
if (!error_message.empty()) {
v8::Local<v8::Value> error = mate::ConvertToV8(isolate, error_message);
callback.Run(error, v8::Null(isolate));
return;
}
callback.Run(v8::Null(isolate), v8::Null(isolate));
}
void RunSetCookiesCallbackOnUIThread(v8::Isolate* isolate,
const std::string& error_message,
bool set_success,
const Cookies::CookiesCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
if (!error_message.empty()) {
v8::Local<v8::Value> error = mate::ConvertToV8(isolate, error_message);
callback.Run(error, v8::Null(isolate));
return;
}
if (!set_success) {
v8::Local<v8::Value> error = mate::ConvertToV8(
isolate, "Failed to set cookies");
callback.Run(error, v8::Null(isolate));
}
callback.Run(v8::Null(isolate), v8::Null(isolate));
}
bool MatchesDomain(const base::DictionaryValue* filter,
const std::string& cookie_domain) {
std::string filter_domain;
if (!filter->GetString("domain", &filter_domain))
return true;
// Add a leading '.' character to the filter domain if it doesn't exist.
if (net::cookie_util::DomainIsHostOnly(filter_domain))
filter_domain.insert(0, ".");
std::string sub_domain(cookie_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_domain.length();) {
if (sub_domain == filter_domain) {
return true;
}
const size_t next_dot = sub_domain.find('.', 1); // Skip over leading dot.
sub_domain.erase(0, next_dot);
}
return false;
}
bool MatchesCookie(const base::DictionaryValue* filter,
const net::CanonicalCookie& cookie) {
std::string name, domain, path;
bool is_secure, session;
if (filter->GetString("name", &name) && name != cookie.Name())
return false;
if (filter->GetString("path", &path) && path != cookie.Path())
return false;
if (!MatchesDomain(filter, cookie.Domain()))
return false;
if (filter->GetBoolean("secure", &is_secure) &&
is_secure != cookie.IsSecure())
return false;
if (filter->GetBoolean("session", &session) &&
session != cookie.IsPersistent())
return false;
return true;
}
} // namespace
namespace mate {
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("host_only", net::cookie_util::DomainIsHostOnly(val.Domain()));
dict.Set("path", val.Path());
dict.Set("secure", val.IsSecure());
dict.Set("http_only", val.IsHttpOnly());
dict.Set("session", val.IsPersistent());
if (!val.IsPersistent())
dict.Set("expirationDate", val.ExpiryDate().ToDoubleT());
return dict.GetHandle();
}
};
} // namespace mate
namespace atom {
namespace api {
Cookies::Cookies(content::BrowserContext* browser_context) :
browser_context_(browser_context) {
}
Cookies::~Cookies() {
}
void Cookies::Get(const base::DictionaryValue& options,
const CookiesCallback& callback) {
scoped_ptr<base::DictionaryValue> filter(
options.DeepCopyWithoutEmptyChildren());
content::BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(&Cookies::GetCookiesOnIOThread, base::Unretained(this),
Passed(&filter), callback));
}
void Cookies::GetCookiesOnIOThread(scoped_ptr<base::DictionaryValue> filter,
const CookiesCallback& callback) {
net::CookieStore* cookie_store = browser_context_->GetRequestContext()
->GetURLRequestContext()->cookie_store();
std::string url;
filter->GetString("url", &url);
if (!GetCookieListFromStore(cookie_store, url,
base::Bind(&Cookies::OnGetCookies, base::Unretained(this),
Passed(&filter), callback))) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&RunGetCookiesCallbackOnUIThread, isolate(),
"Url is not valid", net::CookieList(), callback));
}
}
void Cookies::OnGetCookies(scoped_ptr<base::DictionaryValue> filter,
const CookiesCallback& callback,
const net::CookieList& cookie_list) {
net::CookieList result;
for (const auto& cookie : cookie_list) {
if (MatchesCookie(filter.get(), cookie))
result.push_back(cookie);
}
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
&RunGetCookiesCallbackOnUIThread, isolate(), "", result, callback));
}
void Cookies::Remove(const mate::Dictionary& details,
const CookiesCallback& callback) {
GURL url;
std::string name;
std::string error_message;
if (!details.Get("url", &url) || !details.Get("name", &name)) {
error_message = "Details(url, name) of removing cookie are required.";
}
if (error_message.empty() && !url.is_valid()) {
error_message = "Url is not valid.";
}
if (!error_message.empty()) {
RunRemoveCookiesCallbackOnUIThread(isolate(), error_message, callback);
return;
}
content::BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(&Cookies::RemoveCookiesOnIOThread, base::Unretained(this),
url, name, callback));
}
void Cookies::RemoveCookiesOnIOThread(const GURL& url, const std::string& name,
const CookiesCallback& callback) {
net::CookieStore* cookie_store = browser_context_->GetRequestContext()
->GetURLRequestContext()->cookie_store();
cookie_store->DeleteCookieAsync(url, name,
base::Bind(&Cookies::OnRemoveCookies, base::Unretained(this), callback));
}
void Cookies::OnRemoveCookies(const CookiesCallback& callback) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&RunRemoveCookiesCallbackOnUIThread, isolate(), "", callback));
}
void Cookies::Set(const base::DictionaryValue& options,
const CookiesCallback& callback) {
std::string url;
std::string error_message;
if (!options.GetString("url", &url)) {
error_message = "The url field is required.";
}
GURL gurl(url);
if (error_message.empty() && !gurl.is_valid()) {
error_message = "Url is not valid.";
}
if (!error_message.empty()) {
RunSetCookiesCallbackOnUIThread(isolate(), error_message, false, callback);
return;
}
scoped_ptr<base::DictionaryValue> details(
options.DeepCopyWithoutEmptyChildren());
content::BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(&Cookies::SetCookiesOnIOThread, base::Unretained(this),
Passed(&details), gurl, callback));
}
void Cookies::SetCookiesOnIOThread(scoped_ptr<base::DictionaryValue> details,
const GURL& url,
const CookiesCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
net::CookieStore* cookie_store = browser_context_->GetRequestContext()
->GetURLRequestContext()->cookie_store();
std::string name, value, domain, path;
bool secure = false;
bool http_only = false;
double expiration_date;
details->GetString("name", &name);
details->GetString("value", &value);
details->GetString("domain", &domain);
details->GetString("path", &path);
details->GetBoolean("secure", &secure);
details->GetBoolean("http_only", &http_only);
base::Time expiration_time;
if (details->GetDouble("expirationDate", &expiration_date)) {
expiration_time = (expiration_date == 0) ?
base::Time::UnixEpoch() :
base::Time::FromDoubleT(expiration_date);
}
cookie_store->GetCookieMonster()->SetCookieWithDetailsAsync(
url,
name,
value,
domain,
path,
expiration_time,
secure,
http_only,
false,
net::COOKIE_PRIORITY_DEFAULT,
base::Bind(&Cookies::OnSetCookies, base::Unretained(this), callback));
}
void Cookies::OnSetCookies(const CookiesCallback& callback,
bool set_success) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&RunSetCookiesCallbackOnUIThread, isolate(), "", set_success,
callback));
}
mate::ObjectTemplateBuilder Cookies::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
return mate::ObjectTemplateBuilder(isolate)
.SetMethod("get", &Cookies::Get)
.SetMethod("remove", &Cookies::Remove)
.SetMethod("set", &Cookies::Set);
}
// static
mate::Handle<Cookies> Cookies::Create(
v8::Isolate* isolate,
content::BrowserContext* browser_context) {
return mate::CreateHandle(isolate, new Cookies(browser_context));
}
} // namespace api
} // namespace atom

View File

@@ -0,0 +1,78 @@
// 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 "base/callback.h"
#include "base/values.h"
#include "native_mate/wrappable.h"
#include "native_mate/handle.h"
#include "native_mate/dictionary.h"
#include "net/cookies/canonical_cookie.h"
namespace content {
class BrowserContext;
}
namespace atom {
namespace api {
class Cookies : public mate::Wrappable {
public:
// node.js style callback function(error, result)
typedef base::Callback<void(v8::Local<v8::Value>, v8::Local<v8::Value>)>
CookiesCallback;
static mate::Handle<Cookies> Create(v8::Isolate* isolate,
content::BrowserContext* browser_context);
protected:
explicit Cookies(content::BrowserContext* browser_context);
~Cookies();
void Get(const base::DictionaryValue& options,
const CookiesCallback& callback);
void Remove(const mate::Dictionary& details,
const CookiesCallback& callback);
void Set(const base::DictionaryValue& details,
const CookiesCallback& callback);
void GetCookiesOnIOThread(scoped_ptr<base::DictionaryValue> filter,
const CookiesCallback& callback);
void OnGetCookies(scoped_ptr<base::DictionaryValue> filter,
const CookiesCallback& callback,
const net::CookieList& cookie_list);
void RemoveCookiesOnIOThread(const GURL& url,
const std::string& name,
const CookiesCallback& callback);
void OnRemoveCookies(const CookiesCallback& callback);
void SetCookiesOnIOThread(scoped_ptr<base::DictionaryValue> details,
const GURL& url,
const CookiesCallback& callback);
void OnSetCookies(const CookiesCallback& callback,
bool set_success);
// mate::Wrappable implementations:
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override;
private:
content::BrowserContext* browser_context_;
DISALLOW_COPY_AND_ASSIGN(Cookies);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_COOKIES_H_

View File

@@ -55,11 +55,10 @@ bool Menu::IsCommandIdVisible(int command_id) const {
bool Menu::GetAcceleratorForCommandId(int command_id,
ui::Accelerator* accelerator) {
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
v8::Local<v8::Value> val = get_accelerator_.Run(command_id);
return mate::ConvertFromV8(isolate, val, accelerator);
return mate::ConvertFromV8(isolate(), val, accelerator);
}
void Menu::ExecuteCommand(int command_id, int event_flags) {

View File

@@ -22,7 +22,7 @@ void MenuMac::Popup(Window* window) {
NativeWindow* native_window = window->window();
if (!native_window)
return;
content::WebContents* web_contents = native_window->GetWebContents();
content::WebContents* web_contents = native_window->web_contents();
if (!web_contents)
return;
@@ -54,7 +54,7 @@ void MenuMac::PopupAt(Window* window, int x, int y) {
NativeWindow* native_window = window->window();
if (!native_window)
return;
content::WebContents* web_contents = native_window->GetWebContents();
content::WebContents* web_contents = native_window->web_contents();
if (!web_contents)
return;

View File

@@ -24,7 +24,7 @@ void MenuViews::PopupAt(Window* window, int x, int y) {
NativeWindow* native_window = static_cast<NativeWindow*>(window->window());
if (!native_window)
return;
content::WebContents* web_contents = native_window->GetWebContents();
content::WebContents* web_contents = native_window->web_contents();
if (!web_contents)
return;
content::RenderWidgetHostView* view = web_contents->GetRenderWidgetHostView();

View File

@@ -0,0 +1,128 @@
// 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_power_save_blocker.h"
#include <string>
#include "content/public/browser/power_save_blocker.h"
#include "native_mate/dictionary.h"
#include "atom/common/node_includes.h"
namespace mate {
template<>
struct Converter<content::PowerSaveBlocker::PowerSaveBlockerType> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
content::PowerSaveBlocker::PowerSaveBlockerType* out) {
using content::PowerSaveBlocker;
std::string type;
if (!ConvertFromV8(isolate, val, &type))
return false;
if (type == "prevent-app-suspension")
*out = PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension;
else if (type == "prevent-display-sleep")
*out = PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep;
else
return false;
return true;
}
};
} // namespace mate
namespace atom {
namespace api {
PowerSaveBlocker::PowerSaveBlocker()
: current_blocker_type_(
content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension) {
}
PowerSaveBlocker::~PowerSaveBlocker() {
}
void PowerSaveBlocker::UpdatePowerSaveBlocker() {
if (power_save_blocker_types_.empty()) {
power_save_blocker_.reset();
return;
}
// |kPowerSaveBlockPreventAppSuspension| keeps system active, but allows
// screen to be turned off.
// |kPowerSaveBlockPreventDisplaySleep| keeps system and screen active, has a
// higher precedence level than |kPowerSaveBlockPreventAppSuspension|.
//
// Only the highest-precedence blocker type takes effect.
content::PowerSaveBlocker::PowerSaveBlockerType new_blocker_type =
content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension;
for (const auto& element : power_save_blocker_types_) {
if (element.second ==
content::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep) {
new_blocker_type =
content::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep;
break;
}
}
if (!power_save_blocker_ || new_blocker_type != current_blocker_type_) {
scoped_ptr<content::PowerSaveBlocker> new_blocker =
content::PowerSaveBlocker::Create(
new_blocker_type,
content::PowerSaveBlocker::kReasonOther,
ATOM_PRODUCT_NAME);
power_save_blocker_.swap(new_blocker);
current_blocker_type_ = new_blocker_type;
}
}
int PowerSaveBlocker::Start(
content::PowerSaveBlocker::PowerSaveBlockerType type) {
static int count = 0;
power_save_blocker_types_[count] = type;
UpdatePowerSaveBlocker();
return count++;
}
bool PowerSaveBlocker::Stop(int id) {
bool success = power_save_blocker_types_.erase(id) > 0;
UpdatePowerSaveBlocker();
return success;
}
bool PowerSaveBlocker::IsStarted(int id) {
return power_save_blocker_types_.find(id) != power_save_blocker_types_.end();
}
mate::ObjectTemplateBuilder PowerSaveBlocker::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
return mate::ObjectTemplateBuilder(isolate)
.SetMethod("start", &PowerSaveBlocker::Start)
.SetMethod("stop", &PowerSaveBlocker::Stop)
.SetMethod("isStarted", &PowerSaveBlocker::IsStarted);
}
// static
mate::Handle<PowerSaveBlocker> PowerSaveBlocker::Create(v8::Isolate* isolate) {
return CreateHandle(isolate, new PowerSaveBlocker);
}
} // 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("powerSaveBlocker", atom::api::PowerSaveBlocker::Create(isolate));
}
} // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_power_save_blocker, Initialize);

View File

@@ -0,0 +1,59 @@
// 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_POWER_SAVE_BLOCKER_H_
#define ATOM_BROWSER_API_ATOM_API_POWER_SAVE_BLOCKER_H_
#include <map>
#include "base/memory/scoped_ptr.h"
#include "content/public/browser/power_save_blocker.h"
#include "native_mate/handle.h"
#include "native_mate/wrappable.h"
namespace mate {
class Dictionary;
}
namespace atom {
namespace api {
class PowerSaveBlocker : public mate::Wrappable {
public:
static mate::Handle<PowerSaveBlocker> Create(v8::Isolate* isolate);
protected:
PowerSaveBlocker();
virtual ~PowerSaveBlocker();
// mate::Wrappable implementations:
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override;
private:
void UpdatePowerSaveBlocker();
int Start(content::PowerSaveBlocker::PowerSaveBlockerType type);
bool Stop(int id);
bool IsStarted(int id);
scoped_ptr<content::PowerSaveBlocker> power_save_blocker_;
// Currnet blocker type used by |power_save_blocker_|
content::PowerSaveBlocker::PowerSaveBlockerType current_blocker_type_;
// Map from id to the corresponding blocker type for each request.
using PowerSaveBlockerTypeMap =
std::map<int, content::PowerSaveBlocker::PowerSaveBlockerType>;
PowerSaveBlockerTypeMap power_save_blocker_types_;
DISALLOW_COPY_AND_ASSIGN(PowerSaveBlocker);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_POWER_SAVE_BLOCKER_H_

View File

@@ -4,10 +4,13 @@
#include "atom/browser/api/atom_api_protocol.h"
#include "atom/browser/atom_browser_client.h"
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/browser/net/adapter_request_job.h"
#include "atom/browser/net/atom_url_request_job_factory.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "atom/common/native_mate_converters/gurl_converter.h"
#include "content/public/browser/browser_thread.h"
#include "native_mate/callback.h"
#include "native_mate/dictionary.h"
@@ -64,9 +67,8 @@ class CustomProtocolRequestJob : public AdapterRequestJob {
void GetJobTypeInUI() override {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
v8::Locker locker(registry_->isolate());
v8::HandleScope handle_scope(registry_->isolate());
// Call the JS handler.
Protocol::JsProtocolHandler callback =
@@ -82,7 +84,7 @@ class CustomProtocolRequestJob : public AdapterRequestJob {
return;
} else if (result->IsObject()) {
v8::Local<v8::Object> obj = result->ToObject();
mate::Dictionary dict(isolate, obj);
mate::Dictionary dict(registry_->isolate(), obj);
std::string name = mate::V8ToString(obj->GetConstructorName());
if (name == "RequestStringJob") {
std::string mime_type, charset, data;
@@ -115,14 +117,24 @@ class CustomProtocolRequestJob : public AdapterRequestJob {
GetWeakPtr(), path));
return;
} else if (name == "RequestErrorJob") {
// Default value net::ERR_NOT_IMPLEMENTED
int error = -11;
int error = net::ERR_NOT_IMPLEMENTED;
dict.Get("error", &error);
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(&AdapterRequestJob::CreateErrorJobAndStart,
GetWeakPtr(), error));
return;
} else if (name == "RequestHttpJob") {
GURL url;
std::string method, referrer;
dict.Get("url", &url);
dict.Get("method", &method);
dict.Get("referrer", &referrer);
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(&AdapterRequestJob::CreateHttpJobAndStart, GetWeakPtr(),
registry_->browser_context(), url, method, referrer));
return;
}
}
@@ -179,8 +191,9 @@ class CustomProtocolHandler : public ProtocolHandler {
} // namespace
Protocol::Protocol()
: job_factory_(AtomBrowserContext::Get()->job_factory()) {
Protocol::Protocol(AtomBrowserContext* browser_context)
: browser_context_(browser_context),
job_factory_(browser_context->job_factory()) {
CHECK(job_factory_);
}
@@ -194,6 +207,7 @@ mate::ObjectTemplateBuilder Protocol::GetObjectTemplateBuilder(
return mate::ObjectTemplateBuilder(isolate)
.SetMethod("registerProtocol", &Protocol::RegisterProtocol)
.SetMethod("unregisterProtocol", &Protocol::UnregisterProtocol)
.SetMethod("registerStandardSchemes", &Protocol::RegisterStandardSchemes)
.SetMethod("isHandledProtocol", &Protocol::IsHandledProtocol)
.SetMethod("interceptProtocol", &Protocol::InterceptProtocol)
.SetMethod("uninterceptProtocol", &Protocol::UninterceptProtocol);
@@ -226,6 +240,11 @@ void Protocol::UnregisterProtocol(v8::Isolate* isolate,
base::Unretained(this), scheme));
}
void Protocol::RegisterStandardSchemes(
const std::vector<std::string>& schemes) {
atom::AtomBrowserClient::SetCustomSchemes(schemes);
}
bool Protocol::IsHandledProtocol(const std::string& scheme) {
return job_factory_->IsHandledProtocol(scheme);
}
@@ -332,8 +351,9 @@ void Protocol::EmitEventInUI(const std::string& event,
}
// static
mate::Handle<Protocol> Protocol::Create(v8::Isolate* isolate) {
return CreateHandle(isolate, new Protocol);
mate::Handle<Protocol> Protocol::Create(
v8::Isolate* isolate, AtomBrowserContext* browser_context) {
return mate::CreateHandle(isolate, new Protocol(browser_context));
}
} // namespace api
@@ -346,7 +366,9 @@ 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("protocol", atom::api::Protocol::Create(isolate));
auto browser_context = static_cast<atom::AtomBrowserContext*>(
atom::AtomBrowserMainParts::Get()->browser_context());
dict.Set("protocol", atom::api::Protocol::Create(isolate, browser_context));
}
} // namespace

View File

@@ -7,6 +7,7 @@
#include <string>
#include <map>
#include <vector>
#include "atom/browser/api/event_emitter.h"
#include "base/callback.h"
@@ -18,6 +19,7 @@ class URLRequest;
namespace atom {
class AtomBrowserContext;
class AtomURLRequestJobFactory;
namespace api {
@@ -27,12 +29,15 @@ class Protocol : public mate::EventEmitter {
typedef base::Callback<v8::Local<v8::Value>(const net::URLRequest*)>
JsProtocolHandler;
static mate::Handle<Protocol> Create(v8::Isolate* isolate);
static mate::Handle<Protocol> Create(
v8::Isolate* isolate, AtomBrowserContext* browser_context);
JsProtocolHandler GetProtocolHandler(const std::string& scheme);
AtomBrowserContext* browser_context() const { return browser_context_; }
protected:
Protocol();
explicit Protocol(AtomBrowserContext* browser_context);
// mate::Wrappable implementations:
virtual mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
@@ -41,6 +46,9 @@ class Protocol : public mate::EventEmitter {
private:
typedef std::map<std::string, JsProtocolHandler> ProtocolHandlersMap;
// Register schemes to standard scheme list.
void RegisterStandardSchemes(const std::vector<std::string>& schemes);
// Register/unregister an networking |scheme| which would be handled by
// |callback|.
void RegisterProtocol(v8::Isolate* isolate,
@@ -68,6 +76,7 @@ class Protocol : public mate::EventEmitter {
// Do protocol.emit(event, parameter) under UI thread.
void EmitEventInUI(const std::string& event, const std::string& parameter);
AtomBrowserContext* browser_context_;
AtomURLRequestJobFactory* job_factory_;
ProtocolHandlersMap protocol_handlers_;

View File

@@ -0,0 +1,125 @@
// 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_session.h"
#include <string>
#include "atom/browser/api/atom_api_cookies.h"
#include "atom/browser/atom_browser_context.h"
#include "atom/common/native_mate_converters/gurl_converter.h"
#include "base/thread_task_runner_handle.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#include "native_mate/callback.h"
#include "native_mate/object_template_builder.h"
#include "net/base/load_flags.h"
#include "net/proxy/proxy_service.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "atom/common/node_includes.h"
namespace atom {
namespace api {
namespace {
class ResolveProxyHelper {
public:
ResolveProxyHelper(AtomBrowserContext* browser_context,
const GURL& url,
Session::ResolveProxyCallback callback)
: callback_(callback),
original_thread_(base::ThreadTaskRunnerHandle::Get()) {
scoped_refptr<net::URLRequestContextGetter> context_getter =
browser_context->GetRequestContext();
context_getter->GetNetworkTaskRunner()->PostTask(
FROM_HERE,
base::Bind(&ResolveProxyHelper::ResolveProxy,
base::Unretained(this), context_getter, url));
}
void OnResolveProxyCompleted(int result) {
std::string proxy;
if (result == net::OK)
proxy = proxy_info_.ToPacString();
original_thread_->PostTask(FROM_HERE,
base::Bind(callback_, proxy));
delete this;
}
private:
void ResolveProxy(scoped_refptr<net::URLRequestContextGetter> context_getter,
const GURL& url) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
net::ProxyService* proxy_service =
context_getter->GetURLRequestContext()->proxy_service();
net::CompletionCallback completion_callback =
base::Bind(&ResolveProxyHelper::OnResolveProxyCompleted,
base::Unretained(this));
// Start the request.
int result = proxy_service->ResolveProxy(
url, net::LOAD_NORMAL, &proxy_info_, completion_callback,
&pac_req_, nullptr, net::BoundNetLog());
// Completed synchronously.
if (result != net::ERR_IO_PENDING)
completion_callback.Run(result);
}
Session::ResolveProxyCallback callback_;
net::ProxyInfo proxy_info_;
net::ProxyService::PacRequest* pac_req_;
scoped_refptr<base::SingleThreadTaskRunner> original_thread_;
DISALLOW_COPY_AND_ASSIGN(ResolveProxyHelper);
};
} // namespace
Session::Session(AtomBrowserContext* browser_context)
: browser_context_(browser_context) {
AttachAsUserData(browser_context);
}
Session::~Session() {
}
void Session::ResolveProxy(const GURL& url, ResolveProxyCallback callback) {
new ResolveProxyHelper(browser_context_, url, callback);
}
v8::Local<v8::Value> Session::Cookies(v8::Isolate* isolate) {
if (cookies_.IsEmpty()) {
auto handle = atom::api::Cookies::Create(isolate, browser_context_);
cookies_.Reset(isolate, handle.ToV8());
}
return v8::Local<v8::Value>::New(isolate, cookies_);
}
mate::ObjectTemplateBuilder Session::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
return mate::ObjectTemplateBuilder(isolate)
.SetMethod("resolveProxy", &Session::ResolveProxy)
.SetProperty("cookies", &Session::Cookies);
}
// static
mate::Handle<Session> Session::CreateFrom(
v8::Isolate* isolate,
AtomBrowserContext* browser_context) {
auto existing = TrackableObject::FromWrappedClass(isolate, browser_context);
if (existing)
return mate::CreateHandle(isolate, static_cast<Session*>(existing));
return mate::CreateHandle(isolate, new Session(browser_context));
}
} // namespace api
} // namespace atom

View File

@@ -0,0 +1,53 @@
// 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_SESSION_H_
#define ATOM_BROWSER_API_ATOM_API_SESSION_H_
#include <string>
#include "atom/browser/api/trackable_object.h"
#include "base/callback.h"
#include "native_mate/handle.h"
class GURL;
namespace atom {
class AtomBrowserContext;
namespace api {
class Session: public mate::TrackableObject<Session> {
public:
using ResolveProxyCallback = base::Callback<void(std::string)>;
// Gets or creates Session from the |browser_context|.
static mate::Handle<Session> CreateFrom(
v8::Isolate* isolate, AtomBrowserContext* browser_context);
protected:
explicit Session(AtomBrowserContext* browser_context);
~Session();
// mate::Wrappable implementations:
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override;
private:
void ResolveProxy(const GURL& url, ResolveProxyCallback callback);
v8::Local<v8::Value> Cookies(v8::Isolate* isolate);
v8::Global<v8::Value> cookies_;
AtomBrowserContext* browser_context_; // weak ref
DISALLOW_COPY_AND_ASSIGN(Session);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_SESSION_H_

View File

@@ -6,10 +6,14 @@
#include <set>
#include "atom/browser/api/atom_api_session.h"
#include "atom/browser/atom_browser_client.h"
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/browser/native_window.h"
#include "atom/browser/web_view_guest_delegate.h"
#include "atom/common/api/api_messages.h"
#include "atom/common/event_emitter_caller.h"
#include "atom/common/native_mate_converters/gfx_converter.h"
#include "atom/common/native_mate_converters/gurl_converter.h"
#include "atom/common/native_mate_converters/image_converter.h"
@@ -18,15 +22,15 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "brightray/browser/inspectable_web_contents.h"
#include "chrome/browser/printing/print_view_manager_basic.h"
#include "chrome/browser/printing/print_preview_message_handler.h"
#include "content/public/browser/favicon_status.h"
#include "content/public/browser/guest_host.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/resource_request_details.h"
#include "content/public/browser/service_worker_context.h"
#include "content/public/browser/storage_partition.h"
@@ -40,13 +44,22 @@
#include "atom/common/node_includes.h"
namespace {
struct PrintSettings {
bool silent;
bool print_background;
};
} // namespace
namespace mate {
template<>
struct Converter<atom::api::SetSizeParams> {
struct Converter<atom::SetSizeParams> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
atom::api::SetSizeParams* out) {
atom::SetSizeParams* out) {
mate::Dictionary params;
if (!ConvertFromV8(isolate, val, &params))
return false;
@@ -64,6 +77,35 @@ struct Converter<atom::api::SetSizeParams> {
}
};
template<>
struct Converter<PrintSettings> {
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
PrintSettings* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
dict.Get("silent", &(out->silent));
dict.Get("printBackground", &(out->print_background));
return true;
}
};
template<>
struct Converter<WindowOpenDisposition> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
WindowOpenDisposition val) {
std::string disposition = "other";
switch (val) {
case CURRENT_TAB: disposition = "default"; break;
case NEW_FOREGROUND_TAB: disposition = "foreground-tab"; break;
case NEW_BACKGROUND_TAB: disposition = "background-tab"; break;
case NEW_POPUP: case NEW_WINDOW: disposition = "new-window"; break;
default: break;
}
return mate::ConvertToV8(isolate, disposition);
}
};
} // namespace mate
@@ -73,9 +115,6 @@ namespace api {
namespace {
const int kDefaultWidth = 300;
const int kDefaultHeight = 300;
v8::Persistent<v8::ObjectTemplate> template_;
// The wrapWebContents funtion which is implemented in JavaScript
@@ -99,44 +138,50 @@ content::ServiceWorkerContext* GetServiceWorkerContext(
} // namespace
WebContents::WebContents(brightray::InspectableWebContents* web_contents)
: WebContents(web_contents->GetWebContents()) {
inspectable_web_contents_ = web_contents;
}
WebContents::WebContents(content::WebContents* web_contents)
: CommonWebContentsDelegate(false),
content::WebContentsObserver(web_contents),
guest_opaque_(true),
guest_host_(nullptr),
auto_size_enabled_(false),
is_full_page_plugin_(false),
inspectable_web_contents_(nullptr) {
: content::WebContentsObserver(web_contents),
type_(REMOTE) {
AttachAsUserData(web_contents);
}
WebContents::WebContents(const mate::Dictionary& options)
: CommonWebContentsDelegate(true),
guest_opaque_(true),
guest_host_(nullptr),
auto_size_enabled_(false),
is_full_page_plugin_(false) {
auto browser_context = AtomBrowserContext::Get();
content::SiteInstance* site_instance = content::SiteInstance::CreateForURL(
browser_context, GURL("chrome-guest://fake-host"));
WebContents::WebContents(const mate::Dictionary& options) {
bool is_guest = false;
options.Get("isGuest", &is_guest);
content::WebContents::CreateParams params(browser_context, site_instance);
params.guest_delegate = this;
auto web_contents = content::WebContents::Create(params);
type_ = is_guest ? WEB_VIEW : BROWSER_WINDOW;
NativeWindow* owner_window = nullptr;
WebContents* embedder = nullptr;
if (options.Get("embedder", &embedder) && embedder)
owner_window = NativeWindow::FromWebContents(embedder->web_contents());
auto browser_context = AtomBrowserMainParts::Get()->browser_context();
content::WebContents* web_contents;
if (is_guest) {
content::SiteInstance* site_instance = content::SiteInstance::CreateForURL(
browser_context, GURL("chrome-guest://fake-host"));
content::WebContents::CreateParams params(browser_context, site_instance);
guest_delegate_.reset(new WebViewGuestDelegate);
params.guest_delegate = guest_delegate_.get();
web_contents = content::WebContents::Create(params);
} else {
content::WebContents::CreateParams params(browser_context);
web_contents = content::WebContents::Create(params);
}
InitWithWebContents(web_contents, owner_window);
inspectable_web_contents_ = managed_web_contents();
Observe(web_contents);
AttachAsUserData(web_contents);
InitWithWebContents(web_contents);
Observe(GetWebContents());
if (is_guest) {
guest_delegate_->Initialize(this);
NativeWindow* owner_window = nullptr;
WebContents* embedder = nullptr;
if (options.Get("embedder", &embedder) && embedder) {
// New WebContents's owner_window is the embedder's owner_window.
auto relay = NativeWindowRelay::FromWebContents(embedder->web_contents());
if (relay)
owner_window = relay->window.get();
}
if (owner_window)
SetOwnerWindow(owner_window);
}
}
WebContents::~WebContents() {
@@ -148,8 +193,12 @@ bool WebContents::AddMessageToConsole(content::WebContents* source,
const base::string16& message,
int32 line_no,
const base::string16& source_id) {
Emit("console-message", level, message, line_no, source_id);
return true;
if (type_ == BROWSER_WINDOW) {
return false;
} else {
Emit("console-message", level, message, line_no, source_id);
return true;
}
}
bool WebContents::ShouldCreateWebContents(
@@ -161,22 +210,21 @@ bool WebContents::ShouldCreateWebContents(
const GURL& target_url,
const std::string& partition_id,
content::SessionStorageNamespace* session_storage_namespace) {
Emit("-new-window",
target_url,
frame_name,
static_cast<int>(NEW_FOREGROUND_TAB));
if (type_ == BROWSER_WINDOW)
Emit("-new-window", target_url, frame_name, NEW_FOREGROUND_TAB);
else
Emit("new-window", target_url, frame_name, NEW_FOREGROUND_TAB);
return false;
}
void WebContents::CloseContents(content::WebContents* source) {
Emit("close");
}
content::WebContents* WebContents::OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) {
if (params.disposition != CURRENT_TAB) {
Emit("-new-window", params.url, "", static_cast<int>(params.disposition));
if (type_ == BROWSER_WINDOW)
Emit("-new-window", params.url, "", params.disposition);
else
Emit("new-window", params.url, "", params.disposition);
return nullptr;
}
@@ -187,15 +235,43 @@ content::WebContents* WebContents::OpenURLFromTab(
return CommonWebContentsDelegate::OpenURLFromTab(source, params);
}
void WebContents::BeforeUnloadFired(content::WebContents* tab,
bool proceed,
bool* proceed_to_fire_unload) {
if (type_ == BROWSER_WINDOW)
*proceed_to_fire_unload = proceed;
else
*proceed_to_fire_unload = true;
}
void WebContents::MoveContents(content::WebContents* source,
const gfx::Rect& pos) {
Emit("move", pos);
}
void WebContents::CloseContents(content::WebContents* source) {
Emit("closed");
if (type_ == BROWSER_WINDOW)
owner_window()->CloseContents(source);
}
void WebContents::ActivateContents(content::WebContents* source) {
Emit("activate");
}
bool WebContents::IsPopupOrPanel(const content::WebContents* source) const {
return type_ == BROWSER_WINDOW;
}
void WebContents::HandleKeyboardEvent(
content::WebContents* source,
const content::NativeWebKeyboardEvent& event) {
if (!attached())
return;
// Send the unhandled keyboard events back to the embedder to reprocess them.
embedder_web_contents_->GetDelegate()->HandleKeyboardEvent(
web_contents(), event);
if (type_ == BROWSER_WINDOW) {
owner_window()->HandleKeyboardEvent(source, event);
} else if (type_ == WEB_VIEW && guest_delegate_) {
// Send the unhandled keyboard events back to the embedder.
guest_delegate_->HandleKeyboardEvent(source, event);
}
}
void WebContents::EnterFullscreenModeForTab(content::WebContents* source,
@@ -209,10 +285,35 @@ void WebContents::ExitFullscreenModeForTab(content::WebContents* source) {
Emit("leave-html-full-screen");
}
void WebContents::RendererUnresponsive(content::WebContents* source) {
Emit("unresponsive");
if (type_ == BROWSER_WINDOW)
owner_window()->RendererUnresponsive(source);
}
void WebContents::RendererResponsive(content::WebContents* source) {
Emit("responsive");
if (type_ == BROWSER_WINDOW)
owner_window()->RendererResponsive(source);
}
void WebContents::BeforeUnloadFired(const base::TimeTicks& proceed_time) {
// Do nothing, we override this method just to avoid compilation error since
// there are two virtual functions named BeforeUnloadFired.
}
void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) {
Emit("render-view-deleted",
render_view_host->GetProcess()->GetID(),
render_view_host->GetRoutingID());
int process_id = render_view_host->GetProcess()->GetID();
Emit("render-view-deleted", process_id);
// process.emit('ATOM_BROWSER_RELEASE_RENDER_VIEW', processId);
// Tell the rpc server that a render view has been deleted and we need to
// release all objects owned by it.
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
node::Environment* env = node::Environment::GetCurrent(isolate());
mate::EmitEvent(isolate(), env->process_object(),
"ATOM_BROWSER_RELEASE_RENDER_VIEW", process_id);
}
void WebContents::RenderProcessGone(base::TerminationStatus status) {
@@ -227,11 +328,6 @@ void WebContents::PluginCrashed(const base::FilePath& plugin_path,
Emit("plugin-crashed", info.name, info.version);
}
void WebContents::OnGpuProcessCrashed(base::TerminationStatus exit_code) {
if (exit_code == base::TERMINATION_STATUS_PROCESS_CRASHED)
Emit("gpu-crashed");
}
void WebContents::DocumentLoadedInFrame(
content::RenderFrameHost* render_frame_host) {
if (!render_frame_host->GetParent())
@@ -273,9 +369,8 @@ void WebContents::DidStopLoading() {
void WebContents::DidGetResourceResponseStart(
const content::ResourceRequestDetails& details) {
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
base::DictionaryValue response_headers;
net::HttpResponseHeaders* headers = details.headers.get();
@@ -356,25 +451,11 @@ bool WebContents::OnMessageReceived(const IPC::Message& message) {
return handled;
}
void WebContents::RenderViewReady() {
if (!is_guest())
return;
// We don't want to accidentally set the opacity of an interstitial page.
// WebContents::GetRenderWidgetHostView will return the RWHV of an
// interstitial page if one is showing at this time. We only want opacity
// to apply to web pages.
auto render_view_host_view = web_contents()->GetRenderViewHost()->GetView();
if (guest_opaque_)
render_view_host_view->SetBackgroundColorToDefault();
else
render_view_host_view->SetBackgroundColor(SK_ColorTRANSPARENT);
}
void WebContents::WebContentsDestroyed() {
// The RenderViewDeleted was not called when the WebContents is destroyed.
RenderViewDeleted(web_contents()->GetRenderViewHost());
Emit("destroyed");
RemoveFromWeakMap();
}
void WebContents::NavigationEntryCommitted(
@@ -383,40 +464,12 @@ void WebContents::NavigationEntryCommitted(
details.is_in_page, details.did_replace_entry);
}
void WebContents::DidAttach(int guest_proxy_routing_id) {
Emit("did-attach");
}
content::WebContents* WebContents::GetOwnerWebContents() const {
return embedder_web_contents_;
}
void WebContents::GuestSizeChanged(const gfx::Size& new_size) {
if (!auto_size_enabled_)
return;
GuestSizeChangedDueToAutoSize(guest_size_, new_size);
guest_size_ = new_size;
}
void WebContents::SetGuestHost(content::GuestHost* guest_host) {
guest_host_ = guest_host;
}
void WebContents::WillAttach(content::WebContents* embedder_web_contents,
int element_instance_id,
bool is_full_page_plugin) {
embedder_web_contents_ = embedder_web_contents;
is_full_page_plugin_ = is_full_page_plugin;
}
void WebContents::Destroy() {
if (is_guest() && managed_web_contents()) {
if (type_ == WEB_VIEW && managed_web_contents()) {
// When force destroying the "destroyed" event is not emitted.
WebContentsDestroyed();
// Give the content module an opportunity to perform some cleanup.
guest_host_->WillDestroy();
guest_host_ = nullptr;
guest_delegate_->Destroy();
Observe(nullptr);
DestroyWebContents();
@@ -427,6 +480,14 @@ bool WebContents::IsAlive() const {
return web_contents() != NULL;
}
int WebContents::GetID() const {
return web_contents()->GetRenderProcessHost()->GetID();
}
bool WebContents::Equal(const WebContents* web_contents) const {
return GetID() == web_contents->GetID();
}
void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) {
content::NavigationController::LoadURLParams params(url);
@@ -480,14 +541,6 @@ void WebContents::GoToOffset(int offset) {
web_contents()->GetController().GoToOffset(offset);
}
int WebContents::GetRoutingID() const {
return web_contents()->GetRoutingID();
}
int WebContents::GetProcessID() const {
return web_contents()->GetRenderProcessHost()->GetID();
}
bool WebContents::IsCrashed() const {
return web_contents()->IsCrashed();
}
@@ -505,29 +558,32 @@ void WebContents::ExecuteJavaScript(const base::string16& code) {
}
void WebContents::OpenDevTools(mate::Arguments* args) {
if (!inspectable_web_contents())
if (type_ == REMOTE)
return;
bool detach = false;
if (is_guest()) {
if (type_ == WEB_VIEW) {
detach = true;
} else if (args && args->Length() == 1) {
mate::Dictionary options;
args->GetNext(&options) && options.Get("detach", &detach);
}
inspectable_web_contents()->SetCanDock(!detach);
inspectable_web_contents()->ShowDevTools();
managed_web_contents()->SetCanDock(!detach);
managed_web_contents()->ShowDevTools();
}
void WebContents::CloseDevTools() {
if (!inspectable_web_contents())
if (type_ == REMOTE)
return;
inspectable_web_contents()->CloseDevTools();
managed_web_contents()->CloseDevTools();
}
bool WebContents::IsDevToolsOpened() {
if (!inspectable_web_contents())
if (type_ == REMOTE)
return false;
return inspectable_web_contents()->IsDevToolsViewShowing();
return managed_web_contents()->IsDevToolsViewShowing();
}
void WebContents::ToggleDevTools() {
@@ -538,8 +594,9 @@ void WebContents::ToggleDevTools() {
}
void WebContents::InspectElement(int x, int y) {
if (!inspectable_web_contents())
if (type_ == REMOTE)
return;
OpenDevTools(nullptr);
scoped_refptr<content::DevToolsAgentHost> agent(
content::DevToolsAgentHost::GetOrCreateFor(web_contents()));
@@ -547,18 +604,29 @@ void WebContents::InspectElement(int x, int y) {
}
void WebContents::InspectServiceWorker() {
if (!inspectable_web_contents())
if (type_ == REMOTE)
return;
for (const auto& agent_host : content::DevToolsAgentHost::GetOrCreateAll()) {
if (agent_host->GetType() ==
content::DevToolsAgentHost::TYPE_SERVICE_WORKER) {
OpenDevTools(nullptr);
inspectable_web_contents()->AttachTo(agent_host);
managed_web_contents()->AttachTo(agent_host);
break;
}
}
}
v8::Local<v8::Value> WebContents::Session(v8::Isolate* isolate) {
if (session_.IsEmpty()) {
mate::Handle<api::Session> handle = Session::CreateFrom(
isolate,
static_cast<AtomBrowserContext*>(web_contents()->GetBrowserContext()));
session_.Reset(isolate, handle.ToV8());
}
return v8::Local<v8::Value>::New(isolate, session_);
}
void WebContents::HasServiceWorker(
const base::Callback<void(bool)>& callback) {
auto context = GetServiceWorkerContext(web_contents());
@@ -580,6 +648,31 @@ void WebContents::UnregisterServiceWorker(
callback);
}
void WebContents::SetAudioMuted(bool muted) {
web_contents()->SetAudioMuted(muted);
}
bool WebContents::IsAudioMuted() {
return web_contents()->IsAudioMuted();
}
void WebContents::Print(mate::Arguments* args) {
PrintSettings settings = { false, false };
if (args->Length() == 1 && !args->GetNext(&settings)) {
args->ThrowError();
return;
}
printing::PrintViewManagerBasic::FromWebContents(web_contents())->
PrintNow(settings.silent, settings.print_background);
}
void WebContents::PrintToPDF(const base::DictionaryValue& setting,
const PrintToPDFCallback& callback) {
printing::PrintPreviewMessageHandler::FromWebContents(web_contents())->
PrintToPDF(setting, callback);
}
void WebContents::Undo() {
web_contents()->Undo();
}
@@ -630,79 +723,17 @@ bool WebContents::SendIPCMessage(const base::string16& channel,
}
void WebContents::SetSize(const SetSizeParams& params) {
bool enable_auto_size =
params.enable_auto_size ? *params.enable_auto_size : auto_size_enabled_;
gfx::Size min_size = params.min_size ? *params.min_size : min_auto_size_;
gfx::Size max_size = params.max_size ? *params.max_size : max_auto_size_;
if (params.normal_size)
normal_size_ = *params.normal_size;
min_auto_size_ = min_size;
min_auto_size_.SetToMin(max_size);
max_auto_size_ = max_size;
max_auto_size_.SetToMax(min_size);
enable_auto_size &= !min_auto_size_.IsEmpty() && !max_auto_size_.IsEmpty();
content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
if (enable_auto_size) {
// Autosize is being enabled.
rvh->EnableAutoResize(min_auto_size_, max_auto_size_);
normal_size_.SetSize(0, 0);
} else {
// Autosize is being disabled.
// Use default width/height if missing from partially defined normal size.
if (normal_size_.width() && !normal_size_.height())
normal_size_.set_height(GetDefaultSize().height());
if (!normal_size_.width() && normal_size_.height())
normal_size_.set_width(GetDefaultSize().width());
gfx::Size new_size;
if (!normal_size_.IsEmpty()) {
new_size = normal_size_;
} else if (!guest_size_.IsEmpty()) {
new_size = guest_size_;
} else {
new_size = GetDefaultSize();
}
if (auto_size_enabled_) {
// Autosize was previously enabled.
rvh->DisableAutoResize(new_size);
GuestSizeChangedDueToAutoSize(guest_size_, new_size);
} else {
// Autosize was already disabled.
guest_host_->SizeContents(new_size);
}
guest_size_ = new_size;
}
auto_size_enabled_ = enable_auto_size;
if (guest_delegate_)
guest_delegate_->SetSize(params);
}
void WebContents::SetAllowTransparency(bool allow) {
if (guest_opaque_ != allow)
return;
guest_opaque_ = !allow;
if (!web_contents()->GetRenderViewHost()->GetView())
return;
if (guest_opaque_) {
web_contents()
->GetRenderViewHost()
->GetView()
->SetBackgroundColorToDefault();
} else {
web_contents()->GetRenderViewHost()->GetView()->SetBackgroundColor(
SK_ColorTRANSPARENT);
}
if (guest_delegate_)
guest_delegate_->SetAllowTransparency(allow);
}
bool WebContents::IsGuest() const {
return is_guest();
return type_ == WEB_VIEW;
}
mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
@@ -711,6 +742,8 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
template_.Reset(isolate, mate::ObjectTemplateBuilder(isolate)
.SetMethod("destroy", &WebContents::Destroy)
.SetMethod("isAlive", &WebContents::IsAlive)
.SetMethod("getId", &WebContents::GetID)
.SetMethod("equal", &WebContents::Equal)
.SetMethod("_loadUrl", &WebContents::LoadURL)
.SetMethod("getTitle", &WebContents::GetTitle)
.SetMethod("isLoading", &WebContents::IsLoading)
@@ -720,8 +753,6 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
.SetMethod("_goBack", &WebContents::GoBack)
.SetMethod("_goForward", &WebContents::GoForward)
.SetMethod("_goToOffset", &WebContents::GoToOffset)
.SetMethod("getRoutingId", &WebContents::GetRoutingID)
.SetMethod("getProcessId", &WebContents::GetProcessID)
.SetMethod("isCrashed", &WebContents::IsCrashed)
.SetMethod("setUserAgent", &WebContents::SetUserAgent)
.SetMethod("insertCSS", &WebContents::InsertCSS)
@@ -731,6 +762,8 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
.SetMethod("isDevToolsOpened", &WebContents::IsDevToolsOpened)
.SetMethod("toggleDevTools", &WebContents::ToggleDevTools)
.SetMethod("inspectElement", &WebContents::InspectElement)
.SetMethod("setAudioMuted", &WebContents::SetAudioMuted)
.SetMethod("isAudioMuted", &WebContents::IsAudioMuted)
.SetMethod("undo", &WebContents::Undo)
.SetMethod("redo", &WebContents::Redo)
.SetMethod("cut", &WebContents::Cut)
@@ -750,6 +783,9 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
.SetMethod("unregisterServiceWorker",
&WebContents::UnregisterServiceWorker)
.SetMethod("inspectServiceWorker", &WebContents::InspectServiceWorker)
.SetMethod("print", &WebContents::Print)
.SetMethod("_printToPDF", &WebContents::PrintToPDF)
.SetProperty("session", &WebContents::Session)
.Build());
return mate::ObjectTemplateBuilder(
@@ -769,34 +805,15 @@ void WebContents::OnRendererMessageSync(const base::string16& channel,
EmitWithSender(base::UTF16ToUTF8(channel), web_contents(), message, args);
}
void WebContents::GuestSizeChangedDueToAutoSize(const gfx::Size& old_size,
const gfx::Size& new_size) {
Emit("size-changed",
old_size.width(), old_size.height(),
new_size.width(), new_size.height());
}
gfx::Size WebContents::GetDefaultSize() const {
if (is_full_page_plugin_) {
// Full page plugins default to the size of the owner's viewport.
return embedder_web_contents_->GetRenderWidgetHostView()
->GetVisibleViewportSize();
} else {
return gfx::Size(kDefaultWidth, kDefaultHeight);
}
}
// static
mate::Handle<WebContents> WebContents::CreateFrom(
v8::Isolate* isolate, brightray::InspectableWebContents* web_contents) {
auto handle = mate::CreateHandle(isolate, new WebContents(web_contents));
g_wrap_web_contents.Run(handle.ToV8());
return handle;
}
// static
mate::Handle<WebContents> WebContents::CreateFrom(
v8::Isolate* isolate, content::WebContents* web_contents) {
// We have an existing WebContents object in JS.
auto existing = TrackableObject::FromWrappedClass(isolate, web_contents);
if (existing)
return mate::CreateHandle(isolate, static_cast<WebContents*>(existing));
// Otherwise create a new WebContents wrapper object.
auto handle = mate::CreateHandle(isolate, new WebContents(web_contents));
g_wrap_web_contents.Run(handle.ToV8());
return handle;

View File

@@ -8,12 +8,10 @@
#include <string>
#include <vector>
#include "atom/browser/api/event_emitter.h"
#include "atom/browser/api/trackable_object.h"
#include "atom/browser/common_web_contents_delegate.h"
#include "content/public/browser/browser_plugin_guest_delegate.h"
#include "content/public/common/favicon_url.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/gpu_data_manager_observer.h"
#include "native_mate/handle.h"
#include "ui/gfx/image/image.h"
@@ -28,33 +26,20 @@ class Dictionary;
namespace atom {
struct SetSizeParams;
class WebViewGuestDelegate;
namespace api {
// A struct of parameters for SetSize(). The parameters are all declared as
// scoped pointers since they are all optional. Null pointers indicate that the
// parameter has not been provided, and the last used value should be used. Note
// that when |enable_auto_size| is true, providing |normal_size| is not
// meaningful. This is because the normal size of the guestview is overridden
// whenever autosizing occurs.
struct SetSizeParams {
SetSizeParams() {}
~SetSizeParams() {}
scoped_ptr<bool> enable_auto_size;
scoped_ptr<gfx::Size> min_size;
scoped_ptr<gfx::Size> max_size;
scoped_ptr<gfx::Size> normal_size;
};
class WebContents : public mate::EventEmitter,
public content::BrowserPluginGuestDelegate,
class WebContents : public mate::TrackableObject<WebContents>,
public CommonWebContentsDelegate,
public content::WebContentsObserver,
public content::GpuDataManagerObserver {
public content::WebContentsObserver {
public:
// For node.js callback function type: function(error, buffer)
typedef base::Callback<void(v8::Local<v8::Value>, v8::Local<v8::Value>)>
PrintToPDFCallback;
// Create from an existing WebContents.
static mate::Handle<WebContents> CreateFrom(
v8::Isolate* isolate, brightray::InspectableWebContents* web_contents);
static mate::Handle<WebContents> CreateFrom(
v8::Isolate* isolate, content::WebContents* web_contents);
@@ -64,6 +49,8 @@ class WebContents : public mate::EventEmitter,
void Destroy();
bool IsAlive() const;
int GetID() const;
bool Equal(const WebContents* web_contents) const;
void LoadURL(const GURL& url, const mate::Dictionary& options);
base::string16 GetTitle() const;
bool IsLoading() const;
@@ -73,8 +60,6 @@ class WebContents : public mate::EventEmitter,
void GoBack();
void GoForward();
void GoToOffset(int offset);
int GetRoutingID() const;
int GetProcessID() const;
bool IsCrashed() const;
void SetUserAgent(const std::string& user_agent);
void InsertCSS(const std::string& css);
@@ -85,8 +70,16 @@ class WebContents : public mate::EventEmitter,
void ToggleDevTools();
void InspectElement(int x, int y);
void InspectServiceWorker();
v8::Local<v8::Value> Session(v8::Isolate* isolate);
void HasServiceWorker(const base::Callback<void(bool)>&);
void UnregisterServiceWorker(const base::Callback<void(bool)>&);
void SetAudioMuted(bool muted);
bool IsAudioMuted();
void Print(mate::Arguments* args);
// Print current page as PDF.
void PrintToPDF(const base::DictionaryValue& setting,
const PrintToPDFCallback& callback);
// Editing commands.
void Undo();
@@ -105,26 +98,12 @@ class WebContents : public mate::EventEmitter,
bool SendIPCMessage(const base::string16& channel,
const base::ListValue& args);
// Used to toggle autosize mode for this GuestView, and set both the automatic
// and normal sizes.
// Methods for creating <webview>.
void SetSize(const SetSizeParams& params);
// Sets the transparency of the guest.
void SetAllowTransparency(bool allow);
bool IsGuest() const;
// Returns whether this guest has an associated embedder.
bool attached() const { return !!embedder_web_contents_; }
// Returns the current InspectableWebContents object, nullptr will be returned
// if current WebContents can not beinspected, e.g. it is the devtools.
brightray::InspectableWebContents* inspectable_web_contents() const {
return inspectable_web_contents_;
}
protected:
explicit WebContents(brightray::InspectableWebContents* web_contents);
explicit WebContents(content::WebContents* web_contents);
explicit WebContents(const mate::Dictionary& options);
~WebContents();
@@ -148,18 +127,28 @@ class WebContents : public mate::EventEmitter,
const GURL& target_url,
const std::string& partition_id,
content::SessionStorageNamespace* session_storage_namespace) override;
void CloseContents(content::WebContents* source) override;
content::WebContents* OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) override;
void BeforeUnloadFired(content::WebContents* tab,
bool proceed,
bool* proceed_to_fire_unload) override;
void MoveContents(content::WebContents* source,
const gfx::Rect& pos) override;
void CloseContents(content::WebContents* source) override;
void ActivateContents(content::WebContents* contents) override;
bool IsPopupOrPanel(const content::WebContents* source) const override;
void HandleKeyboardEvent(
content::WebContents* source,
const content::NativeWebKeyboardEvent& event) override;
void EnterFullscreenModeForTab(content::WebContents* source,
const GURL& origin) override;
void ExitFullscreenModeForTab(content::WebContents* source) override;
void RendererUnresponsive(content::WebContents* source) override;
void RendererResponsive(content::WebContents* source) override;
// content::WebContentsObserver:
void BeforeUnloadFired(const base::TimeTicks& proceed_time) override;
void RenderViewDeleted(content::RenderViewHost*) override;
void RenderProcessGone(base::TerminationStatus status) override;
void DocumentLoadedInFrame(
@@ -185,7 +174,6 @@ class WebContents : public mate::EventEmitter,
const content::LoadCommittedDetails& details,
const content::FrameNavigateParams& params) override;
bool OnMessageReceived(const IPC::Message& message) override;
void RenderViewReady() override;
void WebContentsDestroyed() override;
void NavigationEntryCommitted(
const content::LoadCommittedDetails& load_details) override;
@@ -195,19 +183,13 @@ class WebContents : public mate::EventEmitter,
void PluginCrashed(const base::FilePath& plugin_path,
base::ProcessId plugin_pid) override;
// content::BrowserPluginGuestDelegate:
void DidAttach(int guest_proxy_routing_id) final;
content::WebContents* GetOwnerWebContents() const final;
void GuestSizeChanged(const gfx::Size& new_size) final;
void SetGuestHost(content::GuestHost* guest_host) final;
void WillAttach(content::WebContents* embedder_web_contents,
int element_instance_id,
bool is_full_page_plugin) final;
// content::GpuDataManagerObserver:
void OnGpuProcessCrashed(base::TerminationStatus exit_code) override;
private:
enum Type {
BROWSER_WINDOW, // Used by BrowserWindow.
WEB_VIEW, // Used by <webview>.
REMOTE, // Thin wrap around an existing WebContents.
};
// Called when received a message from renderer.
void OnRendererMessage(const base::string16& channel,
const base::ListValue& args);
@@ -217,51 +199,12 @@ class WebContents : public mate::EventEmitter,
const base::ListValue& args,
IPC::Message* message);
// This method is invoked when the contents auto-resized to give the container
// an opportunity to match it if it wishes.
//
// This gives the derived class an opportunity to inform its container element
// or perform other actions.
void GuestSizeChangedDueToAutoSize(const gfx::Size& old_size,
const gfx::Size& new_size);
v8::Global<v8::Value> session_;
// Returns the default size of the guestview.
gfx::Size GetDefaultSize() const;
scoped_ptr<WebViewGuestDelegate> guest_delegate_;
// Stores whether the contents of the guest can be transparent.
bool guest_opaque_;
// The WebContents that attaches this guest view.
content::WebContents* embedder_web_contents_;
// The size of the container element.
gfx::Size element_size_;
// The size of the guest content. Note: In autosize mode, the container
// element may not match the size of the guest.
gfx::Size guest_size_;
// A pointer to the guest_host.
content::GuestHost* guest_host_;
// Indicates whether autosize mode is enabled or not.
bool auto_size_enabled_;
// The maximum size constraints of the container element in autosize mode.
gfx::Size max_auto_size_;
// The minimum size constraints of the container element in autosize mode.
gfx::Size min_auto_size_;
// The size that will be used when autosize mode is disabled.
gfx::Size normal_size_;
// Whether the guest view is inside a plugin document.
bool is_full_page_plugin_;
// Current InspectableWebContents object, can be nullptr for WebContents of
// devtools. It is a weak reference.
brightray::InspectableWebContents* inspectable_web_contents_;
// The type of current WebContents.
Type type_;
DISALLOW_COPY_AND_ASSIGN(WebContents);
};

View File

@@ -20,32 +20,6 @@
#include "atom/common/node_includes.h"
namespace {
struct PrintSettings {
bool silent;
bool print_background;
};
} // namespace
namespace mate {
template<>
struct Converter<PrintSettings> {
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
PrintSettings* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
dict.Get("silent", &(out->silent));
dict.Get("printBackground", &(out->print_background));
return true;
}
};
} // namespace mate
namespace atom {
namespace api {
@@ -64,8 +38,17 @@ void OnCapturePageDone(
} // namespace
Window::Window(const mate::Dictionary& options)
: window_(NativeWindow::Create(options)) {
Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) {
// Creates the WebContents used by BrowserWindow.
mate::Dictionary web_contents_options(isolate, v8::Object::New(isolate));
auto web_contents = WebContents::Create(isolate, web_contents_options);
web_contents_.Reset(isolate, web_contents.ToV8());
api_web_contents_ = web_contents.get();
// Creates BrowserWindow.
window_.reset(NativeWindow::Create(web_contents->managed_web_contents(),
options));
web_contents->SetOwnerWindow(window_.get());
window_->InitFromOptions(options);
window_->AddObserver(this);
}
@@ -80,25 +63,21 @@ void Window::OnPageTitleUpdated(bool* prevent_default,
*prevent_default = Emit("page-title-updated", title);
}
void Window::WillCreatePopupWindow(const base::string16& frame_name,
const GURL& target_url,
const std::string& partition_id,
WindowOpenDisposition disposition) {
Emit("-new-window", target_url, frame_name, static_cast<int>(disposition));
}
void Window::WillNavigate(bool* prevent_default, const GURL& url) {
*prevent_default = Emit("-will-navigate", url);
}
void Window::WillCloseWindow(bool* prevent_default) {
*prevent_default = Emit("close");
}
void Window::OnWindowClosed() {
Emit("closed");
if (api_web_contents_) {
api_web_contents_->DestroyWebContents();
api_web_contents_ = nullptr;
web_contents_.Reset();
}
RemoveFromWeakMap();
window_->RemoveObserver(this);
Emit("closed");
}
void Window::OnWindowBlur() {
@@ -168,23 +147,25 @@ void Window::OnDevToolsFocus() {
void Window::OnDevToolsOpened() {
Emit("devtools-opened");
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
auto handle =
WebContents::CreateFrom(isolate, window_->GetDevToolsWebContents());
devtools_web_contents_.Reset(isolate, handle.ToV8());
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
auto handle = WebContents::CreateFrom(
isolate(), api_web_contents_->GetDevToolsWebContents());
devtools_web_contents_.Reset(isolate(), handle.ToV8());
}
void Window::OnDevToolsClosed() {
Emit("devtools-closed");
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
devtools_web_contents_.Reset();
}
void Window::OnExecuteWindowsCommand(const std::string& command_name) {
Emit("app-command", command_name);
}
// static
mate::Wrappable* Window::New(v8::Isolate* isolate,
const mate::Dictionary& options) {
@@ -193,12 +174,11 @@ mate::Wrappable* Window::New(v8::Isolate* isolate,
"Cannot create BrowserWindow before app is ready");
return nullptr;
}
return new Window(options);
return new Window(isolate, options);
}
void Window::Destroy() {
window_->DestroyWebContents();
window_->CloseImmediately();
window_->CloseContents(nullptr);
}
void Window::Close() {
@@ -420,16 +400,6 @@ void Window::CapturePage(mate::Arguments* args) {
rect, base::Bind(&OnCapturePageDone, args->isolate(), callback));
}
void Window::Print(mate::Arguments* args) {
PrintSettings settings = { false, false };;
if (args->Length() == 1 && !args->GetNext(&settings)) {
args->ThrowError();
return;
}
window_->Print(settings.silent, settings.print_background);
}
void Window::SetProgressBar(double progress) {
window_->SetProgressBar(progress);
}
@@ -439,8 +409,20 @@ void Window::SetOverlayIcon(const gfx::Image& overlay,
window_->SetOverlayIcon(overlay, description);
}
void Window::SetMenu(ui::SimpleMenuModel* menu) {
window_->SetMenu(menu);
void Window::SetMenu(v8::Isolate* isolate, v8::Local<v8::Value> value) {
mate::Handle<Menu> menu;
if (value->IsObject() &&
mate::V8ToString(value->ToObject()->GetConstructorName()) == "Menu" &&
mate::ConvertFromV8(isolate, value, &menu)) {
menu_.Reset(isolate, menu.ToV8());
window_->SetMenu(menu->model());
} else if (value->IsNull()) {
menu_.Reset();
window_->SetMenu(nullptr);
} else {
isolate->ThrowException(v8::Exception::TypeError(
mate::StringToV8(isolate, "Invalid Menu")));
}
}
void Window::SetAutoHideMenuBar(bool auto_hide) {
@@ -473,13 +455,15 @@ bool Window::IsVisibleOnAllWorkspaces() {
return window_->IsVisibleOnAllWorkspaces();
}
int32_t Window::ID() const {
return weak_map_id();
}
v8::Local<v8::Value> Window::WebContents(v8::Isolate* isolate) {
if (web_contents_.IsEmpty()) {
auto handle =
WebContents::CreateFrom(isolate, window_->managed_web_contents());
web_contents_.Reset(isolate, handle.ToV8());
}
return v8::Local<v8::Value>::New(isolate, web_contents_);
if (web_contents_.IsEmpty())
return v8::Null(isolate);
else
return v8::Local<v8::Value>::New(isolate, web_contents_);
}
v8::Local<v8::Value> Window::DevToolsWebContents(v8::Isolate* isolate) {
@@ -541,10 +525,9 @@ void Window::BuildPrototype(v8::Isolate* isolate,
.SetMethod("blurWebView", &Window::BlurWebView)
.SetMethod("isWebViewFocused", &Window::IsWebViewFocused)
.SetMethod("capturePage", &Window::CapturePage)
.SetMethod("print", &Window::Print)
.SetMethod("setProgressBar", &Window::SetProgressBar)
.SetMethod("setOverlayIcon", &Window::SetOverlayIcon)
.SetMethod("_setMenu", &Window::SetMenu)
.SetMethod("setMenu", &Window::SetMenu)
.SetMethod("setAutoHideMenuBar", &Window::SetAutoHideMenuBar)
.SetMethod("isMenuBarAutoHide", &Window::IsMenuBarAutoHide)
.SetMethod("setMenuBarVisibility", &Window::SetMenuBarVisibility)
@@ -557,6 +540,7 @@ void Window::BuildPrototype(v8::Isolate* isolate,
.SetMethod("showDefinitionForSelection",
&Window::ShowDefinitionForSelection)
#endif
.SetProperty("id", &Window::ID)
.SetProperty("webContents", &Window::WebContents)
.SetProperty("devToolsWebContents", &Window::DevToolsWebContents);
}
@@ -568,14 +552,21 @@ void Window::BuildPrototype(v8::Isolate* isolate,
namespace {
using atom::api::Window;
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
using atom::api::Window;
v8::Isolate* isolate = context->GetIsolate();
v8::Local<v8::Function> constructor = mate::CreateConstructor<Window>(
isolate, "BrowserWindow", base::Bind(&Window::New));
mate::Dictionary browser_window(isolate, constructor);
browser_window.SetMethod("fromId",
&mate::TrackableObject<Window>::FromWeakMapID);
browser_window.SetMethod("getAllWindows",
&mate::TrackableObject<Window>::GetAll);
mate::Dictionary dict(isolate, exports);
dict.Set("BrowserWindow", static_cast<v8::Local<v8::Value>>(constructor));
dict.Set("BrowserWindow", browser_window);
}
} // namespace

View File

@@ -10,8 +10,8 @@
#include "base/memory/scoped_ptr.h"
#include "ui/gfx/image/image.h"
#include "atom/browser/api/trackable_object.h"
#include "atom/browser/native_window_observer.h"
#include "atom/browser/api/event_emitter.h"
#include "native_mate/handle.h"
class GURL;
@@ -25,10 +25,6 @@ class Arguments;
class Dictionary;
}
namespace ui {
class SimpleMenuModel;
}
namespace atom {
class NativeWindow;
@@ -37,7 +33,7 @@ namespace api {
class WebContents;
class Window : public mate::EventEmitter,
class Window : public mate::TrackableObject<Window>,
public NativeWindowObserver {
public:
static mate::Wrappable* New(v8::Isolate* isolate,
@@ -49,17 +45,12 @@ class Window : public mate::EventEmitter,
NativeWindow* window() const { return window_.get(); }
protected:
explicit Window(const mate::Dictionary& options);
Window(v8::Isolate* isolate, const mate::Dictionary& options);
virtual ~Window();
// NativeWindowObserver:
void OnPageTitleUpdated(bool* prevent_default,
const std::string& title) override;
void WillCreatePopupWindow(const base::string16& frame_name,
const GURL& target_url,
const std::string& partition_id,
WindowOpenDisposition disposition) override;
void WillNavigate(bool* prevent_default, const GURL& url) override;
void WillCloseWindow(bool* prevent_default) override;
void OnWindowClosed() override;
void OnWindowBlur() override;
@@ -80,6 +71,7 @@ class Window : public mate::EventEmitter,
void OnDevToolsFocus() override;
void OnDevToolsOpened() override;
void OnDevToolsClosed() override;
void OnExecuteWindowsCommand(const std::string& command_name) override;
private:
// APIs for NativeWindow.
@@ -131,11 +123,10 @@ class Window : public mate::EventEmitter,
void SetDocumentEdited(bool edited);
bool IsDocumentEdited();
void CapturePage(mate::Arguments* args);
void Print(mate::Arguments* args);
void SetProgressBar(double progress);
void SetOverlayIcon(const gfx::Image& overlay,
const std::string& description);
void SetMenu(ui::SimpleMenuModel* menu);
void SetMenu(v8::Isolate* isolate, v8::Local<v8::Value> menu);
void SetAutoHideMenuBar(bool auto_hide);
bool IsMenuBarAutoHide();
void SetMenuBarVisibility(bool visible);
@@ -148,11 +139,15 @@ class Window : public mate::EventEmitter,
void SetVisibleOnAllWorkspaces(bool visible);
bool IsVisibleOnAllWorkspaces();
int32_t ID() const;
v8::Local<v8::Value> WebContents(v8::Isolate* isolate);
v8::Local<v8::Value> DevToolsWebContents(v8::Isolate* isolate);
v8::Global<v8::Value> web_contents_;
v8::Global<v8::Value> devtools_web_contents_;
v8::Global<v8::Value> menu_;
api::WebContents* api_web_contents_;
scoped_ptr<NativeWindow> window_;

View File

@@ -6,10 +6,9 @@
#include "atom/browser/api/event.h"
#include "native_mate/arguments.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "atom/common/node_includes.h"
namespace mate {
namespace {
@@ -17,8 +16,8 @@ namespace {
v8::Persistent<v8::ObjectTemplate> event_template;
void PreventDefault(mate::Arguments* args) {
args->GetThis()->Set(StringToV8(args->isolate(), "defaultPrevented"),
v8::True(args->isolate()));
mate::Dictionary self(args->isolate(), args->GetThis());
self.Set("defaultPrevented", true);
}
// Create a pure JavaScript Event object.
@@ -38,11 +37,9 @@ v8::Local<v8::Object> CreateEventObject(v8::Isolate* isolate) {
EventEmitter::EventEmitter() {
}
bool EventEmitter::CallEmit(v8::Isolate* isolate,
const base::StringPiece& name,
content::WebContents* sender,
IPC::Message* message,
ValueArray args) {
v8::Local<v8::Object> EventEmitter::CreateJSEvent(v8::Isolate* isolate,
content::WebContents* sender,
IPC::Message* message) {
v8::Local<v8::Object> event;
bool use_native_event = sender && message;
@@ -53,16 +50,8 @@ bool EventEmitter::CallEmit(v8::Isolate* isolate,
} else {
event = CreateEventObject(isolate);
}
// args = [name, event, args...];
args.insert(args.begin(), event);
args.insert(args.begin(), mate::StringToV8(isolate, name));
// this.emit.apply(this, args);
node::MakeCallback(isolate, GetWrapper(isolate), "emit", args.size(),
&args[0]);
return event->Get(StringToV8(isolate, "defaultPrevented"))->BooleanValue();
mate::Dictionary(isolate, event).Set("sender", GetWrapper(isolate));
return event;
}
} // namespace mate

View File

@@ -7,6 +7,7 @@
#include <vector>
#include "atom/common/event_emitter_caller.h"
#include "native_mate/wrappable.h"
namespace content {
@@ -24,9 +25,6 @@ class EventEmitter : public Wrappable {
public:
typedef std::vector<v8::Local<v8::Value>> ValueArray;
protected:
EventEmitter();
// this.emit(name, new Event(), args...);
template<typename... Args>
bool Emit(const base::StringPiece& name, const Args&... args) {
@@ -39,21 +37,21 @@ class EventEmitter : public Wrappable {
content::WebContents* sender,
IPC::Message* message,
const Args&... args) {
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
ValueArray converted = { ConvertToV8(isolate, args)... };
return CallEmit(isolate, name, sender, message, converted);
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
v8::Local<v8::Object> event = CreateJSEvent(isolate(), sender, message);
EmitEvent(isolate(), GetWrapper(isolate()), name, event, args...);
return event->Get(
StringToV8(isolate(), "defaultPrevented"))->BooleanValue();
}
protected:
EventEmitter();
private:
// Lower level implementations.
bool CallEmit(v8::Isolate* isolate,
const base::StringPiece& name,
content::WebContents* sender,
IPC::Message* message,
ValueArray args);
v8::Local<v8::Object> CreateJSEvent(v8::Isolate* isolate,
content::WebContents* sender,
IPC::Message* message);
DISALLOW_COPY_AND_ASSIGN(EventEmitter);
};

View File

@@ -26,12 +26,13 @@ if process.platform is 'darwin'
setMenu: bindings.dockSetMenu
# Be compatible with old API.
app.once 'ready', -> app.emit 'finish-launching'
app.once 'ready', -> @emit 'finish-launching'
app.terminate = app.quit
app.exit = process.exit
app.getHomeDir = -> app.getPath 'home'
app.getDataPath = -> app.getPath 'userData'
app.setDataPath = (path) -> app.setPath 'userData', path
app.getHomeDir = -> @getPath 'home'
app.getDataPath = -> @getPath 'userData'
app.setDataPath = (path) -> @setPath 'userData', path
app.resolveProxy = -> @defaultSession.resolveProxy.apply @defaultSession, arguments
# Only one App object pemitted.
module.exports = app

View File

@@ -1,49 +1,35 @@
EventEmitter = require('events').EventEmitter
IDWeakMap = require 'id-weak-map'
app = require 'app'
ipc = require 'ipc'
BrowserWindow = process.atomBinding('window').BrowserWindow
BrowserWindow::__proto__ = EventEmitter.prototype
# Store all created windows in the weak map.
BrowserWindow.windows = new IDWeakMap
BrowserWindow::_init = ->
# Simulate the application menu on platforms other than OS X.
if process.platform isnt 'darwin'
menu = app.getApplicationMenu()
@setMenu menu if menu?
# Remember the window ID.
Object.defineProperty this, 'id',
value: BrowserWindow.windows.add(this)
enumerable: true
# Make new windows requested by links behave like "window.open"
@on '-new-window', (event, url, frameName) =>
event.sender = @webContents
@webContents.on '-new-window', (event, url, frameName) ->
options = show: true, width: 800, height: 600
ipc.emit 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', event, url, frameName, options
# Redirect "will-navigate" to webContents.
@on '-will-navigate', (event, url) =>
@webContents.emit 'will-navigate', event, url
# window.move(...)
@webContents.on 'move', (event, size) =>
@setSize size
# Remove the window from weak map immediately when it's destroyed, since we
# could be iterating windows before GC happened.
@once 'closed', =>
BrowserWindow.windows.remove @id if BrowserWindow.windows.has @id
# Hide the auto-hide menu when webContents is focused.
@webContents.on 'activate', =>
if process.platform isnt 'darwin' and @isMenuBarAutoHide() and @isMenuBarVisible()
@setMenuBarVisibility false
BrowserWindow::setMenu = (menu) ->
throw new TypeError('Invalid menu') unless menu is null or menu?.constructor?.name is 'Menu'
@menu = menu # Keep a reference of menu in case of GC.
@_setMenu menu
BrowserWindow.getAllWindows = ->
windows = BrowserWindow.windows
windows.get key for key in windows.keys()
# Redirect focus/blur event to app instance too.
@on 'blur', (event) =>
app.emit 'browser-window-blur', event, this
@on 'focus', (event) =>
app.emit 'browser-window-focus', event, this
BrowserWindow.getFocusedWindow = ->
windows = BrowserWindow.getAllWindows()
@@ -57,9 +43,6 @@ BrowserWindow.fromDevToolsWebContents = (webContents) ->
windows = BrowserWindow.getAllWindows()
return window for window in windows when window.devToolsWebContents?.equal webContents
BrowserWindow.fromId = (id) ->
BrowserWindow.windows.get id
# Helpers.
BrowserWindow::loadUrl = -> @webContents.loadUrl.apply @webContents, arguments
BrowserWindow::send = -> @webContents.send.apply @webContents, arguments
@@ -73,8 +56,6 @@ BrowserWindow::getPageTitle = -> @webContents.getTitle()
BrowserWindow::isLoading = -> @webContents.isLoading()
BrowserWindow::isWaitingForResponse = -> @webContents.isWaitingForResponse()
BrowserWindow::stop = -> @webContents.stop()
BrowserWindow::getRoutingId = -> @webContents.getRoutingId()
BrowserWindow::getProcessId = -> @webContents.getProcessId()
BrowserWindow::isCrashed = -> @webContents.isCrashed()
BrowserWindow::executeJavaScriptInDevTools = (code) -> @devToolsWebContents?.executeJavaScript code
BrowserWindow::openDevTools = -> @webContents.openDevTools.apply @webContents, arguments
@@ -83,5 +64,7 @@ BrowserWindow::isDevToolsOpened = -> @webContents.isDevToolsOpened()
BrowserWindow::toggleDevTools = -> @webContents.toggleDevTools()
BrowserWindow::inspectElement = -> @webContents.inspectElement.apply @webContents, arguments
BrowserWindow::inspectServiceWorker = -> @webContents.inspectServiceWorker()
BrowserWindow::print = -> @webContents.print.apply @webContents, arguments
BrowserWindow::printToPDF = -> @webContents.printToPDF.apply @webContents, arguments
module.exports = BrowserWindow

View File

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

View File

@@ -34,4 +34,8 @@ protocol.RequestErrorJob =
class RequestErrorJob
constructor: (@error) ->
protocol.RequestHttpJob =
class RequestHttpJob
constructor: ({@url, @method, @referrer}) ->
module.exports = protocol

View File

@@ -3,6 +3,9 @@ NavigationController = require './navigation-controller'
binding = process.atomBinding 'web_contents'
ipc = require 'ipc'
nextId = 0
getNextId = -> ++nextId
wrapWebContents = (webContents) ->
# webContents is an EventEmitter.
webContents.__proto__ = EventEmitter.prototype
@@ -21,44 +24,60 @@ wrapWebContents = (webContents) ->
else
webContents.once 'did-finish-load', @_executeJavaScript.bind(this, code)
# The processId and routingId and identify a webContents.
webContents.getId = -> "#{@getProcessId()}-#{@getRoutingId()}"
webContents.equal = (other) -> @getId() is other.getId()
# The navigation controller.
controller = new NavigationController(webContents)
for name, method of NavigationController.prototype when method instanceof Function
do (name, method) ->
webContents[name] = -> method.apply controller, arguments
# Translate |disposition| to string for 'new-window' event.
webContents.on '-new-window', (args..., disposition) ->
disposition =
switch disposition
when 2 then 'default'
when 4 then 'foreground-tab'
when 5 then 'background-tab'
when 6, 7 then 'new-window'
else 'other'
@emit 'new-window', args..., disposition
# Tell the rpc server that a render view has been deleted and we need to
# release all objects owned by it.
webContents.on 'render-view-deleted', (event, processId, routingId) ->
process.emit 'ATOM_BROWSER_RELEASE_RENDER_VIEW', "#{processId}-#{routingId}"
# Dispatch IPC messages to the ipc module.
webContents.on 'ipc-message', (event, packed) ->
[channel, args...] = packed
Object.defineProperty event, 'sender', value: webContents
ipc.emit channel, event, args...
webContents.on 'ipc-message-sync', (event, packed) ->
[channel, args...] = packed
Object.defineProperty event, 'returnValue', set: (value) -> event.sendReply JSON.stringify(value)
Object.defineProperty event, 'sender', value: webContents
ipc.emit channel, event, args...
webContents
webContents.printToPDF = (options, callback) ->
printingSetting =
pageRage:[],
mediaSize:
height_microns:297000,
is_default:true,
name:"ISO_A4",
width_microns:210000,
custom_display_name:"A4",
landscape:false,
color:2,
headerFooterEnabled:false,
marginsType:0,
isFirstRequest:false,
requestID: getNextId(),
previewModifiable:true,
printToPDF:true,
printWithCloudPrint:false,
printWithPrivet:false,
printWithExtension:false,
deviceName:"Save as PDF",
generateDraftData:true,
fitToPageEnabled:false,
duplex:0,
copies:1,
collate:true,
shouldPrintBackgrounds:false,
shouldPrintSelectionOnly:false
if options.landscape
printingSetting.landscape = options.landscape
if options.marginsType
printingSetting.marginsType = options.marginsType
if options.printSelectionOnly
printingSetting.shouldPrintSelectionOnly = options.printSelectionOnly
if options.printBackgrounds
printingSetting.shouldPrintBackgrounds = options.printBackground
@_printToPDF printingSetting, callback
binding._setWrapWebContents wrapWebContents
process.once 'exit', binding._clearWrapWebContents

View File

@@ -0,0 +1,68 @@
// 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/trackable_object.h"
#include "atom/browser/atom_browser_main_parts.h"
#include "base/bind.h"
#include "base/supports_user_data.h"
namespace mate {
namespace {
const char* kTrackedObjectKey = "TrackedObjectKey";
class IDUserData : public base::SupportsUserData::Data {
public:
explicit IDUserData(int32_t id) : id_(id) {}
operator int32_t() const { return id_; }
private:
int32_t id_;
DISALLOW_COPY_AND_ASSIGN(IDUserData);
};
} // namespace
TrackableObjectBase::TrackableObjectBase()
: weak_map_id_(0), wrapped_(nullptr) {
}
TrackableObjectBase::~TrackableObjectBase() {
}
void TrackableObjectBase::AfterInit(v8::Isolate* isolate) {
if (wrapped_)
AttachAsUserData(wrapped_);
}
void TrackableObjectBase::AttachAsUserData(base::SupportsUserData* wrapped) {
if (weak_map_id_ != 0) {
wrapped->SetUserData(kTrackedObjectKey, new IDUserData(weak_map_id_));
wrapped_ = nullptr;
} else {
// If the TrackableObjectBase is not ready yet then delay SetUserData until
// AfterInit is called.
wrapped_ = wrapped;
}
}
// static
int32_t TrackableObjectBase::GetIDFromWrappedClass(base::SupportsUserData* w) {
auto id = static_cast<IDUserData*>(w->GetUserData(kTrackedObjectKey));
if (id)
return *id;
else
return 0;
}
// static
void TrackableObjectBase::RegisterDestructionCallback(void (*c)()) {
atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(base::Bind(c));
}
} // namespace mate

View File

@@ -0,0 +1,116 @@
// 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_TRACKABLE_OBJECT_H_
#define ATOM_BROWSER_API_TRACKABLE_OBJECT_H_
#include <vector>
#include "atom/browser/api/event_emitter.h"
#include "atom/common/id_weak_map.h"
namespace base {
class SupportsUserData;
}
namespace mate {
// Users should use TrackableObject instead.
class TrackableObjectBase : public mate::EventEmitter {
public:
TrackableObjectBase();
// The ID in weak map.
int32_t weak_map_id() const { return weak_map_id_; }
// Wrap TrackableObject into a class that SupportsUserData.
void AttachAsUserData(base::SupportsUserData* wrapped);
protected:
~TrackableObjectBase() override;
// mate::Wrappable:
void AfterInit(v8::Isolate* isolate) override;
// Get the weak_map_id from SupportsUserData.
static int32_t GetIDFromWrappedClass(base::SupportsUserData* wrapped);
// Register a callback that should be destroyed before JavaScript environment
// gets destroyed.
static void RegisterDestructionCallback(void (*callback)());
int32_t weak_map_id_;
base::SupportsUserData* wrapped_;
private:
DISALLOW_COPY_AND_ASSIGN(TrackableObjectBase);
};
// All instances of TrackableObject will be kept in a weak map and can be got
// from its ID.
template<typename T>
class TrackableObject : public TrackableObjectBase {
public:
// Finds out the TrackableObject from its ID in weak map.
static T* FromWeakMapID(v8::Isolate* isolate, int32_t id) {
v8::MaybeLocal<v8::Object> object = weak_map_.Get(isolate, id);
if (object.IsEmpty())
return nullptr;
T* self = nullptr;
mate::ConvertFromV8(isolate, object.ToLocalChecked(), &self);
return self;
}
// Finds out the TrackableObject from the class it wraps.
static T* FromWrappedClass(v8::Isolate* isolate,
base::SupportsUserData* wrapped) {
int32_t id = GetIDFromWrappedClass(wrapped);
if (!id)
return nullptr;
return FromWeakMapID(isolate, id);
}
// Returns all objects in this class's weak map.
static std::vector<v8::Local<v8::Object>> GetAll(v8::Isolate* isolate) {
return weak_map_.Values(isolate);
}
TrackableObject() {
RegisterDestructionCallback(&TrackableObject<T>::ReleaseAllWeakReferences);
}
// Removes this instance from the weak map.
void RemoveFromWeakMap() {
if (weak_map_.Has(weak_map_id()))
weak_map_.Remove(weak_map_id());
}
protected:
~TrackableObject() override {
RemoveFromWeakMap();
}
void AfterInit(v8::Isolate* isolate) override {
weak_map_id_ = weak_map_.Add(isolate, GetWrapper(isolate));
TrackableObjectBase::AfterInit(isolate);
}
private:
// Releases all weak references in weak map, called when app is terminating.
static void ReleaseAllWeakReferences() {
weak_map_.Clear();
}
static atom::IDWeakMap weak_map_;
DISALLOW_COPY_AND_ASSIGN(TrackableObject);
};
template<typename T>
atom::IDWeakMap TrackableObject<T>::weak_map_;
} // namespace mate
#endif // ATOM_BROWSER_API_TRACKABLE_OBJECT_H_

View File

@@ -7,6 +7,7 @@
#include <utility>
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/common/google_api_key.h"
namespace atom {
@@ -39,8 +40,8 @@ void AtomAccessTokenStore::LoadAccessTokens(
token_pair.first = GURL(kGeolocationProviderUrl);
access_token_set.insert(token_pair);
callback.Run(access_token_set,
AtomBrowserContext::Get()->url_request_context_getter());
auto browser_context = AtomBrowserMainParts::Get()->browser_context();
callback.Run(access_token_set, browser_context->url_request_context_getter());
}
void AtomAccessTokenStore::SaveAccessToken(const GURL& server_url,

View File

@@ -9,12 +9,14 @@
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/browser/atom_quota_permission_context.h"
#include "atom/browser/atom_speech_recognition_manager_delegate.h"
#include "atom/browser/browser.h"
#include "atom/browser/native_window.h"
#include "atom/browser/web_view_manager.h"
#include "atom/browser/window_list.h"
#include "atom/common/options_switches.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/strings/string_util.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/printing/printing_message_filter.h"
#include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h"
@@ -43,6 +45,9 @@ int kDefaultRoutingID = 2;
// Next navigation should not restart renderer process.
bool g_suppress_renderer_process_restart = false;
// Custom schemes to be registered to standard.
std::string g_custom_schemes = "";
// Find out the owner of the child process according to |process_id|.
enum ProcessOwner {
OWNER_NATIVE_WINDOW,
@@ -59,7 +64,7 @@ ProcessOwner GetProcessOwner(int process_id,
// First search for NativeWindow.
for (auto native_window : *WindowList::GetInstance())
if (web_contents == native_window->GetWebContents()) {
if (web_contents == native_window->web_contents()) {
*window = native_window;
return OWNER_NATIVE_WINDOW;
}
@@ -73,6 +78,9 @@ ProcessOwner GetProcessOwner(int process_id,
scoped_refptr<net::X509Certificate> ImportCertFromFile(
const base::FilePath& path) {
if (path.empty())
return nullptr;
std::string cert_data;
if (!base::ReadFileToString(path, &cert_data))
return nullptr;
@@ -95,6 +103,11 @@ void AtomBrowserClient::SuppressRendererProcessRestartForOnce() {
g_suppress_renderer_process_restart = true;
}
void AtomBrowserClient::SetCustomSchemes(
const std::vector<std::string>& schemes) {
g_custom_schemes = JoinString(schemes, ',');
}
AtomBrowserClient::AtomBrowserClient() {
}
@@ -103,9 +116,9 @@ AtomBrowserClient::~AtomBrowserClient() {
void AtomBrowserClient::RenderProcessWillLaunch(
content::RenderProcessHost* host) {
int id = host->GetID();
host->AddFilter(new printing::PrintingMessageFilter(host->GetID()));
host->AddFilter(new TtsMessageFilter(id, host->GetBrowserContext()));
int process_id = host->GetID();
host->AddFilter(new printing::PrintingMessageFilter(process_id));
host->AddFilter(new TtsMessageFilter(process_id, host->GetBrowserContext()));
}
content::SpeechRecognitionManagerDelegate*
@@ -177,6 +190,10 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches(
if (process_type != "renderer")
return;
if (!g_custom_schemes.empty())
command_line->AppendSwitchASCII(switches::kRegisterStandardSchemes,
g_custom_schemes);
NativeWindow* window;
WebViewManager::WebViewInfo info;
ProcessOwner owner = GetProcessOwner(process_id, &window, &info);
@@ -197,12 +214,12 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches(
}
void AtomBrowserClient::DidCreatePpapiPlugin(
content::BrowserPpapiHost* browser_host) {
content::BrowserPpapiHost* host) {
auto command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kEnablePlugins))
browser_host->GetPpapiHost()->AddHostFactoryFilter(
scoped_ptr<ppapi::host::HostFactory>(
new chrome::ChromeBrowserPepperHostFactory(browser_host)));
if (command_line->HasSwitch(switches::kEnablePlugins)) {
host->GetPpapiHost()->AddHostFactoryFilter(
make_scoped_ptr(new chrome::ChromeBrowserPepperHostFactory(host)));
}
}
content::QuotaPermissionContext*
@@ -214,23 +231,20 @@ void AtomBrowserClient::SelectClientCertificate(
content::WebContents* web_contents,
net::SSLCertRequestInfo* cert_request_info,
scoped_ptr<content::ClientCertificateDelegate> delegate) {
auto command_line = base::CommandLine::ForCurrentProcess();
auto cert_path = command_line->GetSwitchValueNative(
switches::kClientCertificate);
// TODO(zcbenz): allow users to select certificate from
// client_cert list. Right now defaults to first certificate
// in the list.
scoped_refptr<net::X509Certificate> certificate;
if (cert_path.empty()) {
if (!cert_request_info->client_certs.empty())
certificate = cert_request_info->client_certs[0];
} else {
certificate = ImportCertFromFile(base::FilePath(cert_path));
// --client-certificate=`path`
auto cmd = base::CommandLine::ForCurrentProcess();
if (cmd->HasSwitch(switches::kClientCertificate)) {
auto cert_path = cmd->GetSwitchValuePath(switches::kClientCertificate);
auto certificate = ImportCertFromFile(cert_path);
if (certificate.get())
delegate->ContinueWithCertificate(certificate.get());
return;
}
if (certificate.get())
delegate->ContinueWithCertificate(certificate.get());
if (!cert_request_info->client_certs.empty())
Browser::Get()->ClientCertificateSelector(web_contents,
cert_request_info,
delegate.Pass());
}
brightray::BrowserMainParts* AtomBrowserClient::OverrideCreateBrowserMainParts(

View File

@@ -6,6 +6,7 @@
#define ATOM_BROWSER_ATOM_BROWSER_CLIENT_H_
#include <string>
#include <vector>
#include "brightray/browser/browser_client.h"
@@ -27,6 +28,8 @@ class AtomBrowserClient : public brightray::BrowserClient {
// Don't force renderer process to restart for once.
static void SuppressRendererProcessRestartForOnce();
// Custom schemes to be registered to standard.
static void SetCustomSchemes(const std::vector<std::string>& schemes);
protected:
// content::ContentBrowserClient:
@@ -41,7 +44,7 @@ class AtomBrowserClient : public brightray::BrowserClient {
content::BrowserContext* browser_context,
content::SiteInstance* current_instance,
const GURL& dest_url,
content::SiteInstance** new_instance);
content::SiteInstance** new_instance) override;
void AppendExtraCommandLineSwitches(base::CommandLine* command_line,
int child_process_id) override;
void DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) override;

View File

@@ -5,6 +5,7 @@
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/browser/atom_download_manager_delegate.h"
#include "atom/browser/net/atom_url_request_job_factory.h"
#include "atom/browser/net/asar/asar_protocol_handler.h"
#include "atom/browser/net/http_protocol_handler.h"
@@ -13,7 +14,6 @@
#include "base/command_line.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/worker_pool.h"
#include "chrome/browser/browser_process.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/url_constants.h"
#include "net/ftp/ftp_network_layer.h"
@@ -40,8 +40,7 @@ class NoCacheBackend : public net::HttpCache::BackendFactory {
} // namespace
AtomBrowserContext::AtomBrowserContext()
: fake_browser_process_(new BrowserProcess),
job_factory_(new AtomURLRequestJobFactory) {
: job_factory_(new AtomURLRequestJobFactory) {
}
AtomBrowserContext::~AtomBrowserContext() {
@@ -100,16 +99,20 @@ AtomBrowserContext::CreateHttpCacheBackendFactory(
return brightray::BrowserContext::CreateHttpCacheBackendFactory(base_path);
}
content::DownloadManagerDelegate*
AtomBrowserContext::GetDownloadManagerDelegate() {
if (!download_manager_delegate_.get()) {
auto download_manager = content::BrowserContext::GetDownloadManager(this);
download_manager_delegate_.reset(
new AtomDownloadManagerDelegate(download_manager));
}
return download_manager_delegate_.get();
}
content::BrowserPluginGuestManager* AtomBrowserContext::GetGuestManager() {
if (!guest_manager_)
guest_manager_.reset(new WebViewManager(this));
return guest_manager_.get();
}
// static
AtomBrowserContext* AtomBrowserContext::Get() {
return static_cast<AtomBrowserContext*>(
AtomBrowserMainParts::Get()->browser_context());
}
} // namespace atom

View File

@@ -7,10 +7,9 @@
#include "brightray/browser/browser_context.h"
class BrowserProcess;
namespace atom {
class AtomDownloadManagerDelegate;
class AtomURLRequestJobFactory;
class WebViewManager;
@@ -19,9 +18,6 @@ class AtomBrowserContext : public brightray::BrowserContext {
AtomBrowserContext();
virtual ~AtomBrowserContext();
// Returns the browser context singleton.
static AtomBrowserContext* Get();
// brightray::URLRequestContextGetter::Delegate:
net::URLRequestJobFactory* CreateURLRequestJobFactory(
content::ProtocolHandlerMap* handlers,
@@ -30,13 +26,13 @@ class AtomBrowserContext : public brightray::BrowserContext {
const base::FilePath& base_path) override;
// content::BrowserContext:
content::DownloadManagerDelegate* GetDownloadManagerDelegate() override;
content::BrowserPluginGuestManager* GetGuestManager() override;
AtomURLRequestJobFactory* job_factory() const { return job_factory_; }
private:
// A fake BrowserProcess object that used to feed the source code from chrome.
scoped_ptr<BrowserProcess> fake_browser_process_;
scoped_ptr<AtomDownloadManagerDelegate> download_manager_delegate_;
scoped_ptr<WebViewManager> guest_manager_;
AtomURLRequestJobFactory* job_factory_; // Weak reference.

View File

@@ -4,6 +4,7 @@
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/browser/api/trackable_object.h"
#include "atom/browser/atom_browser_client.h"
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/browser.h"
@@ -11,6 +12,7 @@
#include "atom/common/api/atom_bindings.h"
#include "atom/common/node_bindings.h"
#include "base/command_line.h"
#include "chrome/browser/browser_process.h"
#include "v8/include/v8-debug.h"
#if defined(USE_X11)
@@ -25,7 +27,8 @@ namespace atom {
AtomBrowserMainParts* AtomBrowserMainParts::self_ = NULL;
AtomBrowserMainParts::AtomBrowserMainParts()
: browser_(new Browser),
: fake_browser_process_(new BrowserProcess),
browser_(new Browser),
node_bindings_(NodeBindings::Create(true)),
atom_bindings_(new AtomBindings),
gc_timer_(true, true) {
@@ -34,6 +37,8 @@ AtomBrowserMainParts::AtomBrowserMainParts()
}
AtomBrowserMainParts::~AtomBrowserMainParts() {
for (const auto& callback : destruction_callbacks_)
callback.Run();
}
// static
@@ -42,6 +47,11 @@ AtomBrowserMainParts* AtomBrowserMainParts::Get() {
return self_;
}
void AtomBrowserMainParts::RegisterDestructionCallback(
const base::Closure& callback) {
destruction_callbacks_.push_back(callback);
}
brightray::BrowserContext* AtomBrowserMainParts::CreateBrowserContext() {
return new AtomBrowserContext();
}

View File

@@ -5,9 +5,14 @@
#ifndef ATOM_BROWSER_ATOM_BROWSER_MAIN_PARTS_H_
#define ATOM_BROWSER_ATOM_BROWSER_MAIN_PARTS_H_
#include <list>
#include "base/callback.h"
#include "base/timer/timer.h"
#include "brightray/browser/browser_main_parts.h"
class BrowserProcess;
namespace atom {
class AtomBindings;
@@ -22,6 +27,10 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
static AtomBrowserMainParts* Get();
// Register a callback that should be destroyed before JavaScript environment
// gets destroyed.
void RegisterDestructionCallback(const base::Closure& callback);
Browser* browser() { return browser_.get(); }
protected:
@@ -41,6 +50,9 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
void SetDPIFromGSettings();
#endif
// A fake BrowserProcess object that used to feed the source code from chrome.
scoped_ptr<BrowserProcess> fake_browser_process_;
scoped_ptr<Browser> browser_;
scoped_ptr<JavascriptEnvironment> js_env_;
scoped_ptr<NodeBindings> node_bindings_;
@@ -48,6 +60,9 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
base::Timer gc_timer_;
// List of callbacks should be executed before destroying JS env.
std::list<base::Closure> destruction_callbacks_;
static AtomBrowserMainParts* self_;
DISALLOW_COPY_AND_ASSIGN(AtomBrowserMainParts);

View File

@@ -0,0 +1,138 @@
// 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/atom_download_manager_delegate.h"
#include <string>
#include "atom/browser/native_window.h"
#include "atom/browser/ui/file_dialog.h"
#include "base/bind.h"
#include "base/files/file_util.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_manager.h"
#include "net/base/filename_util.h"
namespace atom {
AtomDownloadManagerDelegate::AtomDownloadManagerDelegate(
content::DownloadManager* manager)
: download_manager_(manager),
weak_ptr_factory_(this) {}
AtomDownloadManagerDelegate::~AtomDownloadManagerDelegate() {
if (download_manager_) {
DCHECK_EQ(static_cast<content::DownloadManagerDelegate*>(this),
download_manager_->GetDelegate());
download_manager_->SetDelegate(nullptr);
download_manager_ = nullptr;
}
}
void AtomDownloadManagerDelegate::CreateDownloadPath(
const GURL& url,
const std::string& content_disposition,
const std::string& suggested_filename,
const std::string& mime_type,
const base::FilePath& default_download_path,
const CreateDownloadPathCallback& callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
auto generated_name = net::GenerateFileName(url,
content_disposition,
std::string(),
suggested_filename,
mime_type,
std::string());
if (!base::PathExists(default_download_path))
base::CreateDirectory(default_download_path);
base::FilePath path(default_download_path.Append(generated_name));
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
base::Bind(callback, path));
}
void AtomDownloadManagerDelegate::OnDownloadPathGenerated(
uint32 download_id,
const content::DownloadTargetCallback& callback,
const base::FilePath& default_path) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
auto item = download_manager_->GetDownload(download_id);
if (!item)
return;
NativeWindow* window = nullptr;
auto relay = NativeWindowRelay::FromWebContents(item->GetWebContents());
if (relay)
window = relay->window.get();
file_dialog::Filters filters;
base::FilePath path;
if (!file_dialog::ShowSaveDialog(window, item->GetURL().spec(), default_path,
filters, &path)) {
return;
}
callback.Run(path,
content::DownloadItem::TARGET_DISPOSITION_PROMPT,
content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, path);
}
void AtomDownloadManagerDelegate::Shutdown() {
weak_ptr_factory_.InvalidateWeakPtrs();
download_manager_ = nullptr;
}
bool AtomDownloadManagerDelegate::DetermineDownloadTarget(
content::DownloadItem* download,
const content::DownloadTargetCallback& callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (default_download_path_.empty()) {
auto path = download_manager_->GetBrowserContext()->GetPath();
default_download_path_ = path.Append(FILE_PATH_LITERAL("Downloads"));
}
if (!download->GetForcedFilePath().empty()) {
callback.Run(download->GetForcedFilePath(),
content::DownloadItem::TARGET_DISPOSITION_OVERWRITE,
content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
download->GetForcedFilePath());
return true;
}
CreateDownloadPathCallback download_path_callback =
base::Bind(&AtomDownloadManagerDelegate::OnDownloadPathGenerated,
weak_ptr_factory_.GetWeakPtr(),
download->GetId(), callback);
content::BrowserThread::PostTask(
content::BrowserThread::FILE, FROM_HERE,
base::Bind(&AtomDownloadManagerDelegate::CreateDownloadPath,
weak_ptr_factory_.GetWeakPtr(),
download->GetURL(),
download->GetContentDisposition(),
download->GetSuggestedFilename(),
download->GetMimeType(),
default_download_path_,
download_path_callback));
return true;
}
bool AtomDownloadManagerDelegate::ShouldOpenDownload(
content::DownloadItem* download,
const content::DownloadOpenDelayedCallback& callback) {
return true;
}
void AtomDownloadManagerDelegate::GetNextId(
const content::DownloadIdCallback& callback) {
static uint32 next_id = content::DownloadItem::kInvalidId + 1;
callback.Run(next_id++);
}
} // namespace atom

View File

@@ -0,0 +1,58 @@
// 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_ATOM_DOWNLOAD_MANAGER_DELEGATE_H_
#define ATOM_BROWSER_ATOM_DOWNLOAD_MANAGER_DELEGATE_H_
#include <string>
#include "base/memory/weak_ptr.h"
#include "content/public/browser/download_manager_delegate.h"
namespace content {
class DownloadManager;
}
namespace atom {
class AtomDownloadManagerDelegate : public content::DownloadManagerDelegate {
public:
using CreateDownloadPathCallback =
base::Callback<void(const base::FilePath&)>;
explicit AtomDownloadManagerDelegate(content::DownloadManager* manager);
virtual ~AtomDownloadManagerDelegate();
// Generate default file path to save the download.
void CreateDownloadPath(const GURL& url,
const std::string& suggested_filename,
const std::string& content_disposition,
const std::string& mime_type,
const base::FilePath& path,
const CreateDownloadPathCallback& callback);
void OnDownloadPathGenerated(uint32 download_id,
const content::DownloadTargetCallback& callback,
const base::FilePath& default_path);
// content::DownloadManagerDelegate:
void Shutdown() override;
bool DetermineDownloadTarget(
content::DownloadItem* download,
const content::DownloadTargetCallback& callback) override;
bool ShouldOpenDownload(
content::DownloadItem* download,
const content::DownloadOpenDelayedCallback& callback) override;
void GetNextId(const content::DownloadIdCallback& callback) override;
private:
content::DownloadManager* download_manager_;
base::FilePath default_download_path_;
base::WeakPtrFactory<AtomDownloadManagerDelegate> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(AtomDownloadManagerDelegate);
};
} // namespace atom
#endif // ATOM_BROWSER_ATOM_DOWNLOAD_MANAGER_DELEGATE_H_

View File

@@ -9,6 +9,8 @@
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/browser/window_list.h"
#include "base/message_loop/message_loop.h"
#include "content/public/browser/client_certificate_delegate.h"
#include "net/ssl/ssl_cert_request_info.h"
namespace atom {
@@ -104,6 +106,17 @@ void Browser::DidFinishLaunching() {
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnFinishLaunching());
}
void Browser::ClientCertificateSelector(
content::WebContents* web_contents,
net::SSLCertRequestInfo* cert_request_info,
scoped_ptr<content::ClientCertificateDelegate> delegate) {
FOR_EACH_OBSERVER(BrowserObserver,
observers_,
OnSelectCertificate(web_contents,
cert_request_info,
delegate.Pass()));
}
void Browser::NotifyAndShutdown() {
bool prevent_default = false;
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnWillQuit(&prevent_default));

View File

@@ -115,6 +115,12 @@ class Browser : public WindowListObserver {
void WillFinishLaunching();
void DidFinishLaunching();
// Called when client certificate is required.
void ClientCertificateSelector(
content::WebContents* web_contents,
net::SSLCertRequestInfo* cert_request_info,
scoped_ptr<content::ClientCertificateDelegate> delegate);
void AddObserver(BrowserObserver* obs) {
observers_.AddObserver(obs);
}

View File

@@ -7,6 +7,17 @@
#include <string>
#include "base/memory/scoped_ptr.h"
#include "content/public/browser/client_certificate_delegate.h"
namespace content {
class WebContents;
}
namespace net {
class SSLCertRequestInfo;
}
namespace atom {
class BrowserObserver {
@@ -40,6 +51,12 @@ class BrowserObserver {
virtual void OnWillFinishLaunching() {}
virtual void OnFinishLaunching() {}
// The browser requires client certificate.
virtual void OnSelectCertificate(
content::WebContents* web_contents,
net::SSLCertRequestInfo* cert_request_info,
scoped_ptr<content::ClientCertificateDelegate> delegate) {}
protected:
virtual ~BrowserObserver() {}
};

View File

@@ -12,13 +12,17 @@
#include "atom/browser/ui/file_dialog.h"
#include "atom/browser/web_dialog_helper.h"
#include "base/files/file_util.h"
#include "chrome/browser/printing/print_preview_message_handler.h"
#include "chrome/browser/printing/print_view_manager_basic.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/common/renderer_preferences.h"
#include "storage/browser/fileapi/isolated_context.h"
using content::BrowserThread;
namespace atom {
namespace {
@@ -85,12 +89,26 @@ base::DictionaryValue* CreateFileSystemValue(const FileSystem& file_system) {
return file_system_value;
}
void WriteToFile(const base::FilePath& path,
const std::string& content) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
DCHECK(!path.empty());
base::WriteFile(path, content.data(), content.size());
}
void AppendToFile(const base::FilePath& path,
const std::string& content) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
DCHECK(!path.empty());
base::AppendToFile(path, content.data(), content.size());
}
} // namespace
CommonWebContentsDelegate::CommonWebContentsDelegate(bool is_guest)
: is_guest_(is_guest),
owner_window_(nullptr),
html_fullscreen_(false),
CommonWebContentsDelegate::CommonWebContentsDelegate()
: html_fullscreen_(false),
native_fullscreen_(false) {
}
@@ -98,22 +116,24 @@ CommonWebContentsDelegate::~CommonWebContentsDelegate() {
}
void CommonWebContentsDelegate::InitWithWebContents(
content::WebContents* web_contents,
NativeWindow* owner_window) {
owner_window_ = owner_window;
content::WebContents* web_contents) {
web_contents->SetDelegate(this);
// Tell renderer to handle all navigations in browser.
auto preferences = web_contents->GetMutableRendererPrefs();
preferences->browser_handles_non_local_top_level_requests = true;
preferences->browser_handles_all_top_level_requests = true;
web_contents->GetRenderViewHost()->SyncRendererPrefs();
printing::PrintViewManagerBasic::CreateForWebContents(web_contents);
printing::PrintPreviewMessageHandler::CreateForWebContents(web_contents);
// Create InspectableWebContents.
web_contents_.reset(brightray::InspectableWebContents::Create(web_contents));
web_contents_->SetDelegate(this);
}
void CommonWebContentsDelegate::SetOwnerWindow(NativeWindow* owner_window) {
content::WebContents* web_contents = GetWebContents();
owner_window_ = owner_window->GetWeakPtr();
NativeWindowRelay* relay = new NativeWindowRelay(owner_window_);
web_contents->SetUserData(relay->key, relay);
}
void CommonWebContentsDelegate::DestroyWebContents() {
web_contents_.reset();
}
@@ -160,11 +180,6 @@ bool CommonWebContentsDelegate::CanOverscrollContent() const {
return false;
}
bool CommonWebContentsDelegate::IsPopupOrPanel(
const content::WebContents* source) const {
return !is_guest_;
}
content::JavaScriptDialogManager*
CommonWebContentsDelegate::GetJavaScriptDialogManager(
content::WebContents* source) {
@@ -185,7 +200,7 @@ void CommonWebContentsDelegate::RunFileChooser(
content::WebContents* guest,
const content::FileChooserParams& params) {
if (!web_dialog_helper_)
web_dialog_helper_.reset(new WebDialogHelper(owner_window_));
web_dialog_helper_.reset(new WebDialogHelper(owner_window()));
web_dialog_helper_->RunFileChooser(guest, params);
}
@@ -193,7 +208,7 @@ void CommonWebContentsDelegate::EnumerateDirectory(content::WebContents* guest,
int request_id,
const base::FilePath& path) {
if (!web_dialog_helper_)
web_dialog_helper_.reset(new WebDialogHelper(owner_window_));
web_dialog_helper_.reset(new WebDialogHelper(owner_window()));
web_dialog_helper_->EnumerateDirectory(guest, request_id, path);
}
@@ -229,7 +244,7 @@ void CommonWebContentsDelegate::DevToolsSaveToFile(
} else {
file_dialog::Filters filters;
base::FilePath default_path(base::FilePath::FromUTF8Unsafe(url));
if (!file_dialog::ShowSaveDialog(owner_window_, url, default_path,
if (!file_dialog::ShowSaveDialog(owner_window(), url, default_path,
filters, &path)) {
base::StringValue url_value(url);
web_contents_->CallClientFunction(
@@ -239,12 +254,11 @@ void CommonWebContentsDelegate::DevToolsSaveToFile(
}
saved_files_[url] = path;
base::WriteFile(path, content.data(), content.size());
// Notify devtools.
base::StringValue url_value(url);
web_contents_->CallClientFunction(
"DevToolsAPI.savedURL", &url_value, nullptr, nullptr);
BrowserThread::PostTaskAndReply(
BrowserThread::FILE, FROM_HERE,
base::Bind(&WriteToFile, path, content),
base::Bind(&CommonWebContentsDelegate::OnDevToolsSaveToFile,
base::Unretained(this), url));
}
void CommonWebContentsDelegate::DevToolsAppendToFile(
@@ -252,12 +266,12 @@ void CommonWebContentsDelegate::DevToolsAppendToFile(
PathsMap::iterator it = saved_files_.find(url);
if (it == saved_files_.end())
return;
base::AppendToFile(it->second, content.data(), content.size());
// Notify devtools.
base::StringValue url_value(url);
web_contents_->CallClientFunction(
"DevToolsAPI.appendedToURL", &url_value, nullptr, nullptr);
BrowserThread::PostTaskAndReply(
BrowserThread::FILE, FROM_HERE,
base::Bind(&AppendToFile, it->second, content),
base::Bind(&CommonWebContentsDelegate::OnDevToolsAppendToFile,
base::Unretained(this), url));
}
void CommonWebContentsDelegate::DevToolsAddFileSystem() {
@@ -265,7 +279,7 @@ void CommonWebContentsDelegate::DevToolsAddFileSystem() {
base::FilePath default_path;
std::vector<base::FilePath> paths;
int flag = file_dialog::FILE_DIALOG_OPEN_DIRECTORY;
if (!file_dialog::ShowOpenDialog(owner_window_, "", default_path,
if (!file_dialog::ShowOpenDialog(owner_window(), "", default_path,
filters, flag, &paths))
return;
@@ -320,6 +334,22 @@ void CommonWebContentsDelegate::DevToolsRemoveFileSystem(
nullptr);
}
void CommonWebContentsDelegate::OnDevToolsSaveToFile(
const std::string& url) {
// Notify DevTools.
base::StringValue url_value(url);
web_contents_->CallClientFunction(
"DevToolsAPI.savedURL", &url_value, nullptr, nullptr);
}
void CommonWebContentsDelegate::OnDevToolsAppendToFile(
const std::string& url) {
// Notify DevTools.
base::StringValue url_value(url);
web_contents_->CallClientFunction(
"DevToolsAPI.appendedToURL", &url_value, nullptr, nullptr);
}
void CommonWebContentsDelegate::SetHtmlApiFullscreen(bool enter_fullscreen) {
// Window is already in fullscreen mode, save the state.
if (enter_fullscreen && owner_window_->IsFullscreen()) {

View File

@@ -23,13 +23,15 @@ class CommonWebContentsDelegate
: public brightray::DefaultWebContentsDelegate,
public brightray::InspectableWebContentsDelegate {
public:
explicit CommonWebContentsDelegate(bool is_guest);
CommonWebContentsDelegate();
virtual ~CommonWebContentsDelegate();
// Create a InspectableWebContents object and takes onwership of
// Creates a InspectableWebContents object and takes onwership of
// |web_contents|.
void InitWithWebContents(content::WebContents* web_contents,
NativeWindow* owner_window);
void InitWithWebContents(content::WebContents* web_contents);
// Set the window as owner window.
void SetOwnerWindow(NativeWindow* owner_window);
// Destroy the managed InspectableWebContents object.
void DestroyWebContents();
@@ -44,7 +46,7 @@ class CommonWebContentsDelegate
return web_contents_.get();
}
bool is_guest() const { return is_guest_; }
NativeWindow* owner_window() const { return owner_window_.get(); }
protected:
// content::WebContentsDelegate:
@@ -55,7 +57,6 @@ class CommonWebContentsDelegate
bool user_gesture,
bool last_unlocked_by_target) override;
bool CanOverscrollContent() const override;
bool IsPopupOrPanel(const content::WebContents* source) const override;
content::JavaScriptDialogManager* GetJavaScriptDialogManager(
content::WebContents* source) override;
content::ColorChooser* OpenColorChooser(
@@ -83,14 +84,17 @@ class CommonWebContentsDelegate
void DevToolsRemoveFileSystem(const std::string& file_system_path) override;
private:
// Callback for when DevToolsSaveToFile has completed.
void OnDevToolsSaveToFile(const std::string& url);
// Callback for when DevToolsAppendToFile has completed.
void OnDevToolsAppendToFile(const std::string& url);
// Set fullscreen mode triggered by html api.
void SetHtmlApiFullscreen(bool enter_fullscreen);
// Whether this is guest WebContents or NativeWindow.
const bool is_guest_;
// The window that this WebContents belongs to.
NativeWindow* owner_window_;
base::WeakPtr<NativeWindow> owner_window_;
// Whether window is fullscreened by HTML5 api.
bool html_fullscreen_;

View File

@@ -33,6 +33,9 @@ for (var i in argv) {
// Create default menu.
app.once('ready', function() {
if (Menu.getApplicationMenu())
return;
var template;
if (process.platform == 'darwin') {
template = [

View File

@@ -38,7 +38,7 @@ createGuest = (embedder, params) ->
webViewManager ?= process.atomBinding 'web_view_manager'
id = getNextInstanceId embedder
guest = webContents.create {embedder}
guest = webContents.create {isGuest: true, embedder}
guestInstances[id] = {guest, embedder}
# Destroy guest when the embedder is gone or navigated.

View File

@@ -41,24 +41,21 @@ createGuest = (embedder, url, frameName, options) ->
# Routed window.open messages.
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPEN', (event, args...) ->
[url, frameName, options] = args
event.sender.emit '-new-window', event, url, frameName, 7
event.sender.emit 'new-window', event, url, frameName, 'new-window'
if event.sender.isGuest() or event.defaultPrevented
event.returnValue = null
else
event.returnValue = createGuest event.sender, args...
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSE', (event, guestId) ->
return unless BrowserWindow.windows.has guestId
BrowserWindow.windows.get(guestId).destroy()
BrowserWindow.fromId(guestId)?.destroy()
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_METHOD', (event, guestId, method, args...) ->
return unless BrowserWindow.windows.has guestId
BrowserWindow.windows.get(guestId)[method] args...
BrowserWindow.fromId(guestId)?[method] args...
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', (event, guestId, message, targetOrigin) ->
return unless BrowserWindow.windows.has guestId
guestContents = BrowserWindow.windows.get(guestId).webContents
if guestContents.getUrl().indexOf(targetOrigin) is 0 or targetOrigin is '*'
guestContents = BrowserWindow.fromId(guestId)?.webContents
if guestContents?.getUrl().indexOf(targetOrigin) is 0 or targetOrigin is '*'
guestContents.send 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', message, targetOrigin
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', (event, message, targetOrigin) ->
@@ -67,5 +64,4 @@ ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', (event, mess
embedder.send 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', message, targetOrigin
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', (event, guestId, method, args...) ->
return unless BrowserWindow.windows.has guestId
BrowserWindow.windows.get(guestId).webContents?[method] args...
BrowserWindow.fromId(guestId)?.webContents?[method] args...

View File

@@ -1,5 +1,5 @@
EventEmitter = require('events').EventEmitter
IDWeakMap = require 'id-weak-map'
IDWeakMap = process.atomBinding('id_weak_map').IDWeakMap
v8Util = process.atomBinding 'v8_util'
# Class to reference all objects.

View File

@@ -9,6 +9,7 @@
#include <vector>
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/browser/browser.h"
#include "atom/browser/window_list.h"
#include "atom/common/api/api_messages.h"
@@ -27,12 +28,8 @@
#include "base/strings/utf_string_conversions.h"
#include "brightray/browser/inspectable_web_contents.h"
#include "brightray/browser/inspectable_web_contents_view.h"
#include "chrome/browser/printing/print_view_manager_basic.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
@@ -59,6 +56,8 @@ using content::NavigationEntry;
using content::RenderWidgetHostView;
using content::RenderWidgetHost;
DEFINE_WEB_CONTENTS_USER_DATA_KEY(atom::NativeWindowRelay);
namespace atom {
namespace {
@@ -84,10 +83,10 @@ std::string RemoveWhitespace(const std::string& str) {
} // namespace
NativeWindow::NativeWindow(content::WebContents* web_contents,
const mate::Dictionary& options)
: CommonWebContentsDelegate(false),
content::WebContentsObserver(web_contents),
NativeWindow::NativeWindow(
brightray::InspectableWebContents* inspectable_web_contents,
const mate::Dictionary& options)
: content::WebContentsObserver(inspectable_web_contents->GetWebContents()),
has_frame_(true),
transparent_(false),
enable_larger_than_screen_(false),
@@ -95,10 +94,9 @@ NativeWindow::NativeWindow(content::WebContents* web_contents,
node_integration_(true),
has_dialog_attached_(false),
zoom_factor_(1.0),
inspectable_web_contents_(inspectable_web_contents),
weak_factory_(this) {
printing::PrintViewManagerBasic::CreateForWebContents(web_contents);
InitWithWebContents(web_contents, this);
inspectable_web_contents->GetView()->SetDelegate(this);
options.Get(switches::kFrame, &has_frame_);
options.Get(switches::kTransparent, &transparent_);
@@ -140,12 +138,8 @@ NativeWindow::NativeWindow(content::WebContents* web_contents,
RemoveWhitespace(browser->GetName()).c_str(),
browser->GetVersion().c_str(),
CHROME_VERSION_STRING);
web_contents->GetMutableRendererPrefs()->user_agent_override =
web_contents()->GetMutableRendererPrefs()->user_agent_override =
content::BuildUserAgentFromProduct(product_name);
// Get notified of title updated message.
registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
content::Source<content::WebContents>(web_contents));
}
NativeWindow::~NativeWindow() {
@@ -154,18 +148,12 @@ NativeWindow::~NativeWindow() {
NotifyWindowClosed();
}
// static
NativeWindow* NativeWindow::Create(const mate::Dictionary& options) {
content::WebContents::CreateParams create_params(AtomBrowserContext::Get());
return Create(content::WebContents::Create(create_params), options);
}
// static
NativeWindow* NativeWindow::FromWebContents(
content::WebContents* web_contents) {
WindowList& window_list = *WindowList::GetInstance();
for (NativeWindow* window : window_list) {
if (window->GetWebContents() == web_contents)
if (window->web_contents() == web_contents)
return window;
}
return nullptr;
@@ -257,11 +245,6 @@ bool NativeWindow::IsDocumentEdited() {
void NativeWindow::SetMenu(ui::MenuModel* menu) {
}
void NativeWindow::Print(bool silent, bool print_background) {
printing::PrintViewManagerBasic::FromWebContents(GetWebContents())->
PrintNow(silent, print_background);
}
void NativeWindow::ShowDefinitionForSelection() {
NOTIMPLEMENTED();
}
@@ -285,24 +268,22 @@ bool NativeWindow::HasModalDialog() {
}
void NativeWindow::FocusOnWebView() {
GetWebContents()->GetRenderViewHost()->Focus();
web_contents()->GetRenderViewHost()->Focus();
}
void NativeWindow::BlurWebView() {
GetWebContents()->GetRenderViewHost()->Blur();
web_contents()->GetRenderViewHost()->Blur();
}
bool NativeWindow::IsWebViewFocused() {
RenderWidgetHostView* host_view =
GetWebContents()->GetRenderViewHost()->GetView();
auto host_view = web_contents()->GetRenderViewHost()->GetView();
return host_view && host_view->HasFocus();
}
void NativeWindow::CapturePage(const gfx::Rect& rect,
const CapturePageCallback& callback) {
content::WebContents* contents = GetWebContents();
RenderWidgetHostView* const view = contents->GetRenderWidgetHostView();
RenderWidgetHost* const host = view ? view->GetRenderWidgetHost() : nullptr;
const auto view = web_contents()->GetRenderWidgetHostView();
const auto host = view ? view->GetRenderWidgetHost() : nullptr;
if (!view || !host) {
callback.Run(SkBitmap());
return;
@@ -332,7 +313,7 @@ void NativeWindow::CapturePage(const gfx::Rect& rect,
kBGRA_8888_SkColorType);
}
void NativeWindow::CloseWebContents() {
void NativeWindow::RequestToClosePage() {
bool prevent_default = false;
FOR_EACH_OBSERVER(NativeWindowObserver,
observers_,
@@ -342,12 +323,6 @@ void NativeWindow::CloseWebContents() {
return;
}
content::WebContents* web_contents(GetWebContents());
if (!web_contents) {
CloseImmediately();
return;
}
// Assume the window is not responding if it doesn't cancel the close and is
// not closed in 5s, in this way we can quickly show the unresponsive
// dialog when the window is busy executing some script withouth waiting for
@@ -355,10 +330,45 @@ void NativeWindow::CloseWebContents() {
if (window_unresposive_closure_.IsCancelled())
ScheduleUnresponsiveEvent(5000);
if (web_contents->NeedToFireBeforeUnload())
web_contents->DispatchBeforeUnload(false);
if (web_contents()->NeedToFireBeforeUnload())
web_contents()->DispatchBeforeUnload(false);
else
web_contents->Close();
web_contents()->Close();
}
void NativeWindow::CloseContents(content::WebContents* source) {
if (!inspectable_web_contents_)
return;
inspectable_web_contents_->GetView()->SetDelegate(nullptr);
inspectable_web_contents_ = nullptr;
Observe(nullptr);
// When the web contents is gone, close the window immediately, but the
// memory will not be freed until you call delete.
// In this way, it would be safe to manage windows via smart pointers. If you
// want to free memory when the window is closed, you can do deleting by
// overriding the OnWindowClosed method in the observer.
CloseImmediately();
// Do not sent "unresponsive" event after window is closed.
window_unresposive_closure_.Cancel();
}
void NativeWindow::RendererUnresponsive(content::WebContents* source) {
// Schedule the unresponsive shortly later, since we may receive the
// responsive event soon. This could happen after the whole application had
// blocked for a while.
// Also notice that when closing this event would be ignored because we have
// explicity started a close timeout counter. This is on purpose because we
// don't want the unresponsive event to be sent too early when user is closing
// the window.
ScheduleUnresponsiveEvent(50);
}
void NativeWindow::RendererResponsive(content::WebContents* source) {
window_unresposive_closure_.Cancel();
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnRendererResponsive());
}
void NativeWindow::AppendExtraCommandLineSwitches(
@@ -433,14 +443,10 @@ void NativeWindow::NotifyWindowClosed() {
if (is_closed_)
return;
WindowList::RemoveWindow(this);
is_closed_ = true;
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowClosed());
// Do not receive any notification after window has been closed, there is a
// crash that seems to be caused by this: http://git.io/YqMG5g.
registrar_.RemoveAll();
WindowList::RemoveWindow(this);
}
void NativeWindow::NotifyWindowBlur() {
@@ -499,50 +505,16 @@ void NativeWindow::NotifyWindowLeaveHtmlFullScreen() {
OnWindowLeaveHtmlFullScreen());
}
bool NativeWindow::ShouldCreateWebContents(
content::WebContents* web_contents,
int route_id,
int main_frame_route_id,
WindowContainerType window_container_type,
const base::string16& frame_name,
const GURL& target_url,
const std::string& partition_id,
content::SessionStorageNamespace* session_storage_namespace) {
FOR_EACH_OBSERVER(NativeWindowObserver,
observers_,
WillCreatePopupWindow(frame_name,
target_url,
partition_id,
NEW_FOREGROUND_TAB));
return false;
void NativeWindow::DevToolsFocused() {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsFocus());
}
// In atom-shell all reloads and navigations started by renderer process would
// be redirected to this method, so we can have precise control of how we
// would open the url (in our case, is to restart the renderer process). See
// AtomRendererClient::ShouldFork for how this is done.
content::WebContents* NativeWindow::OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) {
if (params.disposition != CURRENT_TAB) {
FOR_EACH_OBSERVER(NativeWindowObserver,
observers_,
WillCreatePopupWindow(base::string16(),
params.url,
"",
params.disposition));
return nullptr;
}
void NativeWindow::DevToolsOpened() {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsOpened());
}
// Give user a chance to prevent navigation.
bool prevent_default = false;
FOR_EACH_OBSERVER(NativeWindowObserver,
observers_,
WillNavigate(&prevent_default, params.url));
if (prevent_default)
return nullptr;
return CommonWebContentsDelegate::OpenURLFromTab(source, params);
void NativeWindow::DevToolsClosed() {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsClosed());
}
void NativeWindow::RenderViewCreated(
@@ -557,66 +529,22 @@ void NativeWindow::RenderViewCreated(
impl->SetBackgroundOpaque(false);
}
void NativeWindow::BeforeUnloadFired(content::WebContents* tab,
bool proceed,
bool* proceed_to_fire_unload) {
*proceed_to_fire_unload = proceed;
void NativeWindow::BeforeUnloadDialogCancelled() {
WindowList::WindowCloseCancelled(this);
if (!proceed) {
WindowList::WindowCloseCancelled(this);
// Cancel unresponsive event when window close is cancelled.
window_unresposive_closure_.Cancel();
}
}
void NativeWindow::ActivateContents(content::WebContents* contents) {
FocusOnWebView();
}
void NativeWindow::DeactivateContents(content::WebContents* contents) {
BlurWebView();
}
void NativeWindow::MoveContents(content::WebContents* source,
const gfx::Rect& pos) {
SetBounds(pos);
}
void NativeWindow::CloseContents(content::WebContents* source) {
// Destroy the WebContents before we close the window.
DestroyWebContents();
// When the web contents is gone, close the window immediately, but the
// memory will not be freed until you call delete.
// In this way, it would be safe to manage windows via smart pointers. If you
// want to free memory when the window is closed, you can do deleting by
// overriding the OnWindowClosed method in the observer.
CloseImmediately();
// Do not sent "unresponsive" event after window is closed.
// Cancel unresponsive event when window close is cancelled.
window_unresposive_closure_.Cancel();
}
void NativeWindow::RendererUnresponsive(content::WebContents* source) {
// Schedule the unresponsive shortly later, since we may receive the
// responsive event soon. This could happen after the whole application had
// blocked for a while.
// Also notice that when closing this event would be ignored because we have
// explicity started a close timeout counter. This is on purpose because we
// don't want the unresponsive event to be sent too early when user is closing
// the window.
ScheduleUnresponsiveEvent(50);
}
void NativeWindow::RendererResponsive(content::WebContents* source) {
window_unresposive_closure_.Cancel();
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnRendererResponsive());
}
void NativeWindow::BeforeUnloadFired(const base::TimeTicks& proceed_time) {
// Do nothing, we override this method just to avoid compilation error since
// there are two virtual functions named BeforeUnloadFired.
void NativeWindow::TitleWasSet(content::NavigationEntry* entry,
bool explicit_set) {
bool prevent_default = false;
std::string text = base::UTF16ToUTF8(entry->GetTitle());
FOR_EACH_OBSERVER(NativeWindowObserver,
observers_,
OnPageTitleUpdated(&prevent_default, text));
if (!prevent_default)
SetTitle(text);
}
bool NativeWindow::OnMessageReceived(const IPC::Message& message) {
@@ -630,38 +558,6 @@ bool NativeWindow::OnMessageReceived(const IPC::Message& message) {
return handled;
}
void NativeWindow::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
if (type == content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED) {
std::pair<NavigationEntry*, bool>* title =
content::Details<std::pair<NavigationEntry*, bool>>(details).ptr();
if (title->first) {
bool prevent_default = false;
std::string text = base::UTF16ToUTF8(title->first->GetTitle());
FOR_EACH_OBSERVER(NativeWindowObserver,
observers_,
OnPageTitleUpdated(&prevent_default, text));
if (!prevent_default)
SetTitle(text);
}
}
}
void NativeWindow::DevToolsFocused() {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsFocus());
}
void NativeWindow::DevToolsOpened() {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsOpened());
}
void NativeWindow::DevToolsClosed() {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsClosed());
}
void NativeWindow::ScheduleUnresponsiveEvent(int ms) {
if (!window_unresposive_closure_.IsCancelled())
return;

View File

@@ -9,26 +9,30 @@
#include <string>
#include <vector>
#include "atom/browser/common_web_contents_delegate.h"
#include "atom/browser/native_window_observer.h"
#include "atom/browser/ui/accelerator_util.h"
#include "base/cancelable_callback.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_observer.h"
#include "brightray/browser/inspectable_web_contents_view_delegate.h"
#include "content/public/browser/readback_types.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
#include "native_mate/persistent_dictionary.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h"
namespace base {
class CommandLine;
}
namespace brightray {
class InspectableWebContents;
}
namespace content {
class BrowserContext;
class WebContents;
struct NativeWebKeyboardEvent;
struct WebPreferences;
}
@@ -50,9 +54,8 @@ namespace atom {
struct DraggableRegion;
class NativeWindow : public CommonWebContentsDelegate,
public content::WebContentsObserver,
public content::NotificationObserver {
class NativeWindow : public content::WebContentsObserver,
public brightray::InspectableWebContentsViewDelegate {
public:
typedef base::Callback<void(const SkBitmap& bitmap)> CapturePageCallback;
@@ -79,12 +82,9 @@ class NativeWindow : public CommonWebContentsDelegate,
// Create window with existing WebContents, the caller is responsible for
// managing the window's live.
static NativeWindow* Create(content::WebContents* web_contents,
const mate::Dictionary& options);
// Create window with new WebContents, the caller is responsible for
// managing the window's live.
static NativeWindow* Create(const mate::Dictionary& options);
static NativeWindow* Create(
brightray::InspectableWebContents* inspectable_web_contents,
const mate::Dictionary& options);
// Find a window from its WebContents
static NativeWindow* FromWebContents(content::WebContents* web_contents);
@@ -154,9 +154,6 @@ class NativeWindow : public CommonWebContentsDelegate,
virtual void CapturePage(const gfx::Rect& rect,
const CapturePageCallback& callback);
// Print current page.
virtual void Print(bool silent, bool print_background);
// Show popup dictionary.
virtual void ShowDefinitionForSelection();
@@ -166,15 +163,21 @@ class NativeWindow : public CommonWebContentsDelegate,
virtual void SetMenuBarVisibility(bool visible);
virtual bool IsMenuBarVisible();
// The same with closing a tab in a real browser.
//
// Should be called by platform code when user want to close the window.
virtual void CloseWebContents();
base::WeakPtr<NativeWindow> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
// Requests the WebContents to close, can be cancelled by the page.
virtual void RequestToClosePage();
// Methods called by the WebContents.
virtual void CloseContents(content::WebContents* source);
virtual void RendererUnresponsive(content::WebContents* source);
virtual void RendererResponsive(content::WebContents* source);
virtual void HandleKeyboardEvent(
content::WebContents*,
const content::NativeWebKeyboardEvent& event) {}
// Called when renderer process is going to be started.
void AppendExtraCommandLineSwitches(base::CommandLine* command_line);
void OverrideWebkitPrefs(content::WebPreferences* prefs);
@@ -205,7 +208,7 @@ class NativeWindow : public CommonWebContentsDelegate,
}
brightray::InspectableWebContents* inspectable_web_contents() const {
return managed_web_contents();
return inspectable_web_contents_;
}
bool has_frame() const { return has_frame_; }
@@ -215,52 +218,24 @@ class NativeWindow : public CommonWebContentsDelegate,
}
protected:
explicit NativeWindow(content::WebContents* web_contents,
const mate::Dictionary& options);
NativeWindow(brightray::InspectableWebContents* inspectable_web_contents,
const mate::Dictionary& options);
// Called when the window needs to update its draggable region.
virtual void UpdateDraggableRegions(
const std::vector<DraggableRegion>& regions) = 0;
// Implementations of content::WebContentsDelegate.
bool ShouldCreateWebContents(
content::WebContents* web_contents,
int route_id,
int main_frame_route_id,
WindowContainerType window_container_type,
const base::string16& frame_name,
const GURL& target_url,
const std::string& partition_id,
content::SessionStorageNamespace* session_storage_namespace) override;
content::WebContents* OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) override;
void BeforeUnloadFired(content::WebContents* tab,
bool proceed,
bool* proceed_to_fire_unload) override;
void ActivateContents(content::WebContents* contents) override;
void DeactivateContents(content::WebContents* contents) override;
void MoveContents(content::WebContents* source,
const gfx::Rect& pos) override;
void CloseContents(content::WebContents* source) override;
void RendererUnresponsive(content::WebContents* source) override;
void RendererResponsive(content::WebContents* source) override;
// Implementations of content::WebContentsObserver.
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
void BeforeUnloadFired(const base::TimeTicks& proceed_time) override;
bool OnMessageReceived(const IPC::Message& message) override;
// Implementations of content::NotificationObserver.
void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
// Implementations of brightray::InspectableWebContentsDelegate.
// brightray::InspectableWebContentsViewDelegate:
void DevToolsFocused() override;
void DevToolsOpened() override;
void DevToolsClosed() override;
// content::WebContentsObserver:
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
void BeforeUnloadDialogCancelled() override;
void TitleWasSet(content::NavigationEntry* entry, bool explicit_set) override;
bool OnMessageReceived(const IPC::Message& message) override;
// Whether window has standard frame.
bool has_frame_;
@@ -273,6 +248,9 @@ class NativeWindow : public CommonWebContentsDelegate,
// Window icon.
gfx::ImageSkia icon_;
// Observers of this window.
ObserverList<NativeWindowObserver> observers_;
private:
// Schedule a notification unresponsive event.
void ScheduleUnresponsiveEvent(int ms);
@@ -285,12 +263,6 @@ class NativeWindow : public CommonWebContentsDelegate,
const SkBitmap& bitmap,
content::ReadbackResponse response);
// Notification manager.
content::NotificationRegistrar registrar_;
// Observers of this window.
ObserverList<NativeWindowObserver> observers_;
// The windows has been closed.
bool is_closed_;
@@ -313,11 +285,29 @@ class NativeWindow : public CommonWebContentsDelegate,
// Page's default zoom factor.
double zoom_factor_;
// The page this window is viewing.
brightray::InspectableWebContents* inspectable_web_contents_;
base::WeakPtrFactory<NativeWindow> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(NativeWindow);
};
// This class provides a hook to get a NativeWindow from a WebContents.
class NativeWindowRelay :
public content::WebContentsUserData<NativeWindowRelay> {
public:
explicit NativeWindowRelay(base::WeakPtr<NativeWindow> window)
: key(UserDataKey()), window(window) {}
void* key;
base::WeakPtr<NativeWindow> window;
private:
friend class content::WebContentsUserData<NativeWindow>;
};
} // namespace atom
#endif // ATOM_BROWSER_NATIVE_WINDOW_H_

View File

@@ -23,11 +23,11 @@ namespace atom {
class NativeWindowMac : public NativeWindow {
public:
explicit NativeWindowMac(content::WebContents* web_contents,
const mate::Dictionary& options);
virtual ~NativeWindowMac();
NativeWindowMac(brightray::InspectableWebContents* inspectable_web_contents,
const mate::Dictionary& options);
~NativeWindowMac() override;
// NativeWindow implementation.
// NativeWindow:
void Close() override;
void CloseImmediately() override;
void Focus(bool focus) override;
@@ -91,7 +91,7 @@ class NativeWindowMac : public NativeWindow {
void UpdateDraggableRegions(
const std::vector<DraggableRegion>& regions) override;
// Implementations of content::WebContentsDelegate.
// NativeWindow:
void HandleKeyboardEvent(
content::WebContents*,
const content::NativeWebKeyboardEvent&) override;

View File

@@ -68,7 +68,7 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
}
- (void)windowDidBecomeMain:(NSNotification*)notification {
content::WebContents* web_contents = shell_->GetWebContents();
content::WebContents* web_contents = shell_->web_contents();
if (!web_contents)
return;
@@ -82,7 +82,7 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
}
- (void)windowDidResignMain:(NSNotification*)notification {
content::WebContents* web_contents = shell_->GetWebContents();
content::WebContents* web_contents = shell_->web_contents();
if (!web_contents)
return;
@@ -104,7 +104,7 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
- (void)windowDidMove:(NSNotification*)notification {
// TODO(zcbenz): Remove the alias after figuring out a proper
// way to disptach move.
// way to disptach move.
shell_->NotifyWindowMove();
shell_->NotifyWindowMoved();
}
@@ -149,7 +149,7 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
// When user tries to close the window by clicking the close button, we do
// not close the window immediately, instead we try to close the web page
// fisrt, and when the web page is closed the window will also be closed.
shell_->CloseWebContents();
shell_->RequestToClosePage();
return NO;
}
@@ -303,8 +303,9 @@ SkRegion* DraggableRegionsToSkRegion(
} // namespace
NativeWindowMac::NativeWindowMac(content::WebContents* web_contents,
const mate::Dictionary& options)
NativeWindowMac::NativeWindowMac(
brightray::InspectableWebContents* web_contents,
const mate::Dictionary& options)
: NativeWindow(web_contents, options),
is_kiosk_(false),
attention_request_id_(0) {
@@ -385,9 +386,7 @@ NativeWindowMac::NativeWindowMac(content::WebContents* web_contents,
}
NativeWindowMac::~NativeWindowMac() {
// Force InspectableWebContents to be destroyed before we destroy window,
// because it may still be observing the window at this time.
DestroyWebContents();
Observe(nullptr);
}
void NativeWindowMac::Close() {
@@ -678,10 +677,9 @@ void NativeWindowMac::SetOverlayIcon(const gfx::Image& overlay,
}
void NativeWindowMac::ShowDefinitionForSelection() {
content::WebContents* web_contents = GetWebContents();
if (!web_contents)
if (!web_contents())
return;
content::RenderWidgetHostView* rwhv = web_contents->GetRenderWidgetHostView();
auto rwhv = web_contents()->GetRenderWidgetHostView();
if (!rwhv)
return;
rwhv->ShowDefinitionForSelection();
@@ -705,10 +703,9 @@ bool NativeWindowMac::IsVisibleOnAllWorkspaces() {
bool NativeWindowMac::IsWithinDraggableRegion(NSPoint point) const {
if (!draggable_region_)
return false;
content::WebContents* web_contents = GetWebContents();
if (!web_contents)
if (!web_contents())
return false;
NSView* webView = web_contents->GetNativeView();
NSView* webView = web_contents()->GetNativeView();
NSInteger webViewHeight = NSHeight([webView bounds]);
// |draggable_region_| is stored in local platform-indepdent coordiate system
// while |point| is in local Cocoa coordinate system. Do the conversion
@@ -815,16 +812,15 @@ void NativeWindowMac::UninstallView() {
}
void NativeWindowMac::ClipWebView() {
content::WebContents* web_contents = GetWebContents();
if (!web_contents)
if (!web_contents())
return;
NSView* webView = web_contents->GetNativeView();
NSView* webView = web_contents()->GetNativeView();
webView.layer.masksToBounds = YES;
webView.layer.cornerRadius = kAtomWindowCornerRadius;
}
void NativeWindowMac::InstallDraggableRegionView() {
NSView* webView = GetWebContents()->GetNativeView();
NSView* webView = web_contents()->GetNativeView();
base::scoped_nsobject<NSView> controlRegion(
[[ControlRegionView alloc] initWithShellWindow:this]);
[controlRegion setFrame:NSMakeRect(0, 0,
@@ -834,9 +830,10 @@ void NativeWindowMac::InstallDraggableRegionView() {
}
// static
NativeWindow* NativeWindow::Create(content::WebContents* web_contents,
const mate::Dictionary& options) {
return new NativeWindowMac(web_contents, options);
NativeWindow* NativeWindow::Create(
brightray::InspectableWebContents* inspectable_web_contents,
const mate::Dictionary& options) {
return new NativeWindowMac(inspectable_web_contents, options);
}
} // namespace atom

View File

@@ -65,6 +65,9 @@ class NativeWindowObserver {
// Called when renderer recovers.
virtual void OnRendererResponsive() {}
// Called on Windows when App Commands arrive (WM_APPCOMMAND)
virtual void OnExecuteWindowsCommand(const std::string& command_name) {}
};
} // namespace atom

View File

@@ -16,7 +16,8 @@
#include "atom/common/draggable_region.h"
#include "atom/common/options_switches.h"
#include "base/strings/utf_string_conversions.h"
#include "browser/inspectable_web_contents_view.h"
#include "brightray/browser/inspectable_web_contents.h"
#include "brightray/browser/inspectable_web_contents_view.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "native_mate/dictionary.h"
#include "ui/aura/window.h"
@@ -123,6 +124,70 @@ bool IsAltModifier(const content::NativeWebKeyboardEvent& event) {
(modifiers == (Modifiers::AltKey | Modifiers::IsRight));
}
#if defined(OS_WIN)
// Convert Win32 WM_APPCOMMANDS to strings.
const char* AppCommandToString(int command_id) {
switch (command_id) {
case APPCOMMAND_BROWSER_BACKWARD : return "browser-backward";
case APPCOMMAND_BROWSER_FORWARD : return "browser-forward";
case APPCOMMAND_BROWSER_REFRESH : return "browser-refresh";
case APPCOMMAND_BROWSER_STOP : return "browser-stop";
case APPCOMMAND_BROWSER_SEARCH : return "browser-search";
case APPCOMMAND_BROWSER_FAVORITES : return "browser-favorites";
case APPCOMMAND_BROWSER_HOME : return "browser-home";
case APPCOMMAND_VOLUME_MUTE : return "volume-mute";
case APPCOMMAND_VOLUME_DOWN : return "volume-down";
case APPCOMMAND_VOLUME_UP : return "volume-up";
case APPCOMMAND_MEDIA_NEXTTRACK : return "media-nexttrack";
case APPCOMMAND_MEDIA_PREVIOUSTRACK : return "media-previoustrack";
case APPCOMMAND_MEDIA_STOP : return "media-stop";
case APPCOMMAND_MEDIA_PLAY_PAUSE : return "media-play_pause";
case APPCOMMAND_LAUNCH_MAIL : return "launch-mail";
case APPCOMMAND_LAUNCH_MEDIA_SELECT : return "launch-media-select";
case APPCOMMAND_LAUNCH_APP1 : return "launch-app1";
case APPCOMMAND_LAUNCH_APP2 : return "launch-app2";
case APPCOMMAND_BASS_DOWN : return "bass-down";
case APPCOMMAND_BASS_BOOST : return "bass-boost";
case APPCOMMAND_BASS_UP : return "bass-up";
case APPCOMMAND_TREBLE_DOWN : return "treble-down";
case APPCOMMAND_TREBLE_UP : return "treble-up";
case APPCOMMAND_MICROPHONE_VOLUME_MUTE : return "microphone-volume-mute";
case APPCOMMAND_MICROPHONE_VOLUME_DOWN : return "microphone-volume-down";
case APPCOMMAND_MICROPHONE_VOLUME_UP : return "microphone-volume-up";
case APPCOMMAND_HELP : return "help";
case APPCOMMAND_FIND : return "find";
case APPCOMMAND_NEW : return "new";
case APPCOMMAND_OPEN : return "open";
case APPCOMMAND_CLOSE : return "close";
case APPCOMMAND_SAVE : return "save";
case APPCOMMAND_PRINT : return "print";
case APPCOMMAND_UNDO : return "undo";
case APPCOMMAND_REDO : return "redo";
case APPCOMMAND_COPY : return "copy";
case APPCOMMAND_CUT : return "cut";
case APPCOMMAND_PASTE : return "paste";
case APPCOMMAND_REPLY_TO_MAIL : return "reply-to-mail";
case APPCOMMAND_FORWARD_MAIL : return "forward-mail";
case APPCOMMAND_SEND_MAIL : return "send-mail";
case APPCOMMAND_SPELL_CHECK : return "spell-check";
case APPCOMMAND_MIC_ON_OFF_TOGGLE : return "mic-on-off-toggle";
case APPCOMMAND_CORRECTION_LIST : return "correction-list";
case APPCOMMAND_MEDIA_PLAY : return "media-play";
case APPCOMMAND_MEDIA_PAUSE : return "media-pause";
case APPCOMMAND_MEDIA_RECORD : return "media-record";
case APPCOMMAND_MEDIA_FAST_FORWARD : return "media-fast-forward";
case APPCOMMAND_MEDIA_REWIND : return "media-rewind";
case APPCOMMAND_MEDIA_CHANNEL_UP : return "media-channel-up";
case APPCOMMAND_MEDIA_CHANNEL_DOWN : return "media-channel-down";
case APPCOMMAND_DELETE : return "delete";
case APPCOMMAND_DICTATE_OR_COMMAND_CONTROL_TOGGLE:
return "dictate-or-command-control-toggle";
default:
return "unkown";
}
}
#endif
class NativeWindowClientView : public views::ClientView {
public:
NativeWindowClientView(views::Widget* widget,
@@ -132,7 +197,7 @@ class NativeWindowClientView : public views::ClientView {
virtual ~NativeWindowClientView() {}
bool CanClose() override {
static_cast<NativeWindowViews*>(contents_view())->CloseWebContents();
static_cast<NativeWindowViews*>(contents_view())->RequestToClosePage();
return false;
}
@@ -142,8 +207,9 @@ class NativeWindowClientView : public views::ClientView {
} // namespace
NativeWindowViews::NativeWindowViews(content::WebContents* web_contents,
const mate::Dictionary& options)
NativeWindowViews::NativeWindowViews(
brightray::InspectableWebContents* web_contents,
const mate::Dictionary& options)
: NativeWindow(web_contents, options),
window_(new views::Widget),
web_view_(inspectable_web_contents()->GetView()->GetView()),
@@ -726,9 +792,9 @@ void NativeWindowViews::OnWidgetActivationChanged(
else
NotifyWindowBlur();
if (active && GetWebContents() &&
if (active && inspectable_web_contents() &&
!inspectable_web_contents()->IsDevToolsViewShowing())
GetWebContents()->Focus();
web_contents()->Focus();
// Hide menu bar when window is blured.
if (!active && menu_bar_autohide_ && menu_bar_visible_)
@@ -853,6 +919,11 @@ bool NativeWindowViews::ExecuteWindowsCommand(int command_id) {
is_minimized_ = false;
} else if ((command_id & sc_mask) == SC_MAXIMIZE) {
NotifyWindowMaximize();
} else {
std::string command = AppCommandToString(command_id & sc_mask);
FOR_EACH_OBSERVER(NativeWindowObserver,
observers_,
OnExecuteWindowsCommand(command));
}
return false;
}
@@ -870,13 +941,6 @@ void NativeWindowViews::GetDevToolsWindowWMClass(
}
#endif
void NativeWindowViews::ActivateContents(content::WebContents* contents) {
NativeWindow::ActivateContents(contents);
// Hide menu bar when web view is clicked.
if (menu_bar_autohide_ && menu_bar_visible_)
SetMenuBarVisibility(false);
}
void NativeWindowViews::HandleKeyboardEvent(
content::WebContents*,
const content::NativeWebKeyboardEvent& event) {
@@ -945,6 +1009,7 @@ void NativeWindowViews::RegisterAccelerators(ui::MenuModel* menu_model) {
gfx::Rect NativeWindowViews::ContentBoundsToWindowBounds(
const gfx::Rect& bounds) {
gfx::Point origin = bounds.origin();
#if defined(OS_WIN)
gfx::Rect dpi_bounds = gfx::win::DIPToScreenRect(bounds);
gfx::Rect window_bounds = gfx::win::ScreenToDIPRect(
@@ -953,6 +1018,9 @@ gfx::Rect NativeWindowViews::ContentBoundsToWindowBounds(
gfx::Rect window_bounds =
window_->non_client_view()->GetWindowBoundsForClientBounds(bounds);
#endif
// The window's position would also be changed, but we only want to change
// the size.
window_bounds.set_origin(origin);
if (menu_bar_ && menu_bar_visible_)
window_bounds.set_height(window_bounds.height() + kMenuBarHeight);
@@ -969,9 +1037,10 @@ ui::WindowShowState NativeWindowViews::GetRestoredState() {
}
// static
NativeWindow* NativeWindow::Create(content::WebContents* web_contents,
const mate::Dictionary& options) {
return new NativeWindowViews(web_contents, options);
NativeWindow* NativeWindow::Create(
brightray::InspectableWebContents* inspectable_web_contents,
const mate::Dictionary& options) {
return new NativeWindowViews(inspectable_web_contents, options);
}
} // namespace atom

View File

@@ -28,9 +28,9 @@ class NativeWindowViews : public NativeWindow,
public views::WidgetDelegateView,
public views::WidgetObserver {
public:
explicit NativeWindowViews(content::WebContents* web_contents,
const mate::Dictionary& options);
virtual ~NativeWindowViews();
NativeWindowViews(brightray::InspectableWebContents* inspectable_web_contents,
const mate::Dictionary& options);
~NativeWindowViews() override;
// NativeWindow:
void Close() override;
@@ -120,15 +120,14 @@ class NativeWindowViews : public NativeWindow,
bool ExecuteWindowsCommand(int command_id) override;
#endif
// brightray::InspectableWebContentsDelegate:
// brightray::InspectableWebContentsViewDelegate:
gfx::ImageSkia GetDevToolsWindowIcon() override;
#if defined(USE_X11)
void GetDevToolsWindowWMClass(
std::string* name, std::string* class_name) override;
#endif
// content::WebContentsDelegate:
void ActivateContents(content::WebContents* contents) override;
// NativeWindow:
void HandleKeyboardEvent(
content::WebContents*,
const content::NativeWebKeyboardEvent& event) override;

View File

@@ -4,8 +4,10 @@
#include "atom/browser/net/adapter_request_job.h"
#include "atom/browser/atom_browser_context.h"
#include "base/threading/sequenced_worker_pool.h"
#include "atom/browser/net/url_request_buffer_job.h"
#include "atom/browser/net/url_request_fetch_job.h"
#include "atom/browser/net/url_request_string_job.h"
#include "atom/browser/net/asar/url_request_asar_job.h"
#include "atom/common/asar/asar_util.h"
@@ -66,6 +68,14 @@ bool AdapterRequestJob::GetCharset(std::string* charset) {
return real_job_->GetCharset(charset);
}
void AdapterRequestJob::GetResponseInfo(net::HttpResponseInfo* info) {
real_job_->GetResponseInfo(info);
}
int AdapterRequestJob::GetResponseCode() const {
return real_job_->GetResponseCode();
}
base::WeakPtr<AdapterRequestJob> AdapterRequestJob::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
@@ -104,6 +114,21 @@ void AdapterRequestJob::CreateFileJobAndStart(const base::FilePath& path) {
real_job_->Start();
}
void AdapterRequestJob::CreateHttpJobAndStart(
AtomBrowserContext* browser_context,
const GURL& url,
const std::string& method,
const std::string& referrer) {
if (!url.is_valid()) {
CreateErrorJobAndStart(net::ERR_INVALID_URL);
return;
}
real_job_ = new URLRequestFetchJob(browser_context, request(),
network_delegate(), url, method, referrer);
real_job_->Start();
}
void AdapterRequestJob::CreateJobFromProtocolHandlerAndStart() {
real_job_ = protocol_handler_->MaybeCreateJob(request(),
network_delegate());

View File

@@ -9,6 +9,7 @@
#include "base/memory/ref_counted_memory.h"
#include "base/memory/weak_ptr.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_job.h"
#include "net/url_request/url_request_job_factory.h"
#include "v8/include/v8.h"
@@ -19,6 +20,8 @@ class FilePath;
namespace atom {
class AtomBrowserContext;
// Ask JS which type of job it wants, and then delegate corresponding methods.
class AdapterRequestJob : public net::URLRequestJob {
public:
@@ -40,6 +43,8 @@ class AdapterRequestJob : public net::URLRequestJob {
net::Filter* SetupFilter() const override;
bool GetMimeType(std::string* mime_type) const override;
bool GetCharset(std::string* charset) override;
void GetResponseInfo(net::HttpResponseInfo* info) override;
int GetResponseCode() const override;
base::WeakPtr<AdapterRequestJob> GetWeakPtr();
@@ -56,6 +61,10 @@ class AdapterRequestJob : public net::URLRequestJob {
const std::string& charset,
scoped_refptr<base::RefCountedBytes> data);
void CreateFileJobAndStart(const base::FilePath& path);
void CreateHttpJobAndStart(AtomBrowserContext* browser_context,
const GURL& url,
const std::string& method,
const std::string& referrer);
void CreateJobFromProtocolHandlerAndStart();
private:

View File

@@ -0,0 +1,184 @@
// 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/net/url_request_fetch_job.h"
#include <algorithm>
#include <string>
#include "atom/browser/atom_browser_context.h"
#include "base/strings/string_util.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_fetcher_response_writer.h"
#include "net/url_request/url_request_status.h"
namespace atom {
namespace {
// Convert string to RequestType.
net::URLFetcher::RequestType GetRequestType(const std::string& raw) {
std::string method = StringToUpperASCII(raw);
if (method.empty() || method == "GET")
return net::URLFetcher::GET;
else if (method == "POST")
return net::URLFetcher::POST;
else if (method == "HEAD")
return net::URLFetcher::HEAD;
else if (method == "DELETE")
return net::URLFetcher::DELETE_REQUEST;
else if (method == "PUT")
return net::URLFetcher::PUT;
else if (method == "PATCH")
return net::URLFetcher::PATCH;
else // Use "GET" as fallback.
return net::URLFetcher::GET;
}
// Pipe the response writer back to URLRequestFetchJob.
class ResponsePiper : public net::URLFetcherResponseWriter {
public:
explicit ResponsePiper(URLRequestFetchJob* job)
: first_write_(true), job_(job) {}
// net::URLFetcherResponseWriter:
int Initialize(const net::CompletionCallback& callback) override {
return net::OK;
}
int Write(net::IOBuffer* buffer,
int num_bytes,
const net::CompletionCallback& callback) override {
if (first_write_) {
// The URLFetcherResponseWriter doesn't have an event when headers have
// been read, so we have to emulate by hooking to first write event.
job_->HeadersCompleted();
first_write_ = false;
}
return job_->DataAvailable(buffer, num_bytes);
}
int Finish(const net::CompletionCallback& callback) override {
return net::OK;
}
private:
bool first_write_;
URLRequestFetchJob* job_;
DISALLOW_COPY_AND_ASSIGN(ResponsePiper);
};
} // namespace
URLRequestFetchJob::URLRequestFetchJob(
AtomBrowserContext* browser_context,
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
const GURL& url,
const std::string& method,
const std::string& referrer)
: net::URLRequestJob(request, network_delegate),
pending_buffer_size_(0) {
// Use |request|'s method if |method| is not specified.
net::URLFetcher::RequestType request_type;
if (method.empty())
request_type = GetRequestType(request->method());
else
request_type = GetRequestType(method);
fetcher_.reset(net::URLFetcher::Create(url, request_type, this));
fetcher_->SetRequestContext(browser_context->url_request_context_getter());
fetcher_->SaveResponseWithWriter(make_scoped_ptr(new ResponsePiper(this)));
// Use |request|'s referrer if |referrer| is not specified.
if (referrer.empty()) {
fetcher_->SetReferrer(request->referrer());
} else {
fetcher_->SetReferrer(referrer);
}
// Use |request|'s headers.
net::HttpRequestHeaders headers;
if (request->GetFullRequestHeaders(&headers)) {
fetcher_->SetExtraRequestHeaders(headers.ToString());
}
}
void URLRequestFetchJob::HeadersCompleted() {
response_info_.reset(new net::HttpResponseInfo);
response_info_->headers = fetcher_->GetResponseHeaders();
NotifyHeadersComplete();
}
int URLRequestFetchJob::DataAvailable(net::IOBuffer* buffer, int num_bytes) {
// Clear the IO_PENDING status.
SetStatus(net::URLRequestStatus());
// Do nothing if pending_buffer_ is empty, i.e. there's no ReadRawData()
// operation waiting for IO completion.
if (!pending_buffer_.get())
return net::ERR_IO_PENDING;
// pending_buffer_ is set to the IOBuffer instance provided to ReadRawData()
// by URLRequestJob.
int bytes_read = std::min(num_bytes, pending_buffer_size_);
memcpy(pending_buffer_->data(), buffer->data(), bytes_read);
// Clear the buffers before notifying the read is complete, so that it is
// safe for the observer to read.
pending_buffer_ = nullptr;
pending_buffer_size_ = 0;
NotifyReadComplete(bytes_read);
return bytes_read;
}
void URLRequestFetchJob::Start() {
fetcher_->Start();
}
void URLRequestFetchJob::Kill() {
URLRequestJob::Kill();
fetcher_.reset();
}
bool URLRequestFetchJob::ReadRawData(net::IOBuffer* dest,
int dest_size,
int* bytes_read) {
pending_buffer_ = dest;
pending_buffer_size_ = dest_size;
SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
return false;
}
bool URLRequestFetchJob::GetMimeType(std::string* mime_type) const {
if (!response_info_)
return false;
return response_info_->headers->GetMimeType(mime_type);
}
void URLRequestFetchJob::GetResponseInfo(net::HttpResponseInfo* info) {
if (response_info_)
*info = *response_info_;
}
int URLRequestFetchJob::GetResponseCode() const {
if (!response_info_)
return -1;
return response_info_->headers->response_code();
}
void URLRequestFetchJob::OnURLFetchComplete(const net::URLFetcher* source) {
pending_buffer_ = nullptr;
pending_buffer_size_ = 0;
NotifyDone(fetcher_->GetStatus());
if (fetcher_->GetStatus().is_success())
NotifyReadComplete(0);
}
} // namespace atom

View File

@@ -0,0 +1,54 @@
// 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_NET_URL_REQUEST_FETCH_JOB_H_
#define ATOM_BROWSER_NET_URL_REQUEST_FETCH_JOB_H_
#include <string>
#include "net/url_request/url_fetcher_delegate.h"
#include "net/url_request/url_request_job.h"
namespace atom {
class AtomBrowserContext;
class URLRequestFetchJob : public net::URLRequestJob,
public net::URLFetcherDelegate {
public:
URLRequestFetchJob(AtomBrowserContext* browser_context,
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
const GURL& url,
const std::string& method,
const std::string& referrer);
void HeadersCompleted();
int DataAvailable(net::IOBuffer* buffer, int num_bytes);
// net::URLRequestJob:
void Start() override;
void Kill() override;
bool ReadRawData(net::IOBuffer* buf,
int buf_size,
int* bytes_read) override;
bool GetMimeType(std::string* mime_type) const override;
void GetResponseInfo(net::HttpResponseInfo* info) override;
int GetResponseCode() const override;
// net::URLFetcherDelegate:
void OnURLFetchComplete(const net::URLFetcher* source) override;
private:
scoped_ptr<net::URLFetcher> fetcher_;
scoped_refptr<net::IOBuffer> pending_buffer_;
int pending_buffer_size_;
scoped_ptr<net::HttpResponseInfo> response_info_;
DISALLOW_COPY_AND_ASSIGN(URLRequestFetchJob);
};
} // namespace atom
#endif // ATOM_BROWSER_NET_URL_REQUEST_FETCH_JOB_H_

View File

@@ -17,7 +17,7 @@
<key>CFBundleIconFile</key>
<string>atom.icns</string>
<key>CFBundleVersion</key>
<string>0.28.0</string>
<string>0.29.0</string>
<key>LSMinimumSystemVersion</key>
<string>10.8.0</string>
<key>NSMainNibFile</key>
@@ -26,5 +26,7 @@
<string>AtomApplication</string>
<key>NSSupportsAutomaticGraphicsSwitching</key>
<true/>
<key>NSHighResolutionCapable</key>
<true/>
</dict>
</plist>

View File

@@ -50,8 +50,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,28,0,0
PRODUCTVERSION 0,28,0,0
FILEVERSION 0,29,0,0
PRODUCTVERSION 0,29,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -68,12 +68,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "GitHub, Inc."
VALUE "FileDescription", "Electron"
VALUE "FileVersion", "0.28.0"
VALUE "FileVersion", "0.29.0"
VALUE "InternalName", "electron.exe"
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
VALUE "OriginalFilename", "electron.exe"
VALUE "ProductName", "Electron"
VALUE "ProductVersion", "0.28.0"
VALUE "ProductVersion", "0.29.0"
VALUE "SquirrelAwareVersion", "1"
END
END

View File

@@ -152,9 +152,9 @@ bool StringToAccelerator(const std::string& description,
key = ui::VKEY_HOME;
} else if (tokens[i] == "end") {
key = ui::VKEY_END;
} else if (tokens[i] == "pagedown") {
key = ui::VKEY_PRIOR;
} else if (tokens[i] == "pageup") {
key = ui::VKEY_PRIOR;
} else if (tokens[i] == "pagedown") {
key = ui::VKEY_NEXT;
} else if (tokens[i] == "esc" || tokens[i] == "escape") {
key = ui::VKEY_ESCAPE;

View File

@@ -0,0 +1,175 @@
// 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/web_view_guest_delegate.h"
#include "atom/browser/api/atom_api_web_contents.h"
#include "content/public/browser/guest_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
namespace atom {
namespace {
const int kDefaultWidth = 300;
const int kDefaultHeight = 300;
} // namespace
WebViewGuestDelegate::WebViewGuestDelegate()
: guest_opaque_(true),
guest_host_(nullptr),
auto_size_enabled_(false),
is_full_page_plugin_(false),
api_web_contents_(nullptr) {
}
WebViewGuestDelegate::~WebViewGuestDelegate() {
}
void WebViewGuestDelegate::Initialize(api::WebContents* api_web_contents) {
api_web_contents_ = api_web_contents;
Observe(api_web_contents->GetWebContents());
}
void WebViewGuestDelegate::Destroy() {
// Give the content module an opportunity to perform some cleanup.
guest_host_->WillDestroy();
guest_host_ = nullptr;
}
void WebViewGuestDelegate::SetSize(const SetSizeParams& params) {
bool enable_auto_size =
params.enable_auto_size ? *params.enable_auto_size : auto_size_enabled_;
gfx::Size min_size = params.min_size ? *params.min_size : min_auto_size_;
gfx::Size max_size = params.max_size ? *params.max_size : max_auto_size_;
if (params.normal_size)
normal_size_ = *params.normal_size;
min_auto_size_ = min_size;
min_auto_size_.SetToMin(max_size);
max_auto_size_ = max_size;
max_auto_size_.SetToMax(min_size);
enable_auto_size &= !min_auto_size_.IsEmpty() && !max_auto_size_.IsEmpty();
auto rvh = web_contents()->GetRenderViewHost();
if (enable_auto_size) {
// Autosize is being enabled.
rvh->EnableAutoResize(min_auto_size_, max_auto_size_);
normal_size_.SetSize(0, 0);
} else {
// Autosize is being disabled.
// Use default width/height if missing from partially defined normal size.
if (normal_size_.width() && !normal_size_.height())
normal_size_.set_height(GetDefaultSize().height());
if (!normal_size_.width() && normal_size_.height())
normal_size_.set_width(GetDefaultSize().width());
gfx::Size new_size;
if (!normal_size_.IsEmpty()) {
new_size = normal_size_;
} else if (!guest_size_.IsEmpty()) {
new_size = guest_size_;
} else {
new_size = GetDefaultSize();
}
if (auto_size_enabled_) {
// Autosize was previously enabled.
rvh->DisableAutoResize(new_size);
GuestSizeChangedDueToAutoSize(guest_size_, new_size);
} else {
// Autosize was already disabled.
guest_host_->SizeContents(new_size);
}
guest_size_ = new_size;
}
auto_size_enabled_ = enable_auto_size;
}
void WebViewGuestDelegate::SetAllowTransparency(bool allow) {
if (guest_opaque_ != allow)
return;
auto render_view_host = web_contents()->GetRenderViewHost();
guest_opaque_ = !allow;
if (!render_view_host->GetView())
return;
if (guest_opaque_) {
render_view_host->GetView()->SetBackgroundColorToDefault();
} else {
render_view_host->GetView()->SetBackgroundColor(SK_ColorTRANSPARENT);
}
}
void WebViewGuestDelegate::HandleKeyboardEvent(
content::WebContents* source,
const content::NativeWebKeyboardEvent& event) {
if (embedder_web_contents_)
embedder_web_contents_->GetDelegate()->HandleKeyboardEvent(source, event);
}
void WebViewGuestDelegate::RenderViewReady() {
// We don't want to accidentally set the opacity of an interstitial page.
// WebContents::GetRenderWidgetHostView will return the RWHV of an
// interstitial page if one is showing at this time. We only want opacity
// to apply to web pages.
auto render_view_host_view = web_contents()->GetRenderViewHost()->GetView();
if (guest_opaque_)
render_view_host_view->SetBackgroundColorToDefault();
else
render_view_host_view->SetBackgroundColor(SK_ColorTRANSPARENT);
}
void WebViewGuestDelegate::DidAttach(int guest_proxy_routing_id) {
api_web_contents_->Emit("did-attach");
}
content::WebContents* WebViewGuestDelegate::GetOwnerWebContents() const {
return embedder_web_contents_;
}
void WebViewGuestDelegate::GuestSizeChanged(const gfx::Size& new_size) {
if (!auto_size_enabled_)
return;
GuestSizeChangedDueToAutoSize(guest_size_, new_size);
guest_size_ = new_size;
}
void WebViewGuestDelegate::SetGuestHost(content::GuestHost* guest_host) {
guest_host_ = guest_host;
}
void WebViewGuestDelegate::WillAttach(
content::WebContents* embedder_web_contents,
int element_instance_id,
bool is_full_page_plugin) {
embedder_web_contents_ = embedder_web_contents;
is_full_page_plugin_ = is_full_page_plugin;
}
void WebViewGuestDelegate::GuestSizeChangedDueToAutoSize(
const gfx::Size& old_size, const gfx::Size& new_size) {
api_web_contents_->Emit("size-changed",
old_size.width(), old_size.height(),
new_size.width(), new_size.height());
}
gfx::Size WebViewGuestDelegate::GetDefaultSize() const {
if (is_full_page_plugin_) {
// Full page plugins default to the size of the owner's viewport.
return embedder_web_contents_->GetRenderWidgetHostView()
->GetVisibleViewportSize();
} else {
return gfx::Size(kDefaultWidth, kDefaultHeight);
}
}
} // namespace atom

View File

@@ -0,0 +1,122 @@
// 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_WEB_VIEW_GUEST_DELEGATE_H_
#define ATOM_BROWSER_WEB_VIEW_GUEST_DELEGATE_H_
#include "content/public/browser/browser_plugin_guest_delegate.h"
#include "content/public/browser/web_contents_observer.h"
namespace content {
struct NativeWebKeyboardEvent;
}
namespace atom {
namespace api {
class WebContents;
}
// A struct of parameters for SetSize(). The parameters are all declared as
// scoped pointers since they are all optional. Null pointers indicate that the
// parameter has not been provided, and the last used value should be used. Note
// that when |enable_auto_size| is true, providing |normal_size| is not
// meaningful. This is because the normal size of the guestview is overridden
// whenever autosizing occurs.
struct SetSizeParams {
SetSizeParams() {}
~SetSizeParams() {}
scoped_ptr<bool> enable_auto_size;
scoped_ptr<gfx::Size> min_size;
scoped_ptr<gfx::Size> max_size;
scoped_ptr<gfx::Size> normal_size;
};
class WebViewGuestDelegate : public content::BrowserPluginGuestDelegate,
public content::WebContentsObserver {
public:
WebViewGuestDelegate();
~WebViewGuestDelegate() override;
void Initialize(api::WebContents* api_web_contents);
// Called when the WebContents is going to be destroyed.
void Destroy();
// Used to toggle autosize mode for this GuestView, and set both the automatic
// and normal sizes.
void SetSize(const SetSizeParams& params);
// Sets the transparency of the guest.
void SetAllowTransparency(bool allow);
// Transfer the keyboard event to embedder.
void HandleKeyboardEvent(content::WebContents* source,
const content::NativeWebKeyboardEvent& event);
protected:
// content::WebContentsObserver:
void RenderViewReady() override;
// content::BrowserPluginGuestDelegate:
void DidAttach(int guest_proxy_routing_id) final;
content::WebContents* GetOwnerWebContents() const final;
void GuestSizeChanged(const gfx::Size& new_size) final;
void SetGuestHost(content::GuestHost* guest_host) final;
void WillAttach(content::WebContents* embedder_web_contents,
int element_instance_id,
bool is_full_page_plugin) final;
private:
// This method is invoked when the contents auto-resized to give the container
// an opportunity to match it if it wishes.
//
// This gives the derived class an opportunity to inform its container element
// or perform other actions.
void GuestSizeChangedDueToAutoSize(const gfx::Size& old_size,
const gfx::Size& new_size);
// Returns the default size of the guestview.
gfx::Size GetDefaultSize() const;
// Stores whether the contents of the guest can be transparent.
bool guest_opaque_;
// The WebContents that attaches this guest view.
content::WebContents* embedder_web_contents_;
// The size of the container element.
gfx::Size element_size_;
// The size of the guest content. Note: In autosize mode, the container
// element may not match the size of the guest.
gfx::Size guest_size_;
// A pointer to the guest_host.
content::GuestHost* guest_host_;
// Indicates whether autosize mode is enabled or not.
bool auto_size_enabled_;
// The maximum size constraints of the container element in autosize mode.
gfx::Size max_auto_size_;
// The minimum size constraints of the container element in autosize mode.
gfx::Size min_auto_size_;
// The size that will be used when autosize mode is disabled.
gfx::Size normal_size_;
// Whether the guest view is inside a plugin document.
bool is_full_page_plugin_;
api::WebContents* api_web_contents_;
DISALLOW_COPY_AND_ASSIGN(WebViewGuestDelegate);
};
} // namespace atom
#endif // ATOM_BROWSER_WEB_VIEW_GUEST_DELEGATE_H_

View File

@@ -4,9 +4,6 @@
#include "atom/common/api/atom_api_id_weak_map.h"
#include <algorithm>
#include "base/logging.h"
#include "native_mate/constructor.h"
#include "native_mate/object_template_builder.h"
@@ -16,53 +13,37 @@ namespace atom {
namespace api {
IDWeakMap::IDWeakMap()
: next_id_(0) {
IDWeakMap::IDWeakMap() {
}
IDWeakMap::~IDWeakMap() {
}
int32_t IDWeakMap::Add(v8::Isolate* isolate, v8::Local<v8::Object> object) {
int32_t key = GetNextID();
object->SetHiddenValue(mate::StringToV8(isolate, "IDWeakMapKey"),
mate::Converter<int32_t>::ToV8(isolate, key));
map_[key] = new mate::RefCountedPersistent<v8::Object>(isolate, object);
map_[key]->SetWeak(this, WeakCallback);
return key;
return map_.Add(isolate, object);
}
v8::Local<v8::Value> IDWeakMap::Get(v8::Isolate* isolate, int32_t key) {
if (!Has(key)) {
node::ThrowError(isolate, "Invalid key");
v8::MaybeLocal<v8::Object> result = map_.Get(isolate, key);
if (result.IsEmpty()) {
isolate->ThrowException(v8::Exception::Error(
mate::StringToV8(isolate, "Invalid key")));
return v8::Undefined(isolate);
} else {
return result.ToLocalChecked();
}
return map_[key]->NewHandle();
}
bool IDWeakMap::Has(int32_t key) const {
return map_.find(key) != map_.end();
return map_.Has(key);
}
std::vector<int32_t> IDWeakMap::Keys() const {
std::vector<int32_t> keys;
keys.reserve(map_.size());
for (auto it = map_.begin(); it != map_.end(); ++it)
keys.push_back(it->first);
return keys;
return map_.Keys();
}
void IDWeakMap::Remove(int32_t key) {
if (Has(key))
map_.erase(key);
else
LOG(WARNING) << "Object with key " << key << " is being GCed for twice.";
}
int IDWeakMap::GetNextID() {
return ++next_id_;
map_.Remove(key);
}
// static
@@ -76,14 +57,6 @@ void IDWeakMap::BuildPrototype(v8::Isolate* isolate,
.SetMethod("remove", &IDWeakMap::Remove);
}
// static
void IDWeakMap::WeakCallback(
const v8::WeakCallbackData<v8::Object, IDWeakMap>& data) {
int32_t key = data.GetValue()->GetHiddenValue(
mate::StringToV8(data.GetIsolate(), "IDWeakMapKey"))->Int32Value();
data.GetParameter()->Remove(key);
}
} // namespace api
} // namespace atom
@@ -99,7 +72,7 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
isolate,
"IDWeakMap",
base::Bind(&mate::NewOperatorFactory<IDWeakMap>));
exports->Set(mate::StringToV8(isolate, "IDWeakMap"), constructor);
exports->Set(mate::StringToSymbol(isolate, "IDWeakMap"), constructor);
}
} // namespace

View File

@@ -6,11 +6,9 @@
#ifndef ATOM_COMMON_API_ATOM_API_ID_WEAK_MAP_H_
#define ATOM_COMMON_API_ATOM_API_ID_WEAK_MAP_H_
#include <map>
#include <vector>
#include "base/basictypes.h"
#include "native_mate/scoped_persistent.h"
#include "atom/common/id_weak_map.h"
#include "native_mate/wrappable.h"
namespace atom {
@@ -33,16 +31,8 @@ class IDWeakMap : public mate::Wrappable {
bool Has(int32_t key) const;
std::vector<int32_t> Keys() const;
void Remove(int32_t key);
int GetNextID();
static void WeakCallback(
const v8::WeakCallbackData<v8::Object, IDWeakMap>& data);
int32_t next_id_;
typedef scoped_refptr<mate::RefCountedPersistent<v8::Object> >
RefCountedV8Object;
std::map<int32_t, RefCountedV8Object> map_;
atom::IDWeakMap map_;
DISALLOW_COPY_AND_ASSIGN(IDWeakMap);
};

View File

@@ -26,6 +26,11 @@ void Crash() {
static_cast<DummyClass*>(NULL)->crash = true;
}
void Hang() {
for (;;)
base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
}
// Called when there is a fatal error in V8, we just crash the process here so
// we can get the stack trace.
void FatalErrorCallback(const char* location, const char* message) {
@@ -54,6 +59,7 @@ void AtomBindings::BindTo(v8::Isolate* isolate,
mate::Dictionary dict(isolate, process);
dict.SetMethod("crash", &Crash);
dict.SetMethod("hang", &Hang);
dict.SetMethod("log", &Log);
dict.SetMethod("activateUvLoop",
base::Bind(&AtomBindings::ActivateUVLoop, base::Unretained(this)));

View File

@@ -1,3 +0,0 @@
IDWeakMap = process.atomBinding('id_weak_map').IDWeakMap
module.exports = IDWeakMap

View File

@@ -2,8 +2,10 @@
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/app/atom_main_args.h"
#include "vendor/node/deps/uv/include/uv.h"
#include "atom/common/atom_command_line.h"
#include "base/command_line.h"
#include "node/deps/uv/include/uv.h"
namespace atom {
@@ -19,4 +21,11 @@ void AtomCommandLine::Init(int argc, const char* const* argv) {
}
}
#if defined(OS_LINUX)
// static
void AtomCommandLine::InitializeFromCommandLine() {
argv_ = base::CommandLine::ForCurrentProcess()->argv();
}
#endif
} // namespace atom

View File

@@ -2,13 +2,13 @@
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_APP_ATOM_MAIN_ARGS_H_
#define ATOM_APP_ATOM_MAIN_ARGS_H_
#ifndef ATOM_COMMON_ATOM_COMMAND_LINE_H_
#define ATOM_COMMON_ATOM_COMMAND_LINE_H_
#include <string>
#include <vector>
#include "base/macros.h"
#include "base/basictypes.h"
namespace atom {
@@ -18,6 +18,12 @@ class AtomCommandLine {
static void Init(int argc, const char* const* argv);
static std::vector<std::string> argv() { return argv_; }
#if defined(OS_LINUX)
// On Linux the command line has to be read from base::CommandLine since
// it is using zygote.
static void InitializeFromCommandLine();
#endif
private:
static std::vector<std::string> argv_;
@@ -26,4 +32,4 @@ class AtomCommandLine {
} // namespace atom
#endif // ATOM_APP_ATOM_MAIN_ARGS_H_
#endif // ATOM_COMMON_ATOM_COMMAND_LINE_H_

View File

@@ -6,7 +6,7 @@
#define ATOM_VERSION_H
#define ATOM_MAJOR_VERSION 0
#define ATOM_MINOR_VERSION 28
#define ATOM_MINOR_VERSION 29
#define ATOM_PATCH_VERSION 0
#define ATOM_VERSION_IS_RELEASE 1

View File

@@ -0,0 +1,33 @@
// 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/common/event_emitter_caller.h"
namespace mate {
namespace internal {
v8::Local<v8::Value> CallEmitWithArgs(v8::Isolate* isolate,
v8::Local<v8::Object> obj,
ValueVector* args) {
v8::Local<v8::String> emit_name = StringToSymbol(isolate, "emit");
v8::Local<v8::Value> emit = obj->Get(emit_name);
if (emit.IsEmpty() || !emit->IsFunction()) {
isolate->ThrowException(v8::Exception::TypeError(
StringToV8(isolate, "\"emit\" is not a function")));
return v8::Undefined(isolate);
}
v8::MaybeLocal<v8::Value> result = emit.As<v8::Function>()->Call(
isolate->GetCurrentContext(), obj, args->size(), &args->front());
if (result.IsEmpty()) {
return v8::Undefined(isolate);
}
return result.ToLocalChecked();
}
} // namespace internal
} // namespace mate

View File

@@ -0,0 +1,53 @@
// 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_COMMON_EVENT_EMITTER_CALLER_H_
#define ATOM_COMMON_EVENT_EMITTER_CALLER_H_
#include <vector>
#include "native_mate/converter.h"
namespace mate {
namespace internal {
using ValueVector = std::vector<v8::Local<v8::Value>>;
v8::Local<v8::Value> CallEmitWithArgs(v8::Isolate* isolate,
v8::Local<v8::Object> obj,
ValueVector* args);
} // namespace internal
// obj.emit.apply(obj, name, args...);
// The caller is responsible of allocating a HandleScope.
template<typename StringType, typename... Args>
v8::Local<v8::Value> EmitEvent(v8::Isolate* isolate,
v8::Local<v8::Object> obj,
const StringType& name,
const internal::ValueVector& args) {
internal::ValueVector concatenated_args = { StringToV8(isolate, name) };
concatenated_args.reserve(1 + args.size());
concatenated_args.insert(concatenated_args.end(), args.begin(), args.end());
return internal::CallEmitWithArgs(isolate, obj, &concatenated_args);
}
// obj.emit(name, args...);
// The caller is responsible of allocating a HandleScope.
template<typename StringType, typename... Args>
v8::Local<v8::Value> EmitEvent(v8::Isolate* isolate,
v8::Local<v8::Object> obj,
const StringType& name,
const Args&... args) {
internal::ValueVector converted_args = {
StringToV8(isolate, name),
ConvertToV8(isolate, args)...,
};
return internal::CallEmitWithArgs(isolate, obj, &converted_args);
}
} // namespace mate
#endif // ATOM_COMMON_EVENT_EMITTER_CALLER_H_

View File

@@ -0,0 +1,82 @@
// 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/common/id_weak_map.h"
#include <utility>
#include "native_mate/converter.h"
namespace atom {
IDWeakMap::IDWeakMap() : next_id_(0) {
}
IDWeakMap::~IDWeakMap() {
}
int32_t IDWeakMap::Add(v8::Isolate* isolate, v8::Local<v8::Object> object) {
int32_t id = GetNextID();
object->SetHiddenValue(mate::StringToSymbol(isolate, "IDWeakMapKey"),
mate::Converter<int32_t>::ToV8(isolate, id));
auto global = make_linked_ptr(new v8::Global<v8::Object>(isolate, object));
global->SetWeak(this, &WeakCallback);
map_[id] = global;
return id;
}
v8::MaybeLocal<v8::Object> IDWeakMap::Get(v8::Isolate* isolate, int32_t id) {
auto iter = map_.find(id);
if (iter == map_.end())
return v8::MaybeLocal<v8::Object>();
else
return v8::Local<v8::Object>::New(isolate, *iter->second);
}
bool IDWeakMap::Has(int32_t id) const {
return map_.find(id) != map_.end();
}
std::vector<int32_t> IDWeakMap::Keys() const {
std::vector<int32_t> keys;
keys.reserve(map_.size());
for (const auto& iter : map_)
keys.emplace_back(iter.first);
return keys;
}
std::vector<v8::Local<v8::Object>> IDWeakMap::Values(v8::Isolate* isolate) {
std::vector<v8::Local<v8::Object>> keys;
keys.reserve(map_.size());
for (const auto& iter : map_)
keys.emplace_back(v8::Local<v8::Object>::New(isolate, *iter.second));
return keys;
}
void IDWeakMap::Remove(int32_t id) {
auto iter = map_.find(id);
if (iter == map_.end())
LOG(WARNING) << "Removing unexist object with ID " << id;
else
map_.erase(iter);
}
void IDWeakMap::Clear() {
map_.clear();
}
int32_t IDWeakMap::GetNextID() {
return ++next_id_;
}
// static
void IDWeakMap::WeakCallback(
const v8::WeakCallbackData<v8::Object, IDWeakMap>& data) {
int32_t id = data.GetValue()->GetHiddenValue(
mate::StringToV8(data.GetIsolate(), "IDWeakMapKey"))->Int32Value();
data.GetParameter()->Remove(id);
}
} // namespace atom

61
atom/common/id_weak_map.h Normal file
View File

@@ -0,0 +1,61 @@
// 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_COMMON_ID_WEAK_MAP_H_
#define ATOM_COMMON_ID_WEAK_MAP_H_
#include <unordered_map>
#include <vector>
#include "base/memory/linked_ptr.h"
#include "v8/include/v8.h"
namespace atom {
// Like ES6's WeakMap, but the key is Integer and the value is Weak Pointer.
class IDWeakMap {
public:
IDWeakMap();
~IDWeakMap();
// Adds |object| to WeakMap and returns its allocated |id|.
int32_t Add(v8::Isolate* isolate, v8::Local<v8::Object> object);
// Gets the object from WeakMap by its |id|.
v8::MaybeLocal<v8::Object> Get(v8::Isolate* isolate, int32_t id);
// Whethere there is an object with |id| in this WeakMap.
bool Has(int32_t id) const;
// Returns IDs of all available objects.
std::vector<int32_t> Keys() const;
// Returns all objects.
std::vector<v8::Local<v8::Object>> Values(v8::Isolate* isolate);
// Remove object with |id| in the WeakMap.
void Remove(int32_t key);
// Clears the weak map.
void Clear();
private:
// Returns next available ID.
int32_t GetNextID();
static void WeakCallback(
const v8::WeakCallbackData<v8::Object, IDWeakMap>& data);
// ID of next stored object.
int32_t next_id_;
// Map of stored objects.
std::unordered_map<int32_t, linked_ptr<v8::Global<v8::Object>>> map_;
DISALLOW_COPY_AND_ASSIGN(IDWeakMap);
};
} // namespace atom
#endif // ATOM_COMMON_ID_WEAK_MAP_H_

View File

@@ -20,6 +20,7 @@ process.on 'exit', ->
splitPath = (p) ->
return [false] if typeof p isnt 'string'
return [true, p, ''] if p.substr(-5) is '.asar'
p = path.normalize p
index = p.lastIndexOf ".asar#{path.sep}"
return [false] if index is -1
[true, p.substr(0, index + 5), p.substr(index + 6)]
@@ -322,6 +323,10 @@ exports.wrapFsWithAsar = (fs) ->
return undefined unless info
return '' if info.size is 0
if info.unpacked
realPath = archive.copyFileOut filePath
return fs.readFileSync realPath, encoding: 'utf8'
buffer = new Buffer(info.size)
fd = archive.getFd()
retrun undefined unless fd >= 0

View File

@@ -29,6 +29,12 @@ struct Converter<base::string16> {
}
};
inline v8::Local<v8::String> StringToV8(
v8::Isolate* isolate,
const base::string16& input) {
return ConvertToV8(isolate, input).As<v8::String>();
}
} // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_STRING16_CONVERTER_H_

View File

@@ -7,7 +7,8 @@
#include <string>
#include <vector>
#include "atom/app/atom_main_args.h"
#include "atom/common/atom_command_line.h"
#include "atom/common/event_emitter_caller.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "base/command_line.h"
#include "base/base_paths.h"
@@ -35,6 +36,7 @@ REFERENCE_MODULE(atom_browser_content_tracing);
REFERENCE_MODULE(atom_browser_dialog);
REFERENCE_MODULE(atom_browser_menu);
REFERENCE_MODULE(atom_browser_power_monitor);
REFERENCE_MODULE(atom_browser_power_save_blocker);
REFERENCE_MODULE(atom_browser_protocol);
REFERENCE_MODULE(atom_browser_global_shortcut);
REFERENCE_MODULE(atom_browser_tray);
@@ -128,6 +130,12 @@ void NodeBindings::Initialize() {
node::g_standalone_mode = is_browser_;
node::g_upstream_node_mode = false;
#if defined(OS_LINUX)
// Get real command line in renderer process forked by zygote.
if (!is_browser_)
AtomCommandLine::InitializeFromCommandLine();
#endif
// Parse the debug args.
auto args = AtomCommandLine::argv();
for (const std::string& arg : args)
@@ -179,8 +187,7 @@ void NodeBindings::LoadEnvironment(node::Environment* env) {
if (node::use_debug_agent)
node::EnableDebug(env);
v8::Local<v8::Value> msg = mate::StringToV8(env->isolate(), "loaded");
node::MakeCallback(env->isolate(), env->process_object(), "emit", 1, &msg);
mate::EmitEvent(env->isolate(), env->process_object(), "loaded");
}
void NodeBindings::PrepareMessageLoop() {

View File

@@ -104,6 +104,9 @@ const char kPageVisibility[] = "page-visibility";
// Disable HTTP cache.
const char kDisableHttpCache[] = "disable-http-cache";
// Register schemes to standard.
const char kRegisterStandardSchemes[] = "register-standard-schemes";
} // namespace switches
} // namespace atom

View File

@@ -56,6 +56,7 @@ extern const char kSharedWorker[];
extern const char kPageVisibility[];
extern const char kDisableHttpCache[];
extern const char kRegisterStandardSchemes[];
} // namespace switches

View File

@@ -23,7 +23,7 @@ void OpenItem(const base::FilePath& full_path);
// Open the given external protocol URL in the desktop's default manner.
// (For example, mailto: URLs in the default mail user agent.)
void OpenExternal(const GURL& url);
bool OpenExternal(const GURL& url);
// Move a file to trash.
bool MoveItemToTrash(const base::FilePath& full_path);

View File

@@ -37,12 +37,12 @@ bool XDGUtil(const std::string& util, const std::string& arg) {
return (exit_code == 0);
}
void XDGOpen(const std::string& path) {
XDGUtil("xdg-open", path);
bool XDGOpen(const std::string& path) {
return XDGUtil("xdg-open", path);
}
void XDGEmail(const std::string& email) {
XDGUtil("xdg-email", email);
bool XDGEmail(const std::string& email) {
return XDGUtil("xdg-email", email);
}
} // namespace
@@ -64,11 +64,11 @@ void OpenItem(const base::FilePath& full_path) {
XDGOpen(full_path.value());
}
void OpenExternal(const GURL& url) {
bool OpenExternal(const GURL& url) {
if (url.SchemeIs("mailto"))
XDGEmail(url.spec());
return XDGEmail(url.spec());
else
XDGOpen(url.spec());
return XDGOpen(url.spec());
}
bool MoveItemToTrash(const base::FilePath& full_path) {

View File

@@ -118,26 +118,34 @@ void OpenItem(const base::FilePath& full_path) {
}
}
void OpenExternal(const GURL& url) {
bool OpenExternal(const GURL& url) {
DCHECK([NSThread isMainThread]);
NSString* url_string = base::SysUTF8ToNSString(url.spec());
NSURL* ns_url = [NSURL URLWithString:url_string];
if (!ns_url || ![[NSWorkspace sharedWorkspace] openURL:ns_url])
LOG(WARNING) << "NSWorkspace failed to open URL " << url;
if (!ns_url) {
return false;
}
CFURLRef openingApp = NULL;
OSStatus status = LSGetApplicationForURL((CFURLRef)ns_url,
kLSRolesAll,
NULL,
&openingApp);
if (status != noErr) {
return false;
}
CFRelease(openingApp); // NOT A BUG; LSGetApplicationForURL retains for us
return [[NSWorkspace sharedWorkspace] openURL:ns_url];
}
bool MoveItemToTrash(const base::FilePath& full_path) {
DCHECK([NSThread isMainThread]);
NSString* path_string = base::SysUTF8ToNSString(full_path.value());
NSArray* file_array =
[NSArray arrayWithObject:[path_string lastPathComponent]];
BOOL status = [[NSWorkspace sharedWorkspace]
performFileOperation:NSWorkspaceRecycleOperation
source:[path_string stringByDeletingLastPathComponent]
destination:@""
files:file_array
tag:nil];
if (!path_string || !file_array || !status)
BOOL status = [[NSFileManager defaultManager]
trashItemAtURL:[NSURL fileURLWithPath:path_string]
resultingItemURL:nil
error:nil];
if (!path_string || !status)
LOG(WARNING) << "NSWorkspace failed to move file " << full_path.value()
<< " to trash";
return status;

View File

@@ -135,7 +135,7 @@ void OpenItem(const base::FilePath& full_path) {
ui::win::OpenFileViaShell(full_path);
}
void OpenExternal(const GURL& url) {
bool OpenExternal(const GURL& url) {
// Quote the input scheme to be sure that the command does not have
// parameters unexpected by the external program. This url should already
// have been escaped.
@@ -150,12 +150,12 @@ void OpenExternal(const GURL& url) {
const size_t kMaxUrlLength = 2048;
if (escaped_url.length() > kMaxUrlLength) {
NOTREACHED();
return;
return false;
}
if (base::win::GetVersion() < base::win::VERSION_WIN7) {
if (!ValidateShellCommandForScheme(url.scheme()))
return;
return false;
}
if (reinterpret_cast<ULONG_PTR>(ShellExecuteA(NULL, "open",
@@ -164,8 +164,9 @@ void OpenExternal(const GURL& url) {
// We fail to execute the call. We could display a message to the user.
// TODO(nsylvain): we should also add a dialog to warn on errors. See
// bug 1136923.
return;
return false;
}
return true;
}
bool MoveItemToTrash(const base::FilePath& path) {

View File

@@ -5,18 +5,29 @@ CallbacksRegistry = require 'callbacks-registry'
callbacksRegistry = new CallbacksRegistry
# Check for circular reference.
isCircular = (field, visited) ->
if typeof field is 'object'
if field in visited
return true
visited.push field
return false
# Convert the arguments object into an array of meta data.
wrapArgs = (args) ->
wrapArgs = (args, visited=[]) ->
valueToMeta = (value) ->
if Array.isArray value
type: 'array', value: wrapArgs(value)
type: 'array', value: wrapArgs(value, visited)
else if Buffer.isBuffer value
type: 'buffer', value: Array::slice.call(value, 0)
else if value? and typeof value is 'object' and v8Util.getHiddenValue value, 'atomId'
type: 'remote-object', id: v8Util.getHiddenValue value, 'atomId'
else if value? and typeof value is 'object'
ret = type: 'object', name: value.constructor.name, members: []
ret.members.push(name: prop, value: valueToMeta(field)) for prop, field of value
for prop, field of value
ret.members.push
name: prop
value: valueToMeta(if isCircular(field, visited) then null else field)
ret
else if typeof value is 'function' and v8Util.getHiddenValue value, 'returnValue'
type: 'function-with-return-value', value: valueToMeta(value())

View File

@@ -7,8 +7,11 @@
#include <string>
#include <vector>
#include "atom/common/api/api_messages.h"
// Put this before event_emitter_caller.h to have string16 support.
#include "atom/common/native_mate_converters/string16_converter.h"
#include "atom/common/api/api_messages.h"
#include "atom/common/event_emitter_caller.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "atom/common/options_switches.h"
#include "atom/renderer/atom_renderer_client.h"
@@ -134,13 +137,10 @@ void AtomRenderViewObserver::OnBrowserMessage(const base::string16& channel,
v8::Local<v8::Context> context = frame->mainWorldScriptContext();
v8::Context::Scope context_scope(context);
std::vector<v8::Local<v8::Value>> arguments = ListValueToVector(
isolate, args);
arguments.insert(arguments.begin(), mate::ConvertToV8(isolate, channel));
v8::Local<v8::Object> ipc;
if (GetIPCObject(isolate, context, &ipc))
node::MakeCallback(isolate, ipc, "emit", arguments.size(), &arguments[0]);
if (GetIPCObject(isolate, context, &ipc)) {
mate::EmitEvent(isolate, ipc, channel, ListValueToVector(isolate, args));
}
}
} // namespace atom

View File

@@ -45,7 +45,7 @@ window.open = (url, frameName='', features='') ->
value
options.x ?= options.left if options.left
options.y ?= options.top if options.top
options.title ?= name
options.title ?= frameName
options.width ?= 800
options.height ?= 600
@@ -76,9 +76,10 @@ window.prompt = ->
throw new Error('prompt() is and will not be supported.')
# Simple implementation of postMessage.
window.opener =
postMessage: (message, targetOrigin='*') ->
ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', message, targetOrigin
unless process.guestInstanceId?
window.opener =
postMessage: (message, targetOrigin='*') ->
ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', message, targetOrigin
ipc.on 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', (message, targetOrigin) ->
window.postMessage message, targetOrigin

View File

@@ -275,6 +275,8 @@ registerWebViewElement = ->
"closeDevTools"
"isDevToolsOpened"
"inspectElement"
"setAudioMuted"
"isAudioMuted"
"undo"
"redo"
"cut"
@@ -289,6 +291,8 @@ registerWebViewElement = ->
"send"
"getId"
"inspectServiceWorker"
"print"
"printToPDF"
]
# Forward proto.foo* method calls to WebViewImpl.foo*.

View File

@@ -0,0 +1,140 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/printing/print_preview_message_handler.h"
#include "base/bind.h"
#include "base/memory/shared_memory.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/printing/print_job_manager.h"
#include "chrome/browser/printing/printer_query.h"
#include "chrome/common/print_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "printing/page_size_margins.h"
#include "printing/print_job_constants.h"
#include "printing/pdf_metafile_skia.h"
#include "atom/common/node_includes.h"
using content::BrowserThread;
using content::WebContents;
DEFINE_WEB_CONTENTS_USER_DATA_KEY(printing::PrintPreviewMessageHandler);
namespace {
void StopWorker(int document_cookie) {
if (document_cookie <= 0)
return;
scoped_refptr<printing::PrintQueriesQueue> queue =
g_browser_process->print_job_manager()->queue();
scoped_refptr<printing::PrinterQuery> printer_query =
queue->PopPrinterQuery(document_cookie);
if (printer_query.get()) {
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(&printing::PrinterQuery::StopWorker,
printer_query));
}
}
char* CopyPDFDataOnIOThread(
const PrintHostMsg_DidPreviewDocument_Params& params) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
scoped_ptr<base::SharedMemory> shared_buf(
new base::SharedMemory(params.metafile_data_handle, true));
if (!shared_buf->Map(params.data_size))
return nullptr;
char* memory_pdf_data = static_cast<char*>(shared_buf->memory());
char* pdf_data = new char[params.data_size];
memcpy(pdf_data, memory_pdf_data, params.data_size);
return pdf_data;
}
} // namespace
namespace printing {
PrintPreviewMessageHandler::PrintPreviewMessageHandler(
WebContents* web_contents)
: content::WebContentsObserver(web_contents) {
DCHECK(web_contents);
}
PrintPreviewMessageHandler::~PrintPreviewMessageHandler() {
}
void PrintPreviewMessageHandler::OnMetafileReadyForPrinting(
const PrintHostMsg_DidPreviewDocument_Params& params) {
// Always try to stop the worker.
StopWorker(params.document_cookie);
if (params.expected_pages_count <= 0) {
NOTREACHED();
return;
}
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::IO,
FROM_HERE,
base::Bind(&CopyPDFDataOnIOThread, params),
base::Bind(&PrintPreviewMessageHandler::RunPrintToPDFCallback,
base::Unretained(this),
params.preview_request_id,
params.data_size));
}
void PrintPreviewMessageHandler::OnPrintPreviewFailed(int document_cookie,
int request_id) {
StopWorker(document_cookie);
RunPrintToPDFCallback(request_id, 0, nullptr);
}
bool PrintPreviewMessageHandler::OnMessageReceived(
const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PrintPreviewMessageHandler, message)
IPC_MESSAGE_HANDLER(PrintHostMsg_MetafileReadyForPrinting,
OnMetafileReadyForPrinting)
IPC_MESSAGE_HANDLER(PrintHostMsg_PrintPreviewFailed,
OnPrintPreviewFailed)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void PrintPreviewMessageHandler::PrintToPDF(
const base::DictionaryValue& options,
const atom::api::WebContents::PrintToPDFCallback& callback) {
int request_id;
options.GetInteger(printing::kPreviewRequestID, &request_id);
print_to_pdf_callback_map_[request_id] = callback;
content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
rvh->Send(new PrintMsg_PrintPreview(rvh->GetRoutingID(), options));
}
void PrintPreviewMessageHandler::RunPrintToPDFCallback(
int request_id, uint32 data_size, char* data) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
if (data) {
v8::Local<v8::Value> buffer = node::Buffer::Use(isolate,
data, static_cast<size_t>(data_size));
print_to_pdf_callback_map_[request_id].Run(v8::Null(isolate), buffer);
} else {
v8::Local<v8::String> error_message = v8::String::NewFromUtf8(isolate,
"Fail to generate PDF");
print_to_pdf_callback_map_[request_id].Run(
v8::Exception::Error(error_message), v8::Null(isolate));
}
print_to_pdf_callback_map_.erase(request_id);
}
} // namespace printing

View File

@@ -0,0 +1,59 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_PRINTING_PRINT_PREVIEW_MESSAGE_HANDLER_H_
#define CHROME_BROWSER_PRINTING_PRINT_PREVIEW_MESSAGE_HANDLER_H_
#include <map>
#include "atom/browser/api/atom_api_web_contents.h"
#include "base/compiler_specific.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
struct PrintHostMsg_DidPreviewDocument_Params;
namespace content {
class WebContents;
}
namespace printing {
struct PageSizeMargins;
// Manages the print preview handling for a WebContents.
class PrintPreviewMessageHandler
: public content::WebContentsObserver,
public content::WebContentsUserData<PrintPreviewMessageHandler> {
public:
~PrintPreviewMessageHandler() override;
// content::WebContentsObserver implementation.
bool OnMessageReceived(const IPC::Message& message) override;
void PrintToPDF(const base::DictionaryValue& options,
const atom::api::WebContents::PrintToPDFCallback& callback);
private:
typedef std::map<int, atom::api::WebContents::PrintToPDFCallback>
PrintToPDFCallbackMap;
explicit PrintPreviewMessageHandler(content::WebContents* web_contents);
friend class content::WebContentsUserData<PrintPreviewMessageHandler>;
// Message handlers.
void OnMetafileReadyForPrinting(
const PrintHostMsg_DidPreviewDocument_Params& params);
void OnPrintPreviewFailed(int document_cookie, int request_id);
void RunPrintToPDFCallback(int request_id, uint32 data_size, char* data);
PrintToPDFCallbackMap print_to_pdf_callback_map_;
DISALLOW_COPY_AND_ASSIGN(PrintPreviewMessageHandler);
};
} // namespace printing
#endif // CHROME_BROWSER_PRINTING_PRINT_PREVIEW_MESSAGE_HANDLER_H_

View File

@@ -128,6 +128,8 @@ bool PrintingMessageFilter::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_GetDefaultPrintSettings,
OnGetDefaultPrintSettings)
IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_ScriptedPrint, OnScriptedPrint)
IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_UpdatePrintSettings,
OnUpdatePrintSettings)
#if defined(ENABLE_FULL_PRINTING)
IPC_MESSAGE_HANDLER(PrintHostMsg_CheckForCancel, OnCheckForCancel)
#endif
@@ -372,4 +374,57 @@ void PrintingMessageFilter::UpdateFileDescriptor(int render_view_id, int fd) {
}
#endif
void PrintingMessageFilter::OnUpdatePrintSettings(
int document_cookie, const base::DictionaryValue& job_settings,
IPC::Message* reply_msg) {
scoped_ptr<base::DictionaryValue> new_settings(job_settings.DeepCopy());
scoped_refptr<PrinterQuery> printer_query;
printer_query = queue_->PopPrinterQuery(document_cookie);
if (!printer_query.get()) {
int host_id = render_process_id_;
int routing_id = reply_msg->routing_id();
if (!new_settings->GetInteger(printing::kPreviewInitiatorHostId,
&host_id) ||
!new_settings->GetInteger(printing::kPreviewInitiatorRoutingId,
&routing_id)) {
host_id = content::ChildProcessHost::kInvalidUniqueID;
routing_id = content::ChildProcessHost::kInvalidUniqueID;
}
printer_query = queue_->CreatePrinterQuery(host_id, routing_id);
}
printer_query->SetSettings(
new_settings.Pass(),
base::Bind(&PrintingMessageFilter::OnUpdatePrintSettingsReply, this,
printer_query, reply_msg));
}
void PrintingMessageFilter::OnUpdatePrintSettingsReply(
scoped_refptr<PrinterQuery> printer_query,
IPC::Message* reply_msg) {
PrintMsg_PrintPages_Params params;
if (!printer_query.get() ||
printer_query->last_status() != PrintingContext::OK) {
params.Reset();
} else {
RenderParamsFromPrintSettings(printer_query->settings(), &params.params);
params.params.document_cookie = printer_query->cookie();
params.pages = PageRange::GetPages(printer_query->settings().ranges());
}
PrintHostMsg_UpdatePrintSettings::WriteReplyParams(
reply_msg,
params,
printer_query.get() &&
(printer_query->last_status() == printing::PrintingContext::CANCEL));
Send(reply_msg);
// If user hasn't cancelled.
if (printer_query.get()) {
if (printer_query->cookie() && printer_query->settings().dpi()) {
queue_->QueuePrinterQuery(printer_query.get());
} else {
printer_query->StopWorker();
}
}
}
} // namespace printing

View File

@@ -96,6 +96,15 @@ class PrintingMessageFilter : public content::BrowserMessageFilter {
void OnScriptedPrintReply(scoped_refptr<PrinterQuery> printer_query,
IPC::Message* reply_msg);
// Modify the current print settings based on |job_settings|. The task is
// handled by the print worker thread and the UI thread. The reply occurs on
// the IO thread.
void OnUpdatePrintSettings(int document_cookie,
const base::DictionaryValue& job_settings,
IPC::Message* reply_msg);
void OnUpdatePrintSettingsReply(scoped_refptr<PrinterQuery> printer_query,
IPC::Message* reply_msg);
#if defined(ENABLE_FULL_PRINTING)
// Check to see if print preview has been cancelled.
void OnCheckForCancel(int32 preview_ui_id,

View File

@@ -46,7 +46,9 @@ struct PrintMsg_Print_Params {
int document_cookie;
bool selection_only;
bool supports_alpha_blend;
int preview_request_id;
blink::WebPrintScalingOption print_scaling_option;
bool print_to_pdf;
base::string16 title;
base::string16 url;
bool should_print_backgrounds;
@@ -185,6 +187,27 @@ IPC_STRUCT_BEGIN(PrintHostMsg_ScriptedPrint_Params)
IPC_STRUCT_MEMBER(printing::MarginType, margin_type)
IPC_STRUCT_END()
// Parameters to describe a rendered document.
IPC_STRUCT_BEGIN(PrintHostMsg_DidPreviewDocument_Params)
// A shared memory handle to metafile data.
IPC_STRUCT_MEMBER(base::SharedMemoryHandle, metafile_data_handle)
// Size of metafile data.
IPC_STRUCT_MEMBER(uint32, data_size)
// Cookie for the document to ensure correctness.
IPC_STRUCT_MEMBER(int, document_cookie)
// Store the expected pages count.
IPC_STRUCT_MEMBER(int, expected_pages_count)
// Whether the preview can be modified.
IPC_STRUCT_MEMBER(bool, modifiable)
// The id of the preview request.
IPC_STRUCT_MEMBER(int, preview_request_id)
IPC_STRUCT_END()
// Messages sent from the browser to the renderer.
@@ -198,6 +221,12 @@ IPC_MESSAGE_ROUTED2(PrintMsg_PrintPages,
IPC_MESSAGE_ROUTED1(PrintMsg_PrintingDone,
bool /* success */)
// Tells the render view to switch the CSS to print media type, renders every
// requested pages for print preview using the given |settings|. This gets
// called multiple times as the user updates settings.
IPC_MESSAGE_ROUTED1(PrintMsg_PrintPreview,
base::DictionaryValue /* settings */)
// Messages sent from the renderer to the browser.
#if defined(OS_WIN)
@@ -231,6 +260,14 @@ IPC_MESSAGE_ROUTED1(PrintHostMsg_DidPrintPage,
IPC_SYNC_MESSAGE_ROUTED0_1(PrintHostMsg_GetDefaultPrintSettings,
PrintMsg_Print_Params /* default_settings */)
// The renderer wants to update the current print settings with new
// |job_settings|.
IPC_SYNC_MESSAGE_ROUTED2_2(PrintHostMsg_UpdatePrintSettings,
int /* document_cookie */,
base::DictionaryValue /* job_settings */,
PrintMsg_PrintPages_Params /* current_settings */,
bool /* canceled */)
// It's the renderer that controls the printing process when it is generated
// by javascript. This step is about showing UI to the user to select the
// final print settings. The output parameter is the same as
@@ -247,6 +284,15 @@ IPC_MESSAGE_ROUTED0(PrintHostMsg_ShowInvalidPrinterSettingsError)
IPC_MESSAGE_ROUTED1(PrintHostMsg_PrintingFailed,
int /* document cookie */)
// Sends back to the browser the complete rendered document (non-draft mode,
// used for printing) that was requested by a PrintMsg_PrintPreview message.
// The memory handle in this message is already valid in the browser process.
IPC_MESSAGE_ROUTED1(PrintHostMsg_MetafileReadyForPrinting,
PrintHostMsg_DidPreviewDocument_Params /* params */)
IPC_MESSAGE_ROUTED2(PrintHostMsg_PrintPreviewFailed,
int /* document cookie */,
int /* request_id */);
#if defined(OS_WIN)
// Tell the utility process to start rendering the given PDF into a metafile.

View File

@@ -650,6 +650,7 @@ bool PrintWebViewHelper::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(PrintWebViewHelper, message)
IPC_MESSAGE_HANDLER(PrintMsg_PrintPages, OnPrintPages)
IPC_MESSAGE_HANDLER(PrintMsg_PrintingDone, OnPrintingDone)
IPC_MESSAGE_HANDLER(PrintMsg_PrintPreview, OnPrintPreview)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -712,6 +713,128 @@ void PrintWebViewHelper::OnPrintingDone(bool success) {
DidFinishPrinting(success ? OK : FAIL_PRINT);
}
void PrintWebViewHelper::OnPrintPreview(const base::DictionaryValue& settings) {
blink::WebLocalFrame* frame;
if (GetPrintFrame(&frame)) {
print_preview_context_.InitWithFrame(frame);
if (!print_preview_context_.source_frame()) {
DidFinishPrinting(FAIL_PREVIEW);
return;
}
if (!UpdatePrintSettings(print_preview_context_.source_frame(),
print_preview_context_.source_node(), settings)) {
DidFinishPrinting(FAIL_PREVIEW);
return;
}
is_print_ready_metafile_sent_ = false;
PrepareFrameForPreviewDocument();
}
}
void PrintWebViewHelper::PrepareFrameForPreviewDocument() {
reset_prep_frame_view_ = false;
if (!print_pages_params_) {
DidFinishPrinting(FAIL_PREVIEW);
return;
}
// Don't reset loading frame or WebKit will fail assert. Just retry when
// current selection is loaded.
if (prep_frame_view_ && prep_frame_view_->IsLoadingSelection()) {
reset_prep_frame_view_ = true;
return;
}
const PrintMsg_Print_Params& print_params = print_pages_params_->params;
prep_frame_view_.reset(new PrepareFrameAndViewForPrint(
print_params, print_preview_context_.source_frame(),
print_preview_context_.source_node(), ignore_css_margins_));
prep_frame_view_->CopySelectionIfNeeded(
render_view()->GetWebkitPreferences(),
base::Bind(&PrintWebViewHelper::OnFramePreparedForPreviewDocument,
base::Unretained(this)));
}
void PrintWebViewHelper::OnFramePreparedForPreviewDocument() {
if (reset_prep_frame_view_) {
PrepareFrameForPreviewDocument();
return;
}
DidFinishPrinting(CreatePreviewDocument() ? OK : FAIL_PREVIEW);
}
bool PrintWebViewHelper::CreatePreviewDocument() {
if (!print_pages_params_)
return false;
const PrintMsg_Print_Params& print_params = print_pages_params_->params;
const std::vector<int>& pages = print_pages_params_->pages;
if (!print_preview_context_.CreatePreviewDocument(prep_frame_view_.release(),
pages)) {
return false;
}
while (!print_preview_context_.IsFinalPageRendered()) {
int page_number = print_preview_context_.GetNextPageNumber();
DCHECK_GE(page_number, 0);
if (!RenderPreviewPage(page_number, print_params))
return false;
// We must call PrepareFrameAndViewForPrint::FinishPrinting() (by way of
// print_preview_context_.AllPagesRendered()) before calling
// FinalizePrintReadyDocument() when printing a PDF because the plugin
// code does not generate output until we call FinishPrinting(). We do not
// generate draft pages for PDFs, so IsFinalPageRendered() and
// IsLastPageOfPrintReadyMetafile() will be true in the same iteration of
// the loop.
if (print_preview_context_.IsFinalPageRendered())
print_preview_context_.AllPagesRendered();
if (print_preview_context_.IsLastPageOfPrintReadyMetafile()) {
DCHECK(print_preview_context_.IsModifiable() ||
print_preview_context_.IsFinalPageRendered());
if (!FinalizePrintReadyDocument())
return false;
}
}
print_preview_context_.Finished();
return true;
}
bool PrintWebViewHelper::FinalizePrintReadyDocument() {
DCHECK(!is_print_ready_metafile_sent_);
print_preview_context_.FinalizePrintReadyDocument();
// Get the size of the resulting metafile.
PdfMetafileSkia* metafile = print_preview_context_.metafile();
uint32 buf_size = metafile->GetDataSize();
DCHECK_GT(buf_size, 0u);
PrintHostMsg_DidPreviewDocument_Params preview_params;
preview_params.data_size = buf_size;
preview_params.document_cookie = print_pages_params_->params.document_cookie;
preview_params.expected_pages_count =
print_preview_context_.total_page_count();
preview_params.modifiable = print_preview_context_.IsModifiable();
preview_params.preview_request_id =
print_pages_params_->params.preview_request_id;
// Ask the browser to create the shared memory for us.
if (!CopyMetafileDataToSharedMem(metafile,
&(preview_params.metafile_data_handle))) {
LOG(ERROR) << "CopyMetafileDataToSharedMem failed";
print_preview_context_.set_error(PREVIEW_ERROR_METAFILE_COPY_FAILED);
return false;
}
is_print_ready_metafile_sent_ = true;
Send(new PrintHostMsg_MetafileReadyForPrinting(routing_id(), preview_params));
return true;
}
void PrintWebViewHelper::PrintNode(const blink::WebNode& node) {
if (node.isNull() || !node.document().frame()) {
// This can occur when the context menu refers to an invalid WebNode.
@@ -786,6 +909,15 @@ void PrintWebViewHelper::DidFinishPrinting(PrintingResult result) {
Send(new PrintHostMsg_PrintingFailed(routing_id(), cookie));
}
break;
case FAIL_PREVIEW:
LOG(ERROR) << "PREVIEW FAILED.";
if (print_pages_params_) {
Send(new PrintHostMsg_PrintPreviewFailed(routing_id(),
print_pages_params_->params.document_cookie,
print_pages_params_->params.preview_request_id));
}
break;
}
prep_frame_view_.reset();
print_pages_params_.reset();
@@ -916,6 +1048,68 @@ bool PrintWebViewHelper::CalculateNumberOfPages(blink::WebLocalFrame* frame,
return true;
}
bool PrintWebViewHelper::UpdatePrintSettings(
blink::WebLocalFrame* frame,
const blink::WebNode& node,
const base::DictionaryValue& passed_job_settings) {
const base::DictionaryValue* job_settings = &passed_job_settings;
base::DictionaryValue modified_job_settings;
if (job_settings->empty()) {
if (!print_for_preview_)
print_preview_context_.set_error(PREVIEW_ERROR_BAD_SETTING);
return false;
}
bool source_is_html = true;
if (print_for_preview_) {
if (!job_settings->GetBoolean(kSettingPreviewModifiable, &source_is_html)) {
NOTREACHED();
}
} else {
source_is_html = !PrintingNodeOrPdfFrame(frame, node);
}
if (print_for_preview_ || !source_is_html) {
modified_job_settings.MergeDictionary(job_settings);
modified_job_settings.SetBoolean(kSettingHeaderFooterEnabled, false);
modified_job_settings.SetInteger(kSettingMarginsType, NO_MARGINS);
job_settings = &modified_job_settings;
}
// Send the cookie so that UpdatePrintSettings can reuse PrinterQuery when
// possible.
int cookie =
print_pages_params_ ? print_pages_params_->params.document_cookie : 0;
PrintMsg_PrintPages_Params settings;
bool canceled = false;
Send(new PrintHostMsg_UpdatePrintSettings(routing_id(), cookie, *job_settings,
&settings, &canceled));
if (canceled) {
notify_browser_of_print_failure_ = false;
return false;
}
if (!print_for_preview_) {
job_settings->GetInteger(kPreviewRequestID,
&settings.params.preview_request_id);
settings.params.print_to_pdf = true;
UpdateFrameMarginsCssInfo(*job_settings);
settings.params.print_scaling_option =
blink::WebPrintScalingOptionSourceSize;
}
SetPrintPagesParams(settings);
if (!PrintMsg_Print_Params_IsValid(settings.params)) {
if (!print_for_preview_)
print_preview_context_.set_error(PREVIEW_ERROR_INVALID_PRINTER_SETTINGS);
return false;
}
return true;
}
bool PrintWebViewHelper::GetPrintSettingsFromUser(blink::WebFrame* frame,
const blink::WebNode& node,
int expected_pages_count) {
@@ -987,4 +1181,264 @@ void PrintWebViewHelper::SetPrintPagesParams(
print_pages_params_.reset(new PrintMsg_PrintPages_Params(settings));
}
bool PrintWebViewHelper::PreviewPageRendered(int page_number,
PdfMetafileSkia* metafile) {
DCHECK_GE(page_number, FIRST_PAGE_INDEX);
// For non-modifiable files, |metafile| should be NULL, so do not bother
// sending a message. If we don't generate draft metafiles, |metafile| is
// NULL.
if (!print_preview_context_.IsModifiable() ||
!print_preview_context_.generate_draft_pages()) {
DCHECK(!metafile);
return true;
}
if (!metafile) {
NOTREACHED();
print_preview_context_.set_error(
PREVIEW_ERROR_PAGE_RENDERED_WITHOUT_METAFILE);
return false;
}
return true;
}
PrintWebViewHelper::PrintPreviewContext::PrintPreviewContext()
: total_page_count_(0),
current_page_index_(0),
generate_draft_pages_(true),
print_ready_metafile_page_count_(0),
error_(PREVIEW_ERROR_NONE),
state_(UNINITIALIZED) {
}
PrintWebViewHelper::PrintPreviewContext::~PrintPreviewContext() {
}
void PrintWebViewHelper::PrintPreviewContext::InitWithFrame(
blink::WebLocalFrame* web_frame) {
DCHECK(web_frame);
DCHECK(!IsRendering());
state_ = INITIALIZED;
source_frame_.Reset(web_frame);
source_node_.reset();
}
void PrintWebViewHelper::PrintPreviewContext::InitWithNode(
const blink::WebNode& web_node) {
DCHECK(!web_node.isNull());
DCHECK(web_node.document().frame());
DCHECK(!IsRendering());
state_ = INITIALIZED;
source_frame_.Reset(web_node.document().frame());
source_node_ = web_node;
}
void PrintWebViewHelper::PrintPreviewContext::OnPrintPreview() {
DCHECK_EQ(INITIALIZED, state_);
ClearContext();
}
bool PrintWebViewHelper::PrintPreviewContext::CreatePreviewDocument(
PrepareFrameAndViewForPrint* prepared_frame,
const std::vector<int>& pages) {
DCHECK_EQ(INITIALIZED, state_);
state_ = RENDERING;
// Need to make sure old object gets destroyed first.
prep_frame_view_.reset(prepared_frame);
prep_frame_view_->StartPrinting();
total_page_count_ = prep_frame_view_->GetExpectedPageCount();
if (total_page_count_ == 0) {
LOG(ERROR) << "CreatePreviewDocument got 0 page count";
set_error(PREVIEW_ERROR_ZERO_PAGES);
return false;
}
metafile_.reset(new PdfMetafileSkia);
if (!metafile_->Init()) {
set_error(PREVIEW_ERROR_METAFILE_INIT_FAILED);
LOG(ERROR) << "PdfMetafileSkia Init failed";
return false;
}
current_page_index_ = 0;
pages_to_render_ = pages;
// Sort and make unique.
std::sort(pages_to_render_.begin(), pages_to_render_.end());
pages_to_render_.resize(
std::unique(pages_to_render_.begin(), pages_to_render_.end()) -
pages_to_render_.begin());
// Remove invalid pages.
pages_to_render_.resize(std::lower_bound(pages_to_render_.begin(),
pages_to_render_.end(),
total_page_count_) -
pages_to_render_.begin());
print_ready_metafile_page_count_ = pages_to_render_.size();
if (pages_to_render_.empty()) {
print_ready_metafile_page_count_ = total_page_count_;
// Render all pages.
for (int i = 0; i < total_page_count_; ++i)
pages_to_render_.push_back(i);
} else if (generate_draft_pages_) {
int pages_index = 0;
for (int i = 0; i < total_page_count_; ++i) {
if (pages_index < print_ready_metafile_page_count_ &&
i == pages_to_render_[pages_index]) {
pages_index++;
continue;
}
pages_to_render_.push_back(i);
}
}
document_render_time_ = base::TimeDelta();
begin_time_ = base::TimeTicks::Now();
return true;
}
void PrintWebViewHelper::PrintPreviewContext::RenderedPreviewPage(
const base::TimeDelta& page_time) {
DCHECK_EQ(RENDERING, state_);
document_render_time_ += page_time;
UMA_HISTOGRAM_TIMES("PrintPreview.RenderPDFPageTime", page_time);
}
void PrintWebViewHelper::PrintPreviewContext::AllPagesRendered() {
DCHECK_EQ(RENDERING, state_);
state_ = DONE;
prep_frame_view_->FinishPrinting();
}
void PrintWebViewHelper::PrintPreviewContext::FinalizePrintReadyDocument() {
DCHECK(IsRendering());
base::TimeTicks begin_time = base::TimeTicks::Now();
metafile_->FinishDocument();
if (print_ready_metafile_page_count_ <= 0) {
NOTREACHED();
return;
}
UMA_HISTOGRAM_MEDIUM_TIMES("PrintPreview.RenderToPDFTime",
document_render_time_);
base::TimeDelta total_time =
(base::TimeTicks::Now() - begin_time) + document_render_time_;
UMA_HISTOGRAM_MEDIUM_TIMES("PrintPreview.RenderAndGeneratePDFTime",
total_time);
UMA_HISTOGRAM_MEDIUM_TIMES("PrintPreview.RenderAndGeneratePDFTimeAvgPerPage",
total_time / pages_to_render_.size());
}
void PrintWebViewHelper::PrintPreviewContext::Finished() {
DCHECK_EQ(DONE, state_);
state_ = INITIALIZED;
ClearContext();
}
void PrintWebViewHelper::PrintPreviewContext::Failed(bool report_error) {
DCHECK(state_ == INITIALIZED || state_ == RENDERING);
state_ = INITIALIZED;
if (report_error) {
DCHECK_NE(PREVIEW_ERROR_NONE, error_);
UMA_HISTOGRAM_ENUMERATION("PrintPreview.RendererError", error_,
PREVIEW_ERROR_LAST_ENUM);
}
ClearContext();
}
int PrintWebViewHelper::PrintPreviewContext::GetNextPageNumber() {
DCHECK_EQ(RENDERING, state_);
if (IsFinalPageRendered())
return -1;
return pages_to_render_[current_page_index_++];
}
bool PrintWebViewHelper::PrintPreviewContext::IsRendering() const {
return state_ == RENDERING || state_ == DONE;
}
bool PrintWebViewHelper::PrintPreviewContext::IsModifiable() {
// The only kind of node we can print right now is a PDF node.
return !PrintingNodeOrPdfFrame(source_frame(), source_node_);
}
bool PrintWebViewHelper::PrintPreviewContext::HasSelection() {
return IsModifiable() && source_frame()->hasSelection();
}
bool PrintWebViewHelper::PrintPreviewContext::IsLastPageOfPrintReadyMetafile()
const {
DCHECK(IsRendering());
return current_page_index_ == print_ready_metafile_page_count_;
}
bool PrintWebViewHelper::PrintPreviewContext::IsFinalPageRendered() const {
DCHECK(IsRendering());
return static_cast<size_t>(current_page_index_) == pages_to_render_.size();
}
void PrintWebViewHelper::PrintPreviewContext::set_generate_draft_pages(
bool generate_draft_pages) {
DCHECK_EQ(INITIALIZED, state_);
generate_draft_pages_ = generate_draft_pages;
}
void PrintWebViewHelper::PrintPreviewContext::set_error(
enum PrintPreviewErrorBuckets error) {
error_ = error;
}
blink::WebLocalFrame* PrintWebViewHelper::PrintPreviewContext::source_frame() {
DCHECK(state_ != UNINITIALIZED);
return source_frame_.GetFrame();
}
const blink::WebNode&
PrintWebViewHelper::PrintPreviewContext::source_node() const {
DCHECK(state_ != UNINITIALIZED);
return source_node_;
}
blink::WebLocalFrame*
PrintWebViewHelper::PrintPreviewContext::prepared_frame() {
DCHECK(state_ != UNINITIALIZED);
return prep_frame_view_->frame();
}
const blink::WebNode&
PrintWebViewHelper::PrintPreviewContext::prepared_node() const {
DCHECK(state_ != UNINITIALIZED);
return prep_frame_view_->node();
}
int PrintWebViewHelper::PrintPreviewContext::total_page_count() const {
DCHECK(state_ != UNINITIALIZED);
return total_page_count_;
}
bool PrintWebViewHelper::PrintPreviewContext::generate_draft_pages() const {
return generate_draft_pages_;
}
PdfMetafileSkia* PrintWebViewHelper::PrintPreviewContext::metafile() {
DCHECK(IsRendering());
return metafile_.get();
}
int PrintWebViewHelper::PrintPreviewContext::last_error() const {
return error_;
}
void PrintWebViewHelper::PrintPreviewContext::ClearContext() {
prep_frame_view_.reset();
metafile_.reset();
pages_to_render_.clear();
error_ = PREVIEW_ERROR_NONE;
}
} // namespace printing

View File

@@ -76,6 +76,19 @@ class PrintWebViewHelper
OK,
FAIL_PRINT_INIT,
FAIL_PRINT,
FAIL_PREVIEW,
};
enum PrintPreviewErrorBuckets {
PREVIEW_ERROR_NONE, // Always first.
PREVIEW_ERROR_BAD_SETTING,
PREVIEW_ERROR_METAFILE_COPY_FAILED,
PREVIEW_ERROR_METAFILE_INIT_FAILED,
PREVIEW_ERROR_ZERO_PAGES,
PREVIEW_ERROR_MAC_DRAFT_METAFILE_INIT_FAILED,
PREVIEW_ERROR_PAGE_RENDERED_WITHOUT_METAFILE,
PREVIEW_ERROR_INVALID_PRINTER_SETTINGS,
PREVIEW_ERROR_LAST_ENUM // Always last.
};
// RenderViewObserver implementation.
@@ -88,6 +101,8 @@ class PrintWebViewHelper
void OnPrintPages(bool silent, bool print_background);
void OnPrintingDone(bool success);
#endif // !DISABLE_BASIC_PRINTING
void OnPrintPreview(const base::DictionaryValue& settings);
// Get |page_size| and |content_area| information from
// |page_layout_in_points|.
@@ -99,6 +114,24 @@ class PrintWebViewHelper
// Update |ignore_css_margins_| based on settings.
void UpdateFrameMarginsCssInfo(const base::DictionaryValue& settings);
// Prepare frame for creating preview document.
void PrepareFrameForPreviewDocument();
// Continue creating preview document.
void OnFramePreparedForPreviewDocument();
// Finalize the print ready preview document.
bool FinalizePrintReadyDocument();
// Renders a print preview page. |page_number| is 0-based.
// Returns true if print preview should continue, false on failure.
bool RenderPreviewPage(int page_number,
const PrintMsg_Print_Params& print_params);
// Initialize the print preview document.
bool CreatePreviewDocument();
// Main printing code -------------------------------------------------------
void Print(blink::WebLocalFrame* frame,
@@ -120,6 +153,14 @@ class PrintWebViewHelper
const blink::WebNode& node,
int* number_of_pages);
// Update the current print settings with new |passed_job_settings|.
// |passed_job_settings| dictionary contains print job details such as printer
// name, number of copies, page range, etc.
bool UpdatePrintSettings(blink::WebLocalFrame* frame,
const blink::WebNode& node,
const base::DictionaryValue& passed_job_settings);
// Get final print settings from the user.
// Return false if the user cancels or on error.
bool GetPrintSettingsFromUser(blink::WebFrame* frame,
@@ -193,6 +234,13 @@ class PrintWebViewHelper
// Script Initiated Printing ------------------------------------------------
// Notifies the browser a print preview page has been rendered.
// |page_number| is 0-based.
// For a valid |page_number| with modifiable content,
// |metafile| is the rendered page. Otherwise |metafile| is NULL.
// Returns true if print preview should continue, false on failure.
bool PreviewPageRendered(int page_number, PdfMetafileSkia* metafile);
void SetPrintPagesParams(const PrintMsg_PrintPages_Params& settings);
// WebView used only to print the selection.
@@ -213,10 +261,121 @@ class PrintWebViewHelper
// True, when printing from print preview.
bool print_for_preview_;
// Keeps track of the state of print preview between messages.
// TODO(vitalybuka): Create PrintPreviewContext when needed and delete after
// use. Now it's interaction with various messages is confusing.
class PrintPreviewContext {
public:
PrintPreviewContext();
~PrintPreviewContext();
// Initializes the print preview context. Need to be called to set
// the |web_frame| / |web_node| to generate the print preview for.
void InitWithFrame(blink::WebLocalFrame* web_frame);
void InitWithNode(const blink::WebNode& web_node);
// Does bookkeeping at the beginning of print preview.
void OnPrintPreview();
// Create the print preview document. |pages| is empty to print all pages.
// Takes ownership of |prepared_frame|.
bool CreatePreviewDocument(PrepareFrameAndViewForPrint* prepared_frame,
const std::vector<int>& pages);
// Called after a page gets rendered. |page_time| is how long the
// rendering took.
void RenderedPreviewPage(const base::TimeDelta& page_time);
// Updates the print preview context when the required pages are rendered.
void AllPagesRendered();
// Finalizes the print ready preview document.
void FinalizePrintReadyDocument();
// Cleanup after print preview finishes.
void Finished();
// Cleanup after print preview fails.
void Failed(bool report_error);
// Helper functions
int GetNextPageNumber();
bool IsRendering() const;
bool IsModifiable();
bool HasSelection();
bool IsLastPageOfPrintReadyMetafile() const;
bool IsFinalPageRendered() const;
// Setters
void set_generate_draft_pages(bool generate_draft_pages);
void set_error(enum PrintPreviewErrorBuckets error);
// Getters
// Original frame for which preview was requested.
blink::WebLocalFrame* source_frame();
// Original node for which preview was requested.
const blink::WebNode& source_node() const;
// Frame to be use to render preview. May be the same as source_frame(), or
// generated from it, e.g. copy of selected block.
blink::WebLocalFrame* prepared_frame();
// Node to be use to render preview. May be the same as source_node(), or
// generated from it, e.g. copy of selected block.
const blink::WebNode& prepared_node() const;
int total_page_count() const;
bool generate_draft_pages() const;
PdfMetafileSkia* metafile();
int last_error() const;
private:
enum State {
UNINITIALIZED, // Not ready to render.
INITIALIZED, // Ready to render.
RENDERING, // Rendering.
DONE // Finished rendering.
};
// Reset some of the internal rendering context.
void ClearContext();
// Specifies what to render for print preview.
FrameReference source_frame_;
blink::WebNode source_node_;
scoped_ptr<PrepareFrameAndViewForPrint> prep_frame_view_;
scoped_ptr<PdfMetafileSkia> metafile_;
// Total page count in the renderer.
int total_page_count_;
// The current page to render.
int current_page_index_;
// List of page indices that need to be rendered.
std::vector<int> pages_to_render_;
// True, when draft pages needs to be generated.
bool generate_draft_pages_;
// Specifies the total number of pages in the print ready metafile.
int print_ready_metafile_page_count_;
base::TimeDelta document_render_time_;
base::TimeTicks begin_time_;
enum PrintPreviewErrorBuckets error_;
State state_;
};
bool print_node_in_progress_;
bool is_loading_;
bool is_scripted_preview_delayed_;
PrintPreviewContext print_preview_context_;
// Used to fix a race condition where the source is a PDF and print preview
// hangs because RequestPrintPreview is called before DidStopLoading() is
// called. This is a store for the RequestPrintPreview() call and its

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