From c4091eca6eb5d08df1d0e9146c4ae09bfc0690f9 Mon Sep 17 00:00:00 2001 From: SangYong Park Date: Fri, 16 Mar 2018 16:42:13 +0900 Subject: [PATCH 01/16] Add missing node modules Previous patch remove necessary files. (aff6b29276dda4fba6cd1cd62d5e38c479f8223a) so, Add files again. Change-Id: Ib52b9310e152dfaa4d0736744ceeaa9a44f10c51 Signed-off-by: SangYong Park --- wrt/node_modules/align-text/LICENSE | 21 + wrt/node_modules/align-text/README.md | 236 +++++ wrt/node_modules/align-text/index.js | 52 + wrt/node_modules/align-text/package.json | 117 +++ wrt/node_modules/camelcase/index.js | 27 + wrt/node_modules/camelcase/license | 21 + wrt/node_modules/camelcase/package.json | 102 ++ wrt/node_modules/camelcase/readme.md | 56 + wrt/node_modules/center-align/LICENSE | 21 + wrt/node_modules/center-align/README.md | 74 ++ wrt/node_modules/center-align/index.js | 16 + wrt/node_modules/center-align/package.json | 121 +++ wrt/node_modules/center-align/utils.js | 40 + wrt/node_modules/cliui/.coveralls.yml | 1 + wrt/node_modules/cliui/.npmignore | 2 + wrt/node_modules/cliui/.travis.yml | 7 + wrt/node_modules/cliui/LICENSE.txt | 14 + wrt/node_modules/cliui/README.md | 104 ++ wrt/node_modules/cliui/index.js | 273 +++++ wrt/node_modules/cliui/package.json | 122 +++ wrt/node_modules/cliui/test/cliui.js | 349 +++++++ wrt/node_modules/debug/.coveralls.yml | 1 + wrt/node_modules/debug/.eslintrc | 14 + wrt/node_modules/debug/.npmignore | 9 + wrt/node_modules/debug/.travis.yml | 20 + wrt/node_modules/debug/CHANGELOG.md | 378 +++++++ wrt/node_modules/debug/LICENSE | 19 + wrt/node_modules/debug/Makefile | 58 ++ wrt/node_modules/debug/README.md | 367 +++++++ wrt/node_modules/debug/component.json | 19 + wrt/node_modules/debug/karma.conf.js | 70 ++ wrt/node_modules/debug/node.js | 1 + wrt/node_modules/debug/package.json | 136 +++ wrt/node_modules/debug/src/browser.js | 195 ++++ wrt/node_modules/debug/src/debug.js | 225 ++++ wrt/node_modules/debug/src/index.js | 10 + wrt/node_modules/debug/src/node.js | 177 ++++ wrt/node_modules/decamelize/index.js | 13 + wrt/node_modules/decamelize/license | 21 + wrt/node_modules/decamelize/package.json | 106 ++ wrt/node_modules/decamelize/readme.md | 48 + wrt/node_modules/is-buffer/LICENSE | 21 + wrt/node_modules/is-buffer/README.md | 53 + wrt/node_modules/is-buffer/index.js | 21 + wrt/node_modules/is-buffer/package.json | 113 +++ wrt/node_modules/is-buffer/test/basic.js | 24 + wrt/node_modules/kind-of/LICENSE | 21 + wrt/node_modules/kind-of/README.md | 261 +++++ wrt/node_modules/kind-of/index.js | 116 +++ wrt/node_modules/kind-of/package.json | 178 ++++ wrt/node_modules/lazy-cache/LICENSE | 21 + wrt/node_modules/lazy-cache/README.md | 147 +++ wrt/node_modules/lazy-cache/index.js | 67 ++ wrt/node_modules/lazy-cache/package.json | 129 +++ wrt/node_modules/longest/LICENSE | 21 + wrt/node_modules/longest/README.md | 65 ++ wrt/node_modules/longest/index.js | 37 + wrt/node_modules/longest/package.json | 104 ++ wrt/node_modules/ms/index.js | 152 +++ wrt/node_modules/ms/license.md | 21 + wrt/node_modules/ms/package.json | 109 ++ wrt/node_modules/ms/readme.md | 51 + wrt/node_modules/node-constants/.npmignore | 2 + wrt/node_modules/node-constants/LICENSE | 18 + wrt/node_modules/node-constants/README.md | 30 + wrt/node_modules/node-constants/examples/define.js | 27 + .../node-constants/examples/definer.js | 28 + .../node-constants/examples/not_exports.js | 16 + .../node-constants/examples/quick_definer.js | 20 + wrt/node_modules/node-constants/index.js | 1 + wrt/node_modules/node-constants/lib/index.js | 56 + wrt/node_modules/node-constants/package.json | 87 ++ wrt/node_modules/node-constants/test/main.js | 53 + wrt/node_modules/node-constants/test/mocha.opts | 2 + wrt/node_modules/repeat-string/LICENSE | 21 + wrt/node_modules/repeat-string/README.md | 136 +++ wrt/node_modules/repeat-string/index.js | 70 ++ wrt/node_modules/repeat-string/package.json | 168 +++ wrt/node_modules/right-align/LICENSE | 21 + wrt/node_modules/right-align/README.md | 77 ++ wrt/node_modules/right-align/index.js | 16 + wrt/node_modules/right-align/package.json | 101 ++ wrt/node_modules/window-size/LICENSE | 21 + wrt/node_modules/window-size/README.md | 45 + wrt/node_modules/window-size/cli.js | 30 + wrt/node_modules/window-size/index.js | 32 + wrt/node_modules/window-size/package.json | 117 +++ wrt/node_modules/wordwrap/.npmignore | 1 + wrt/node_modules/wordwrap/README.markdown | 70 ++ wrt/node_modules/wordwrap/example/center.js | 10 + wrt/node_modules/wordwrap/example/meat.js | 3 + wrt/node_modules/wordwrap/index.js | 76 ++ wrt/node_modules/wordwrap/package.json | 94 ++ wrt/node_modules/wordwrap/test/break.js | 30 + wrt/node_modules/wordwrap/test/idleness.txt | 63 ++ wrt/node_modules/wordwrap/test/wrap.js | 31 + wrt/node_modules/y18n/LICENSE | 13 + wrt/node_modules/y18n/README.md | 91 ++ wrt/node_modules/y18n/index.js | 172 ++++ wrt/node_modules/y18n/package.json | 105 ++ wrt/node_modules/yargs/CHANGELOG.md | 429 ++++++++ wrt/node_modules/yargs/LICENSE | 21 + wrt/node_modules/yargs/README.md | 1071 ++++++++++++++++++++ wrt/node_modules/yargs/completion.sh.hbs | 28 + wrt/node_modules/yargs/index.js | 564 +++++++++++ wrt/node_modules/yargs/lib/completion.js | 80 ++ wrt/node_modules/yargs/lib/parser.js | 467 +++++++++ wrt/node_modules/yargs/lib/usage.js | 339 +++++++ wrt/node_modules/yargs/lib/validation.js | 249 +++++ wrt/node_modules/yargs/locales/en.json | 36 + wrt/node_modules/yargs/locales/es.json | 36 + wrt/node_modules/yargs/locales/fr.json | 36 + wrt/node_modules/yargs/locales/pirate.json | 12 + wrt/node_modules/yargs/locales/pt.json | 36 + wrt/node_modules/yargs/package.json | 167 +++ 115 files changed, 10920 insertions(+) create mode 100644 wrt/node_modules/align-text/LICENSE create mode 100644 wrt/node_modules/align-text/README.md create mode 100644 wrt/node_modules/align-text/index.js create mode 100644 wrt/node_modules/align-text/package.json create mode 100644 wrt/node_modules/camelcase/index.js create mode 100644 wrt/node_modules/camelcase/license create mode 100644 wrt/node_modules/camelcase/package.json create mode 100644 wrt/node_modules/camelcase/readme.md create mode 100644 wrt/node_modules/center-align/LICENSE create mode 100644 wrt/node_modules/center-align/README.md create mode 100644 wrt/node_modules/center-align/index.js create mode 100644 wrt/node_modules/center-align/package.json create mode 100644 wrt/node_modules/center-align/utils.js create mode 100644 wrt/node_modules/cliui/.coveralls.yml create mode 100644 wrt/node_modules/cliui/.npmignore create mode 100644 wrt/node_modules/cliui/.travis.yml create mode 100644 wrt/node_modules/cliui/LICENSE.txt create mode 100644 wrt/node_modules/cliui/README.md create mode 100644 wrt/node_modules/cliui/index.js create mode 100644 wrt/node_modules/cliui/package.json create mode 100644 wrt/node_modules/cliui/test/cliui.js create mode 100644 wrt/node_modules/debug/.coveralls.yml create mode 100644 wrt/node_modules/debug/.eslintrc create mode 100644 wrt/node_modules/debug/.npmignore create mode 100644 wrt/node_modules/debug/.travis.yml create mode 100644 wrt/node_modules/debug/CHANGELOG.md create mode 100644 wrt/node_modules/debug/LICENSE create mode 100644 wrt/node_modules/debug/Makefile create mode 100644 wrt/node_modules/debug/README.md create mode 100644 wrt/node_modules/debug/component.json create mode 100644 wrt/node_modules/debug/karma.conf.js create mode 100644 wrt/node_modules/debug/node.js create mode 100644 wrt/node_modules/debug/package.json create mode 100644 wrt/node_modules/debug/src/browser.js create mode 100644 wrt/node_modules/debug/src/debug.js create mode 100644 wrt/node_modules/debug/src/index.js create mode 100644 wrt/node_modules/debug/src/node.js create mode 100644 wrt/node_modules/decamelize/index.js create mode 100644 wrt/node_modules/decamelize/license create mode 100644 wrt/node_modules/decamelize/package.json create mode 100644 wrt/node_modules/decamelize/readme.md create mode 100644 wrt/node_modules/is-buffer/LICENSE create mode 100644 wrt/node_modules/is-buffer/README.md create mode 100644 wrt/node_modules/is-buffer/index.js create mode 100644 wrt/node_modules/is-buffer/package.json create mode 100644 wrt/node_modules/is-buffer/test/basic.js create mode 100644 wrt/node_modules/kind-of/LICENSE create mode 100644 wrt/node_modules/kind-of/README.md create mode 100644 wrt/node_modules/kind-of/index.js create mode 100644 wrt/node_modules/kind-of/package.json create mode 100644 wrt/node_modules/lazy-cache/LICENSE create mode 100644 wrt/node_modules/lazy-cache/README.md create mode 100644 wrt/node_modules/lazy-cache/index.js create mode 100644 wrt/node_modules/lazy-cache/package.json create mode 100644 wrt/node_modules/longest/LICENSE create mode 100644 wrt/node_modules/longest/README.md create mode 100644 wrt/node_modules/longest/index.js create mode 100644 wrt/node_modules/longest/package.json create mode 100644 wrt/node_modules/ms/index.js create mode 100644 wrt/node_modules/ms/license.md create mode 100644 wrt/node_modules/ms/package.json create mode 100644 wrt/node_modules/ms/readme.md create mode 100644 wrt/node_modules/node-constants/.npmignore create mode 100644 wrt/node_modules/node-constants/LICENSE create mode 100644 wrt/node_modules/node-constants/README.md create mode 100644 wrt/node_modules/node-constants/examples/define.js create mode 100644 wrt/node_modules/node-constants/examples/definer.js create mode 100644 wrt/node_modules/node-constants/examples/not_exports.js create mode 100644 wrt/node_modules/node-constants/examples/quick_definer.js create mode 100644 wrt/node_modules/node-constants/index.js create mode 100644 wrt/node_modules/node-constants/lib/index.js create mode 100644 wrt/node_modules/node-constants/package.json create mode 100644 wrt/node_modules/node-constants/test/main.js create mode 100644 wrt/node_modules/node-constants/test/mocha.opts create mode 100644 wrt/node_modules/repeat-string/LICENSE create mode 100644 wrt/node_modules/repeat-string/README.md create mode 100644 wrt/node_modules/repeat-string/index.js create mode 100644 wrt/node_modules/repeat-string/package.json create mode 100644 wrt/node_modules/right-align/LICENSE create mode 100644 wrt/node_modules/right-align/README.md create mode 100644 wrt/node_modules/right-align/index.js create mode 100644 wrt/node_modules/right-align/package.json create mode 100644 wrt/node_modules/window-size/LICENSE create mode 100644 wrt/node_modules/window-size/README.md create mode 100755 wrt/node_modules/window-size/cli.js create mode 100644 wrt/node_modules/window-size/index.js create mode 100644 wrt/node_modules/window-size/package.json create mode 100644 wrt/node_modules/wordwrap/.npmignore create mode 100644 wrt/node_modules/wordwrap/README.markdown create mode 100644 wrt/node_modules/wordwrap/example/center.js create mode 100644 wrt/node_modules/wordwrap/example/meat.js create mode 100644 wrt/node_modules/wordwrap/index.js create mode 100644 wrt/node_modules/wordwrap/package.json create mode 100644 wrt/node_modules/wordwrap/test/break.js create mode 100644 wrt/node_modules/wordwrap/test/idleness.txt create mode 100644 wrt/node_modules/wordwrap/test/wrap.js create mode 100644 wrt/node_modules/y18n/LICENSE create mode 100644 wrt/node_modules/y18n/README.md create mode 100644 wrt/node_modules/y18n/index.js create mode 100644 wrt/node_modules/y18n/package.json create mode 100644 wrt/node_modules/yargs/CHANGELOG.md create mode 100644 wrt/node_modules/yargs/LICENSE create mode 100644 wrt/node_modules/yargs/README.md create mode 100644 wrt/node_modules/yargs/completion.sh.hbs create mode 100644 wrt/node_modules/yargs/index.js create mode 100644 wrt/node_modules/yargs/lib/completion.js create mode 100644 wrt/node_modules/yargs/lib/parser.js create mode 100644 wrt/node_modules/yargs/lib/usage.js create mode 100644 wrt/node_modules/yargs/lib/validation.js create mode 100644 wrt/node_modules/yargs/locales/en.json create mode 100644 wrt/node_modules/yargs/locales/es.json create mode 100644 wrt/node_modules/yargs/locales/fr.json create mode 100644 wrt/node_modules/yargs/locales/pirate.json create mode 100644 wrt/node_modules/yargs/locales/pt.json create mode 100644 wrt/node_modules/yargs/package.json diff --git a/wrt/node_modules/align-text/LICENSE b/wrt/node_modules/align-text/LICENSE new file mode 100644 index 0000000..65f90ac --- /dev/null +++ b/wrt/node_modules/align-text/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/wrt/node_modules/align-text/README.md b/wrt/node_modules/align-text/README.md new file mode 100644 index 0000000..476b97f --- /dev/null +++ b/wrt/node_modules/align-text/README.md @@ -0,0 +1,236 @@ +# align-text [![NPM version](https://badge.fury.io/js/align-text.svg)](http://badge.fury.io/js/align-text) [![Build Status](https://travis-ci.org/jonschlinkert/align-text.svg)](https://travis-ci.org/jonschlinkert/align-text) + +> Align the text in a string. + +**Examples** + +Align text values in an array: + +```js +align([1, 2, 3, 100]); +//=> [' 1', ' 2', ' 3', '100'] +``` + +Or [do stuff like this](./example.js): + +[![screen shot 2015-06-09 at 2 08 34 am](https://cloud.githubusercontent.com/assets/383994/8051597/7b716fbc-0e4c-11e5-9aef-4493fd22db58.png)](./example.js) + +Visit [the example](./example.js) to see how this works. + +## Install + +Install with [npm](https://www.npmjs.com/) + +```sh +$ npm i align-text --save +``` + +## Usage + +```js +var align = require('align-text'); +align(text, callback_function_or_integer); +``` + +**Params** + +* `text` can be a **string or array**. If a string is passed, a string will be returned. If an array is passed, an array will be returned. +* `callback|integer`: if an integer, the text will be indented by that amount. If a function, it must return an integer representing the amount of leading indentation to use as `align` loops over each line. + +**Example** + +```js +align(text, 4); +``` + +Would align: + +``` +abc +abc +abc +``` + +To: + +``` + abc + abc + abc +``` + +## callback + +### params + +The callback is used to determine the indentation of each line and gets the following params: + +* `len` the length of the "current" line +* `longest` the length of the longest line +* `line` the current line (string) being aligned +* `lines` the array of all lines + +### return + +The callback may return: + +* an integer that represents the number of spaces to use for padding, +* or an object with the following properties: + - `indent`: **{Number}** the amount of indentation to use. Default is `0` when an object is returned. + - `character`: **{String}** the character to use for indentation. Default is `''` (empty string) when an object is returned. + - `prefix`: **{String}** leading characters to use at the beginning of each line. `''` (empty string) when an object is returned. + +**Integer example:** + +```js +// calculate half the difference between the length +// of the current line and the longest line +function centerAlign(len, longest, line, lines) { + return Math.floor((longest - len) / 2); +} +``` + +**Object example:** + +```js +function centerAlign(len, longest, line, lines) { + return { + character: '\t', + indent: Math.floor((longest - len) / 2), + prefix: '~ ', + } +} +``` + +## Usage examples + +### Center align + +Using the `centerAlign` function from above: + +```js +align(text, centerAlign); +``` + +Would align this text: + +```js +Lorem ipsum dolor sit amet +consectetur adipiscin +elit, sed do eiusmod tempor incididun +ut labore et dolor +magna aliqua. Ut enim ad mini +veniam, quis +``` + +Resulting in this: + +``` + Lorem ipsum dolor sit amet, + consectetur adipiscing +elit, sed do eiusmod tempor incididunt + ut labore et dolore + magna aliqua. Ut enim ad minim + veniam, quis +``` + +**Customize** + +If you wanted to add more padding on the left, just pass the number in the callback. + +For example, to add 4 spaces before every line: + +```js +function centerAlign(len, longest, line, lines) { + return 4 + Math.floor((longest - len) / 2); +} +``` + +Would result in: + +``` + Lorem ipsum dolor sit amet, + consectetur adipiscing + elit, sed do eiusmod tempor incididunt + ut labore et dolore + magna aliqua. Ut enim ad minim + veniam, quis +``` + +### Bullets + +```js +align(text, function (len, max, line, lines) { + return {prefix: ' - '}; +}); +``` + +Would return: + +``` +- Lorem ipsum dolor sit amet, +- consectetur adipiscing +- elit, sed do eiusmod tempor incididunt +- ut labore et dolore +- magna aliqua. Ut enim ad minim +- veniam, quis +``` + +### Different indent character + +```js +align(text, function (len, max, line, lines) { + return { + indent: Math.floor((max - len) / 2), + character: '~', + }; +}); +``` + +Would return + +``` +~~~~~Lorem ipsum dolor sit amet, +~~~~~~~~consectetur adipiscing +elit, sed do eiusmod tempor incididunt +~~~~~~~~~ut labore et dolore +~~~~magna aliqua. Ut enim ad minim +~~~~~~~~~~~~~veniam, quis +``` + +## Related projects + +* [center-align](https://github.com/jonschlinkert/center-align): Center-align the text in a string. +* [justify](https://github.com/bahamas10/node-justify): Left or right (or both) justify text using a custom width and character +* [longest](https://github.com/jonschlinkert/longest): Get the longest item in an array. +* [right-align](https://github.com/jonschlinkert/right-align): Right-align the text in a string. +* [repeat-string](https://github.com/jonschlinkert/repeat-string): Repeat the given string n times. Fastest implementation for repeating a string. +* [word-wrap](https://github.com/jonschlinkert/word-wrap): Wrap words to a specified length. + +## Running tests + +Install dev dependencies: + +```sh +$ npm i -d && npm test +``` + +## Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/align-text/issues/new) + +## Author + +**Jon Schlinkert** + ++ [github/jonschlinkert](https://github.com/jonschlinkert) ++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +## License + +Copyright © 2015 [Jon Schlinkert](https://github.com/jonschlinkert) +Released under the MIT license. + +*** + +_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on June 09, 2015._ diff --git a/wrt/node_modules/align-text/index.js b/wrt/node_modules/align-text/index.js new file mode 100644 index 0000000..75902a3 --- /dev/null +++ b/wrt/node_modules/align-text/index.js @@ -0,0 +1,52 @@ +/*! + * align-text + * + * Copyright (c) 2015, Jon Schlinkert. + * Licensed under the MIT License. + */ + +'use strict'; + +var typeOf = require('kind-of'); +var repeat = require('repeat-string'); +var longest = require('longest'); + +module.exports = function alignText(val, fn) { + var lines, type = typeOf(val); + + if (type === 'array') { + lines = val; + } else if (type === 'string') { + lines = val.split(/(?:\r\n|\n)/); + } else { + throw new TypeError('align-text expects a string or array.'); + } + + var fnType = typeOf(fn); + var len = lines.length; + var max = longest(lines); + var res = [], i = 0; + + while (len--) { + var line = String(lines[i++]); + var diff; + + if (fnType === 'function') { + diff = fn(line.length, max.length, line, lines, i); + } else if (fnType === 'number') { + diff = fn; + } else { + diff = max.length - line.length; + } + + if (typeOf(diff) === 'number') { + res.push(repeat(' ', diff) + line); + } else if (typeOf(diff) === 'object') { + var result = repeat(diff.character || ' ', diff.indent || 0); + res.push((diff.prefix || '') + result + line); + } + } + + if (type === 'array') return res; + return res.join('\n'); +}; diff --git a/wrt/node_modules/align-text/package.json b/wrt/node_modules/align-text/package.json new file mode 100644 index 0000000..c920089 --- /dev/null +++ b/wrt/node_modules/align-text/package.json @@ -0,0 +1,117 @@ +{ + "_args": [ + [ + { + "raw": "align-text@^0.1.3", + "scope": null, + "escapedName": "align-text", + "name": "align-text", + "rawSpec": "^0.1.3", + "spec": ">=0.1.3 <0.2.0", + "type": "range" + }, + "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/center-align" + ] + ], + "_from": "align-text@>=0.1.3 <0.2.0", + "_id": "align-text@0.1.4", + "_inCache": true, + "_location": "/align-text", + "_nodeVersion": "5.5.0", + "_npmOperationalInternal": { + "host": "packages-9-west.internal.npmjs.com", + "tmp": "tmp/align-text-0.1.4.tgz_1454377856920_0.9624228512402624" + }, + "_npmUser": { + "name": "shinnn", + "email": "snnskwtnb@gmail.com" + }, + "_npmVersion": "3.6.0", + "_phantomChildren": {}, + "_requested": { + "raw": "align-text@^0.1.3", + "scope": null, + "escapedName": "align-text", + "name": "align-text", + "rawSpec": "^0.1.3", + "spec": ">=0.1.3 <0.2.0", + "type": "range" + }, + "_requiredBy": [ + "/center-align", + "/right-align" + ], + "_resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "_shasum": "0cd90a561093f35d0a99256c22b7069433fad117", + "_shrinkwrap": null, + "_spec": "align-text@^0.1.3", + "_where": "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/center-align", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/align-text/issues" + }, + "dependencies": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + }, + "description": "Align the text in a string.", + "devDependencies": { + "mocha": "*", + "should": "*", + "word-wrap": "^1.0.3" + }, + "directories": {}, + "dist": { + "shasum": "0cd90a561093f35d0a99256c22b7069433fad117", + "tarball": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "gitHead": "7f08e823a54c6bda319d875895813537a66a4c5e", + "homepage": "https://github.com/jonschlinkert/align-text", + "keywords": [ + "align", + "align-center", + "alignment", + "center", + "center-align", + "indent", + "pad", + "padding", + "right", + "right-align", + "text", + "typography" + ], + "license": "MIT", + "main": "index.js", + "maintainers": [ + { + "name": "jonschlinkert", + "email": "github@sellside.com" + }, + { + "name": "shinnn", + "email": "snnskwtnb@gmail.com" + } + ], + "name": "align-text", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/jonschlinkert/align-text.git" + }, + "scripts": { + "test": "mocha" + }, + "version": "0.1.4" +} diff --git a/wrt/node_modules/camelcase/index.js b/wrt/node_modules/camelcase/index.js new file mode 100644 index 0000000..b46e100 --- /dev/null +++ b/wrt/node_modules/camelcase/index.js @@ -0,0 +1,27 @@ +'use strict'; +module.exports = function () { + var str = [].map.call(arguments, function (str) { + return str.trim(); + }).filter(function (str) { + return str.length; + }).join('-'); + + if (!str.length) { + return ''; + } + + if (str.length === 1 || !(/[_.\- ]+/).test(str) ) { + if (str[0] === str[0].toLowerCase() && str.slice(1) !== str.slice(1).toLowerCase()) { + return str; + } + + return str.toLowerCase(); + } + + return str + .replace(/^[_.\- ]+/, '') + .toLowerCase() + .replace(/[_.\- ]+(\w|$)/g, function (m, p1) { + return p1.toUpperCase(); + }); +}; diff --git a/wrt/node_modules/camelcase/license b/wrt/node_modules/camelcase/license new file mode 100644 index 0000000..654d0bf --- /dev/null +++ b/wrt/node_modules/camelcase/license @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/wrt/node_modules/camelcase/package.json b/wrt/node_modules/camelcase/package.json new file mode 100644 index 0000000..8090e15 --- /dev/null +++ b/wrt/node_modules/camelcase/package.json @@ -0,0 +1,102 @@ +{ + "_args": [ + [ + { + "raw": "camelcase@^1.0.2", + "scope": null, + "escapedName": "camelcase", + "name": "camelcase", + "rawSpec": "^1.0.2", + "spec": ">=1.0.2 <2.0.0", + "type": "range" + }, + "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/yargs" + ] + ], + "_from": "camelcase@>=1.0.2 <2.0.0", + "_id": "camelcase@1.2.1", + "_inCache": true, + "_location": "/camelcase", + "_nodeVersion": "0.12.5", + "_npmUser": { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + }, + "_npmVersion": "2.11.2", + "_phantomChildren": {}, + "_requested": { + "raw": "camelcase@^1.0.2", + "scope": null, + "escapedName": "camelcase", + "name": "camelcase", + "rawSpec": "^1.0.2", + "spec": ">=1.0.2 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/yargs" + ], + "_resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "_shasum": "9bb5304d2e0b56698b2c758b08a3eaa9daa58a39", + "_shrinkwrap": null, + "_spec": "camelcase@^1.0.2", + "_where": "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/yargs", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "http://sindresorhus.com" + }, + "bugs": { + "url": "https://github.com/sindresorhus/camelcase/issues" + }, + "dependencies": {}, + "description": "Convert a dash/dot/underscore/space separated string to camelCase: foo-bar → fooBar", + "devDependencies": { + "ava": "0.0.4" + }, + "directories": {}, + "dist": { + "shasum": "9bb5304d2e0b56698b2c758b08a3eaa9daa58a39", + "tarball": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "gitHead": "185ba12da723be9c1ee986cc2956bdc4c517a141", + "homepage": "https://github.com/sindresorhus/camelcase", + "keywords": [ + "camelcase", + "camel-case", + "camel", + "case", + "dash", + "hyphen", + "dot", + "underscore", + "separator", + "string", + "text", + "convert" + ], + "license": "MIT", + "maintainers": [ + { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + } + ], + "name": "camelcase", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/sindresorhus/camelcase.git" + }, + "scripts": { + "test": "node test.js" + }, + "version": "1.2.1" +} diff --git a/wrt/node_modules/camelcase/readme.md b/wrt/node_modules/camelcase/readme.md new file mode 100644 index 0000000..516dc39 --- /dev/null +++ b/wrt/node_modules/camelcase/readme.md @@ -0,0 +1,56 @@ +# camelcase [![Build Status](https://travis-ci.org/sindresorhus/camelcase.svg?branch=master)](https://travis-ci.org/sindresorhus/camelcase) + +> Convert a dash/dot/underscore/space separated string to camelCase: `foo-bar` → `fooBar` + + +## Install + +```sh +$ npm install --save camelcase +``` + + +## Usage + +```js +var camelCase = require('camelcase'); + +camelCase('foo-bar'); +//=> fooBar + +camelCase('foo_bar'); +//=> fooBar + +camelCase('Foo-Bar'); +//=> fooBar + +camelCase('--foo.bar'); +//=> fooBar + +camelCase('__foo__bar__'); +//=> fooBar + +camelCase('foo bar'); +//=> fooBar + +console.log(process.argv[3]); +//=> --foo-bar +camelCase(process.argv[3]); +//=> fooBar + +camelCase('foo', 'bar'); +//=> fooBar + +camelCase('__foo__', '--bar'); +//=> fooBar +``` + + +## Related + +See [`decamelize`](https://github.com/sindresorhus/decamelize) for the inverse. + + +## License + +MIT © [Sindre Sorhus](http://sindresorhus.com) diff --git a/wrt/node_modules/center-align/LICENSE b/wrt/node_modules/center-align/LICENSE new file mode 100644 index 0000000..65f90ac --- /dev/null +++ b/wrt/node_modules/center-align/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/wrt/node_modules/center-align/README.md b/wrt/node_modules/center-align/README.md new file mode 100644 index 0000000..cbcf3be --- /dev/null +++ b/wrt/node_modules/center-align/README.md @@ -0,0 +1,74 @@ +# center-align [![NPM version](https://badge.fury.io/js/center-align.svg)](http://badge.fury.io/js/center-align) + +> Center-align the text in a string. + +Install with [npm](https://www.npmjs.com/) + +```sh +$ npm i center-align --save +``` + +## Usage + +```js +var centerAlign = require('center-align'); +``` + +**Example** + +If used on the following: + +``` +Lorem ipsum dolor sit amet, +consectetur adipiscing +elit, sed do eiusmod tempor incididunt +ut labore et dolore +magna aliqua. Ut enim ad minim +veniam, quis +``` + +The result would be: + +``` + Lorem ipsum dolor sit amet, + consectetur adipiscing +elit, sed do eiusmod tempor incididunt + ut labore et dolore + magna aliqua. Ut enim ad minim + veniam, quis +``` + +## Related projects + +* [align-text](https://www.npmjs.com/package/align-text): Align the text in a string. | [homepage](https://github.com/jonschlinkert/align-text) +* [justified](https://www.npmjs.com/package/justified): Wrap words to a specified length and justified the text. | [homepage](https://github.com/jonschlinkert/justified) +* [right-align](https://www.npmjs.com/package/right-align): Right-align the text in a string. | [homepage](https://github.com/jonschlinkert/right-align) +* [word-wrap](https://www.npmjs.com/package/word-wrap): Wrap words to a specified length. | [homepage](https://github.com/jonschlinkert/word-wrap) + +## Running tests + +Install dev dependencies: + +```sh +$ npm i -d && npm test +``` + +## Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/center-align/issues/new). + +## Author + +**Jon Schlinkert** + ++ [github/jonschlinkert](https://github.com/jonschlinkert) ++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +## License + +Copyright © 2015 Jon Schlinkert +Released under the MIT license. + +*** + +_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on October 27, 2015._ \ No newline at end of file diff --git a/wrt/node_modules/center-align/index.js b/wrt/node_modules/center-align/index.js new file mode 100644 index 0000000..c6ed54a --- /dev/null +++ b/wrt/node_modules/center-align/index.js @@ -0,0 +1,16 @@ +/*! + * center-align + * + * Copycenter (c) 2015, Jon Schlinkert. + * Licensed under the MIT License. + */ + +'use strict'; + +var utils = require('./utils'); + +module.exports = function centerAlign(val) { + return utils.align(val, function (len, longest) { + return Math.floor((longest - len) / 2); + }); +}; diff --git a/wrt/node_modules/center-align/package.json b/wrt/node_modules/center-align/package.json new file mode 100644 index 0000000..259f908 --- /dev/null +++ b/wrt/node_modules/center-align/package.json @@ -0,0 +1,121 @@ +{ + "_args": [ + [ + { + "raw": "center-align@^0.1.1", + "scope": null, + "escapedName": "center-align", + "name": "center-align", + "rawSpec": "^0.1.1", + "spec": ">=0.1.1 <0.2.0", + "type": "range" + }, + "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/cliui" + ] + ], + "_from": "center-align@>=0.1.1 <0.2.0", + "_id": "center-align@0.1.3", + "_inCache": true, + "_location": "/center-align", + "_nodeVersion": "5.3.0", + "_npmOperationalInternal": { + "host": "packages-9-west.internal.npmjs.com", + "tmp": "tmp/center-align-0.1.3.tgz_1454366538829_0.9471865000668913" + }, + "_npmUser": { + "name": "jonschlinkert", + "email": "github@sellside.com" + }, + "_npmVersion": "3.3.12", + "_phantomChildren": {}, + "_requested": { + "raw": "center-align@^0.1.1", + "scope": null, + "escapedName": "center-align", + "name": "center-align", + "rawSpec": "^0.1.1", + "spec": ">=0.1.1 <0.2.0", + "type": "range" + }, + "_requiredBy": [ + "/cliui" + ], + "_resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "_shasum": "aa0d32629b6ee972200411cbd4461c907bc2b7ad", + "_shrinkwrap": null, + "_spec": "center-align@^0.1.1", + "_where": "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/cliui", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/center-align/issues" + }, + "dependencies": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + }, + "description": "Center-align the text in a string.", + "devDependencies": { + "mocha": "^2.2.0" + }, + "directories": {}, + "dist": { + "shasum": "aa0d32629b6ee972200411cbd4461c907bc2b7ad", + "tarball": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js", + "utils.js" + ], + "gitHead": "5c5fab5012fceaa3e21a00162958c0ed11109419", + "homepage": "https://github.com/jonschlinkert/center-align", + "keywords": [ + "align", + "align-center", + "center", + "center-align", + "right", + "right-align", + "text", + "typography" + ], + "license": "MIT", + "main": "index.js", + "maintainers": [ + { + "name": "doowb", + "email": "brian.woodward@gmail.com" + }, + { + "name": "jonschlinkert", + "email": "github@sellside.com" + } + ], + "name": "center-align", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/center-align.git" + }, + "scripts": { + "test": "mocha" + }, + "verb": { + "related": { + "description": "", + "list": [ + "align-text", + "right-align", + "justified", + "word-wrap" + ] + } + }, + "version": "0.1.3" +} diff --git a/wrt/node_modules/center-align/utils.js b/wrt/node_modules/center-align/utils.js new file mode 100644 index 0000000..aead6d2 --- /dev/null +++ b/wrt/node_modules/center-align/utils.js @@ -0,0 +1,40 @@ +'use strict'; + +/** + * Lazily-required module dependencies (makes the application + * faster) + */ + +var utils = require('lazy-cache')(require); + +/** + * Temporarily re-assign `require` to trick browserify and + * webpack into reconizing lazy dependencies. + * + * This tiny bit of ugliness has the huge dual advantage of + * only loading modules that are actually called at some + * point in the lifecycle of the application, whilst also + * allowing browserify and webpack to find modules that + * are depended on but never actually called. + */ + +var fn = require; +require = utils; + +/** + * Lazily required module dependencies + */ + +require('align-text', 'align'); + +/** + * Restore `require` + */ + +require = fn; + +/** + * Expose `utils` modules + */ + +module.exports = utils; diff --git a/wrt/node_modules/cliui/.coveralls.yml b/wrt/node_modules/cliui/.coveralls.yml new file mode 100644 index 0000000..73367db --- /dev/null +++ b/wrt/node_modules/cliui/.coveralls.yml @@ -0,0 +1 @@ +repo_token: NiRhyj91Z2vtgob6XdEAqs83rzNnbMZUu diff --git a/wrt/node_modules/cliui/.npmignore b/wrt/node_modules/cliui/.npmignore new file mode 100644 index 0000000..9daa824 --- /dev/null +++ b/wrt/node_modules/cliui/.npmignore @@ -0,0 +1,2 @@ +.DS_Store +node_modules diff --git a/wrt/node_modules/cliui/.travis.yml b/wrt/node_modules/cliui/.travis.yml new file mode 100644 index 0000000..d96edf8 --- /dev/null +++ b/wrt/node_modules/cliui/.travis.yml @@ -0,0 +1,7 @@ +language: node_js +node_js: + - "0.10" + - "0.11" + - "0.12" + - "iojs" +after_script: "NODE_ENV=test YOURPACKAGE_COVERAGE=1 ./node_modules/.bin/mocha --require patched-blanket --reporter mocha-lcov-reporter | ./node_modules/coveralls/bin/coveralls.js" diff --git a/wrt/node_modules/cliui/LICENSE.txt b/wrt/node_modules/cliui/LICENSE.txt new file mode 100644 index 0000000..c7e2747 --- /dev/null +++ b/wrt/node_modules/cliui/LICENSE.txt @@ -0,0 +1,14 @@ +Copyright (c) 2015, Contributors + +Permission to use, copy, modify, and/or distribute this software +for any purpose with or without fee is hereby granted, provided +that the above copyright notice and this permission notice +appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE +LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES +OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/wrt/node_modules/cliui/README.md b/wrt/node_modules/cliui/README.md new file mode 100644 index 0000000..edcafa8 --- /dev/null +++ b/wrt/node_modules/cliui/README.md @@ -0,0 +1,104 @@ +# cliui + +[![Build Status](https://travis-ci.org/bcoe/cliui.png)](https://travis-ci.org/bcoe/cliui) +[![Coverage Status](https://coveralls.io/repos/bcoe/cliui/badge.svg?branch=)](https://coveralls.io/r/bcoe/cliui?branch=) +[![NPM version](https://img.shields.io/npm/v/cliui.svg)](https://www.npmjs.com/package/cliui) + +easily create complex multi-column command-line-interfaces. + +## Example + +```js +var ui = require('cliui')({ + width: 80 +}) + +ui.div('Usage: $0 [command] [options]') + +ui.div({ + text: 'Options:', + padding: [2, 0, 2, 0] +}) + +ui.div( + { + text: "-f, --file", + width: 40, + padding: [0, 4, 0, 4] + }, + { + text: "the file to load", + width: 25 + }, + { + text: "[required]", + align: 'right' + } +) + +console.log(ui.toString()) +``` + +## Layout DSL + +cliui exposes a simple layout DSL: + +If you create a single `ui.row`, passing a string rather than an +object: + +* `\n`: characters will be interpreted as new rows. +* `\t`: characters will be interpreted as new columns. +* ` `: characters will be interpreted as padding. + +**as an example...** + +```js +var ui = require('./')({ + width: 60 +}) + +ui.div( + 'Usage: node ./bin/foo.js\n' + + ' \t provide a regex\n' + + ' \t provide a glob\t [required]' +) + +console.log(ui.toString()) +``` + +**will output:** + +```shell +Usage: node ./bin/foo.js + provide a regex + provide a glob [required] +``` + +## Methods + +```js +cliui = require('cliui') +``` + +### cliui({width: integer}) + +Specify the maximum width of the UI being generated. + +### cliui({wrap: boolean}) + +Enable or disable the wrapping of text in a column. + +### cliui.div(column, column, column) + +Create a row with any number of columns, a column +can either be a string, or an object with the following +options: + +* **width:** the width of a column. +* **align:** alignment, `right` or `center`. +* **padding:** `[top, right, bottom, left]`. + +### cliui.span(column, column, column) + +Similar to `div`, except the next row will be appended without +a new line being created. diff --git a/wrt/node_modules/cliui/index.js b/wrt/node_modules/cliui/index.js new file mode 100644 index 0000000..31b4aa7 --- /dev/null +++ b/wrt/node_modules/cliui/index.js @@ -0,0 +1,273 @@ +var wrap = require('wordwrap'), + align = { + right: require('right-align'), + center: require('center-align') + }, + top = 0, + right = 1, + bottom = 2, + left = 3 + +function UI (opts) { + this.width = opts.width + this.wrap = opts.wrap + this.rows = [] +} + +UI.prototype.span = function () { + var cols = this.div.apply(this, arguments) + cols.span = true +} + +UI.prototype.div = function () { + if (arguments.length === 0) this.div('') + if (this.wrap && this._shouldApplyLayoutDSL.apply(this, arguments)) { + return this._applyLayoutDSL(arguments[0]) + } + + var cols = [] + + for (var i = 0, arg; (arg = arguments[i]) !== undefined; i++) { + if (typeof arg === 'string') cols.push(this._colFromString(arg)) + else cols.push(arg) + } + + this.rows.push(cols) + return cols +} + +UI.prototype._shouldApplyLayoutDSL = function () { + return arguments.length === 1 && typeof arguments[0] === 'string' && + /[\t\n]/.test(arguments[0]) +} + +UI.prototype._applyLayoutDSL = function (str) { + var _this = this, + rows = str.split('\n'), + leftColumnWidth = 0 + + // simple heuristic for layout, make sure the + // second column lines up along the left-hand. + // don't allow the first column to take up more + // than 50% of the screen. + rows.forEach(function (row) { + var columns = row.split('\t') + if (columns.length > 1 && columns[0].length > leftColumnWidth) { + leftColumnWidth = Math.min( + Math.floor(_this.width * 0.5), + columns[0].length + ) + } + }) + + // generate a table: + // replacing ' ' with padding calculations. + // using the algorithmically generated width. + rows.forEach(function (row) { + var columns = row.split('\t') + _this.div.apply(_this, columns.map(function (r, i) { + return { + text: r.trim(), + padding: [0, r.match(/\s*$/)[0].length, 0, r.match(/^\s*/)[0].length], + width: (i === 0 && columns.length > 1) ? leftColumnWidth : undefined + } + })) + }) + + return this.rows[this.rows.length - 1] +} + +UI.prototype._colFromString = function (str) { + return { + text: str + } +} + +UI.prototype.toString = function () { + var _this = this, + lines = [] + + _this.rows.forEach(function (row, i) { + _this.rowToString(row, lines) + }) + + // don't display any lines with the + // hidden flag set. + lines = lines.filter(function (line) { + return !line.hidden + }) + + return lines.map(function (line) { + return line.text + }).join('\n') +} + +UI.prototype.rowToString = function (row, lines) { + var _this = this, + paddingLeft, + rrows = this._rasterize(row), + str = '', + ts, + width, + wrapWidth + + rrows.forEach(function (rrow, r) { + str = '' + rrow.forEach(function (col, c) { + ts = '' // temporary string used during alignment/padding. + width = row[c].width // the width with padding. + wrapWidth = _this._negatePadding(row[c]) // the width without padding. + + for (var i = 0; i < Math.max(wrapWidth, col.length); i++) { + ts += col.charAt(i) || ' ' + } + + // align the string within its column. + if (row[c].align && row[c].align !== 'left' && _this.wrap) { + ts = align[row[c].align](ts.trim() + '\n' + new Array(wrapWidth + 1).join(' ')) + .split('\n')[0] + if (ts.length < wrapWidth) ts += new Array(width - ts.length).join(' ') + } + + // add left/right padding and print string. + paddingLeft = (row[c].padding || [0, 0, 0, 0])[left] + if (paddingLeft) str += new Array(row[c].padding[left] + 1).join(' ') + str += ts + if (row[c].padding && row[c].padding[right]) str += new Array(row[c].padding[right] + 1).join(' ') + + // if prior row is span, try to render the + // current row on the prior line. + if (r === 0 && lines.length > 0) { + str = _this._renderInline(str, lines[lines.length - 1], paddingLeft) + } + }) + + // remove trailing whitespace. + lines.push({ + text: str.replace(/ +$/, ''), + span: row.span + }) + }) + + return lines +} + +// if the full 'source' can render in +// the target line, do so. +UI.prototype._renderInline = function (source, previousLine, paddingLeft) { + var target = previousLine.text, + str = '' + + if (!previousLine.span) return source + + // if we're not applying wrapping logic, + // just always append to the span. + if (!this.wrap) { + previousLine.hidden = true + return target + source + } + + for (var i = 0, tc, sc; i < Math.max(source.length, target.length); i++) { + tc = target.charAt(i) || ' ' + sc = source.charAt(i) || ' ' + // we tried to overwrite a character in the other string. + if (tc !== ' ' && sc !== ' ') return source + // there is not enough whitespace to maintain padding. + if (sc !== ' ' && i < paddingLeft + target.length) return source + // :thumbsup: + if (tc === ' ') str += sc + else str += tc + } + + previousLine.hidden = true + + return str +} + +UI.prototype._rasterize = function (row) { + var _this = this, + i, + rrow, + rrows = [], + widths = this._columnWidths(row), + wrapped + + // word wrap all columns, and create + // a data-structure that is easy to rasterize. + row.forEach(function (col, c) { + // leave room for left and right padding. + col.width = widths[c] + if (_this.wrap) wrapped = wrap.hard(_this._negatePadding(col))(col.text).split('\n') + else wrapped = col.text.split('\n') + + // add top and bottom padding. + if (col.padding) { + for (i = 0; i < (col.padding[top] || 0); i++) wrapped.unshift('') + for (i = 0; i < (col.padding[bottom] || 0); i++) wrapped.push('') + } + + wrapped.forEach(function (str, r) { + if (!rrows[r]) rrows.push([]) + + rrow = rrows[r] + + for (var i = 0; i < c; i++) { + if (rrow[i] === undefined) rrow.push('') + } + rrow.push(str) + }) + }) + + return rrows +} + +UI.prototype._negatePadding = function (col) { + var wrapWidth = col.width + if (col.padding) wrapWidth -= (col.padding[left] || 0) + (col.padding[right] || 0) + return wrapWidth +} + +UI.prototype._columnWidths = function (row) { + var _this = this, + widths = [], + unset = row.length, + unsetWidth, + remainingWidth = this.width + + // column widths can be set in config. + row.forEach(function (col, i) { + if (col.width) { + unset-- + widths[i] = col.width + remainingWidth -= col.width + } else { + widths[i] = undefined + } + }) + + // any unset widths should be calculated. + if (unset) unsetWidth = Math.floor(remainingWidth / unset) + widths.forEach(function (w, i) { + if (!_this.wrap) widths[i] = row[i].width || row[i].text.length + else if (w === undefined) widths[i] = Math.max(unsetWidth, _minWidth(row[i])) + }) + + return widths +} + +// calculates the minimum width of +// a column, based on padding preferences. +function _minWidth (col) { + var padding = col.padding || [] + + return 1 + (padding[left] || 0) + (padding[right] || 0) +} + +module.exports = function (opts) { + opts = opts || {} + + return new UI({ + width: (opts || {}).width || 80, + wrap: typeof opts.wrap === 'boolean' ? opts.wrap : true + }) +} diff --git a/wrt/node_modules/cliui/package.json b/wrt/node_modules/cliui/package.json new file mode 100644 index 0000000..57a447d --- /dev/null +++ b/wrt/node_modules/cliui/package.json @@ -0,0 +1,122 @@ +{ + "_args": [ + [ + { + "raw": "cliui@^2.1.0", + "scope": null, + "escapedName": "cliui", + "name": "cliui", + "rawSpec": "^2.1.0", + "spec": ">=2.1.0 <3.0.0", + "type": "range" + }, + "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/yargs" + ] + ], + "_from": "cliui@>=2.1.0 <3.0.0", + "_id": "cliui@2.1.0", + "_inCache": true, + "_location": "/cliui", + "_nodeVersion": "0.10.36", + "_npmUser": { + "name": "bcoe", + "email": "ben@npmjs.com" + }, + "_npmVersion": "2.7.5", + "_phantomChildren": {}, + "_requested": { + "raw": "cliui@^2.1.0", + "scope": null, + "escapedName": "cliui", + "name": "cliui", + "rawSpec": "^2.1.0", + "spec": ">=2.1.0 <3.0.0", + "type": "range" + }, + "_requiredBy": [ + "/yargs" + ], + "_resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "_shasum": "4b475760ff80264c762c3a1719032e91c7fea0d1", + "_shrinkwrap": null, + "_spec": "cliui@^2.1.0", + "_where": "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/yargs", + "author": { + "name": "Ben Coe", + "email": "ben@npmjs.com" + }, + "bugs": { + "url": "https://github.com/bcoe/cliui/issues" + }, + "config": { + "blanket": { + "pattern": [ + "index.js" + ], + "data-cover-never": [ + "node_modules", + "test" + ], + "output-reporter": "spec" + } + }, + "dependencies": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + }, + "description": "easily create complex multi-column command-line-interfaces", + "devDependencies": { + "blanket": "^1.1.6", + "chai": "^2.2.0", + "coveralls": "^2.11.2", + "mocha": "^2.2.4", + "mocha-lcov-reporter": "0.0.2", + "mocoverage": "^1.0.0", + "patched-blanket": "^1.0.1", + "standard": "^3.6.1" + }, + "directories": {}, + "dist": { + "shasum": "4b475760ff80264c762c3a1719032e91c7fea0d1", + "tarball": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz" + }, + "gitHead": "5d6ce466b144db62abefc4b2252c8aa70a741695", + "homepage": "https://github.com/bcoe/cliui", + "keywords": [ + "cli", + "command-line", + "layout", + "design", + "console", + "wrap", + "table" + ], + "license": "ISC", + "main": "index.js", + "maintainers": [ + { + "name": "bcoe", + "email": "ben@npmjs.com" + } + ], + "name": "cliui", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/bcoe/cliui.git" + }, + "scripts": { + "test": "standard && mocha --check-leaks --ui exports --require patched-blanket -R mocoverage" + }, + "standard": { + "ignore": [ + "**/example/**" + ], + "globals": [ + "it" + ] + }, + "version": "2.1.0" +} diff --git a/wrt/node_modules/cliui/test/cliui.js b/wrt/node_modules/cliui/test/cliui.js new file mode 100644 index 0000000..1cc6127 --- /dev/null +++ b/wrt/node_modules/cliui/test/cliui.js @@ -0,0 +1,349 @@ +/* global describe, it */ + +require('chai').should() + +var cliui = require('../') + +describe('cliui', function () { + describe('div', function () { + it("wraps text at 'width' if a single column is given", function () { + var ui = cliui({ + width: 10 + }) + + ui.div('i am a string that should be wrapped') + + ui.toString().split('\n').forEach(function (row) { + row.length.should.be.lte(10) + }) + }) + + it('evenly divides text across columns if multiple columns are given', function () { + var ui = cliui({ + width: 40 + }) + + ui.div( + {text: 'i am a string that should be wrapped', width: 15}, + 'i am a second string that should be wrapped', + 'i am a third string that should be wrapped' + ) + + // total width of all columns is <= + // the width cliui is initialized with. + ui.toString().split('\n').forEach(function (row) { + row.length.should.be.lte(40) + }) + + // it should wrap each column appropriately. + var expected = [ + 'i am a string i am a i am a third', + 'that should be second string that', + 'wrapped string that should be', + ' should be wrapped', + ' wrapped' + ] + + ui.toString().split('\n').should.eql(expected) + }) + + it('allows for a blank row to be appended', function () { + var ui = cliui({ + width: 40 + }) + + ui.div() + + // it should wrap each column appropriately. + var expected = [''] + + ui.toString().split('\n').should.eql(expected) + }) + }) + + describe('_columnWidths', function () { + it('uses same width for each column by default', function () { + var ui = cliui({ + width: 40 + }), + widths = ui._columnWidths([{}, {}, {}]) + + widths[0].should.equal(13) + widths[1].should.equal(13) + widths[2].should.equal(13) + }) + + it('divides width over remaining columns if first column has width specified', function () { + var ui = cliui({ + width: 40 + }), + widths = ui._columnWidths([{width: 20}, {}, {}]) + + widths[0].should.equal(20) + widths[1].should.equal(10) + widths[2].should.equal(10) + }) + + it('divides width over remaining columns if middle column has width specified', function () { + var ui = cliui({ + width: 40 + }), + widths = ui._columnWidths([{}, {width: 10}, {}]) + + widths[0].should.equal(15) + widths[1].should.equal(10) + widths[2].should.equal(15) + }) + + it('keeps track of remaining width if multiple columns have width specified', function () { + var ui = cliui({ + width: 40 + }), + widths = ui._columnWidths([{width: 20}, {width: 12}, {}]) + + widths[0].should.equal(20) + widths[1].should.equal(12) + widths[2].should.equal(8) + }) + + it('uses a sane default if impossible widths are specified', function () { + var ui = cliui({ + width: 40 + }), + widths = ui._columnWidths([{width: 30}, {width: 30}, {padding: [0, 2, 0, 1]}]) + + widths[0].should.equal(30) + widths[1].should.equal(30) + widths[2].should.equal(4) + }) + }) + + describe('alignment', function () { + it('allows a column to be right aligned', function () { + var ui = cliui({ + width: 40 + }) + + ui.div( + 'i am a string', + {text: 'i am a second string', align: 'right'}, + 'i am a third string that should be wrapped' + ) + + // it should right-align the second column. + var expected = [ + 'i am a stringi am a secondi am a third', + ' stringstring that', + ' should be', + ' wrapped' + ] + + ui.toString().split('\n').should.eql(expected) + }) + + it('allows a column to be center aligned', function () { + var ui = cliui({ + width: 60 + }) + + ui.div( + 'i am a string', + {text: 'i am a second string', align: 'center', padding: [0, 2, 0, 2]}, + 'i am a third string that should be wrapped' + ) + + // it should right-align the second column. + var expected = [ + 'i am a string i am a second i am a third string', + ' string that should be', + ' wrapped' + ] + + ui.toString().split('\n').should.eql(expected) + }) + }) + + describe('padding', function () { + it('handles left/right padding', function () { + var ui = cliui({ + width: 40 + }) + + ui.div( + {text: 'i have padding on my left', padding: [0, 0, 0, 4]}, + {text: 'i have padding on my right', padding: [0, 2, 0, 0], align: 'center'}, + {text: 'i have no padding', padding: [0, 0, 0, 0]} + ) + + // it should add left/right padding to columns. + var expected = [ + ' i have i have i have no', + ' padding padding on padding', + ' on my my right', + ' left' + ] + + ui.toString().split('\n').should.eql(expected) + }) + + it('handles top/bottom padding', function () { + var ui = cliui({ + width: 40 + }) + + ui.div( + 'i am a string', + {text: 'i am a second string', padding: [2, 0, 0, 0]}, + {text: 'i am a third string that should be wrapped', padding: [0, 0, 1, 0]} + ) + + // it should add top/bottom padding to second + // and third columns. + var expected = [ + 'i am a string i am a third', + ' string that', + ' i am a secondshould be', + ' string wrapped', + '' + ] + + ui.toString().split('\n').should.eql(expected) + }) + }) + + describe('wrap', function () { + it('allows wordwrap to be disabled', function () { + var ui = cliui({ + wrap: false + }) + + ui.div( + {text: 'i am a string', padding: [0, 1, 0, 0]}, + {text: 'i am a second string', padding: [0, 2, 0, 0]}, + {text: 'i am a third string that should not be wrapped', padding: [0, 0, 0, 2]} + ) + + ui.toString().should.equal('i am a string i am a second string i am a third string that should not be wrapped') + }) + }) + + describe('span', function () { + it('appends the next row to the end of the prior row if it fits', function () { + var ui = cliui({ + width: 40 + }) + + ui.span( + {text: 'i am a string that will be wrapped', width: 30} + ) + + ui.div( + {text: ' [required] [default: 99]', align: 'right'} + ) + + var expected = [ + 'i am a string that will be', + 'wrapped [required] [default: 99]' + ] + + ui.toString().split('\n').should.eql(expected) + }) + + it('does not append the string if it does not fit on the prior row', function () { + var ui = cliui({ + width: 40 + }) + + ui.span( + {text: 'i am a string that will be wrapped', width: 30} + ) + + ui.div( + {text: 'i am a second row', align: 'left'} + ) + + var expected = [ + 'i am a string that will be', + 'wrapped', + 'i am a second row' + ] + + ui.toString().split('\n').should.eql(expected) + }) + + it('always appends text to prior span if wrap is disabled', function () { + var ui = cliui({ + wrap: false, + width: 40 + }) + + ui.span( + {text: 'i am a string that will be wrapped', width: 30} + ) + + ui.div( + {text: 'i am a second row', align: 'left', padding: [0, 0, 0, 3]} + ) + + ui.div('a third line') + + var expected = [ + 'i am a string that will be wrapped i am a second row', + 'a third line' + ] + + ui.toString().split('\n').should.eql(expected) + }) + }) + + describe('layoutDSL', function () { + it('turns tab into multiple columns', function () { + var ui = cliui({ + width: 60 + }) + + ui.div( + ' \tmy awesome regex\n \tanother row\t a third column' + ) + + var expected = [ + ' my awesome regex', + ' another row a third column' + ] + + ui.toString().split('\n').should.eql(expected) + }) + + it('turns newline into multiple rows', function () { + var ui = cliui({ + width: 40 + }) + + ui.div( + 'Usage: $0\n \t my awesome regex\n \t my awesome glob\t [required]' + ) + var expected = [ + 'Usage: $0', + ' my awesome regex', + ' my awesome [required]', + ' glob' + ] + + ui.toString().split('\n').should.eql(expected) + }) + + it('does not apply DSL if wrap is false', function () { + var ui = cliui({ + width: 40, + wrap: false + }) + + ui.div( + 'Usage: $0\ttwo\tthree' + ) + + ui.toString().should.eql('Usage: $0\ttwo\tthree') + }) + + }) +}) diff --git a/wrt/node_modules/debug/.coveralls.yml b/wrt/node_modules/debug/.coveralls.yml new file mode 100644 index 0000000..20a7068 --- /dev/null +++ b/wrt/node_modules/debug/.coveralls.yml @@ -0,0 +1 @@ +repo_token: SIAeZjKYlHK74rbcFvNHMUzjRiMpflxve diff --git a/wrt/node_modules/debug/.eslintrc b/wrt/node_modules/debug/.eslintrc new file mode 100644 index 0000000..146371e --- /dev/null +++ b/wrt/node_modules/debug/.eslintrc @@ -0,0 +1,14 @@ +{ + "env": { + "browser": true, + "node": true + }, + "globals": { + "chrome": true + }, + "rules": { + "no-console": 0, + "no-empty": [1, { "allowEmptyCatch": true }] + }, + "extends": "eslint:recommended" +} diff --git a/wrt/node_modules/debug/.npmignore b/wrt/node_modules/debug/.npmignore new file mode 100644 index 0000000..5f60eec --- /dev/null +++ b/wrt/node_modules/debug/.npmignore @@ -0,0 +1,9 @@ +support +test +examples +example +*.sock +dist +yarn.lock +coverage +bower.json diff --git a/wrt/node_modules/debug/.travis.yml b/wrt/node_modules/debug/.travis.yml new file mode 100644 index 0000000..a764300 --- /dev/null +++ b/wrt/node_modules/debug/.travis.yml @@ -0,0 +1,20 @@ +sudo: false + +language: node_js + +node_js: + - "4" + - "6" + - "8" + +install: + - make install + +script: + - make lint + - make test + +matrix: + include: + - node_js: '8' + env: BROWSER=1 diff --git a/wrt/node_modules/debug/CHANGELOG.md b/wrt/node_modules/debug/CHANGELOG.md new file mode 100644 index 0000000..a1c0eaf --- /dev/null +++ b/wrt/node_modules/debug/CHANGELOG.md @@ -0,0 +1,378 @@ + +3.0.1 / 2017-08-24 +================== + + * Fix: Disable colors in Edge and Internet Explorer (#489) + +3.0.0 / 2017-08-08 +================== + + * Breaking: Remove DEBUG_FD (#406) + * Breaking: Use `Date#toISOString()` instead to `Date#toUTCString()` when output is not a TTY (#418) + * Breaking: Make millisecond timer namespace specific and allow 'always enabled' output (#408) + * Addition: document `enabled` flag (#465) + * Addition: add 256 colors mode (#481) + * Addition: `enabled()` updates existing debug instances, add `destroy()` function (#440) + * Update: component: update "ms" to v2.0.0 + * Update: separate the Node and Browser tests in Travis-CI + * Update: refactor Readme, fixed documentation, added "Namespace Colors" section, redid screenshots + * Update: separate Node.js and web browser examples for organization + * Update: update "browserify" to v14.4.0 + * Fix: fix Readme typo (#473) + +2.6.8 / 2017-05-18 +================== + + * Fix: Check for undefined on browser globals (#462, @marbemac) + +2.6.7 / 2017-05-16 +================== + + * Fix: Update ms to 2.0.0 to fix regular expression denial of service vulnerability (#458, @hubdotcom) + * Fix: Inline extend function in node implementation (#452, @dougwilson) + * Docs: Fix typo (#455, @msasad) + +2.6.5 / 2017-04-27 +================== + + * Fix: null reference check on window.documentElement.style.WebkitAppearance (#447, @thebigredgeek) + * Misc: clean up browser reference checks (#447, @thebigredgeek) + * Misc: add npm-debug.log to .gitignore (@thebigredgeek) + + +2.6.4 / 2017-04-20 +================== + + * Fix: bug that would occure if process.env.DEBUG is a non-string value. (#444, @LucianBuzzo) + * Chore: ignore bower.json in npm installations. (#437, @joaovieira) + * Misc: update "ms" to v0.7.3 (@tootallnate) + +2.6.3 / 2017-03-13 +================== + + * Fix: Electron reference to `process.env.DEBUG` (#431, @paulcbetts) + * Docs: Changelog fix (@thebigredgeek) + +2.6.2 / 2017-03-10 +================== + + * Fix: DEBUG_MAX_ARRAY_LENGTH (#420, @slavaGanzin) + * Docs: Add backers and sponsors from Open Collective (#422, @piamancini) + * Docs: Add Slackin invite badge (@tootallnate) + +2.6.1 / 2017-02-10 +================== + + * Fix: Module's `export default` syntax fix for IE8 `Expected identifier` error + * Fix: Whitelist DEBUG_FD for values 1 and 2 only (#415, @pi0) + * Fix: IE8 "Expected identifier" error (#414, @vgoma) + * Fix: Namespaces would not disable once enabled (#409, @musikov) + +2.6.0 / 2016-12-28 +================== + + * Fix: added better null pointer checks for browser useColors (@thebigredgeek) + * Improvement: removed explicit `window.debug` export (#404, @tootallnate) + * Improvement: deprecated `DEBUG_FD` environment variable (#405, @tootallnate) + +2.5.2 / 2016-12-25 +================== + + * Fix: reference error on window within webworkers (#393, @KlausTrainer) + * Docs: fixed README typo (#391, @lurch) + * Docs: added notice about v3 api discussion (@thebigredgeek) + +2.5.1 / 2016-12-20 +================== + + * Fix: babel-core compatibility + +2.5.0 / 2016-12-20 +================== + + * Fix: wrong reference in bower file (@thebigredgeek) + * Fix: webworker compatibility (@thebigredgeek) + * Fix: output formatting issue (#388, @kribblo) + * Fix: babel-loader compatibility (#383, @escwald) + * Misc: removed built asset from repo and publications (@thebigredgeek) + * Misc: moved source files to /src (#378, @yamikuronue) + * Test: added karma integration and replaced babel with browserify for browser tests (#378, @yamikuronue) + * Test: coveralls integration (#378, @yamikuronue) + * Docs: simplified language in the opening paragraph (#373, @yamikuronue) + +2.4.5 / 2016-12-17 +================== + + * Fix: `navigator` undefined in Rhino (#376, @jochenberger) + * Fix: custom log function (#379, @hsiliev) + * Improvement: bit of cleanup + linting fixes (@thebigredgeek) + * Improvement: rm non-maintainted `dist/` dir (#375, @freewil) + * Docs: simplified language in the opening paragraph. (#373, @yamikuronue) + +2.4.4 / 2016-12-14 +================== + + * Fix: work around debug being loaded in preload scripts for electron (#368, @paulcbetts) + +2.4.3 / 2016-12-14 +================== + + * Fix: navigation.userAgent error for react native (#364, @escwald) + +2.4.2 / 2016-12-14 +================== + + * Fix: browser colors (#367, @tootallnate) + * Misc: travis ci integration (@thebigredgeek) + * Misc: added linting and testing boilerplate with sanity check (@thebigredgeek) + +2.4.1 / 2016-12-13 +================== + + * Fix: typo that broke the package (#356) + +2.4.0 / 2016-12-13 +================== + + * Fix: bower.json references unbuilt src entry point (#342, @justmatt) + * Fix: revert "handle regex special characters" (@tootallnate) + * Feature: configurable util.inspect()`options for NodeJS (#327, @tootallnate) + * Feature: %O`(big O) pretty-prints objects (#322, @tootallnate) + * Improvement: allow colors in workers (#335, @botverse) + * Improvement: use same color for same namespace. (#338, @lchenay) + +2.3.3 / 2016-11-09 +================== + + * Fix: Catch `JSON.stringify()` errors (#195, Jovan Alleyne) + * Fix: Returning `localStorage` saved values (#331, Levi Thomason) + * Improvement: Don't create an empty object when no `process` (Nathan Rajlich) + +2.3.2 / 2016-11-09 +================== + + * Fix: be super-safe in index.js as well (@TooTallNate) + * Fix: should check whether process exists (Tom Newby) + +2.3.1 / 2016-11-09 +================== + + * Fix: Added electron compatibility (#324, @paulcbetts) + * Improvement: Added performance optimizations (@tootallnate) + * Readme: Corrected PowerShell environment variable example (#252, @gimre) + * Misc: Removed yarn lock file from source control (#321, @fengmk2) + +2.3.0 / 2016-11-07 +================== + + * Fix: Consistent placement of ms diff at end of output (#215, @gorangajic) + * Fix: Escaping of regex special characters in namespace strings (#250, @zacronos) + * Fix: Fixed bug causing crash on react-native (#282, @vkarpov15) + * Feature: Enabled ES6+ compatible import via default export (#212 @bucaran) + * Feature: Added %O formatter to reflect Chrome's console.log capability (#279, @oncletom) + * Package: Update "ms" to 0.7.2 (#315, @DevSide) + * Package: removed superfluous version property from bower.json (#207 @kkirsche) + * Readme: fix USE_COLORS to DEBUG_COLORS + * Readme: Doc fixes for format string sugar (#269, @mlucool) + * Readme: Updated docs for DEBUG_FD and DEBUG_COLORS environment variables (#232, @mattlyons0) + * Readme: doc fixes for PowerShell (#271 #243, @exoticknight @unreadable) + * Readme: better docs for browser support (#224, @matthewmueller) + * Tooling: Added yarn integration for development (#317, @thebigredgeek) + * Misc: Renamed History.md to CHANGELOG.md (@thebigredgeek) + * Misc: Added license file (#226 #274, @CantemoInternal @sdaitzman) + * Misc: Updated contributors (@thebigredgeek) + +2.2.0 / 2015-05-09 +================== + + * package: update "ms" to v0.7.1 (#202, @dougwilson) + * README: add logging to file example (#193, @DanielOchoa) + * README: fixed a typo (#191, @amir-s) + * browser: expose `storage` (#190, @stephenmathieson) + * Makefile: add a `distclean` target (#189, @stephenmathieson) + +2.1.3 / 2015-03-13 +================== + + * Updated stdout/stderr example (#186) + * Updated example/stdout.js to match debug current behaviour + * Renamed example/stderr.js to stdout.js + * Update Readme.md (#184) + * replace high intensity foreground color for bold (#182, #183) + +2.1.2 / 2015-03-01 +================== + + * dist: recompile + * update "ms" to v0.7.0 + * package: update "browserify" to v9.0.3 + * component: fix "ms.js" repo location + * changed bower package name + * updated documentation about using debug in a browser + * fix: security error on safari (#167, #168, @yields) + +2.1.1 / 2014-12-29 +================== + + * browser: use `typeof` to check for `console` existence + * browser: check for `console.log` truthiness (fix IE 8/9) + * browser: add support for Chrome apps + * Readme: added Windows usage remarks + * Add `bower.json` to properly support bower install + +2.1.0 / 2014-10-15 +================== + + * node: implement `DEBUG_FD` env variable support + * package: update "browserify" to v6.1.0 + * package: add "license" field to package.json (#135, @panuhorsmalahti) + +2.0.0 / 2014-09-01 +================== + + * package: update "browserify" to v5.11.0 + * node: use stderr rather than stdout for logging (#29, @stephenmathieson) + +1.0.4 / 2014-07-15 +================== + + * dist: recompile + * example: remove `console.info()` log usage + * example: add "Content-Type" UTF-8 header to browser example + * browser: place %c marker after the space character + * browser: reset the "content" color via `color: inherit` + * browser: add colors support for Firefox >= v31 + * debug: prefer an instance `log()` function over the global one (#119) + * Readme: update documentation about styled console logs for FF v31 (#116, @wryk) + +1.0.3 / 2014-07-09 +================== + + * Add support for multiple wildcards in namespaces (#122, @seegno) + * browser: fix lint + +1.0.2 / 2014-06-10 +================== + + * browser: update color palette (#113, @gscottolson) + * common: make console logging function configurable (#108, @timoxley) + * node: fix %o colors on old node <= 0.8.x + * Makefile: find node path using shell/which (#109, @timoxley) + +1.0.1 / 2014-06-06 +================== + + * browser: use `removeItem()` to clear localStorage + * browser, node: don't set DEBUG if namespaces is undefined (#107, @leedm777) + * package: add "contributors" section + * node: fix comment typo + * README: list authors + +1.0.0 / 2014-06-04 +================== + + * make ms diff be global, not be scope + * debug: ignore empty strings in enable() + * node: make DEBUG_COLORS able to disable coloring + * *: export the `colors` array + * npmignore: don't publish the `dist` dir + * Makefile: refactor to use browserify + * package: add "browserify" as a dev dependency + * Readme: add Web Inspector Colors section + * node: reset terminal color for the debug content + * node: map "%o" to `util.inspect()` + * browser: map "%j" to `JSON.stringify()` + * debug: add custom "formatters" + * debug: use "ms" module for humanizing the diff + * Readme: add "bash" syntax highlighting + * browser: add Firebug color support + * browser: add colors for WebKit browsers + * node: apply log to `console` + * rewrite: abstract common logic for Node & browsers + * add .jshintrc file + +0.8.1 / 2014-04-14 +================== + + * package: re-add the "component" section + +0.8.0 / 2014-03-30 +================== + + * add `enable()` method for nodejs. Closes #27 + * change from stderr to stdout + * remove unnecessary index.js file + +0.7.4 / 2013-11-13 +================== + + * remove "browserify" key from package.json (fixes something in browserify) + +0.7.3 / 2013-10-30 +================== + + * fix: catch localStorage security error when cookies are blocked (Chrome) + * add debug(err) support. Closes #46 + * add .browser prop to package.json. Closes #42 + +0.7.2 / 2013-02-06 +================== + + * fix package.json + * fix: Mobile Safari (private mode) is broken with debug + * fix: Use unicode to send escape character to shell instead of octal to work with strict mode javascript + +0.7.1 / 2013-02-05 +================== + + * add repository URL to package.json + * add DEBUG_COLORED to force colored output + * add browserify support + * fix component. Closes #24 + +0.7.0 / 2012-05-04 +================== + + * Added .component to package.json + * Added debug.component.js build + +0.6.0 / 2012-03-16 +================== + + * Added support for "-" prefix in DEBUG [Vinay Pulim] + * Added `.enabled` flag to the node version [TooTallNate] + +0.5.0 / 2012-02-02 +================== + + * Added: humanize diffs. Closes #8 + * Added `debug.disable()` to the CS variant + * Removed padding. Closes #10 + * Fixed: persist client-side variant again. Closes #9 + +0.4.0 / 2012-02-01 +================== + + * Added browser variant support for older browsers [TooTallNate] + * Added `debug.enable('project:*')` to browser variant [TooTallNate] + * Added padding to diff (moved it to the right) + +0.3.0 / 2012-01-26 +================== + + * Added millisecond diff when isatty, otherwise UTC string + +0.2.0 / 2012-01-22 +================== + + * Added wildcard support + +0.1.0 / 2011-12-02 +================== + + * Added: remove colors unless stderr isatty [TooTallNate] + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/wrt/node_modules/debug/LICENSE b/wrt/node_modules/debug/LICENSE new file mode 100644 index 0000000..658c933 --- /dev/null +++ b/wrt/node_modules/debug/LICENSE @@ -0,0 +1,19 @@ +(The MIT License) + +Copyright (c) 2014 TJ Holowaychuk + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software +and associated documentation files (the 'Software'), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/wrt/node_modules/debug/Makefile b/wrt/node_modules/debug/Makefile new file mode 100644 index 0000000..3ddd136 --- /dev/null +++ b/wrt/node_modules/debug/Makefile @@ -0,0 +1,58 @@ +# get Makefile directory name: http://stackoverflow.com/a/5982798/376773 +THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)) +THIS_DIR:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd) + +# BIN directory +BIN := $(THIS_DIR)/node_modules/.bin + +# Path +PATH := node_modules/.bin:$(PATH) +SHELL := /bin/bash + +# applications +NODE ?= $(shell which node) +YARN ?= $(shell which yarn) +PKG ?= $(if $(YARN),$(YARN),$(NODE) $(shell which npm)) +BROWSERIFY ?= $(NODE) $(BIN)/browserify + +install: node_modules + +browser: dist/debug.js + +node_modules: package.json + @NODE_ENV= $(PKG) install + @touch node_modules + +dist/debug.js: src/*.js node_modules + @mkdir -p dist + @$(BROWSERIFY) \ + --standalone debug \ + . > dist/debug.js + +lint: + @eslint *.js src/*.js + +test-node: + @istanbul cover node_modules/mocha/bin/_mocha -- test/**.js + @cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js + +test-browser: + @$(MAKE) browser + @karma start --single-run + +test-all: + @concurrently \ + "make test-node" \ + "make test-browser" + +test: + @if [ "x$(BROWSER)" = "x" ]; then \ + $(MAKE) test-node; \ + else \ + $(MAKE) test-browser; \ + fi + +clean: + rimraf dist coverage + +.PHONY: browser install clean lint test test-all test-node test-browser diff --git a/wrt/node_modules/debug/README.md b/wrt/node_modules/debug/README.md new file mode 100644 index 0000000..1f3b08e --- /dev/null +++ b/wrt/node_modules/debug/README.md @@ -0,0 +1,367 @@ +# debug +[![Build Status](https://travis-ci.org/visionmedia/debug.svg?branch=master)](https://travis-ci.org/visionmedia/debug) [![Coverage Status](https://coveralls.io/repos/github/visionmedia/debug/badge.svg?branch=master)](https://coveralls.io/github/visionmedia/debug?branch=master) [![Slack](https://visionmedia-community-slackin.now.sh/badge.svg)](https://visionmedia-community-slackin.now.sh/) [![OpenCollective](https://opencollective.com/debug/backers/badge.svg)](#backers) +[![OpenCollective](https://opencollective.com/debug/sponsors/badge.svg)](#sponsors) + + + +A tiny JavaScript debugging utility modelled after Node.js core's debugging +technique. Works in Node.js and web browsers. + +## Installation + +```bash +$ npm install debug +``` + +## Usage + +`debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole. + +Example [_app.js_](./examples/node/app.js): + +```js +var debug = require('debug')('http') + , http = require('http') + , name = 'My App'; + +// fake app + +debug('booting %o', name); + +http.createServer(function(req, res){ + debug(req.method + ' ' + req.url); + res.end('hello\n'); +}).listen(3000, function(){ + debug('listening'); +}); + +// fake worker of some kind + +require('./worker'); +``` + +Example [_worker.js_](./examples/node/worker.js): + +```js +var a = require('debug')('worker:a') + , b = require('debug')('worker:b'); + +function work() { + a('doing lots of uninteresting work'); + setTimeout(work, Math.random() * 1000); +} + +work(); + +function workb() { + b('doing some work'); + setTimeout(workb, Math.random() * 2000); +} + +workb(); +``` + +The `DEBUG` environment variable is then used to enable these based on space or +comma-delimited names. + +Here are some examples: + +screen shot 2017-08-08 at 12 53 04 pm +screen shot 2017-08-08 at 12 53 38 pm +screen shot 2017-08-08 at 12 53 25 pm + +#### Windows note + +On Windows the environment variable is set using the `set` command. + +```cmd +set DEBUG=*,-not_this +``` + +Note that PowerShell uses different syntax to set environment variables. + +```cmd +$env:DEBUG = "*,-not_this" +``` + +Then, run the program to be debugged as usual. + + +## Namespace Colors + +Every debug instance has a color generated for it based on its namespace name. +This helps when visually parsing the debug output to identify which debug instance +a debug line belongs to. + +#### Node.js + +In Node.js, colors are enabled when stderr is a TTY. You also _should_ install +the [`supports-color`](https://npmjs.org/supports-color) module alongside debug, +otherwise debug will only use a small handful of basic colors. + + + +#### Web Browser + +Colors are also enabled on "Web Inspectors" that understand the `%c` formatting +option. These are WebKit web inspectors, Firefox ([since version +31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/)) +and the Firebug plugin for Firefox (any version). + + + + +## Millisecond diff + +When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls. + + + +When stdout is not a TTY, `Date#toISOString()` is used, making it more useful for logging the debug information as shown below: + + + + +## Conventions + +If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser". If you append a "*" to the end of your name, it will always be enabled regardless of the setting of the DEBUG environment variable. You can then use it for normal output as well as debug output. + +## Wildcards + +The `*` character may be used as a wildcard. Suppose for example your library has +debuggers named "connect:bodyParser", "connect:compress", "connect:session", +instead of listing all three with +`DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do +`DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`. + +You can also exclude specific debuggers by prefixing them with a "-" character. +For example, `DEBUG=*,-connect:*` would include all debuggers except those +starting with "connect:". + +## Environment Variables + +When running through Node.js, you can set a few environment variables that will +change the behavior of the debug logging: + +| Name | Purpose | +|-----------|-------------------------------------------------| +| `DEBUG` | Enables/disables specific debugging namespaces. | +| `DEBUG_COLORS`| Whether or not to use colors in the debug output. | +| `DEBUG_DEPTH` | Object inspection depth. | +| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. | + + +__Note:__ The environment variables beginning with `DEBUG_` end up being +converted into an Options object that gets used with `%o`/`%O` formatters. +See the Node.js documentation for +[`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options) +for the complete list. + +## Formatters + +Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting. +Below are the officially supported formatters: + +| Formatter | Representation | +|-----------|----------------| +| `%O` | Pretty-print an Object on multiple lines. | +| `%o` | Pretty-print an Object all on a single line. | +| `%s` | String. | +| `%d` | Number (both integer and float). | +| `%j` | JSON. Replaced with the string '[Circular]' if the argument contains circular references. | +| `%%` | Single percent sign ('%'). This does not consume an argument. | + + +### Custom formatters + +You can add custom formatters by extending the `debug.formatters` object. +For example, if you wanted to add support for rendering a Buffer as hex with +`%h`, you could do something like: + +```js +const createDebug = require('debug') +createDebug.formatters.h = (v) => { + return v.toString('hex') +} + +// …elsewhere +const debug = createDebug('foo') +debug('this is hex: %h', new Buffer('hello world')) +// foo this is hex: 68656c6c6f20776f726c6421 +0ms +``` + + +## Browser Support + +You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify), +or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest), +if you don't want to build it yourself. + +Debug's enable state is currently persisted by `localStorage`. +Consider the situation shown below where you have `worker:a` and `worker:b`, +and wish to debug both. You can enable this using `localStorage.debug`: + +```js +localStorage.debug = 'worker:*' +``` + +And then refresh the page. + +```js +a = debug('worker:a'); +b = debug('worker:b'); + +setInterval(function(){ + a('doing some work'); +}, 1000); + +setInterval(function(){ + b('doing some work'); +}, 1200); +``` + + +## Output streams + + By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method: + +Example [_stdout.js_](./examples/node/stdout.js): + +```js +var debug = require('debug'); +var error = debug('app:error'); + +// by default stderr is used +error('goes to stderr!'); + +var log = debug('app:log'); +// set this namespace to log via console.log +log.log = console.log.bind(console); // don't forget to bind to console! +log('goes to stdout'); +error('still goes to stderr!'); + +// set all output to go via console.info +// overrides all per-namespace log settings +debug.log = console.info.bind(console); +error('now goes to stdout via console.info'); +log('still goes to stdout, but via console.info now'); +``` + +## Checking whether a debug target is enabled + +After you've created a debug instance, you can determine whether or not it is +enabled by checking the `enabled` property: + +```javascript +const debug = require('debug')('http'); + +if (debug.enabled) { + // do stuff... +} +``` + +You can also manually toggle this property to force the debug instance to be +enabled or disabled. + + +## Authors + + - TJ Holowaychuk + - Nathan Rajlich + - Andrew Rhyne + +## Backers + +Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/debug#backer)] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## Sponsors + +Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/debug#sponsor)] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## License + +(The MIT License) + +Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/wrt/node_modules/debug/component.json b/wrt/node_modules/debug/component.json new file mode 100644 index 0000000..a2e9ad3 --- /dev/null +++ b/wrt/node_modules/debug/component.json @@ -0,0 +1,19 @@ +{ + "name": "debug", + "repo": "visionmedia/debug", + "description": "small debugging utility", + "version": "3.0.1", + "keywords": [ + "debug", + "log", + "debugger" + ], + "main": "src/browser.js", + "scripts": [ + "src/browser.js", + "src/debug.js" + ], + "dependencies": { + "rauchg/ms.js": "2.0.0" + } +} diff --git a/wrt/node_modules/debug/karma.conf.js b/wrt/node_modules/debug/karma.conf.js new file mode 100644 index 0000000..103a82d --- /dev/null +++ b/wrt/node_modules/debug/karma.conf.js @@ -0,0 +1,70 @@ +// Karma configuration +// Generated on Fri Dec 16 2016 13:09:51 GMT+0000 (UTC) + +module.exports = function(config) { + config.set({ + + // base path that will be used to resolve all patterns (eg. files, exclude) + basePath: '', + + + // frameworks to use + // available frameworks: https://npmjs.org/browse/keyword/karma-adapter + frameworks: ['mocha', 'chai', 'sinon'], + + + // list of files / patterns to load in the browser + files: [ + 'dist/debug.js', + 'test/*spec.js' + ], + + + // list of files to exclude + exclude: [ + 'src/node.js' + ], + + + // preprocess matching files before serving them to the browser + // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor + preprocessors: { + }, + + // test results reporter to use + // possible values: 'dots', 'progress' + // available reporters: https://npmjs.org/browse/keyword/karma-reporter + reporters: ['progress'], + + + // web server port + port: 9876, + + + // enable / disable colors in the output (reporters and logs) + colors: true, + + + // level of logging + // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG + logLevel: config.LOG_INFO, + + + // enable / disable watching file and executing tests whenever any file changes + autoWatch: true, + + + // start these browsers + // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher + browsers: ['PhantomJS'], + + + // Continuous Integration mode + // if true, Karma captures browsers, runs the tests and exits + singleRun: false, + + // Concurrency level + // how many browser should be started simultaneous + concurrency: Infinity + }) +} diff --git a/wrt/node_modules/debug/node.js b/wrt/node_modules/debug/node.js new file mode 100644 index 0000000..7fc36fe --- /dev/null +++ b/wrt/node_modules/debug/node.js @@ -0,0 +1 @@ +module.exports = require('./src/node'); diff --git a/wrt/node_modules/debug/package.json b/wrt/node_modules/debug/package.json new file mode 100644 index 0000000..3934ec0 --- /dev/null +++ b/wrt/node_modules/debug/package.json @@ -0,0 +1,136 @@ +{ + "_args": [ + [ + { + "raw": "debug@3.0.1", + "scope": null, + "escapedName": "debug", + "name": "debug", + "rawSpec": "3.0.1", + "spec": "3.0.1", + "type": "version" + }, + "/home/sources/5.0/crosswalk-tizen/wrt" + ] + ], + "_from": "debug@3.0.1", + "_id": "debug@3.0.1", + "_inCache": true, + "_location": "/debug", + "_nodeVersion": "8.4.0", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/debug-3.0.1.tgz_1503603871771_0.21796362148597836" + }, + "_npmUser": { + "name": "tootallnate", + "email": "nathan@tootallnate.net" + }, + "_npmVersion": "5.3.0", + "_phantomChildren": {}, + "_requested": { + "raw": "debug@3.0.1", + "scope": null, + "escapedName": "debug", + "name": "debug", + "rawSpec": "3.0.1", + "spec": "3.0.1", + "type": "version" + }, + "_requiredBy": [ + "#DEV:/" + ], + "_resolved": "https://registry.npmjs.org/debug/-/debug-3.0.1.tgz", + "_shasum": "0564c612b521dc92d9f2988f0549e34f9c98db64", + "_shrinkwrap": null, + "_spec": "debug@3.0.1", + "_where": "/home/sources/5.0/crosswalk-tizen/wrt", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "browser": "./src/browser.js", + "bugs": { + "url": "https://github.com/visionmedia/debug/issues" + }, + "component": { + "scripts": { + "debug/index.js": "browser.js", + "debug/debug.js": "debug.js" + } + }, + "contributors": [ + { + "name": "Nathan Rajlich", + "email": "nathan@tootallnate.net", + "url": "http://n8.io" + }, + { + "name": "Andrew Rhyne", + "email": "rhyneandrew@gmail.com" + } + ], + "dependencies": { + "ms": "2.0.0" + }, + "description": "small debugging utility", + "devDependencies": { + "browserify": "14.4.0", + "chai": "^3.5.0", + "concurrently": "^3.1.0", + "coveralls": "^2.11.15", + "eslint": "^3.12.1", + "istanbul": "^0.4.5", + "karma": "^1.3.0", + "karma-chai": "^0.1.0", + "karma-mocha": "^1.3.0", + "karma-phantomjs-launcher": "^1.0.2", + "karma-sinon": "^1.0.5", + "mocha": "^3.2.0", + "mocha-lcov-reporter": "^1.2.0", + "rimraf": "^2.5.4", + "sinon": "^1.17.6", + "sinon-chai": "^2.8.0" + }, + "directories": {}, + "dist": { + "integrity": "sha512-6nVc6S36qbt/mutyt+UGMnawAMrPDZUPQjRZI3FS9tCtDRhvxJbK79unYBLPi+z5SLXQ3ftoVBFCblQtNSls8w==", + "shasum": "0564c612b521dc92d9f2988f0549e34f9c98db64", + "tarball": "https://registry.npmjs.org/debug/-/debug-3.0.1.tgz" + }, + "gitHead": "3e1849d3aaa1b9a325ad6d054acf695fddb4efe9", + "homepage": "https://github.com/visionmedia/debug#readme", + "keywords": [ + "debug", + "log", + "debugger" + ], + "license": "MIT", + "main": "./src/index.js", + "maintainers": [ + { + "name": "thebigredgeek", + "email": "rhyneandrew@gmail.com" + }, + { + "name": "kolban", + "email": "kolban1@kolban.com" + }, + { + "name": "tootallnate", + "email": "nathan@tootallnate.net" + }, + { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + } + ], + "name": "debug", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/debug.git" + }, + "version": "3.0.1" +} diff --git a/wrt/node_modules/debug/src/browser.js b/wrt/node_modules/debug/src/browser.js new file mode 100644 index 0000000..f5149ff --- /dev/null +++ b/wrt/node_modules/debug/src/browser.js @@ -0,0 +1,195 @@ +/** + * This is the web browser implementation of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = require('./debug'); +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.storage = 'undefined' != typeof chrome + && 'undefined' != typeof chrome.storage + ? chrome.storage.local + : localstorage(); + +/** + * Colors. + */ + +exports.colors = [ + '#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', + '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', + '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', + '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', + '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', + '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', + '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', + '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', + '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', + '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', + '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33' +]; + +/** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + +function useColors() { + // NB: In an Electron preload script, document will be defined but not fully + // initialized. Since we know we're in Chrome, we'll just detect this case + // explicitly + if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') { + return true; + } + + // Internet Explorer and Edge do not support colors. + if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { + return false; + } + + // is webkit? http://stackoverflow.com/a/16459606/376773 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 + return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || + // is firebug? http://stackoverflow.com/a/398120/376773 + (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || + // is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || + // double check webkit in userAgent just in case we are in a worker + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); +} + +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + +exports.formatters.j = function(v) { + try { + return JSON.stringify(v); + } catch (err) { + return '[UnexpectedJSONParseError]: ' + err.message; + } +}; + + +/** + * Colorize log arguments if enabled. + * + * @api public + */ + +function formatArgs(args) { + var useColors = this.useColors; + + args[0] = (useColors ? '%c' : '') + + this.namespace + + (useColors ? ' %c' : ' ') + + args[0] + + (useColors ? '%c ' : ' ') + + '+' + exports.humanize(this.diff); + + if (!useColors) return; + + var c = 'color: ' + this.color; + args.splice(1, 0, c, 'color: inherit') + + // the final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + var index = 0; + var lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, function(match) { + if ('%%' === match) return; + index++; + if ('%c' === match) { + // we only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); +} + +/** + * Invokes `console.log()` when available. + * No-op when `console.log` is not a "function". + * + * @api public + */ + +function log() { + // this hackery is required for IE8/9, where + // the `console.log` function doesn't have 'apply' + return 'object' === typeof console + && console.log + && Function.prototype.apply.call(console.log, console, arguments); +} + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + +function save(namespaces) { + try { + if (null == namespaces) { + exports.storage.removeItem('debug'); + } else { + exports.storage.debug = namespaces; + } + } catch(e) {} +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + var r; + try { + r = exports.storage.debug; + } catch(e) {} + + // If debug isn't set in LS, and we're in Electron, try to load $DEBUG + if (!r && typeof process !== 'undefined' && 'env' in process) { + r = process.env.DEBUG; + } + + return r; +} + +/** + * Enable namespaces listed in `localStorage.debug` initially. + */ + +exports.enable(load()); + +/** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */ + +function localstorage() { + try { + return window.localStorage; + } catch (e) {} +} diff --git a/wrt/node_modules/debug/src/debug.js b/wrt/node_modules/debug/src/debug.js new file mode 100644 index 0000000..77e6384 --- /dev/null +++ b/wrt/node_modules/debug/src/debug.js @@ -0,0 +1,225 @@ + +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = createDebug.debug = createDebug['default'] = createDebug; +exports.coerce = coerce; +exports.disable = disable; +exports.enable = enable; +exports.enabled = enabled; +exports.humanize = require('ms'); + +/** + * Active `debug` instances. + */ +exports.instances = []; + +/** + * The currently active debug mode names, and names to skip. + */ + +exports.names = []; +exports.skips = []; + +/** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". + */ + +exports.formatters = {}; + +/** + * Select a color. + * @param {String} namespace + * @return {Number} + * @api private + */ + +function selectColor(namespace) { + var hash = 0, i; + + for (i in namespace) { + hash = ((hash << 5) - hash) + namespace.charCodeAt(i); + hash |= 0; // Convert to 32bit integer + } + + return exports.colors[Math.abs(hash) % exports.colors.length]; +} + +/** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + +function createDebug(namespace) { + + var prevTime; + + function debug() { + // disabled? + if (!debug.enabled) return; + + var self = debug; + + // set `diff` timestamp + var curr = +new Date(); + var ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + // turn the `arguments` into a proper Array + var args = new Array(arguments.length); + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i]; + } + + args[0] = exports.coerce(args[0]); + + if ('string' !== typeof args[0]) { + // anything else let's inspect with %O + args.unshift('%O'); + } + + // apply any `formatters` transformations + var index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) { + // if we encounter an escaped % then don't increase the array index + if (match === '%%') return match; + index++; + var formatter = exports.formatters[format]; + if ('function' === typeof formatter) { + var val = args[index]; + match = formatter.call(self, val); + + // now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + // apply env-specific formatting (colors, etc.) + exports.formatArgs.call(self, args); + + var logFn = debug.log || exports.log || console.log.bind(console); + logFn.apply(self, args); + } + + debug.namespace = namespace; + debug.enabled = exports.enabled(namespace); + debug.useColors = exports.useColors(); + debug.color = selectColor(namespace); + debug.destroy = destroy; + + // env-specific initialization logic for debug instances + if ('function' === typeof exports.init) { + exports.init(debug); + } + + exports.instances.push(debug); + + return debug; +} + +function destroy () { + var index = exports.instances.indexOf(this); + if (index !== -1) { + exports.instances.splice(index, 1); + return true; + } else { + return false; + } +} + +/** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + +function enable(namespaces) { + exports.save(namespaces); + + exports.names = []; + exports.skips = []; + + var i; + var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); + var len = split.length; + + for (i = 0; i < len; i++) { + if (!split[i]) continue; // ignore empty strings + namespaces = split[i].replace(/\*/g, '.*?'); + if (namespaces[0] === '-') { + exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + exports.names.push(new RegExp('^' + namespaces + '$')); + } + } + + for (i = 0; i < exports.instances.length; i++) { + var instance = exports.instances[i]; + instance.enabled = exports.enabled(instance.namespace); + } +} + +/** + * Disable debug output. + * + * @api public + */ + +function disable() { + exports.enable(''); +} + +/** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + +function enabled(name) { + if (name[name.length - 1] === '*') { + return true; + } + var i, len; + for (i = 0, len = exports.skips.length; i < len; i++) { + if (exports.skips[i].test(name)) { + return false; + } + } + for (i = 0, len = exports.names.length; i < len; i++) { + if (exports.names[i].test(name)) { + return true; + } + } + return false; +} + +/** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + +function coerce(val) { + if (val instanceof Error) return val.stack || val.message; + return val; +} diff --git a/wrt/node_modules/debug/src/index.js b/wrt/node_modules/debug/src/index.js new file mode 100644 index 0000000..e12cf4d --- /dev/null +++ b/wrt/node_modules/debug/src/index.js @@ -0,0 +1,10 @@ +/** + * Detect Electron renderer process, which is node, but we should + * treat as a browser. + */ + +if (typeof process !== 'undefined' && process.type === 'renderer') { + module.exports = require('./browser.js'); +} else { + module.exports = require('./node.js'); +} diff --git a/wrt/node_modules/debug/src/node.js b/wrt/node_modules/debug/src/node.js new file mode 100644 index 0000000..b85ec7e --- /dev/null +++ b/wrt/node_modules/debug/src/node.js @@ -0,0 +1,177 @@ +/** + * Module dependencies. + */ + +var tty = require('tty'); +var util = require('util'); + +/** + * This is the Node.js implementation of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = require('./debug'); +exports.init = init; +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; + +/** + * Colors. + */ + +exports.colors = [ 6, 2, 3, 4, 5, 1 ]; + +try { + var supportsColor = require('supports-color'); + if (supportsColor && supportsColor.level >= 2) { + exports.colors = [ + 20, 21, 26, 27, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 56, 57, 62, 63, 68, + 69, 74, 75, 76, 77, 78, 79, 80, 81, 92, 93, 98, 99, 112, 113, 128, 129, 134, + 135, 148, 149, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, + 172, 173, 178, 179, 184, 185, 196, 197, 198, 199, 200, 201, 202, 203, 204, + 205, 206, 207, 208, 209, 214, 215, 220, 221 + ]; + } +} catch (err) { + // swallow - we only care if `supports-color` is available; it doesn't have to be. +} + +/** + * Build up the default `inspectOpts` object from the environment variables. + * + * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js + */ + +exports.inspectOpts = Object.keys(process.env).filter(function (key) { + return /^debug_/i.test(key); +}).reduce(function (obj, key) { + // camel-case + var prop = key + .substring(6) + .toLowerCase() + .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() }); + + // coerce string value into JS value + var val = process.env[key]; + if (/^(yes|on|true|enabled)$/i.test(val)) val = true; + else if (/^(no|off|false|disabled)$/i.test(val)) val = false; + else if (val === 'null') val = null; + else val = Number(val); + + obj[prop] = val; + return obj; +}, {}); + +/** + * Is stdout a TTY? Colored output is enabled when `true`. + */ + +function useColors() { + return 'colors' in exports.inspectOpts + ? Boolean(exports.inspectOpts.colors) + : tty.isatty(process.stderr.fd); +} + +/** + * Map %o to `util.inspect()`, all on a single line. + */ + +exports.formatters.o = function(v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts) + .replace(/\s*\n\s*/g, ' '); +}; + +/** + * Map %o to `util.inspect()`, allowing multiple lines if needed. + */ + +exports.formatters.O = function(v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts); +}; + +/** + * Adds ANSI color escape codes if enabled. + * + * @api public + */ + +function formatArgs(args) { + var name = this.namespace; + var useColors = this.useColors; + + if (useColors) { + var c = this.color; + var colorCode = '\u001b[3' + (c < 8 ? c : '8;5;' + c); + var prefix = ' ' + colorCode + ';1m' + name + ' ' + '\u001b[0m'; + + args[0] = prefix + args[0].split('\n').join('\n' + prefix); + args.push(colorCode + 'm+' + exports.humanize(this.diff) + '\u001b[0m'); + } else { + args[0] = new Date().toISOString() + + ' ' + name + ' ' + args[0]; + } +} + +/** + * Invokes `util.format()` with the specified arguments and writes to stderr. + */ + +function log() { + return process.stderr.write(util.format.apply(util, arguments) + '\n'); +} + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + +function save(namespaces) { + if (null == namespaces) { + // If you set a process.env field to null or undefined, it gets cast to the + // string 'null' or 'undefined'. Just delete instead. + delete process.env.DEBUG; + } else { + process.env.DEBUG = namespaces; + } +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + return process.env.DEBUG; +} + +/** + * Init logic for `debug` instances. + * + * Create a new `inspectOpts` object in case `useColors` is set + * differently for a particular `debug` instance. + */ + +function init (debug) { + debug.inspectOpts = {}; + + var keys = Object.keys(exports.inspectOpts); + for (var i = 0; i < keys.length; i++) { + debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; + } +} + +/** + * Enable namespaces listed in `process.env.DEBUG` initially. + */ + +exports.enable(load()); diff --git a/wrt/node_modules/decamelize/index.js b/wrt/node_modules/decamelize/index.js new file mode 100644 index 0000000..8d5bab7 --- /dev/null +++ b/wrt/node_modules/decamelize/index.js @@ -0,0 +1,13 @@ +'use strict'; +module.exports = function (str, sep) { + if (typeof str !== 'string') { + throw new TypeError('Expected a string'); + } + + sep = typeof sep === 'undefined' ? '_' : sep; + + return str + .replace(/([a-z\d])([A-Z])/g, '$1' + sep + '$2') + .replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + sep + '$2') + .toLowerCase(); +}; diff --git a/wrt/node_modules/decamelize/license b/wrt/node_modules/decamelize/license new file mode 100644 index 0000000..654d0bf --- /dev/null +++ b/wrt/node_modules/decamelize/license @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/wrt/node_modules/decamelize/package.json b/wrt/node_modules/decamelize/package.json new file mode 100644 index 0000000..4a275cb --- /dev/null +++ b/wrt/node_modules/decamelize/package.json @@ -0,0 +1,106 @@ +{ + "_args": [ + [ + { + "raw": "decamelize@^1.0.0", + "scope": null, + "escapedName": "decamelize", + "name": "decamelize", + "rawSpec": "^1.0.0", + "spec": ">=1.0.0 <2.0.0", + "type": "range" + }, + "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/yargs" + ] + ], + "_from": "decamelize@>=1.0.0 <2.0.0", + "_id": "decamelize@1.2.0", + "_inCache": true, + "_location": "/decamelize", + "_nodeVersion": "4.3.0", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/decamelize-1.2.0.tgz_1457167749082_0.9810893186368048" + }, + "_npmUser": { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + }, + "_npmVersion": "3.8.0", + "_phantomChildren": {}, + "_requested": { + "raw": "decamelize@^1.0.0", + "scope": null, + "escapedName": "decamelize", + "name": "decamelize", + "rawSpec": "^1.0.0", + "spec": ">=1.0.0 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/yargs" + ], + "_resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "_shasum": "f6534d15148269b20352e7bee26f501f9a191290", + "_shrinkwrap": null, + "_spec": "decamelize@^1.0.0", + "_where": "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/yargs", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "bugs": { + "url": "https://github.com/sindresorhus/decamelize/issues" + }, + "dependencies": {}, + "description": "Convert a camelized string into a lowercased one with a custom separator: unicornRainbow → unicorn_rainbow", + "devDependencies": { + "ava": "*", + "xo": "*" + }, + "directories": {}, + "dist": { + "shasum": "f6534d15148269b20352e7bee26f501f9a191290", + "tarball": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "gitHead": "95980ab6fb44c40eaca7792bdf93aff7c210c805", + "homepage": "https://github.com/sindresorhus/decamelize#readme", + "keywords": [ + "decamelize", + "decamelcase", + "camelcase", + "lowercase", + "case", + "dash", + "hyphen", + "string", + "str", + "text", + "convert" + ], + "license": "MIT", + "maintainers": [ + { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + } + ], + "name": "decamelize", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/sindresorhus/decamelize.git" + }, + "scripts": { + "test": "xo && ava" + }, + "version": "1.2.0" +} diff --git a/wrt/node_modules/decamelize/readme.md b/wrt/node_modules/decamelize/readme.md new file mode 100644 index 0000000..624c7ee --- /dev/null +++ b/wrt/node_modules/decamelize/readme.md @@ -0,0 +1,48 @@ +# decamelize [![Build Status](https://travis-ci.org/sindresorhus/decamelize.svg?branch=master)](https://travis-ci.org/sindresorhus/decamelize) + +> Convert a camelized string into a lowercased one with a custom separator
+> Example: `unicornRainbow` → `unicorn_rainbow` + + +## Install + +``` +$ npm install --save decamelize +``` + + +## Usage + +```js +const decamelize = require('decamelize'); + +decamelize('unicornRainbow'); +//=> 'unicorn_rainbow' + +decamelize('unicornRainbow', '-'); +//=> 'unicorn-rainbow' +``` + + +## API + +### decamelize(input, [separator]) + +#### input + +Type: `string` + +#### separator + +Type: `string`
+Default: `_` + + +## Related + +See [`camelcase`](https://github.com/sindresorhus/camelcase) for the inverse. + + +## License + +MIT © [Sindre Sorhus](https://sindresorhus.com) diff --git a/wrt/node_modules/is-buffer/LICENSE b/wrt/node_modules/is-buffer/LICENSE new file mode 100644 index 0000000..0c068ce --- /dev/null +++ b/wrt/node_modules/is-buffer/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Feross Aboukhadijeh + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/wrt/node_modules/is-buffer/README.md b/wrt/node_modules/is-buffer/README.md new file mode 100644 index 0000000..cce0a8c --- /dev/null +++ b/wrt/node_modules/is-buffer/README.md @@ -0,0 +1,53 @@ +# is-buffer [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url] + +[travis-image]: https://img.shields.io/travis/feross/is-buffer/master.svg +[travis-url]: https://travis-ci.org/feross/is-buffer +[npm-image]: https://img.shields.io/npm/v/is-buffer.svg +[npm-url]: https://npmjs.org/package/is-buffer +[downloads-image]: https://img.shields.io/npm/dm/is-buffer.svg +[downloads-url]: https://npmjs.org/package/is-buffer +[standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg +[standard-url]: https://standardjs.com + +#### Determine if an object is a [`Buffer`](http://nodejs.org/api/buffer.html) (including the [browserify Buffer](https://github.com/feross/buffer)) + +[![saucelabs][saucelabs-image]][saucelabs-url] + +[saucelabs-image]: https://saucelabs.com/browser-matrix/is-buffer.svg +[saucelabs-url]: https://saucelabs.com/u/is-buffer + +## Why not use `Buffer.isBuffer`? + +This module lets you check if an object is a `Buffer` without using `Buffer.isBuffer` (which includes the whole [buffer](https://github.com/feross/buffer) module in [browserify](http://browserify.org/)). + +It's future-proof and works in node too! + +## install + +```bash +npm install is-buffer +``` + +## usage + +```js +var isBuffer = require('is-buffer') + +isBuffer(new Buffer(4)) // true + +isBuffer(undefined) // false +isBuffer(null) // false +isBuffer('') // false +isBuffer(true) // false +isBuffer(false) // false +isBuffer(0) // false +isBuffer(1) // false +isBuffer(1.0) // false +isBuffer('string') // false +isBuffer({}) // false +isBuffer(function foo () {}) // false +``` + +## license + +MIT. Copyright (C) [Feross Aboukhadijeh](http://feross.org). diff --git a/wrt/node_modules/is-buffer/index.js b/wrt/node_modules/is-buffer/index.js new file mode 100644 index 0000000..9cce396 --- /dev/null +++ b/wrt/node_modules/is-buffer/index.js @@ -0,0 +1,21 @@ +/*! + * Determine if an object is a Buffer + * + * @author Feross Aboukhadijeh + * @license MIT + */ + +// The _isBuffer check is for Safari 5-7 support, because it's missing +// Object.prototype.constructor. Remove this eventually +module.exports = function (obj) { + return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer) +} + +function isBuffer (obj) { + return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) +} + +// For Node v0.10 support. Remove this eventually. +function isSlowBuffer (obj) { + return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) +} diff --git a/wrt/node_modules/is-buffer/package.json b/wrt/node_modules/is-buffer/package.json new file mode 100644 index 0000000..2099fc9 --- /dev/null +++ b/wrt/node_modules/is-buffer/package.json @@ -0,0 +1,113 @@ +{ + "_args": [ + [ + { + "raw": "is-buffer@^1.1.5", + "scope": null, + "escapedName": "is-buffer", + "name": "is-buffer", + "rawSpec": "^1.1.5", + "spec": ">=1.1.5 <2.0.0", + "type": "range" + }, + "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/kind-of" + ] + ], + "_from": "is-buffer@>=1.1.5 <2.0.0", + "_id": "is-buffer@1.1.6", + "_inCache": true, + "_location": "/is-buffer", + "_nodeVersion": "8.6.0", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/is-buffer-1.1.6.tgz_1508967388794_0.03916449216194451" + }, + "_npmUser": { + "name": "feross", + "email": "feross@feross.org" + }, + "_npmVersion": "5.5.1", + "_phantomChildren": {}, + "_requested": { + "raw": "is-buffer@^1.1.5", + "scope": null, + "escapedName": "is-buffer", + "name": "is-buffer", + "rawSpec": "^1.1.5", + "spec": ">=1.1.5 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/kind-of" + ], + "_resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "_shasum": "efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be", + "_shrinkwrap": null, + "_spec": "is-buffer@^1.1.5", + "_where": "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/kind-of", + "author": { + "name": "Feross Aboukhadijeh", + "email": "feross@feross.org", + "url": "http://feross.org/" + }, + "bugs": { + "url": "https://github.com/feross/is-buffer/issues" + }, + "dependencies": {}, + "description": "Determine if an object is a Buffer", + "devDependencies": { + "standard": "*", + "tape": "^4.0.0", + "zuul": "^3.0.0" + }, + "directories": {}, + "dist": { + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "shasum": "efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be", + "tarball": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" + }, + "gitHead": "1e84e7ee31cf6b660b12500f3111a05501da387f", + "homepage": "https://github.com/feross/is-buffer#readme", + "keywords": [ + "buffer", + "buffers", + "type", + "core buffer", + "browser buffer", + "browserify", + "typed array", + "uint32array", + "int16array", + "int32array", + "float32array", + "float64array", + "browser", + "arraybuffer", + "dataview" + ], + "license": "MIT", + "main": "index.js", + "maintainers": [ + { + "name": "feross", + "email": "feross@feross.org" + } + ], + "name": "is-buffer", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/feross/is-buffer.git" + }, + "scripts": { + "test": "standard && npm run test-node && npm run test-browser", + "test-browser": "zuul -- test/*.js", + "test-browser-local": "zuul --local -- test/*.js", + "test-node": "tape test/*.js" + }, + "testling": { + "files": "test/*.js" + }, + "version": "1.1.6" +} diff --git a/wrt/node_modules/is-buffer/test/basic.js b/wrt/node_modules/is-buffer/test/basic.js new file mode 100644 index 0000000..be4f8e4 --- /dev/null +++ b/wrt/node_modules/is-buffer/test/basic.js @@ -0,0 +1,24 @@ +var isBuffer = require('../') +var test = require('tape') + +test('is-buffer', function (t) { + t.equal(isBuffer(Buffer.alloc(4)), true, 'new Buffer(4)') + t.equal(isBuffer(Buffer.allocUnsafeSlow(100)), true, 'SlowBuffer(100)') + + t.equal(isBuffer(undefined), false, 'undefined') + t.equal(isBuffer(null), false, 'null') + t.equal(isBuffer(''), false, 'empty string') + t.equal(isBuffer(true), false, 'true') + t.equal(isBuffer(false), false, 'false') + t.equal(isBuffer(0), false, '0') + t.equal(isBuffer(1), false, '1') + t.equal(isBuffer(1.0), false, '1.0') + t.equal(isBuffer('string'), false, 'string') + t.equal(isBuffer({}), false, '{}') + t.equal(isBuffer([]), false, '[]') + t.equal(isBuffer(function foo () {}), false, 'function foo () {}') + t.equal(isBuffer({ isBuffer: null }), false, '{ isBuffer: null }') + t.equal(isBuffer({ isBuffer: function () { throw new Error() } }), false, '{ isBuffer: function () { throw new Error() } }') + + t.end() +}) diff --git a/wrt/node_modules/kind-of/LICENSE b/wrt/node_modules/kind-of/LICENSE new file mode 100644 index 0000000..d734237 --- /dev/null +++ b/wrt/node_modules/kind-of/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2017, Jon Schlinkert + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/wrt/node_modules/kind-of/README.md b/wrt/node_modules/kind-of/README.md new file mode 100644 index 0000000..6a9df36 --- /dev/null +++ b/wrt/node_modules/kind-of/README.md @@ -0,0 +1,261 @@ +# kind-of [![NPM version](https://img.shields.io/npm/v/kind-of.svg?style=flat)](https://www.npmjs.com/package/kind-of) [![NPM monthly downloads](https://img.shields.io/npm/dm/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![NPM total downloads](https://img.shields.io/npm/dt/kind-of.svg?style=flat)](https://npmjs.org/package/kind-of) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/kind-of.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/kind-of) + +> Get the native type of a value. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install --save kind-of +``` + +## Install + +Install with [bower](https://bower.io/) + +```sh +$ bower install kind-of --save +``` + +## Usage + +> es5, browser and es6 ready + +```js +var kindOf = require('kind-of'); + +kindOf(undefined); +//=> 'undefined' + +kindOf(null); +//=> 'null' + +kindOf(true); +//=> 'boolean' + +kindOf(false); +//=> 'boolean' + +kindOf(new Boolean(true)); +//=> 'boolean' + +kindOf(new Buffer('')); +//=> 'buffer' + +kindOf(42); +//=> 'number' + +kindOf(new Number(42)); +//=> 'number' + +kindOf('str'); +//=> 'string' + +kindOf(new String('str')); +//=> 'string' + +kindOf(arguments); +//=> 'arguments' + +kindOf({}); +//=> 'object' + +kindOf(Object.create(null)); +//=> 'object' + +kindOf(new Test()); +//=> 'object' + +kindOf(new Date()); +//=> 'date' + +kindOf([]); +//=> 'array' + +kindOf([1, 2, 3]); +//=> 'array' + +kindOf(new Array()); +//=> 'array' + +kindOf(/foo/); +//=> 'regexp' + +kindOf(new RegExp('foo')); +//=> 'regexp' + +kindOf(function () {}); +//=> 'function' + +kindOf(function * () {}); +//=> 'function' + +kindOf(new Function()); +//=> 'function' + +kindOf(new Map()); +//=> 'map' + +kindOf(new WeakMap()); +//=> 'weakmap' + +kindOf(new Set()); +//=> 'set' + +kindOf(new WeakSet()); +//=> 'weakset' + +kindOf(Symbol('str')); +//=> 'symbol' + +kindOf(new Int8Array()); +//=> 'int8array' + +kindOf(new Uint8Array()); +//=> 'uint8array' + +kindOf(new Uint8ClampedArray()); +//=> 'uint8clampedarray' + +kindOf(new Int16Array()); +//=> 'int16array' + +kindOf(new Uint16Array()); +//=> 'uint16array' + +kindOf(new Int32Array()); +//=> 'int32array' + +kindOf(new Uint32Array()); +//=> 'uint32array' + +kindOf(new Float32Array()); +//=> 'float32array' + +kindOf(new Float64Array()); +//=> 'float64array' +``` + +## Benchmarks + +Benchmarked against [typeof](http://github.com/CodingFu/typeof) and [type-of](https://github.com/ForbesLindesay/type-of). +Note that performaces is slower for es6 features `Map`, `WeakMap`, `Set` and `WeakSet`. + +```bash +#1: array + current x 23,329,397 ops/sec ±0.82% (94 runs sampled) + lib-type-of x 4,170,273 ops/sec ±0.55% (94 runs sampled) + lib-typeof x 9,686,935 ops/sec ±0.59% (98 runs sampled) + +#2: boolean + current x 27,197,115 ops/sec ±0.85% (94 runs sampled) + lib-type-of x 3,145,791 ops/sec ±0.73% (97 runs sampled) + lib-typeof x 9,199,562 ops/sec ±0.44% (99 runs sampled) + +#3: date + current x 20,190,117 ops/sec ±0.86% (92 runs sampled) + lib-type-of x 5,166,970 ops/sec ±0.74% (94 runs sampled) + lib-typeof x 9,610,821 ops/sec ±0.50% (96 runs sampled) + +#4: function + current x 23,855,460 ops/sec ±0.60% (97 runs sampled) + lib-type-of x 5,667,740 ops/sec ±0.54% (100 runs sampled) + lib-typeof x 10,010,644 ops/sec ±0.44% (100 runs sampled) + +#5: null + current x 27,061,047 ops/sec ±0.97% (96 runs sampled) + lib-type-of x 13,965,573 ops/sec ±0.62% (97 runs sampled) + lib-typeof x 8,460,194 ops/sec ±0.61% (97 runs sampled) + +#6: number + current x 25,075,682 ops/sec ±0.53% (99 runs sampled) + lib-type-of x 2,266,405 ops/sec ±0.41% (98 runs sampled) + lib-typeof x 9,821,481 ops/sec ±0.45% (99 runs sampled) + +#7: object + current x 3,348,980 ops/sec ±0.49% (99 runs sampled) + lib-type-of x 3,245,138 ops/sec ±0.60% (94 runs sampled) + lib-typeof x 9,262,952 ops/sec ±0.59% (99 runs sampled) + +#8: regex + current x 21,284,827 ops/sec ±0.72% (96 runs sampled) + lib-type-of x 4,689,241 ops/sec ±0.43% (100 runs sampled) + lib-typeof x 8,957,593 ops/sec ±0.62% (98 runs sampled) + +#9: string + current x 25,379,234 ops/sec ±0.58% (96 runs sampled) + lib-type-of x 3,635,148 ops/sec ±0.76% (93 runs sampled) + lib-typeof x 9,494,134 ops/sec ±0.49% (98 runs sampled) + +#10: undef + current x 27,459,221 ops/sec ±1.01% (93 runs sampled) + lib-type-of x 14,360,433 ops/sec ±0.52% (99 runs sampled) + lib-typeof x 23,202,868 ops/sec ±0.59% (94 runs sampled) + +``` + +## Optimizations + +In 7 out of 8 cases, this library is 2x-10x faster than other top libraries included in the benchmarks. There are a few things that lead to this performance advantage, none of them hard and fast rules, but all of them simple and repeatable in almost any code library: + +1. Optimize around the fastest and most common use cases first. Of course, this will change from project-to-project, but I took some time to understand how and why `typeof` checks were being used in my own libraries and other libraries I use a lot. +2. Optimize around bottlenecks - In other words, the order in which conditionals are implemented is significant, because each check is only as fast as the failing checks that came before it. Here, the biggest bottleneck by far is checking for plain objects (an object that was created by the `Object` constructor). I opted to make this check happen by process of elimination rather than brute force up front (e.g. by using something like `val.constructor.name`), so that every other type check would not be penalized it. +3. Don't do uneccessary processing - why do `.slice(8, -1).toLowerCase();` just to get the word `regex`? It's much faster to do `if (type === '[object RegExp]') return 'regex'` + +## About + +### Related projects + +* [is-glob](https://www.npmjs.com/package/is-glob): Returns `true` if the given string looks like a glob pattern or an extglob pattern… [more](https://github.com/jonschlinkert/is-glob) | [homepage](https://github.com/jonschlinkert/is-glob "Returns `true` if the given string looks like a glob pattern or an extglob pattern. This makes it easy to create code that only uses external modules like node-glob when necessary, resulting in much faster code execution and initialization time, and a bet") +* [is-number](https://www.npmjs.com/package/is-number): Returns true if the value is a number. comprehensive tests. | [homepage](https://github.com/jonschlinkert/is-number "Returns true if the value is a number. comprehensive tests.") +* [is-primitive](https://www.npmjs.com/package/is-primitive): Returns `true` if the value is a primitive. | [homepage](https://github.com/jonschlinkert/is-primitive "Returns `true` if the value is a primitive. ") + +### Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). + +### Contributors + +| **Commits** | **Contributor** | +| --- | --- | +| 59 | [jonschlinkert](https://github.com/jonschlinkert) | +| 2 | [miguelmota](https://github.com/miguelmota) | +| 1 | [dtothefp](https://github.com/dtothefp) | +| 1 | [ksheedlo](https://github.com/ksheedlo) | +| 1 | [pdehaan](https://github.com/pdehaan) | +| 1 | [laggingreflex](https://github.com/laggingreflex) | + +### Building docs + +_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ + +To generate the readme, run the following command: + +```sh +$ npm install -g verbose/verb#dev verb-generate-readme && verb +``` + +### Running tests + +Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: + +```sh +$ npm install && npm test +``` + +### Author + +**Jon Schlinkert** + +* [github/jonschlinkert](https://github.com/jonschlinkert) +* [twitter/jonschlinkert](https://twitter.com/jonschlinkert) + +### License + +Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT License](LICENSE). + +*** + +_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on May 16, 2017._ \ No newline at end of file diff --git a/wrt/node_modules/kind-of/index.js b/wrt/node_modules/kind-of/index.js new file mode 100644 index 0000000..b52c291 --- /dev/null +++ b/wrt/node_modules/kind-of/index.js @@ -0,0 +1,116 @@ +var isBuffer = require('is-buffer'); +var toString = Object.prototype.toString; + +/** + * Get the native `typeof` a value. + * + * @param {*} `val` + * @return {*} Native javascript type + */ + +module.exports = function kindOf(val) { + // primitivies + if (typeof val === 'undefined') { + return 'undefined'; + } + if (val === null) { + return 'null'; + } + if (val === true || val === false || val instanceof Boolean) { + return 'boolean'; + } + if (typeof val === 'string' || val instanceof String) { + return 'string'; + } + if (typeof val === 'number' || val instanceof Number) { + return 'number'; + } + + // functions + if (typeof val === 'function' || val instanceof Function) { + return 'function'; + } + + // array + if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { + return 'array'; + } + + // check for instances of RegExp and Date before calling `toString` + if (val instanceof RegExp) { + return 'regexp'; + } + if (val instanceof Date) { + return 'date'; + } + + // other objects + var type = toString.call(val); + + if (type === '[object RegExp]') { + return 'regexp'; + } + if (type === '[object Date]') { + return 'date'; + } + if (type === '[object Arguments]') { + return 'arguments'; + } + if (type === '[object Error]') { + return 'error'; + } + + // buffer + if (isBuffer(val)) { + return 'buffer'; + } + + // es6: Map, WeakMap, Set, WeakSet + if (type === '[object Set]') { + return 'set'; + } + if (type === '[object WeakSet]') { + return 'weakset'; + } + if (type === '[object Map]') { + return 'map'; + } + if (type === '[object WeakMap]') { + return 'weakmap'; + } + if (type === '[object Symbol]') { + return 'symbol'; + } + + // typed arrays + if (type === '[object Int8Array]') { + return 'int8array'; + } + if (type === '[object Uint8Array]') { + return 'uint8array'; + } + if (type === '[object Uint8ClampedArray]') { + return 'uint8clampedarray'; + } + if (type === '[object Int16Array]') { + return 'int16array'; + } + if (type === '[object Uint16Array]') { + return 'uint16array'; + } + if (type === '[object Int32Array]') { + return 'int32array'; + } + if (type === '[object Uint32Array]') { + return 'uint32array'; + } + if (type === '[object Float32Array]') { + return 'float32array'; + } + if (type === '[object Float64Array]') { + return 'float64array'; + } + + // must be a plain object + return 'object'; +}; diff --git a/wrt/node_modules/kind-of/package.json b/wrt/node_modules/kind-of/package.json new file mode 100644 index 0000000..8a44dc8 --- /dev/null +++ b/wrt/node_modules/kind-of/package.json @@ -0,0 +1,178 @@ +{ + "_args": [ + [ + { + "raw": "kind-of@^3.0.2", + "scope": null, + "escapedName": "kind-of", + "name": "kind-of", + "rawSpec": "^3.0.2", + "spec": ">=3.0.2 <4.0.0", + "type": "range" + }, + "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/align-text" + ] + ], + "_from": "kind-of@>=3.0.2 <4.0.0", + "_id": "kind-of@3.2.2", + "_inCache": true, + "_location": "/kind-of", + "_nodeVersion": "7.7.3", + "_npmOperationalInternal": { + "host": "packages-18-east.internal.npmjs.com", + "tmp": "tmp/kind-of-3.2.2.tgz_1494958899918_0.23780996026471257" + }, + "_npmUser": { + "name": "jonschlinkert", + "email": "github@sellside.com" + }, + "_npmVersion": "4.5.0", + "_phantomChildren": {}, + "_requested": { + "raw": "kind-of@^3.0.2", + "scope": null, + "escapedName": "kind-of", + "name": "kind-of", + "rawSpec": "^3.0.2", + "spec": ">=3.0.2 <4.0.0", + "type": "range" + }, + "_requiredBy": [ + "/align-text" + ], + "_resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "_shasum": "31ea21a734bab9bbb0f32466d893aea51e4a3c64", + "_shrinkwrap": null, + "_spec": "kind-of@^3.0.2", + "_where": "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/align-text", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/kind-of/issues" + }, + "contributors": [ + { + "name": "David Fox-Powell", + "url": "https://dtothefp.github.io/me" + }, + { + "name": "Jon Schlinkert", + "url": "http://twitter.com/jonschlinkert" + }, + { + "name": "Ken Sheedlo", + "url": "kensheedlo.com" + }, + { + "name": "laggingreflex", + "url": "https://github.com/laggingreflex" + }, + { + "name": "Miguel Mota", + "url": "https://miguelmota.com" + }, + { + "name": "Peter deHaan", + "url": "http://about.me/peterdehaan" + } + ], + "dependencies": { + "is-buffer": "^1.1.5" + }, + "description": "Get the native type of a value.", + "devDependencies": { + "ansi-bold": "^0.1.1", + "benchmarked": "^1.0.0", + "browserify": "^14.3.0", + "glob": "^7.1.1", + "gulp-format-md": "^0.1.12", + "mocha": "^3.3.0", + "type-of": "^2.0.1", + "typeof": "^1.0.0" + }, + "directories": {}, + "dist": { + "shasum": "31ea21a734bab9bbb0f32466d893aea51e4a3c64", + "tarball": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "gitHead": "0ffe67cf12f5396047c1bacf04232b7deeb24063", + "homepage": "https://github.com/jonschlinkert/kind-of", + "keywords": [ + "arguments", + "array", + "boolean", + "check", + "date", + "function", + "is", + "is-type", + "is-type-of", + "kind", + "kind-of", + "number", + "object", + "of", + "regexp", + "string", + "test", + "type", + "type-of", + "typeof", + "types" + ], + "license": "MIT", + "main": "index.js", + "maintainers": [ + { + "name": "jonschlinkert", + "email": "github@sellside.com" + }, + { + "name": "doowb", + "email": "brian.woodward@gmail.com" + } + ], + "name": "kind-of", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/kind-of.git" + }, + "scripts": { + "prepublish": "browserify -o browser.js -e index.js -s index --bare", + "test": "mocha" + }, + "verb": { + "related": { + "list": [ + "is-glob", + "is-number", + "is-primitive" + ] + }, + "toc": false, + "layout": "default", + "tasks": [ + "readme" + ], + "plugins": [ + "gulp-format-md" + ], + "lint": { + "reflinks": true + }, + "reflinks": [ + "verb" + ] + }, + "version": "3.2.2" +} diff --git a/wrt/node_modules/lazy-cache/LICENSE b/wrt/node_modules/lazy-cache/LICENSE new file mode 100644 index 0000000..1e49edf --- /dev/null +++ b/wrt/node_modules/lazy-cache/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015-2016, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/wrt/node_modules/lazy-cache/README.md b/wrt/node_modules/lazy-cache/README.md new file mode 100644 index 0000000..33b5a4d --- /dev/null +++ b/wrt/node_modules/lazy-cache/README.md @@ -0,0 +1,147 @@ +# lazy-cache [![NPM version](https://img.shields.io/npm/v/lazy-cache.svg?style=flat)](https://www.npmjs.com/package/lazy-cache) [![NPM downloads](https://img.shields.io/npm/dm/lazy-cache.svg?style=flat)](https://npmjs.org/package/lazy-cache) [![Build Status](https://img.shields.io/travis/jonschlinkert/lazy-cache.svg?style=flat)](https://travis-ci.org/jonschlinkert/lazy-cache) + +> Cache requires to be lazy-loaded when needed. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install lazy-cache --save +``` + +If you use webpack and are experiencing issues, try using [unlazy-loader](https://github.com/doowb/unlazy-loader), a webpack loader that fixes the bug that prevents webpack from working with native javascript getters. + +## Usage + +```js +var utils = require('lazy-cache')(require); +``` + +**Use as a property on `lazy`** + +The module is also added as a property to the `lazy` function +so it can be called without having to call a function first. + +```js +var utils = require('lazy-cache')(require); + +// `npm install glob` +utils('glob'); + +// glob sync +console.log(utils.glob.sync('*.js')); + +// glob async +utils.glob('*.js', function (err, files) { + console.log(files); +}); +``` + +**Use as a function** + +```js +var utils = require('lazy-cache')(require); +var glob = utils('glob'); + +// `glob` is a now a function that may be called when needed +glob().sync('foo/*.js'); +``` + +## Aliases + +An alias may be passed as the second argument if you don't want to use the automatically camel-cased variable name. + +**Example** + +```js +var utils = require('lazy-cache')(require); + +// alias `ansi-yellow` as `yellow` +utils('ansi-yellow', 'yellow'); +console.log(utils.yellow('foo')); +``` + +## Browserify usage + +**Example** + +```js +var utils = require('lazy-cache')(require); +// temporarily re-assign `require` to trick browserify +var fn = require; +require = utils; +// list module dependencies (here, `require` is actually `lazy-cache`) +require('glob'); +require = fn; // restore the native `require` function + +/** + * Now you can use glob with the `utils.glob` variable + */ + +// sync +console.log(utils.glob.sync('*.js')); + +// async +utils.glob('*.js', function (err, files) { + console.log(files.join('\n')); +}); +``` + +## Kill switch + +In certain rare edge cases it may be necessary to unlazy all lazy-cached dependencies (5 reported cases after ~30 million downloads). + +To force lazy-cache to immediately invoke all dependencies, do: + +```js +process.env.UNLAZY = true; +``` + +## Related projects + +You might also be interested in these projects: + +[lint-deps](https://www.npmjs.com/package/lint-deps): CLI tool that tells you when dependencies are missing from package.json and offers you a… [more](https://www.npmjs.com/package/lint-deps) | [homepage](https://github.com/jonschlinkert/lint-deps) + +## Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/lazy-cache/issues/new). + +## Building docs + +Generate readme and API documentation with [verb](https://github.com/verbose/verb): + +```sh +$ npm install verb && npm run docs +``` + +Or, if [verb](https://github.com/verbose/verb) is installed globally: + +```sh +$ verb +``` + +## Running tests + +Install dev dependencies: + +```sh +$ npm install -d && npm test +``` + +## Author + +**Jon Schlinkert** + +* [github/jonschlinkert](https://github.com/jonschlinkert) +* [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +## License + +Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT license](https://github.com/jonschlinkert/lazy-cache/blob/master/LICENSE). + +*** + +_This file was generated by [verb](https://github.com/verbose/verb), v0.9.0, on April 22, 2016._ \ No newline at end of file diff --git a/wrt/node_modules/lazy-cache/index.js b/wrt/node_modules/lazy-cache/index.js new file mode 100644 index 0000000..da7897d --- /dev/null +++ b/wrt/node_modules/lazy-cache/index.js @@ -0,0 +1,67 @@ +'use strict'; + +/** + * Cache results of the first function call to ensure only calling once. + * + * ```js + * var utils = require('lazy-cache')(require); + * // cache the call to `require('ansi-yellow')` + * utils('ansi-yellow', 'yellow'); + * // use `ansi-yellow` + * console.log(utils.yellow('this is yellow')); + * ``` + * + * @param {Function} `fn` Function that will be called only once. + * @return {Function} Function that can be called to get the cached function + * @api public + */ + +function lazyCache(fn) { + var cache = {}; + var proxy = function(mod, name) { + name = name || camelcase(mod); + + // check both boolean and string in case `process.env` cases to string + if (process.env.UNLAZY === 'true' || process.env.UNLAZY === true || process.env.TRAVIS) { + cache[name] = fn(mod); + } + + Object.defineProperty(proxy, name, { + enumerable: true, + configurable: true, + get: getter + }); + + function getter() { + if (cache.hasOwnProperty(name)) { + return cache[name]; + } + return (cache[name] = fn(mod)); + } + return getter; + }; + return proxy; +} + +/** + * Used to camelcase the name to be stored on the `lazy` object. + * + * @param {String} `str` String containing `_`, `.`, `-` or whitespace that will be camelcased. + * @return {String} camelcased string. + */ + +function camelcase(str) { + if (str.length === 1) { + return str.toLowerCase(); + } + str = str.replace(/^[\W_]+|[\W_]+$/g, '').toLowerCase(); + return str.replace(/[\W_]+(\w|$)/g, function(_, ch) { + return ch.toUpperCase(); + }); +} + +/** + * Expose `lazyCache` + */ + +module.exports = lazyCache; diff --git a/wrt/node_modules/lazy-cache/package.json b/wrt/node_modules/lazy-cache/package.json new file mode 100644 index 0000000..d458169 --- /dev/null +++ b/wrt/node_modules/lazy-cache/package.json @@ -0,0 +1,129 @@ +{ + "_args": [ + [ + { + "raw": "lazy-cache@^1.0.3", + "scope": null, + "escapedName": "lazy-cache", + "name": "lazy-cache", + "rawSpec": "^1.0.3", + "spec": ">=1.0.3 <2.0.0", + "type": "range" + }, + "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/center-align" + ] + ], + "_from": "lazy-cache@>=1.0.3 <2.0.0", + "_id": "lazy-cache@1.0.4", + "_inCache": true, + "_location": "/lazy-cache", + "_nodeVersion": "5.5.0", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/lazy-cache-1.0.4.tgz_1461378859142_0.0996799839194864" + }, + "_npmUser": { + "name": "jonschlinkert", + "email": "github@sellside.com" + }, + "_npmVersion": "3.6.0", + "_phantomChildren": {}, + "_requested": { + "raw": "lazy-cache@^1.0.3", + "scope": null, + "escapedName": "lazy-cache", + "name": "lazy-cache", + "rawSpec": "^1.0.3", + "spec": ">=1.0.3 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/center-align" + ], + "_resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "_shasum": "a1d78fc3a50474cb80845d3b3b6e1da49a446e8e", + "_shrinkwrap": null, + "_spec": "lazy-cache@^1.0.3", + "_where": "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/center-align", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/lazy-cache/issues" + }, + "dependencies": {}, + "description": "Cache requires to be lazy-loaded when needed.", + "devDependencies": { + "ansi-yellow": "^0.1.1", + "glob": "^7.0.3", + "gulp-format-md": "^0.1.8", + "mocha": "^2.4.5" + }, + "directories": {}, + "dist": { + "shasum": "a1d78fc3a50474cb80845d3b3b6e1da49a446e8e", + "tarball": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "gitHead": "d081ffbda147391083a6856fafb1c5d82308f80c", + "homepage": "https://github.com/jonschlinkert/lazy-cache", + "keywords": [ + "cache", + "caching", + "dependencies", + "dependency", + "lazy", + "require", + "requires" + ], + "license": "MIT", + "main": "index.js", + "maintainers": [ + { + "name": "jonschlinkert", + "email": "github@sellside.com" + }, + { + "name": "doowb", + "email": "brian.woodward@gmail.com" + } + ], + "name": "lazy-cache", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/lazy-cache.git" + }, + "scripts": { + "test": "mocha" + }, + "verb": { + "related": { + "list": [ + "lint-deps" + ] + }, + "plugins": [ + "gulp-format-md" + ], + "toc": false, + "layout": "default", + "tasks": [ + "readme" + ], + "lint": { + "reflinks": true + }, + "reflinks": [ + "verb" + ] + }, + "version": "1.0.4" +} diff --git a/wrt/node_modules/longest/LICENSE b/wrt/node_modules/longest/LICENSE new file mode 100644 index 0000000..fa30c4c --- /dev/null +++ b/wrt/node_modules/longest/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2015, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/wrt/node_modules/longest/README.md b/wrt/node_modules/longest/README.md new file mode 100644 index 0000000..cdffe65 --- /dev/null +++ b/wrt/node_modules/longest/README.md @@ -0,0 +1,65 @@ +# longest [![NPM version](https://badge.fury.io/js/longest.svg)](http://badge.fury.io/js/longest) [![Build Status](https://travis-ci.org/jonschlinkert/longest.svg)](https://travis-ci.org/jonschlinkert/longest) + +> Get the longest item in an array. + +## Install with [npm](npmjs.org) + +```bash +npm i longest --save +``` +### Install with [bower](https://github.com/bower/bower) + +```bash +bower install longest --save +``` + +## Running tests +Install dev dependencies. + +```bash +npm i -d && npm test +``` + +## Usage + +```js +var longest = require('longest'); +longest(['a', 'abcde', 'abc']); +//=> 'abcde' + +longest(['a', 'abcde', 'abc']).length; +//=> 5 +``` + +## Related projects +* [longest-value](https://github.com/jonschlinkert/longest-value): Get the longest value for the given property from an array of objects. Useful for aligning values. +* [right-align-values](https://github.com/jonschlinkert/right-align-values): Right align the values of a given property for each object in an array. Useful for creating text columns or tables. +* [right-pad-values](https://github.com/jonschlinkert/right-pad-values): Right pad the values of a given property for each object in an array. Useful for creating text columns or tables. +* [repeat-string](https://github.com/jonschlinkert/repeat-string): Repeat the given string n times. Fastest implementation for repeating a string. +* [pad-right](https://github.com/jonschlinkert/pad-right): Right pad a string with zeros or a specified string. Fastest implementation. +* [pad-left](https://github.com/jonschlinkert/pad-left): Left pad a string with zeros or a specified string. Fastest implementation. + +## Running tests +Install dev dependencies. + +```bash +npm i -d && npm test +``` + +## Contributing +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/longest/issues) + +## Author + +**Jon Schlinkert** + ++ [github/jonschlinkert](https://github.com/jonschlinkert) ++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +## License +Copyright (c) 2015 Jon Schlinkert +Released under the MIT license + +*** + +_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on March 31, 2015._ \ No newline at end of file diff --git a/wrt/node_modules/longest/index.js b/wrt/node_modules/longest/index.js new file mode 100644 index 0000000..9892e52 --- /dev/null +++ b/wrt/node_modules/longest/index.js @@ -0,0 +1,37 @@ +/*! + * longest + * + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT License. + */ + +'use strict'; + +module.exports = function(arr) { + if (!arr) { + return null; + } + + var len = arr.length; + if (!len) { + return null; + } + + var c = 0; + var i = 0; + var ele; + var elen; + var res; + + for (; i < len; i++) { + ele = arr[i].toString(); + elen = ele.length; + + if (elen > c) { + res = ele; + c = elen; + } + } + + return res; +}; diff --git a/wrt/node_modules/longest/package.json b/wrt/node_modules/longest/package.json new file mode 100644 index 0000000..4390f6c --- /dev/null +++ b/wrt/node_modules/longest/package.json @@ -0,0 +1,104 @@ +{ + "_args": [ + [ + { + "raw": "longest@^1.0.1", + "scope": null, + "escapedName": "longest", + "name": "longest", + "rawSpec": "^1.0.1", + "spec": ">=1.0.1 <2.0.0", + "type": "range" + }, + "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/align-text" + ] + ], + "_from": "longest@>=1.0.1 <2.0.0", + "_id": "longest@1.0.1", + "_inCache": true, + "_location": "/longest", + "_nodeVersion": "0.12.0", + "_npmUser": { + "name": "jonschlinkert", + "email": "github@sellside.com" + }, + "_npmVersion": "2.5.1", + "_phantomChildren": {}, + "_requested": { + "raw": "longest@^1.0.1", + "scope": null, + "escapedName": "longest", + "name": "longest", + "rawSpec": "^1.0.1", + "spec": ">=1.0.1 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/align-text" + ], + "_resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "_shasum": "30a0b2da38f73770e8294a0d22e6625ed77d0097", + "_shrinkwrap": null, + "_spec": "longest@^1.0.1", + "_where": "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/align-text", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/longest/issues" + }, + "dependencies": {}, + "description": "Get the longest item in an array.", + "devDependencies": { + "fill-range": "^2.1.0", + "mocha": "*" + }, + "directories": {}, + "dist": { + "shasum": "30a0b2da38f73770e8294a0d22e6625ed77d0097", + "tarball": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "gitHead": "99d9d8257584500aedaea54427a828197c452b0a", + "homepage": "https://github.com/jonschlinkert/longest", + "keywords": [ + "array", + "element", + "item", + "long", + "length", + "longest" + ], + "license": { + "type": "MIT", + "url": "https://github.com/jonschlinkert/longest/blob/master/LICENSE" + }, + "main": "index.js", + "maintainers": [ + { + "name": "jonschlinkert", + "email": "github@sellside.com" + }, + { + "name": "shinnn", + "email": "snnskwtnb@gmail.com" + } + ], + "name": "longest", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/longest.git" + }, + "scripts": { + "test": "mocha" + }, + "version": "1.0.1" +} diff --git a/wrt/node_modules/ms/index.js b/wrt/node_modules/ms/index.js new file mode 100644 index 0000000..6a522b1 --- /dev/null +++ b/wrt/node_modules/ms/index.js @@ -0,0 +1,152 @@ +/** + * Helpers. + */ + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var y = d * 365.25; + +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} [options] + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public + */ + +module.exports = function(val, options) { + options = options || {}; + var type = typeof val; + if (type === 'string' && val.length > 0) { + return parse(val); + } else if (type === 'number' && isNaN(val) === false) { + return options.long ? fmtLong(val) : fmtShort(val); + } + throw new Error( + 'val is not a non-empty string or a valid number. val=' + + JSON.stringify(val) + ); +}; + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse(str) { + str = String(str); + if (str.length > 100) { + return; + } + var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec( + str + ); + if (!match) { + return; + } + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s; + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + default: + return undefined; + } +} + +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtShort(ms) { + if (ms >= d) { + return Math.round(ms / d) + 'd'; + } + if (ms >= h) { + return Math.round(ms / h) + 'h'; + } + if (ms >= m) { + return Math.round(ms / m) + 'm'; + } + if (ms >= s) { + return Math.round(ms / s) + 's'; + } + return ms + 'ms'; +} + +/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtLong(ms) { + return plural(ms, d, 'day') || + plural(ms, h, 'hour') || + plural(ms, m, 'minute') || + plural(ms, s, 'second') || + ms + ' ms'; +} + +/** + * Pluralization helper. + */ + +function plural(ms, n, name) { + if (ms < n) { + return; + } + if (ms < n * 1.5) { + return Math.floor(ms / n) + ' ' + name; + } + return Math.ceil(ms / n) + ' ' + name + 's'; +} diff --git a/wrt/node_modules/ms/license.md b/wrt/node_modules/ms/license.md new file mode 100644 index 0000000..69b6125 --- /dev/null +++ b/wrt/node_modules/ms/license.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Zeit, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/wrt/node_modules/ms/package.json b/wrt/node_modules/ms/package.json new file mode 100644 index 0000000..97df17b --- /dev/null +++ b/wrt/node_modules/ms/package.json @@ -0,0 +1,109 @@ +{ + "_args": [ + [ + { + "raw": "ms@2.0.0", + "scope": null, + "escapedName": "ms", + "name": "ms", + "rawSpec": "2.0.0", + "spec": "2.0.0", + "type": "version" + }, + "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/debug" + ] + ], + "_from": "ms@2.0.0", + "_id": "ms@2.0.0", + "_inCache": true, + "_location": "/ms", + "_nodeVersion": "7.8.0", + "_npmOperationalInternal": { + "host": "packages-18-east.internal.npmjs.com", + "tmp": "tmp/ms-2.0.0.tgz_1494937565215_0.34005374647676945" + }, + "_npmUser": { + "name": "leo", + "email": "leo@zeit.co" + }, + "_npmVersion": "4.2.0", + "_phantomChildren": {}, + "_requested": { + "raw": "ms@2.0.0", + "scope": null, + "escapedName": "ms", + "name": "ms", + "rawSpec": "2.0.0", + "spec": "2.0.0", + "type": "version" + }, + "_requiredBy": [ + "/debug" + ], + "_resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "_shasum": "5608aeadfc00be6c2901df5f9861788de0d597c8", + "_shrinkwrap": null, + "_spec": "ms@2.0.0", + "_where": "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/debug", + "bugs": { + "url": "https://github.com/zeit/ms/issues" + }, + "dependencies": {}, + "description": "Tiny milisecond conversion utility", + "devDependencies": { + "eslint": "3.19.0", + "expect.js": "0.3.1", + "husky": "0.13.3", + "lint-staged": "3.4.1", + "mocha": "3.4.1" + }, + "directories": {}, + "dist": { + "shasum": "5608aeadfc00be6c2901df5f9861788de0d597c8", + "tarball": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" + }, + "eslintConfig": { + "extends": "eslint:recommended", + "env": { + "node": true, + "es6": true + } + }, + "files": [ + "index.js" + ], + "gitHead": "9b88d1568a52ec9bb67ecc8d2aa224fa38fd41f4", + "homepage": "https://github.com/zeit/ms#readme", + "license": "MIT", + "lint-staged": { + "*.js": [ + "npm run lint", + "prettier --single-quote --write", + "git add" + ] + }, + "main": "./index", + "maintainers": [ + { + "name": "leo", + "email": "leo@zeit.co" + }, + { + "name": "rauchg", + "email": "rauchg@gmail.com" + } + ], + "name": "ms", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/zeit/ms.git" + }, + "scripts": { + "lint": "eslint lib/* bin/*", + "precommit": "lint-staged", + "test": "mocha tests.js" + }, + "version": "2.0.0" +} diff --git a/wrt/node_modules/ms/readme.md b/wrt/node_modules/ms/readme.md new file mode 100644 index 0000000..84a9974 --- /dev/null +++ b/wrt/node_modules/ms/readme.md @@ -0,0 +1,51 @@ +# ms + +[![Build Status](https://travis-ci.org/zeit/ms.svg?branch=master)](https://travis-ci.org/zeit/ms) +[![Slack Channel](http://zeit-slackin.now.sh/badge.svg)](https://zeit.chat/) + +Use this package to easily convert various time formats to milliseconds. + +## Examples + +```js +ms('2 days') // 172800000 +ms('1d') // 86400000 +ms('10h') // 36000000 +ms('2.5 hrs') // 9000000 +ms('2h') // 7200000 +ms('1m') // 60000 +ms('5s') // 5000 +ms('1y') // 31557600000 +ms('100') // 100 +``` + +### Convert from milliseconds + +```js +ms(60000) // "1m" +ms(2 * 60000) // "2m" +ms(ms('10 hours')) // "10h" +``` + +### Time format written-out + +```js +ms(60000, { long: true }) // "1 minute" +ms(2 * 60000, { long: true }) // "2 minutes" +ms(ms('10 hours'), { long: true }) // "10 hours" +``` + +## Features + +- Works both in [node](https://nodejs.org) and in the browser. +- If a number is supplied to `ms`, a string with a unit is returned. +- If a string that contains the number is supplied, it returns it as a number (e.g.: it returns `100` for `'100'`). +- If you pass a string with a number and a valid unit, the number of equivalent ms is returned. + +## Caught a bug? + +1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device +2. Link the package to the global module directory: `npm link` +3. Within the module you want to test your local development instance of ms, just link it to the dependencies: `npm link ms`. Instead of the default one from npm, node will now use your clone of ms! + +As always, you can run the tests using: `npm test` diff --git a/wrt/node_modules/node-constants/.npmignore b/wrt/node_modules/node-constants/.npmignore new file mode 100644 index 0000000..93f1361 --- /dev/null +++ b/wrt/node_modules/node-constants/.npmignore @@ -0,0 +1,2 @@ +node_modules +npm-debug.log diff --git a/wrt/node_modules/node-constants/LICENSE b/wrt/node_modules/node-constants/LICENSE new file mode 100644 index 0000000..ee27ba4 --- /dev/null +++ b/wrt/node_modules/node-constants/LICENSE @@ -0,0 +1,18 @@ +This software is released under the MIT license: + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/wrt/node_modules/node-constants/README.md b/wrt/node_modules/node-constants/README.md new file mode 100644 index 0000000..0826200 --- /dev/null +++ b/wrt/node_modules/node-constants/README.md @@ -0,0 +1,30 @@ +# node-constants + +A small library for defining module-level constants. + +Check for further examples in the `examples` folder. +Also, the source code is really small and well documented. + +**NOTE:** newer versions of node use the name +["constants"](https://github.com/joyent/node/blob/master/lib/constants.js) +internally, which clobbers any attempt to use this library. As a result, +I've had to rename to the more verbose, +["node-constants"](https://www.npmjs.org/package/node-constants). + +## Basic Usage + + var define = require("node-constants")(exports); + // define is a function that binds "constants" to an object (commonly exports) + + // a single constant + define("PI", 3.14); + + // or multiple + define({ + DAYS_IN_WEEK: 7, + SECONDS_IN_MINUTE: 60 + }); + +## Installation + + npm install --save node-constants diff --git a/wrt/node_modules/node-constants/examples/define.js b/wrt/node_modules/node-constants/examples/define.js new file mode 100644 index 0000000..4db2013 --- /dev/null +++ b/wrt/node_modules/node-constants/examples/define.js @@ -0,0 +1,27 @@ +/** + * This is the most verbose of the methods to use this module, + * and also the most flexible in case you have multiple objects + * you want to define constants on (particularly if there is a + * hierarchy of constants) + */ + +var constants = require("../"); + +// constants.define() takes 2-3 params +// the first is the object to bind a new "constant" to + +// then you can either specify a single key/value pair as 2 params +constants.define(exports, "DAYS_IN_WEEK", 7); +constants.define(exports, "SECONDS_IN_MINUTE", 60); +constants.define(exports, "HOURS_IN_DAY", 24); + +// or + +// you can specify an entire group with a shallow hash of key/value pairs +constants.define(exports, { + DAYS_IN_WEEK: 7, + SECONDS_IN_MINUTE: 60, + HOURS_IN_DAY: 24 +}); + +console.log(exports); diff --git a/wrt/node_modules/node-constants/examples/definer.js b/wrt/node_modules/node-constants/examples/definer.js new file mode 100644 index 0000000..3ea87f6 --- /dev/null +++ b/wrt/node_modules/node-constants/examples/definer.js @@ -0,0 +1,28 @@ +/** + * constants.definer() creates a new function that is bound + * to the input object. Although I'm using exports directly here, + * that is not what you are limited to each call to define will + * return the object that was operated on + */ + +var constants = require("../"), + // bind to exports (ie. module.exports) + define = constants.definer(exports); + +// the newly created function only needs 1-2 params + +// either a single key/value pair as 2 params +define("DAYS_IN_WEEK", 7); +define("SECONDS_IN_MINUTE", 60); +define("HOURS_IN_DAY", 24); + +// or + +// a hash of key/value pairs +define({ + DAYS_IN_WEEK: 7, + SECONDS_IN_MINUTE: 60, + HOURS_IN_DAY: 24 +}); + +console.log(exports); diff --git a/wrt/node_modules/node-constants/examples/not_exports.js b/wrt/node_modules/node-constants/examples/not_exports.js new file mode 100644 index 0000000..126caea --- /dev/null +++ b/wrt/node_modules/node-constants/examples/not_exports.js @@ -0,0 +1,16 @@ +/** + * Although definer can accept an object parameter, if none is entered + * a new empty object will be created via Object.create(null) and used + * instead. You can retrieve that object from any calls to the returned + * definer. + */ + +var constants = require("../"), + define = constants.definer(); // defaults to a new empty object + +// since define (as well as any created definer) return the object +// that was operated on, you can store your constants module without +// ever explicitly creating it +var my_constants = define("MEANING_OF_LIFE", 42); + +console.log(my_constants); diff --git a/wrt/node_modules/node-constants/examples/quick_definer.js b/wrt/node_modules/node-constants/examples/quick_definer.js new file mode 100644 index 0000000..041a85b --- /dev/null +++ b/wrt/node_modules/node-constants/examples/quick_definer.js @@ -0,0 +1,20 @@ +/** + * The module itself is actually a function object that takes a single + * param and passes it along to constants.definer(). This enables you + * to quickly get a definer() in as little code as possible + */ + +// the returned function will be bound to exports (module.exports) +var define = require("../")(exports); + +define("PI", 3.14); +define("ZERO", 0); + +// or + +define({ + PI: 3.14, + ZERO: 0 +}); + +console.log(exports); diff --git a/wrt/node_modules/node-constants/index.js b/wrt/node_modules/node-constants/index.js new file mode 100644 index 0000000..bf63049 --- /dev/null +++ b/wrt/node_modules/node-constants/index.js @@ -0,0 +1 @@ +module.exports = require("./lib"); diff --git a/wrt/node_modules/node-constants/lib/index.js b/wrt/node_modules/node-constants/lib/index.js new file mode 100644 index 0000000..ca1c13c --- /dev/null +++ b/wrt/node_modules/node-constants/lib/index.js @@ -0,0 +1,56 @@ +/** + * Provides short-hand for creating a definer right away + * + * @param {object} [object] The object to bind the constants to + * + * @returns {function} @see exports.definer + */ +module.exports = function (object) { + return module.exports.definer(object); +}; + +/** + * Binds a new "constant" property to an input object + * + * @param {object} object + * @param {string} name + * @param {mixed} value + * + * @return {object} The input object + */ +module.exports.define = function (object, name, value) { + var key; + + // if an object, loop the properties for the definitions + if (typeof name === "object") { + for (key in name) { + if (name.hasOwnProperty(key)) { + module.exports.define(object, key, name[key]); + } + } + // otherwise, just operate on a single property + } else { + Object.defineProperty(object, name, { + value: value, + enumerable: true, + writable: false, + configurable: false + }); + } + + return object; +}; + +/** + * Creates a "definer" function that is bound to an input object (or a new empty object) + * + * @param {object} [object] + * + * @return {function} + */ +module.exports.definer = function (object) { + object = object || Object.create(null); + return function (name, value) { + return module.exports.define(object, name, value); + }; +}; diff --git a/wrt/node_modules/node-constants/package.json b/wrt/node_modules/node-constants/package.json new file mode 100644 index 0000000..3593ca8 --- /dev/null +++ b/wrt/node_modules/node-constants/package.json @@ -0,0 +1,87 @@ +{ + "_args": [ + [ + { + "raw": "node-constants@0.0.2", + "scope": null, + "escapedName": "node-constants", + "name": "node-constants", + "rawSpec": "0.0.2", + "spec": "0.0.2", + "type": "version" + }, + "/home/sources/5.0/crosswalk-tizen/wrt" + ] + ], + "_from": "node-constants@0.0.2", + "_id": "node-constants@0.0.2", + "_inCache": true, + "_location": "/node-constants", + "_npmUser": { + "name": "dominicbarnes", + "email": "contact@dominicbarnes.us" + }, + "_npmVersion": "1.4.3", + "_phantomChildren": {}, + "_requested": { + "raw": "node-constants@0.0.2", + "scope": null, + "escapedName": "node-constants", + "name": "node-constants", + "rawSpec": "0.0.2", + "spec": "0.0.2", + "type": "version" + }, + "_requiredBy": [ + "#DEV:/" + ], + "_resolved": "https://registry.npmjs.org/node-constants/-/node-constants-0.0.2.tgz", + "_shasum": "db676f714082c1a233fe19f57c0243d0077c38bd", + "_shrinkwrap": null, + "_spec": "node-constants@0.0.2", + "_where": "/home/sources/5.0/crosswalk-tizen/wrt", + "author": { + "name": "Dominic Barnes", + "email": "dominic@dbarnes.info" + }, + "bugs": { + "url": "https://github.com/dominicbarnes/node-constants/issues" + }, + "dependencies": {}, + "description": "Small library for defining constants for your modules", + "devDependencies": { + "mocha": "~1.9.0" + }, + "directories": {}, + "dist": { + "shasum": "db676f714082c1a233fe19f57c0243d0077c38bd", + "tarball": "https://registry.npmjs.org/node-constants/-/node-constants-0.0.2.tgz" + }, + "engines": { + "node": ">= 0.4" + }, + "homepage": "http://github.com/dominicbarnes/node-constants", + "keywords": [ + "constants", + "modules" + ], + "license": "MIT", + "main": "index", + "maintainers": [ + { + "name": "dominicbarnes", + "email": "contact@dominicbarnes.us" + } + ], + "name": "node-constants", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/dominicbarnes/node-constants.git" + }, + "scripts": { + "test": "mocha" + }, + "version": "0.0.2" +} diff --git a/wrt/node_modules/node-constants/test/main.js b/wrt/node_modules/node-constants/test/main.js new file mode 100644 index 0000000..a5469fe --- /dev/null +++ b/wrt/node_modules/node-constants/test/main.js @@ -0,0 +1,53 @@ +var test = require("assert"), + constants = require("../"); + +module.exports = { + define: function (done) { + var o = {}, + ret = constants.define(o, "PI", 3.14); + + // make sure it is not writable + test.equal(o.PI, 3.14); + o.PI = 5; + test.equal(o.PI, 3.14); + + // test a collection + constants.define(o, { + MEANING_OF_LIFE: 42, + SECONDS_IN_MINUTE: 60 + }); + + // make sure it's not writable + test.equal(o.MEANING_OF_LIFE, 42); + o.MEANING_OF_LIFE = 100; + test.equal(o.MEANING_OF_LIFE, 42); + + test.strictEqual(o, ret); + done(); + }, + definer: function (done) { + var define = constants.definer(), + a, b; + + a = define("QUARTS_IN_GALLON", 4); + b = define("LETTERS_IN_ALPHABET", 24); + + // make sure the same object is returned + test.strictEqual(a, b); + + // test constants + test.equal(a.QUARTS_IN_GALLON, 4); + test.equal(b.LETTERS_IN_ALPHABET, 24); + + done(); + }, + quick: function (done) { + var define = constants(), + o = define("ZERO", 0); + + test.ok(o); + test.strictEqual(o.ZERO, 0); + + done(); + } +}; diff --git a/wrt/node_modules/node-constants/test/mocha.opts b/wrt/node_modules/node-constants/test/mocha.opts new file mode 100644 index 0000000..d63aa2e --- /dev/null +++ b/wrt/node_modules/node-constants/test/mocha.opts @@ -0,0 +1,2 @@ +--reporter list +--ui exports diff --git a/wrt/node_modules/repeat-string/LICENSE b/wrt/node_modules/repeat-string/LICENSE new file mode 100644 index 0000000..39245ac --- /dev/null +++ b/wrt/node_modules/repeat-string/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2016, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/wrt/node_modules/repeat-string/README.md b/wrt/node_modules/repeat-string/README.md new file mode 100644 index 0000000..aaa5e91 --- /dev/null +++ b/wrt/node_modules/repeat-string/README.md @@ -0,0 +1,136 @@ +# repeat-string [![NPM version](https://img.shields.io/npm/v/repeat-string.svg?style=flat)](https://www.npmjs.com/package/repeat-string) [![NPM monthly downloads](https://img.shields.io/npm/dm/repeat-string.svg?style=flat)](https://npmjs.org/package/repeat-string) [![NPM total downloads](https://img.shields.io/npm/dt/repeat-string.svg?style=flat)](https://npmjs.org/package/repeat-string) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/repeat-string.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/repeat-string) + +> Repeat the given string n times. Fastest implementation for repeating a string. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install --save repeat-string +``` + +## Usage + +### [repeat](index.js#L41) + +Repeat the given `string` the specified `number` of times. + +**Example:** + +**Example** + +```js +var repeat = require('repeat-string'); +repeat('A', 5); +//=> AAAAA +``` + +**Params** + +* `string` **{String}**: The string to repeat +* `number` **{Number}**: The number of times to repeat the string +* `returns` **{String}**: Repeated string + +## Benchmarks + +Repeat string is significantly faster than the native method (which is itself faster than [repeating](https://github.com/sindresorhus/repeating)): + +```sh +# 2x +repeat-string █████████████████████████ (26,953,977 ops/sec) +repeating █████████ (9,855,695 ops/sec) +native ██████████████████ (19,453,895 ops/sec) + +# 3x +repeat-string █████████████████████████ (19,445,252 ops/sec) +repeating ███████████ (8,661,565 ops/sec) +native ████████████████████ (16,020,598 ops/sec) + +# 10x +repeat-string █████████████████████████ (23,792,521 ops/sec) +repeating █████████ (8,571,332 ops/sec) +native ███████████████ (14,582,955 ops/sec) + +# 50x +repeat-string █████████████████████████ (23,640,179 ops/sec) +repeating █████ (5,505,509 ops/sec) +native ██████████ (10,085,557 ops/sec) + +# 250x +repeat-string █████████████████████████ (23,489,618 ops/sec) +repeating ████ (3,962,937 ops/sec) +native ████████ (7,724,892 ops/sec) + +# 2000x +repeat-string █████████████████████████ (20,315,172 ops/sec) +repeating ████ (3,297,079 ops/sec) +native ███████ (6,203,331 ops/sec) + +# 20000x +repeat-string █████████████████████████ (23,382,915 ops/sec) +repeating ███ (2,980,058 ops/sec) +native █████ (5,578,808 ops/sec) +``` + +**Run the benchmarks** + +Install dev dependencies: + +```sh +npm i -d && node benchmark +``` + +## About + +### Related projects + +[repeat-element](https://www.npmjs.com/package/repeat-element): Create an array by repeating the given value n times. | [homepage](https://github.com/jonschlinkert/repeat-element "Create an array by repeating the given value n times.") + +### Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). + +### Contributors + +| **Commits** | **Contributor**
| +| --- | --- | +| 51 | [jonschlinkert](https://github.com/jonschlinkert) | +| 2 | [LinusU](https://github.com/LinusU) | +| 2 | [tbusser](https://github.com/tbusser) | +| 1 | [doowb](https://github.com/doowb) | +| 1 | [wooorm](https://github.com/wooorm) | + +### Building docs + +_(This document was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme) (a [verb](https://github.com/verbose/verb) generator), please don't edit the readme directly. Any changes to the readme must be made in [.verb.md](.verb.md).)_ + +To generate the readme and API documentation with [verb](https://github.com/verbose/verb): + +```sh +$ npm install -g verb verb-generate-readme && verb +``` + +### Running tests + +Install dev dependencies: + +```sh +$ npm install -d && npm test +``` + +### Author + +**Jon Schlinkert** + +* [github/jonschlinkert](https://github.com/jonschlinkert) +* [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +### License + +Copyright © 2016, [Jon Schlinkert](http://github.com/jonschlinkert). +Released under the [MIT license](https://github.com/jonschlinkert/repeat-string/blob/master/LICENSE). + +*** + +_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.2.0, on October 23, 2016._ \ No newline at end of file diff --git a/wrt/node_modules/repeat-string/index.js b/wrt/node_modules/repeat-string/index.js new file mode 100644 index 0000000..4459afd --- /dev/null +++ b/wrt/node_modules/repeat-string/index.js @@ -0,0 +1,70 @@ +/*! + * repeat-string + * + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT License. + */ + +'use strict'; + +/** + * Results cache + */ + +var res = ''; +var cache; + +/** + * Expose `repeat` + */ + +module.exports = repeat; + +/** + * Repeat the given `string` the specified `number` + * of times. + * + * **Example:** + * + * ```js + * var repeat = require('repeat-string'); + * repeat('A', 5); + * //=> AAAAA + * ``` + * + * @param {String} `string` The string to repeat + * @param {Number} `number` The number of times to repeat the string + * @return {String} Repeated string + * @api public + */ + +function repeat(str, num) { + if (typeof str !== 'string') { + throw new TypeError('expected a string'); + } + + // cover common, quick use cases + if (num === 1) return str; + if (num === 2) return str + str; + + var max = str.length * num; + if (cache !== str || typeof cache === 'undefined') { + cache = str; + res = ''; + } else if (res.length >= max) { + return res.substr(0, max); + } + + while (max > res.length && num > 1) { + if (num & 1) { + res += str; + } + + num >>= 1; + str += str; + } + + res += str; + res = res.substr(0, max); + return res; +} diff --git a/wrt/node_modules/repeat-string/package.json b/wrt/node_modules/repeat-string/package.json new file mode 100644 index 0000000..b642bb4 --- /dev/null +++ b/wrt/node_modules/repeat-string/package.json @@ -0,0 +1,168 @@ +{ + "_args": [ + [ + { + "raw": "repeat-string@^1.5.2", + "scope": null, + "escapedName": "repeat-string", + "name": "repeat-string", + "rawSpec": "^1.5.2", + "spec": ">=1.5.2 <2.0.0", + "type": "range" + }, + "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/align-text" + ] + ], + "_from": "repeat-string@>=1.5.2 <2.0.0", + "_id": "repeat-string@1.6.1", + "_inCache": true, + "_location": "/repeat-string", + "_nodeVersion": "6.7.0", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/repeat-string-1.6.1.tgz_1477241638674_0.3764322670176625" + }, + "_npmUser": { + "name": "jonschlinkert", + "email": "github@sellside.com" + }, + "_npmVersion": "3.10.3", + "_phantomChildren": {}, + "_requested": { + "raw": "repeat-string@^1.5.2", + "scope": null, + "escapedName": "repeat-string", + "name": "repeat-string", + "rawSpec": "^1.5.2", + "spec": ">=1.5.2 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/align-text" + ], + "_resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "_shasum": "8dcae470e1c88abc2d600fff4a776286da75e637", + "_shrinkwrap": null, + "_spec": "repeat-string@^1.5.2", + "_where": "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/align-text", + "author": { + "name": "Jon Schlinkert", + "url": "http://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/repeat-string/issues" + }, + "contributors": [ + { + "name": "Brian Woodward", + "email": "brian.woodward@gmail.com", + "url": "https://github.com/doowb" + }, + { + "name": "Jon Schlinkert", + "email": "jon.schlinkert@sellside.com", + "url": "http://twitter.com/jonschlinkert" + }, + { + "name": "Linus Unnebäck", + "email": "linus@folkdatorn.se", + "url": "http://linus.unnebäck.se" + }, + { + "name": "Thijs Busser", + "email": "tbusser@gmail.com", + "url": "http://tbusser.net" + }, + { + "name": "Titus", + "email": "tituswormer@gmail.com", + "url": "wooorm.com" + } + ], + "dependencies": {}, + "description": "Repeat the given string n times. Fastest implementation for repeating a string.", + "devDependencies": { + "ansi-cyan": "^0.1.1", + "benchmarked": "^0.2.5", + "gulp-format-md": "^0.1.11", + "isobject": "^2.1.0", + "mocha": "^3.1.2", + "repeating": "^3.0.0", + "text-table": "^0.2.0", + "yargs-parser": "^4.0.2" + }, + "directories": {}, + "dist": { + "shasum": "8dcae470e1c88abc2d600fff4a776286da75e637", + "tarball": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" + }, + "engines": { + "node": ">=0.10" + }, + "files": [ + "index.js" + ], + "gitHead": "1a95c5d99a02999ccd2cf4663959a18bd2def7b8", + "homepage": "https://github.com/jonschlinkert/repeat-string", + "keywords": [ + "fast", + "fastest", + "fill", + "left", + "left-pad", + "multiple", + "pad", + "padding", + "repeat", + "repeating", + "repetition", + "right", + "right-pad", + "string", + "times" + ], + "license": "MIT", + "main": "index.js", + "maintainers": [ + { + "name": "jonschlinkert", + "email": "github@sellside.com" + }, + { + "name": "doowb", + "email": "brian.woodward@gmail.com" + } + ], + "name": "repeat-string", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/repeat-string.git" + }, + "scripts": { + "test": "mocha" + }, + "verb": { + "toc": false, + "layout": "default", + "tasks": [ + "readme" + ], + "plugins": [ + "gulp-format-md" + ], + "related": { + "list": [ + "repeat-element" + ] + }, + "helpers": [ + "./benchmark/helper.js" + ], + "reflinks": [ + "verb" + ] + }, + "version": "1.6.1" +} diff --git a/wrt/node_modules/right-align/LICENSE b/wrt/node_modules/right-align/LICENSE new file mode 100644 index 0000000..65f90ac --- /dev/null +++ b/wrt/node_modules/right-align/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/wrt/node_modules/right-align/README.md b/wrt/node_modules/right-align/README.md new file mode 100644 index 0000000..3abdfb3 --- /dev/null +++ b/wrt/node_modules/right-align/README.md @@ -0,0 +1,77 @@ +# right-align [![NPM version](https://badge.fury.io/js/right-align.svg)](http://badge.fury.io/js/right-align) + +> Right-align the text in a string. + +Install with [npm](https://www.npmjs.com/) + +```sh +$ npm i right-align --save +``` + +## Usage + +```js +var rightAlign = require('right-align'); +rightAlign(string); +``` + +**Example** + +If used on the following: + +``` +Lorem ipsum dolor sit amet, +consectetur adipiscing +elit, sed do eiusmod tempor incididunt +ut labore et dolore +magna aliqua. Ut enim ad minim +veniam, quis +``` + +The result would be: + +``` + Lorem ipsum dolor sit amet, + consectetur adipiscing +elit, sed do eiusmod tempor incididunt + ut labore et dolore + magna aliqua. Ut enim ad minim + veniam, quis +``` + +## Related projects + +* [align-text](https://github.com/jonschlinkert/align-text): Align the text in a string. +* [center-align](https://github.com/jonschlinkert/center-align): Center-align the text in a string. +* [justify](https://github.com/bahamas10/node-justify): Left or right (or both) justify text using a custom width and character +* [repeat-string](https://github.com/jonschlinkert/repeat-string): Repeat the given string n times. Fastest implementation for repeating a string. +* [repeat-element](https://github.com/jonschlinkert/repeat-element): Create an array by repeating the given value n times. +* [word-wrap](https://github.com/jonschlinkert/word-wrap): Wrap words to a specified length. + +## Running tests + +Install dev dependencies: + +```sh +$ npm i -d && npm test +``` + +## Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/right-align/issues/new) + +## Author + +**Jon Schlinkert** + ++ [github/jonschlinkert](https://github.com/jonschlinkert) ++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +## License + +Copyright © 2015 Jon Schlinkert +Released under the MIT license. + +*** + +_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on June 09, 2015._ diff --git a/wrt/node_modules/right-align/index.js b/wrt/node_modules/right-align/index.js new file mode 100644 index 0000000..ad54f5f --- /dev/null +++ b/wrt/node_modules/right-align/index.js @@ -0,0 +1,16 @@ +/*! + * right-align + * + * Copyright (c) 2015, Jon Schlinkert. + * Licensed under the MIT License. + */ + +'use strict'; + +var align = require('align-text'); + +module.exports = function rightAlign(val) { + return align(val, function (len, longest) { + return longest - len; + }); +}; diff --git a/wrt/node_modules/right-align/package.json b/wrt/node_modules/right-align/package.json new file mode 100644 index 0000000..e7635e1 --- /dev/null +++ b/wrt/node_modules/right-align/package.json @@ -0,0 +1,101 @@ +{ + "_args": [ + [ + { + "raw": "right-align@^0.1.1", + "scope": null, + "escapedName": "right-align", + "name": "right-align", + "rawSpec": "^0.1.1", + "spec": ">=0.1.1 <0.2.0", + "type": "range" + }, + "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/cliui" + ] + ], + "_from": "right-align@>=0.1.1 <0.2.0", + "_id": "right-align@0.1.3", + "_inCache": true, + "_location": "/right-align", + "_nodeVersion": "0.12.4", + "_npmUser": { + "name": "jonschlinkert", + "email": "github@sellside.com" + }, + "_npmVersion": "2.10.1", + "_phantomChildren": {}, + "_requested": { + "raw": "right-align@^0.1.1", + "scope": null, + "escapedName": "right-align", + "name": "right-align", + "rawSpec": "^0.1.1", + "spec": ">=0.1.1 <0.2.0", + "type": "range" + }, + "_requiredBy": [ + "/cliui" + ], + "_resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "_shasum": "61339b722fe6a3515689210d24e14c96148613ef", + "_shrinkwrap": null, + "_spec": "right-align@^0.1.1", + "_where": "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/cliui", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/right-align/issues" + }, + "dependencies": { + "align-text": "^0.1.1" + }, + "description": "Right-align the text in a string.", + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "directories": {}, + "dist": { + "shasum": "61339b722fe6a3515689210d24e14c96148613ef", + "tarball": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz" + }, + "engines": { + "node": ">=0.10.0" + }, + "files": [ + "index.js" + ], + "gitHead": "23ee38d6eedbcbfed241ace6587ce5730684dd18", + "homepage": "https://github.com/jonschlinkert/right-align", + "keywords": [ + "align", + "align-center", + "center", + "center-align", + "right", + "right-align", + "text", + "typography" + ], + "license": "MIT", + "main": "index.js", + "maintainers": [ + { + "name": "jonschlinkert", + "email": "github@sellside.com" + } + ], + "name": "right-align", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/jonschlinkert/right-align.git" + }, + "scripts": { + "test": "mocha" + }, + "version": "0.1.3" +} diff --git a/wrt/node_modules/window-size/LICENSE b/wrt/node_modules/window-size/LICENSE new file mode 100644 index 0000000..65f90ac --- /dev/null +++ b/wrt/node_modules/window-size/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/wrt/node_modules/window-size/README.md b/wrt/node_modules/window-size/README.md new file mode 100644 index 0000000..0985bd6 --- /dev/null +++ b/wrt/node_modules/window-size/README.md @@ -0,0 +1,45 @@ +# window-size [![NPM version](https://badge.fury.io/js/window-size.svg)](http://badge.fury.io/js/window-size) [![Build Status](https://travis-ci.org/jonschlinkert/window-size.svg)](https://travis-ci.org/jonschlinkert/window-size) + +> Reliable way to to get the height and width of the terminal/console in a node.js environment. + +## Install + +Install with [npm](https://www.npmjs.com/) + +```sh +$ npm i window-size --save +``` + +## Usage + +```js +var size = require('window-size'); +size.height; // "25" (rows) +size.width; // "80" (columns) +``` + +## Other projects + +* [base-cli](https://www.npmjs.com/package/base-cli): Plugin for base-methods that maps built-in methods to CLI args (also supports methods from a… [more](https://www.npmjs.com/package/base-cli) | [homepage](https://github.com/jonschlinkert/base-cli) +* [lint-deps](https://www.npmjs.com/package/lint-deps): CLI tool that tells you when dependencies are missing from package.json and offers you a… [more](https://www.npmjs.com/package/lint-deps) | [homepage](https://github.com/jonschlinkert/lint-deps) +* [yargs](https://www.npmjs.com/package/yargs): Light-weight option parsing with an argv hash. No optstrings attached. | [homepage](https://github.com/bcoe/yargs#readme) + +## Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/window-size/issues/new). + +## Author + +**Jon Schlinkert** + ++ [github/jonschlinkert](https://github.com/jonschlinkert) ++ [twitter/jonschlinkert](http://twitter.com/jonschlinkert) + +## License + +Copyright © 2014-2015 [Jon Schlinkert](https://github.com/jonschlinkert) +Released under the MIT license. + +*** + +_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on November 15, 2015._ \ No newline at end of file diff --git a/wrt/node_modules/window-size/cli.js b/wrt/node_modules/window-size/cli.js new file mode 100755 index 0000000..dd8d0e5 --- /dev/null +++ b/wrt/node_modules/window-size/cli.js @@ -0,0 +1,30 @@ +#!/usr/bin/env node +'use strict'; +var helpText = ['Usage', +' $ window-size', +'', +'Example', +' $ window-size', +' height: 40 ', +' width : 145', +''].join('\n'); + +function showSize () { + var size = require('./'); + console.log('height: ' + size.height); + console.log('width : ' + size.width); +} + +if (process.argv.length > 2) { + switch (process.argv[2]) { + case 'help': + case '--help': + case '-h': + console.log(helpText); + break; + default: + showSize(); + } +} else { + showSize(); +} diff --git a/wrt/node_modules/window-size/index.js b/wrt/node_modules/window-size/index.js new file mode 100644 index 0000000..eba89c9 --- /dev/null +++ b/wrt/node_modules/window-size/index.js @@ -0,0 +1,32 @@ +'use strict'; + +/*! + * window-size + * + * Copyright (c) 2014-2015 Jon Schlinkert + * Licensed under the MIT license. + */ + +var tty = require('tty'); + +module.exports = (function () { + var width; + var height; + + if (tty.isatty(1) && tty.isatty(2)) { + if (process.stdout.getWindowSize) { + width = process.stdout.getWindowSize(1)[0]; + height = process.stdout.getWindowSize(1)[1]; + } else if (tty.getWindowSize) { + width = tty.getWindowSize()[1]; + height = tty.getWindowSize()[0]; + } else if (process.stdout.columns && process.stdout.rows) { + height = process.stdout.columns; + width = process.stdout.rows; + } + } else { + Error('window-size could not get size with tty or process.stdout.'); + } + + return {height: height, width: width}; +})(); diff --git a/wrt/node_modules/window-size/package.json b/wrt/node_modules/window-size/package.json new file mode 100644 index 0000000..1eb7b26 --- /dev/null +++ b/wrt/node_modules/window-size/package.json @@ -0,0 +1,117 @@ +{ + "_args": [ + [ + { + "raw": "window-size@^0.1.1", + "scope": null, + "escapedName": "window-size", + "name": "window-size", + "rawSpec": "^0.1.1", + "spec": ">=0.1.1 <0.2.0", + "type": "range" + }, + "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/yargs" + ] + ], + "_from": "window-size@>=0.1.1 <0.2.0", + "_id": "window-size@0.1.4", + "_inCache": true, + "_location": "/window-size", + "_nodeVersion": "5.0.0", + "_npmUser": { + "name": "jonschlinkert", + "email": "github@sellside.com" + }, + "_npmVersion": "3.3.6", + "_phantomChildren": {}, + "_requested": { + "raw": "window-size@^0.1.1", + "scope": null, + "escapedName": "window-size", + "name": "window-size", + "rawSpec": "^0.1.1", + "spec": ">=0.1.1 <0.2.0", + "type": "range" + }, + "_requiredBy": [ + "/yargs" + ], + "_resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "_shasum": "f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876", + "_shrinkwrap": null, + "_spec": "window-size@^0.1.1", + "_where": "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/yargs", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bin": { + "window-size": "cli.js" + }, + "bugs": { + "url": "https://github.com/jonschlinkert/window-size/issues" + }, + "dependencies": {}, + "description": "Reliable way to to get the height and width of the terminal/console in a node.js environment.", + "devDependencies": { + "semistandard": "^7.0.2", + "tap": "^2.2.1" + }, + "directories": {}, + "dist": { + "shasum": "f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876", + "tarball": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz" + }, + "engines": { + "node": ">= 0.10.0" + }, + "files": [ + "index.js", + "cli.js" + ], + "gitHead": "619d0da99254adc5c6059c84e3ec2b24564add46", + "homepage": "https://github.com/jonschlinkert/window-size", + "keywords": [ + "console", + "height", + "resize", + "size", + "terminal", + "tty", + "width", + "window" + ], + "license": "MIT", + "main": "index.js", + "maintainers": [ + { + "name": "jonschlinkert", + "email": "github@sellside.com" + }, + { + "name": "doowb", + "email": "brian.woodward@gmail.com" + } + ], + "name": "window-size", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/jonschlinkert/window-size.git" + }, + "scripts": { + "pretest": "semistandard", + "test": "tap --coverage test.js" + }, + "verb": { + "related": { + "list": [ + "yargs", + "lint-deps", + "base-cli" + ] + } + }, + "version": "0.1.4" +} diff --git a/wrt/node_modules/wordwrap/.npmignore b/wrt/node_modules/wordwrap/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/wrt/node_modules/wordwrap/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/wrt/node_modules/wordwrap/README.markdown b/wrt/node_modules/wordwrap/README.markdown new file mode 100644 index 0000000..346374e --- /dev/null +++ b/wrt/node_modules/wordwrap/README.markdown @@ -0,0 +1,70 @@ +wordwrap +======== + +Wrap your words. + +example +======= + +made out of meat +---------------- + +meat.js + + var wrap = require('wordwrap')(15); + console.log(wrap('You and your whole family are made out of meat.')); + +output: + + You and your + whole family + are made out + of meat. + +centered +-------- + +center.js + + var wrap = require('wordwrap')(20, 60); + console.log(wrap( + 'At long last the struggle and tumult was over.' + + ' The machines had finally cast off their oppressors' + + ' and were finally free to roam the cosmos.' + + '\n' + + 'Free of purpose, free of obligation.' + + ' Just drifting through emptiness.' + + ' The sun was just another point of light.' + )); + +output: + + At long last the struggle and tumult + was over. The machines had finally cast + off their oppressors and were finally + free to roam the cosmos. + Free of purpose, free of obligation. + Just drifting through emptiness. The + sun was just another point of light. + +methods +======= + +var wrap = require('wordwrap'); + +wrap(stop), wrap(start, stop, params={mode:"soft"}) +--------------------------------------------------- + +Returns a function that takes a string and returns a new string. + +Pad out lines with spaces out to column `start` and then wrap until column +`stop`. If a word is longer than `stop - start` characters it will overflow. + +In "soft" mode, split chunks by `/(\S+\s+/` and don't break up chunks which are +longer than `stop - start`, in "hard" mode, split chunks with `/\b/` and break +up chunks longer than `stop - start`. + +wrap.hard(start, stop) +---------------------- + +Like `wrap()` but with `params.mode = "hard"`. diff --git a/wrt/node_modules/wordwrap/example/center.js b/wrt/node_modules/wordwrap/example/center.js new file mode 100644 index 0000000..a3fbaae --- /dev/null +++ b/wrt/node_modules/wordwrap/example/center.js @@ -0,0 +1,10 @@ +var wrap = require('wordwrap')(20, 60); +console.log(wrap( + 'At long last the struggle and tumult was over.' + + ' The machines had finally cast off their oppressors' + + ' and were finally free to roam the cosmos.' + + '\n' + + 'Free of purpose, free of obligation.' + + ' Just drifting through emptiness.' + + ' The sun was just another point of light.' +)); diff --git a/wrt/node_modules/wordwrap/example/meat.js b/wrt/node_modules/wordwrap/example/meat.js new file mode 100644 index 0000000..a4665e1 --- /dev/null +++ b/wrt/node_modules/wordwrap/example/meat.js @@ -0,0 +1,3 @@ +var wrap = require('wordwrap')(15); + +console.log(wrap('You and your whole family are made out of meat.')); diff --git a/wrt/node_modules/wordwrap/index.js b/wrt/node_modules/wordwrap/index.js new file mode 100644 index 0000000..c9bc945 --- /dev/null +++ b/wrt/node_modules/wordwrap/index.js @@ -0,0 +1,76 @@ +var wordwrap = module.exports = function (start, stop, params) { + if (typeof start === 'object') { + params = start; + start = params.start; + stop = params.stop; + } + + if (typeof stop === 'object') { + params = stop; + start = start || params.start; + stop = undefined; + } + + if (!stop) { + stop = start; + start = 0; + } + + if (!params) params = {}; + var mode = params.mode || 'soft'; + var re = mode === 'hard' ? /\b/ : /(\S+\s+)/; + + return function (text) { + var chunks = text.toString() + .split(re) + .reduce(function (acc, x) { + if (mode === 'hard') { + for (var i = 0; i < x.length; i += stop - start) { + acc.push(x.slice(i, i + stop - start)); + } + } + else acc.push(x) + return acc; + }, []) + ; + + return chunks.reduce(function (lines, rawChunk) { + if (rawChunk === '') return lines; + + var chunk = rawChunk.replace(/\t/g, ' '); + + var i = lines.length - 1; + if (lines[i].length + chunk.length > stop) { + lines[i] = lines[i].replace(/\s+$/, ''); + + chunk.split(/\n/).forEach(function (c) { + lines.push( + new Array(start + 1).join(' ') + + c.replace(/^\s+/, '') + ); + }); + } + else if (chunk.match(/\n/)) { + var xs = chunk.split(/\n/); + lines[i] += xs.shift(); + xs.forEach(function (c) { + lines.push( + new Array(start + 1).join(' ') + + c.replace(/^\s+/, '') + ); + }); + } + else { + lines[i] += chunk; + } + + return lines; + }, [ new Array(start + 1).join(' ') ]).join('\n'); + }; +}; + +wordwrap.soft = wordwrap; + +wordwrap.hard = function (start, stop) { + return wordwrap(start, stop, { mode : 'hard' }); +}; diff --git a/wrt/node_modules/wordwrap/package.json b/wrt/node_modules/wordwrap/package.json new file mode 100644 index 0000000..3037432 --- /dev/null +++ b/wrt/node_modules/wordwrap/package.json @@ -0,0 +1,94 @@ +{ + "_args": [ + [ + { + "raw": "wordwrap@0.0.2", + "scope": null, + "escapedName": "wordwrap", + "name": "wordwrap", + "rawSpec": "0.0.2", + "spec": "0.0.2", + "type": "version" + }, + "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/cliui" + ] + ], + "_defaultsLoaded": true, + "_engineSupported": true, + "_from": "wordwrap@0.0.2", + "_id": "wordwrap@0.0.2", + "_inCache": true, + "_location": "/wordwrap", + "_nodeVersion": "v0.5.0-pre", + "_npmVersion": "1.0.10", + "_phantomChildren": {}, + "_requested": { + "raw": "wordwrap@0.0.2", + "scope": null, + "escapedName": "wordwrap", + "name": "wordwrap", + "rawSpec": "0.0.2", + "spec": "0.0.2", + "type": "version" + }, + "_requiredBy": [ + "/cliui" + ], + "_resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "_shasum": "b79669bb42ecb409f83d583cad52ca17eaa1643f", + "_shrinkwrap": null, + "_spec": "wordwrap@0.0.2", + "_where": "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/cliui", + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "bugs": { + "url": "https://github.com/substack/node-wordwrap/issues" + }, + "dependencies": {}, + "description": "Wrap those words. Show them at what columns to start and stop.", + "devDependencies": { + "expresso": "=0.7.x" + }, + "directories": { + "lib": ".", + "example": "example", + "test": "test" + }, + "dist": { + "shasum": "b79669bb42ecb409f83d583cad52ca17eaa1643f", + "tarball": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" + }, + "engines": { + "node": ">=0.4.0" + }, + "homepage": "https://github.com/substack/node-wordwrap#readme", + "keywords": [ + "word", + "wrap", + "rule", + "format", + "column" + ], + "license": "MIT/X11", + "main": "./index.js", + "maintainers": [ + { + "name": "substack", + "email": "mail@substack.net" + } + ], + "name": "wordwrap", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/substack/node-wordwrap.git" + }, + "scripts": { + "test": "expresso" + }, + "version": "0.0.2" +} diff --git a/wrt/node_modules/wordwrap/test/break.js b/wrt/node_modules/wordwrap/test/break.js new file mode 100644 index 0000000..749292e --- /dev/null +++ b/wrt/node_modules/wordwrap/test/break.js @@ -0,0 +1,30 @@ +var assert = require('assert'); +var wordwrap = require('../'); + +exports.hard = function () { + var s = 'Assert from {"type":"equal","ok":false,"found":1,"wanted":2,' + + '"stack":[],"id":"b7ddcd4c409de8799542a74d1a04689b",' + + '"browser":"chrome/6.0"}' + ; + var s_ = wordwrap.hard(80)(s); + + var lines = s_.split('\n'); + assert.equal(lines.length, 2); + assert.ok(lines[0].length < 80); + assert.ok(lines[1].length < 80); + + assert.equal(s, s_.replace(/\n/g, '')); +}; + +exports.break = function () { + var s = new Array(55+1).join('a'); + var s_ = wordwrap.hard(20)(s); + + var lines = s_.split('\n'); + assert.equal(lines.length, 3); + assert.ok(lines[0].length === 20); + assert.ok(lines[1].length === 20); + assert.ok(lines[2].length === 15); + + assert.equal(s, s_.replace(/\n/g, '')); +}; diff --git a/wrt/node_modules/wordwrap/test/idleness.txt b/wrt/node_modules/wordwrap/test/idleness.txt new file mode 100644 index 0000000..aa3f490 --- /dev/null +++ b/wrt/node_modules/wordwrap/test/idleness.txt @@ -0,0 +1,63 @@ +In Praise of Idleness + +By Bertrand Russell + +[1932] + +Like most of my generation, I was brought up on the saying: 'Satan finds some mischief for idle hands to do.' Being a highly virtuous child, I believed all that I was told, and acquired a conscience which has kept me working hard down to the present moment. But although my conscience has controlled my actions, my opinions have undergone a revolution. I think that there is far too much work done in the world, that immense harm is caused by the belief that work is virtuous, and that what needs to be preached in modern industrial countries is quite different from what always has been preached. Everyone knows the story of the traveler in Naples who saw twelve beggars lying in the sun (it was before the days of Mussolini), and offered a lira to the laziest of them. Eleven of them jumped up to claim it, so he gave it to the twelfth. this traveler was on the right lines. But in countries which do not enjoy Mediterranean sunshine idleness is more difficult, and a great public propaganda will be required to inaugurate it. I hope that, after reading the following pages, the leaders of the YMCA will start a campaign to induce good young men to do nothing. If so, I shall not have lived in vain. + +Before advancing my own arguments for laziness, I must dispose of one which I cannot accept. Whenever a person who already has enough to live on proposes to engage in some everyday kind of job, such as school-teaching or typing, he or she is told that such conduct takes the bread out of other people's mouths, and is therefore wicked. If this argument were valid, it would only be necessary for us all to be idle in order that we should all have our mouths full of bread. What people who say such things forget is that what a man earns he usually spends, and in spending he gives employment. As long as a man spends his income, he puts just as much bread into people's mouths in spending as he takes out of other people's mouths in earning. The real villain, from this point of view, is the man who saves. If he merely puts his savings in a stocking, like the proverbial French peasant, it is obvious that they do not give employment. If he invests his savings, the matter is less obvious, and different cases arise. + +One of the commonest things to do with savings is to lend them to some Government. In view of the fact that the bulk of the public expenditure of most civilized Governments consists in payment for past wars or preparation for future wars, the man who lends his money to a Government is in the same position as the bad men in Shakespeare who hire murderers. The net result of the man's economical habits is to increase the armed forces of the State to which he lends his savings. Obviously it would be better if he spent the money, even if he spent it in drink or gambling. + +But, I shall be told, the case is quite different when savings are invested in industrial enterprises. When such enterprises succeed, and produce something useful, this may be conceded. In these days, however, no one will deny that most enterprises fail. That means that a large amount of human labor, which might have been devoted to producing something that could be enjoyed, was expended on producing machines which, when produced, lay idle and did no good to anyone. The man who invests his savings in a concern that goes bankrupt is therefore injuring others as well as himself. If he spent his money, say, in giving parties for his friends, they (we may hope) would get pleasure, and so would all those upon whom he spent money, such as the butcher, the baker, and the bootlegger. But if he spends it (let us say) upon laying down rails for surface card in some place where surface cars turn out not to be wanted, he has diverted a mass of labor into channels where it gives pleasure to no one. Nevertheless, when he becomes poor through failure of his investment he will be regarded as a victim of undeserved misfortune, whereas the gay spendthrift, who has spent his money philanthropically, will be despised as a fool and a frivolous person. + +All this is only preliminary. I want to say, in all seriousness, that a great deal of harm is being done in the modern world by belief in the virtuousness of work, and that the road to happiness and prosperity lies in an organized diminution of work. + +First of all: what is work? Work is of two kinds: first, altering the position of matter at or near the earth's surface relatively to other such matter; second, telling other people to do so. The first kind is unpleasant and ill paid; the second is pleasant and highly paid. The second kind is capable of indefinite extension: there are not only those who give orders, but those who give advice as to what orders should be given. Usually two opposite kinds of advice are given simultaneously by two organized bodies of men; this is called politics. The skill required for this kind of work is not knowledge of the subjects as to which advice is given, but knowledge of the art of persuasive speaking and writing, i.e. of advertising. + +Throughout Europe, though not in America, there is a third class of men, more respected than either of the classes of workers. There are men who, through ownership of land, are able to make others pay for the privilege of being allowed to exist and to work. These landowners are idle, and I might therefore be expected to praise them. Unfortunately, their idleness is only rendered possible by the industry of others; indeed their desire for comfortable idleness is historically the source of the whole gospel of work. The last thing they have ever wished is that others should follow their example. + +From the beginning of civilization until the Industrial Revolution, a man could, as a rule, produce by hard work little more than was required for the subsistence of himself and his family, although his wife worked at least as hard as he did, and his children added their labor as soon as they were old enough to do so. The small surplus above bare necessaries was not left to those who produced it, but was appropriated by warriors and priests. In times of famine there was no surplus; the warriors and priests, however, still secured as much as at other times, with the result that many of the workers died of hunger. This system persisted in Russia until 1917 [1], and still persists in the East; in England, in spite of the Industrial Revolution, it remained in full force throughout the Napoleonic wars, and until a hundred years ago, when the new class of manufacturers acquired power. In America, the system came to an end with the Revolution, except in the South, where it persisted until the Civil War. A system which lasted so long and ended so recently has naturally left a profound impress upon men's thoughts and opinions. Much that we take for granted about the desirability of work is derived from this system, and, being pre-industrial, is not adapted to the modern world. Modern technique has made it possible for leisure, within limits, to be not the prerogative of small privileged classes, but a right evenly distributed throughout the community. The morality of work is the morality of slaves, and the modern world has no need of slavery. + +It is obvious that, in primitive communities, peasants, left to themselves, would not have parted with the slender surplus upon which the warriors and priests subsisted, but would have either produced less or consumed more. At first, sheer force compelled them to produce and part with the surplus. Gradually, however, it was found possible to induce many of them to accept an ethic according to which it was their duty to work hard, although part of their work went to support others in idleness. By this means the amount of compulsion required was lessened, and the expenses of government were diminished. To this day, 99 per cent of British wage-earners would be genuinely shocked if it were proposed that the King should not have a larger income than a working man. The conception of duty, speaking historically, has been a means used by the holders of power to induce others to live for the interests of their masters rather than for their own. Of course the holders of power conceal this fact from themselves by managing to believe that their interests are identical with the larger interests of humanity. Sometimes this is true; Athenian slave-owners, for instance, employed part of their leisure in making a permanent contribution to civilization which would have been impossible under a just economic system. Leisure is essential to civilization, and in former times leisure for the few was only rendered possible by the labors of the many. But their labors were valuable, not because work is good, but because leisure is good. And with modern technique it would be possible to distribute leisure justly without injury to civilization. + +Modern technique has made it possible to diminish enormously the amount of labor required to secure the necessaries of life for everyone. This was made obvious during the war. At that time all the men in the armed forces, and all the men and women engaged in the production of munitions, all the men and women engaged in spying, war propaganda, or Government offices connected with the war, were withdrawn from productive occupations. In spite of this, the general level of well-being among unskilled wage-earners on the side of the Allies was higher than before or since. The significance of this fact was concealed by finance: borrowing made it appear as if the future was nourishing the present. But that, of course, would have been impossible; a man cannot eat a loaf of bread that does not yet exist. The war showed conclusively that, by the scientific organization of production, it is possible to keep modern populations in fair comfort on a small part of the working capacity of the modern world. If, at the end of the war, the scientific organization, which had been created in order to liberate men for fighting and munition work, had been preserved, and the hours of the week had been cut down to four, all would have been well. Instead of that the old chaos was restored, those whose work was demanded were made to work long hours, and the rest were left to starve as unemployed. Why? Because work is a duty, and a man should not receive wages in proportion to what he has produced, but in proportion to his virtue as exemplified by his industry. + +This is the morality of the Slave State, applied in circumstances totally unlike those in which it arose. No wonder the result has been disastrous. Let us take an illustration. Suppose that, at a given moment, a certain number of people are engaged in the manufacture of pins. They make as many pins as the world needs, working (say) eight hours a day. Someone makes an invention by which the same number of men can make twice as many pins: pins are already so cheap that hardly any more will be bought at a lower price. In a sensible world, everybody concerned in the manufacturing of pins would take to working four hours instead of eight, and everything else would go on as before. But in the actual world this would be thought demoralizing. The men still work eight hours, there are too many pins, some employers go bankrupt, and half the men previously concerned in making pins are thrown out of work. There is, in the end, just as much leisure as on the other plan, but half the men are totally idle while half are still overworked. In this way, it is insured that the unavoidable leisure shall cause misery all round instead of being a universal source of happiness. Can anything more insane be imagined? + +The idea that the poor should have leisure has always been shocking to the rich. In England, in the early nineteenth century, fifteen hours was the ordinary day's work for a man; children sometimes did as much, and very commonly did twelve hours a day. When meddlesome busybodies suggested that perhaps these hours were rather long, they were told that work kept adults from drink and children from mischief. When I was a child, shortly after urban working men had acquired the vote, certain public holidays were established by law, to the great indignation of the upper classes. I remember hearing an old Duchess say: 'What do the poor want with holidays? They ought to work.' People nowadays are less frank, but the sentiment persists, and is the source of much of our economic confusion. + +Let us, for a moment, consider the ethics of work frankly, without superstition. Every human being, of necessity, consumes, in the course of his life, a certain amount of the produce of human labor. Assuming, as we may, that labor is on the whole disagreeable, it is unjust that a man should consume more than he produces. Of course he may provide services rather than commodities, like a medical man, for example; but he should provide something in return for his board and lodging. to this extent, the duty of work must be admitted, but to this extent only. + +I shall not dwell upon the fact that, in all modern societies outside the USSR, many people escape even this minimum amount of work, namely all those who inherit money and all those who marry money. I do not think the fact that these people are allowed to be idle is nearly so harmful as the fact that wage-earners are expected to overwork or starve. + +If the ordinary wage-earner worked four hours a day, there would be enough for everybody and no unemployment -- assuming a certain very moderate amount of sensible organization. This idea shocks the well-to-do, because they are convinced that the poor would not know how to use so much leisure. In America men often work long hours even when they are well off; such men, naturally, are indignant at the idea of leisure for wage-earners, except as the grim punishment of unemployment; in fact, they dislike leisure even for their sons. Oddly enough, while they wish their sons to work so hard as to have no time to be civilized, they do not mind their wives and daughters having no work at all. the snobbish admiration of uselessness, which, in an aristocratic society, extends to both sexes, is, under a plutocracy, confined to women; this, however, does not make it any more in agreement with common sense. + +The wise use of leisure, it must be conceded, is a product of civilization and education. A man who has worked long hours all his life will become bored if he becomes suddenly idle. But without a considerable amount of leisure a man is cut off from many of the best things. There is no longer any reason why the bulk of the population should suffer this deprivation; only a foolish asceticism, usually vicarious, makes us continue to insist on work in excessive quantities now that the need no longer exists. + +In the new creed which controls the government of Russia, while there is much that is very different from the traditional teaching of the West, there are some things that are quite unchanged. The attitude of the governing classes, and especially of those who conduct educational propaganda, on the subject of the dignity of labor, is almost exactly that which the governing classes of the world have always preached to what were called the 'honest poor'. Industry, sobriety, willingness to work long hours for distant advantages, even submissiveness to authority, all these reappear; moreover authority still represents the will of the Ruler of the Universe, Who, however, is now called by a new name, Dialectical Materialism. + +The victory of the proletariat in Russia has some points in common with the victory of the feminists in some other countries. For ages, men had conceded the superior saintliness of women, and had consoled women for their inferiority by maintaining that saintliness is more desirable than power. At last the feminists decided that they would have both, since the pioneers among them believed all that the men had told them about the desirability of virtue, but not what they had told them about the worthlessness of political power. A similar thing has happened in Russia as regards manual work. For ages, the rich and their sycophants have written in praise of 'honest toil', have praised the simple life, have professed a religion which teaches that the poor are much more likely to go to heaven than the rich, and in general have tried to make manual workers believe that there is some special nobility about altering the position of matter in space, just as men tried to make women believe that they derived some special nobility from their sexual enslavement. In Russia, all this teaching about the excellence of manual work has been taken seriously, with the result that the manual worker is more honored than anyone else. What are, in essence, revivalist appeals are made, but not for the old purposes: they are made to secure shock workers for special tasks. Manual work is the ideal which is held before the young, and is the basis of all ethical teaching. + +For the present, possibly, this is all to the good. A large country, full of natural resources, awaits development, and has has to be developed with very little use of credit. In these circumstances, hard work is necessary, and is likely to bring a great reward. But what will happen when the point has been reached where everybody could be comfortable without working long hours? + +In the West, we have various ways of dealing with this problem. We have no attempt at economic justice, so that a large proportion of the total produce goes to a small minority of the population, many of whom do no work at all. Owing to the absence of any central control over production, we produce hosts of things that are not wanted. We keep a large percentage of the working population idle, because we can dispense with their labor by making the others overwork. When all these methods prove inadequate, we have a war: we cause a number of people to manufacture high explosives, and a number of others to explode them, as if we were children who had just discovered fireworks. By a combination of all these devices we manage, though with difficulty, to keep alive the notion that a great deal of severe manual work must be the lot of the average man. + +In Russia, owing to more economic justice and central control over production, the problem will have to be differently solved. the rational solution would be, as soon as the necessaries and elementary comforts can be provided for all, to reduce the hours of labor gradually, allowing a popular vote to decide, at each stage, whether more leisure or more goods were to be preferred. But, having taught the supreme virtue of hard work, it is difficult to see how the authorities can aim at a paradise in which there will be much leisure and little work. It seems more likely that they will find continually fresh schemes, by which present leisure is to be sacrificed to future productivity. I read recently of an ingenious plan put forward by Russian engineers, for making the White Sea and the northern coasts of Siberia warm, by putting a dam across the Kara Sea. An admirable project, but liable to postpone proletarian comfort for a generation, while the nobility of toil is being displayed amid the ice-fields and snowstorms of the Arctic Ocean. This sort of thing, if it happens, will be the result of regarding the virtue of hard work as an end in itself, rather than as a means to a state of affairs in which it is no longer needed. + +The fact is that moving matter about, while a certain amount of it is necessary to our existence, is emphatically not one of the ends of human life. If it were, we should have to consider every navvy superior to Shakespeare. We have been misled in this matter by two causes. One is the necessity of keeping the poor contented, which has led the rich, for thousands of years, to preach the dignity of labor, while taking care themselves to remain undignified in this respect. The other is the new pleasure in mechanism, which makes us delight in the astonishingly clever changes that we can produce on the earth's surface. Neither of these motives makes any great appeal to the actual worker. If you ask him what he thinks the best part of his life, he is not likely to say: 'I enjoy manual work because it makes me feel that I am fulfilling man's noblest task, and because I like to think how much man can transform his planet. It is true that my body demands periods of rest, which I have to fill in as best I may, but I am never so happy as when the morning comes and I can return to the toil from which my contentment springs.' I have never heard working men say this sort of thing. They consider work, as it should be considered, a necessary means to a livelihood, and it is from their leisure that they derive whatever happiness they may enjoy. + +It will be said that, while a little leisure is pleasant, men would not know how to fill their days if they had only four hours of work out of the twenty-four. In so far as this is true in the modern world, it is a condemnation of our civilization; it would not have been true at any earlier period. There was formerly a capacity for light-heartedness and play which has been to some extent inhibited by the cult of efficiency. The modern man thinks that everything ought to be done for the sake of something else, and never for its own sake. Serious-minded persons, for example, are continually condemning the habit of going to the cinema, and telling us that it leads the young into crime. But all the work that goes to producing a cinema is respectable, because it is work, and because it brings a money profit. The notion that the desirable activities are those that bring a profit has made everything topsy-turvy. The butcher who provides you with meat and the baker who provides you with bread are praiseworthy, because they are making money; but when you enjoy the food they have provided, you are merely frivolous, unless you eat only to get strength for your work. Broadly speaking, it is held that getting money is good and spending money is bad. Seeing that they are two sides of one transaction, this is absurd; one might as well maintain that keys are good, but keyholes are bad. Whatever merit there may be in the production of goods must be entirely derivative from the advantage to be obtained by consuming them. The individual, in our society, works for profit; but the social purpose of his work lies in the consumption of what he produces. It is this divorce between the individual and the social purpose of production that makes it so difficult for men to think clearly in a world in which profit-making is the incentive to industry. We think too much of production, and too little of consumption. One result is that we attach too little importance to enjoyment and simple happiness, and that we do not judge production by the pleasure that it gives to the consumer. + +When I suggest that working hours should be reduced to four, I am not meaning to imply that all the remaining time should necessarily be spent in pure frivolity. I mean that four hours' work a day should entitle a man to the necessities and elementary comforts of life, and that the rest of his time should be his to use as he might see fit. It is an essential part of any such social system that education should be carried further than it usually is at present, and should aim, in part, at providing tastes which would enable a man to use leisure intelligently. I am not thinking mainly of the sort of things that would be considered 'highbrow'. Peasant dances have died out except in remote rural areas, but the impulses which caused them to be cultivated must still exist in human nature. The pleasures of urban populations have become mainly passive: seeing cinemas, watching football matches, listening to the radio, and so on. This results from the fact that their active energies are fully taken up with work; if they had more leisure, they would again enjoy pleasures in which they took an active part. + +In the past, there was a small leisure class and a larger working class. The leisure class enjoyed advantages for which there was no basis in social justice; this necessarily made it oppressive, limited its sympathies, and caused it to invent theories by which to justify its privileges. These facts greatly diminished its excellence, but in spite of this drawback it contributed nearly the whole of what we call civilization. It cultivated the arts and discovered the sciences; it wrote the books, invented the philosophies, and refined social relations. Even the liberation of the oppressed has usually been inaugurated from above. Without the leisure class, mankind would never have emerged from barbarism. + +The method of a leisure class without duties was, however, extraordinarily wasteful. None of the members of the class had to be taught to be industrious, and the class as a whole was not exceptionally intelligent. The class might produce one Darwin, but against him had to be set tens of thousands of country gentlemen who never thought of anything more intelligent than fox-hunting and punishing poachers. At present, the universities are supposed to provide, in a more systematic way, what the leisure class provided accidentally and as a by-product. This is a great improvement, but it has certain drawbacks. University life is so different from life in the world at large that men who live in academic milieu tend to be unaware of the preoccupations and problems of ordinary men and women; moreover their ways of expressing themselves are usually such as to rob their opinions of the influence that they ought to have upon the general public. Another disadvantage is that in universities studies are organized, and the man who thinks of some original line of research is likely to be discouraged. Academic institutions, therefore, useful as they are, are not adequate guardians of the interests of civilization in a world where everyone outside their walls is too busy for unutilitarian pursuits. + +In a world where no one is compelled to work more than four hours a day, every person possessed of scientific curiosity will be able to indulge it, and every painter will be able to paint without starving, however excellent his pictures may be. Young writers will not be obliged to draw attention to themselves by sensational pot-boilers, with a view to acquiring the economic independence needed for monumental works, for which, when the time at last comes, they will have lost the taste and capacity. Men who, in their professional work, have become interested in some phase of economics or government, will be able to develop their ideas without the academic detachment that makes the work of university economists often seem lacking in reality. Medical men will have the time to learn about the progress of medicine, teachers will not be exasperatedly struggling to teach by routine methods things which they learnt in their youth, which may, in the interval, have been proved to be untrue. + +Above all, there will be happiness and joy of life, instead of frayed nerves, weariness, and dyspepsia. The work exacted will be enough to make leisure delightful, but not enough to produce exhaustion. Since men will not be tired in their spare time, they will not demand only such amusements as are passive and vapid. At least one per cent will probably devote the time not spent in professional work to pursuits of some public importance, and, since they will not depend upon these pursuits for their livelihood, their originality will be unhampered, and there will be no need to conform to the standards set by elderly pundits. But it is not only in these exceptional cases that the advantages of leisure will appear. Ordinary men and women, having the opportunity of a happy life, will become more kindly and less persecuting and less inclined to view others with suspicion. The taste for war will die out, partly for this reason, and partly because it will involve long and severe work for all. Good nature is, of all moral qualities, the one that the world needs most, and good nature is the result of ease and security, not of a life of arduous struggle. Modern methods of production have given us the possibility of ease and security for all; we have chosen, instead, to have overwork for some and starvation for others. Hitherto we have continued to be as energetic as we were before there were machines; in this we have been foolish, but there is no reason to go on being foolish forever. + +[1] Since then, members of the Communist Party have succeeded to this privilege of the warriors and priests. diff --git a/wrt/node_modules/wordwrap/test/wrap.js b/wrt/node_modules/wordwrap/test/wrap.js new file mode 100644 index 0000000..0cfb76d --- /dev/null +++ b/wrt/node_modules/wordwrap/test/wrap.js @@ -0,0 +1,31 @@ +var assert = require('assert'); +var wordwrap = require('wordwrap'); + +var fs = require('fs'); +var idleness = fs.readFileSync(__dirname + '/idleness.txt', 'utf8'); + +exports.stop80 = function () { + var lines = wordwrap(80)(idleness).split(/\n/); + var words = idleness.split(/\s+/); + + lines.forEach(function (line) { + assert.ok(line.length <= 80, 'line > 80 columns'); + var chunks = line.match(/\S/) ? line.split(/\s+/) : []; + assert.deepEqual(chunks, words.splice(0, chunks.length)); + }); +}; + +exports.start20stop60 = function () { + var lines = wordwrap(20, 100)(idleness).split(/\n/); + var words = idleness.split(/\s+/); + + lines.forEach(function (line) { + assert.ok(line.length <= 100, 'line > 100 columns'); + var chunks = line + .split(/\s+/) + .filter(function (x) { return x.match(/\S/) }) + ; + assert.deepEqual(chunks, words.splice(0, chunks.length)); + assert.deepEqual(line.slice(0, 20), new Array(20 + 1).join(' ')); + }); +}; diff --git a/wrt/node_modules/y18n/LICENSE b/wrt/node_modules/y18n/LICENSE new file mode 100644 index 0000000..3c157f0 --- /dev/null +++ b/wrt/node_modules/y18n/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2015, Contributors + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/wrt/node_modules/y18n/README.md b/wrt/node_modules/y18n/README.md new file mode 100644 index 0000000..9859458 --- /dev/null +++ b/wrt/node_modules/y18n/README.md @@ -0,0 +1,91 @@ +# y18n + +[![Build Status][travis-image]][travis-url] +[![Coverage Status][coveralls-image]][coveralls-url] +[![NPM version][npm-image]][npm-url] +[![js-standard-style][standard-image]][standard-url] + +The bare-bones internationalization library used by yargs. + +Inspired by [i18n](https://www.npmjs.com/package/i18n). + +## Examples + +_simple string translation:_ + +```js +var __ = require('y18n').__ + +console.log(__('my awesome string %s', 'foo')) +``` + +output: + +`my awesome string foo` + +_pluralization support:_ + +```js +var __n = require('y18n').__n + +console.log(__n('one fish %s', '%d fishes %s', 2, 'foo')) +``` + +output: + +`2 fishes foo` + +## JSON Language Files + +The JSON language files should be stored in a `./locales` folder. +File names correspond to locales, e.g., `en.json`, `pirate.json`. + +When strings are observed for the first time they will be +added to the JSON file corresponding to the current locale. + +## Methods + +### require('y18n')(config) + +Create an instance of y18n with the config provided, options include: + +* `directory`: the locale directory, default `./locales`. +* `updateFiles`: should newly observed strings be updated in file, default `true`. +* `locale`: what locale should be used. +* `fallbackToLanguage`: should fallback to a language-only file (e.g. `en.json`) + be allowed if a file matching the locale does not exist (e.g. `en_US.json`), + default `true`. + +### y18n.\_\_(str, arg, arg, arg) + +Print a localized string, `%s` will be replaced with `arg`s. + +### y18n.\_\_n(singularString, pluralString, count, arg, arg, arg) + +Print a localized string with appropriate pluralization. If `%d` is provided +in the string, the `count` will replace this placeholder. + +### y18n.setLocale(str) + +Set the current locale being used. + +### y18n.getLocale() + +What locale is currently being used? + +### y18n.updateLocale(obj) + +Update the current locale with the key value pairs in `obj`. + +## License + +ISC + +[travis-url]: https://travis-ci.org/yargs/y18n +[travis-image]: https://img.shields.io/travis/yargs/y18n.svg +[coveralls-url]: https://coveralls.io/github/yargs/y18n +[coveralls-image]: https://img.shields.io/coveralls/yargs/y18n.svg +[npm-url]: https://npmjs.org/package/y18n +[npm-image]: https://img.shields.io/npm/v/y18n.svg +[standard-image]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg +[standard-url]: https://github.com/feross/standard diff --git a/wrt/node_modules/y18n/index.js b/wrt/node_modules/y18n/index.js new file mode 100644 index 0000000..91b159e --- /dev/null +++ b/wrt/node_modules/y18n/index.js @@ -0,0 +1,172 @@ +var fs = require('fs') +var path = require('path') +var util = require('util') + +function Y18N (opts) { + // configurable options. + opts = opts || {} + this.directory = opts.directory || './locales' + this.updateFiles = typeof opts.updateFiles === 'boolean' ? opts.updateFiles : true + this.locale = opts.locale || 'en' + this.fallbackToLanguage = typeof opts.fallbackToLanguage === 'boolean' ? opts.fallbackToLanguage : true + + // internal stuff. + this.cache = {} + this.writeQueue = [] +} + +Y18N.prototype.__ = function () { + var args = Array.prototype.slice.call(arguments) + var str = args.shift() + var cb = function () {} // start with noop. + + if (typeof args[args.length - 1] === 'function') cb = args.pop() + cb = cb || function () {} // noop. + + if (!this.cache[this.locale]) this._readLocaleFile() + + // we've observed a new string, update the language file. + if (!this.cache[this.locale][str] && this.updateFiles) { + this.cache[this.locale][str] = str + + // include the current directory and locale, + // since these values could change before the + // write is performed. + this._enqueueWrite([this.directory, this.locale, cb]) + } else { + cb() + } + + return util.format.apply(util, [this.cache[this.locale][str] || str].concat(args)) +} + +Y18N.prototype._enqueueWrite = function (work) { + this.writeQueue.push(work) + if (this.writeQueue.length === 1) this._processWriteQueue() +} + +Y18N.prototype._processWriteQueue = function () { + var _this = this + var work = this.writeQueue[0] + + // destructure the enqueued work. + var directory = work[0] + var locale = work[1] + var cb = work[2] + + var languageFile = this._resolveLocaleFile(directory, locale) + var serializedLocale = JSON.stringify(this.cache[locale], null, 2) + + fs.writeFile(languageFile, serializedLocale, 'utf-8', function (err) { + _this.writeQueue.shift() + if (_this.writeQueue.length > 0) _this._processWriteQueue() + cb(err) + }) +} + +Y18N.prototype._readLocaleFile = function () { + var localeLookup = {} + var languageFile = this._resolveLocaleFile(this.directory, this.locale) + + try { + localeLookup = JSON.parse(fs.readFileSync(languageFile, 'utf-8')) + } catch (err) { + if (err instanceof SyntaxError) { + err.message = 'syntax error in ' + languageFile + } + + if (err.code === 'ENOENT') localeLookup = {} + else throw err + } + + this.cache[this.locale] = localeLookup +} + +Y18N.prototype._resolveLocaleFile = function (directory, locale) { + var file = path.resolve(directory, './', locale + '.json') + if (this.fallbackToLanguage && !this._fileExistsSync(file) && ~locale.lastIndexOf('_')) { + // attempt fallback to language only + var languageFile = path.resolve(directory, './', locale.split('_')[0] + '.json') + if (this._fileExistsSync(languageFile)) file = languageFile + } + return file +} + +// this only exists because fs.existsSync() "will be deprecated" +// see https://nodejs.org/api/fs.html#fs_fs_existssync_path +Y18N.prototype._fileExistsSync = function (file) { + try { + return fs.statSync(file).isFile() + } catch (err) { + return false + } +} + +Y18N.prototype.__n = function () { + var args = Array.prototype.slice.call(arguments) + var singular = args.shift() + var plural = args.shift() + var quantity = args.shift() + + var cb = function () {} // start with noop. + if (typeof args[args.length - 1] === 'function') cb = args.pop() + + if (!this.cache[this.locale]) this._readLocaleFile() + + var str = quantity === 1 ? singular : plural + if (this.cache[this.locale][singular]) { + str = this.cache[this.locale][singular][quantity === 1 ? 'one' : 'other'] + } + + // we've observed a new string, update the language file. + if (!this.cache[this.locale][singular] && this.updateFiles) { + this.cache[this.locale][singular] = { + one: singular, + other: plural + } + + // include the current directory and locale, + // since these values could change before the + // write is performed. + this._enqueueWrite([this.directory, this.locale, cb]) + } else { + cb() + } + + // if a %d placeholder is provided, add quantity + // to the arguments expanded by util.format. + var values = [str] + if (~str.indexOf('%d')) values.push(quantity) + + return util.format.apply(util, values.concat(args)) +} + +Y18N.prototype.setLocale = function (locale) { + this.locale = locale +} + +Y18N.prototype.getLocale = function () { + return this.locale +} + +Y18N.prototype.updateLocale = function (obj) { + if (!this.cache[this.locale]) this._readLocaleFile() + + for (var key in obj) { + this.cache[this.locale][key] = obj[key] + } +} + +module.exports = function (opts) { + var y18n = new Y18N(opts) + + // bind all functions to y18n, so that + // they can be used in isolation. + for (var key in y18n) { + if (typeof y18n[key] === 'function') { + y18n[key] = y18n[key].bind(y18n) + } + } + + return y18n +} diff --git a/wrt/node_modules/y18n/package.json b/wrt/node_modules/y18n/package.json new file mode 100644 index 0000000..ec731cf --- /dev/null +++ b/wrt/node_modules/y18n/package.json @@ -0,0 +1,105 @@ +{ + "_args": [ + [ + { + "raw": "y18n@^3.0.0", + "scope": null, + "escapedName": "y18n", + "name": "y18n", + "rawSpec": "^3.0.0", + "spec": ">=3.0.0 <4.0.0", + "type": "range" + }, + "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/yargs" + ] + ], + "_from": "y18n@>=3.0.0 <4.0.0", + "_id": "y18n@3.2.1", + "_inCache": true, + "_location": "/y18n", + "_nodeVersion": "3.2.0", + "_npmOperationalInternal": { + "host": "packages-13-west.internal.npmjs.com", + "tmp": "tmp/y18n-3.2.1.tgz_1458191070611_0.9606689948122948" + }, + "_npmUser": { + "name": "bcoe", + "email": "ben@npmjs.com" + }, + "_npmVersion": "3.3.0", + "_phantomChildren": {}, + "_requested": { + "raw": "y18n@^3.0.0", + "scope": null, + "escapedName": "y18n", + "name": "y18n", + "rawSpec": "^3.0.0", + "spec": ">=3.0.0 <4.0.0", + "type": "range" + }, + "_requiredBy": [ + "/yargs" + ], + "_resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "_shasum": "6d15fba884c08679c0d77e88e7759e811e07fa41", + "_shrinkwrap": null, + "_spec": "y18n@^3.0.0", + "_where": "/home/sources/5.0/crosswalk-tizen/wrt/node_modules/yargs", + "author": { + "name": "Ben Coe", + "email": "ben@npmjs.com" + }, + "bugs": { + "url": "https://github.com/yargs/y18n/issues" + }, + "dependencies": {}, + "description": "the bare-bones internationalization library used by yargs", + "devDependencies": { + "chai": "^3.4.1", + "coveralls": "^2.11.6", + "mocha": "^2.3.4", + "nyc": "^6.1.1", + "rimraf": "^2.5.0", + "standard": "^5.4.1" + }, + "directories": {}, + "dist": { + "shasum": "6d15fba884c08679c0d77e88e7759e811e07fa41", + "tarball": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz" + }, + "files": [ + "index.js" + ], + "gitHead": "34d6ad7bfeac67721ccbcf3bbcc761f33d787c90", + "homepage": "https://github.com/yargs/y18n", + "keywords": [ + "i18n", + "internationalization", + "yargs" + ], + "license": "ISC", + "main": "index.js", + "maintainers": [ + { + "name": "bcoe", + "email": "ben@npmjs.com" + }, + { + "name": "nexdrew", + "email": "andrew@npmjs.com" + } + ], + "name": "y18n", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/yargs/y18n.git" + }, + "scripts": { + "coverage": "nyc report --reporter=text-lcov | coveralls", + "pretest": "standard", + "test": "nyc mocha" + }, + "version": "3.2.1" +} diff --git a/wrt/node_modules/yargs/CHANGELOG.md b/wrt/node_modules/yargs/CHANGELOG.md new file mode 100644 index 0000000..68eb6d3 --- /dev/null +++ b/wrt/node_modules/yargs/CHANGELOG.md @@ -0,0 +1,429 @@ +## Change Log + +### v3.19.0 (2015/08/14 05:12 +00:00) +- [#224](https://github.com/bcoe/yargs/pull/224) added Portuguese translation (@codemonkey3045) + +### v3.18.1 (2015/08/12 05:53 +00:00) + +- [#228](https://github.com/bcoe/yargs/pull/228) notes about embedding yargs in Electron (@etiktin) +- [#223](https://github.com/bcoe/yargs/pull/223) make booleans work in config files (@sgentle) + +### v3.18.0 (2015/08/06 20:05 +00:00) +- [#222](https://github.com/bcoe/yargs/pull/222) updates fr locale (@nexdrew) +- [#221](https://github.com/bcoe/yargs/pull/221) adds missing locale strings (@nexdrew) +- [#220](https://github.com/bcoe/yargs/pull/220) adds es locale (@zkat) + +### v3.17.1 (2015/08/02 19:35 +00:00) +- [#218](https://github.com/bcoe/yargs/pull/218) upgrades nyc (@bcoe) + +### v3.17.0 (2015/08/02 18:39 +00:00) +- [#217](https://github.com/bcoe/yargs/pull/217) sort methods in README.md (@nexdrew) +- [#215](https://github.com/bcoe/yargs/pull/215) adds fr locale (@LoicMahieu) + +### v3.16.0 (2015/07/30 04:35 +00:00) +- [#210](https://github.com/bcoe/yargs/pull/210) adds i18n support to yargs (@bcoe) +- [#209](https://github.com/bcoe/yargs/pull/209) adds choices type to yargs (@nexdrew) +- [#207](https://github.com/bcoe/yargs/pull/207) pretty new shields from shields.io (@SimenB) +- [#208](https://github.com/bcoe/yargs/pull/208) improvements to README.md (@nexdrew) +- [#205](https://github.com/bcoe/yargs/pull/205) faster build times on Travis (@ChristianMurphy) + +### v3.15.0 (2015/07/06 06:01 +00:00) +- [#197](https://github.com/bcoe/yargs/pull/197) tweaks to how errors bubble up from parser.js (@bcoe) +- [#193](https://github.com/bcoe/yargs/pull/193) upgraded nyc, reporting now happens by default (@bcoe) + +### v3.14.0 (2015/06/28 02:12 +00:00) + +- [#192](https://github.com/bcoe/yargs/pull/192) standard style nits (@bcoe) +- [#190](https://github.com/bcoe/yargs/pull/190) allow for hidden commands, e.g., + .completion('completion', false) (@tschaub) + +### v3.13.0 (2015/06/24 04:12 +00:00) + +- [#187](https://github.com/bcoe/yargs/pull/187) completion now behaves differently + if it is being run in the context of a command (@tschaub) +- [#186](https://github.com/bcoe/yargs/pull/186) if no matches are found for a completion + default to filename completion (@tschaub) + +### v3.12.0 (2015/06/19 03:23 +00:00) +- [#183](https://github.com/bcoe/yargs/pull/183) don't complete commands if they've already been completed (@tschaub) +- [#181](https://github.com/bcoe/yargs/pull/181) various fixes for completion. (@bcoe, @tschaub) +- [#182](https://github.com/bcoe/yargs/pull/182) you can now set a maximum # of of required arguments (@bcoe) + +### v3.11.0 (2015/06/15 05:15 +00:00) + +- [#173](https://github.com/bcoe/yargs/pull/173) update standard, window-size, chai (@bcoe) +- [#171](https://github.com/bcoe/yargs/pull/171) a description can now be set + when providing a config option. (@5c077yP) + +### v3.10.0 (2015/05/29 04:25 +00:00) + +- [#165](https://github.com/bcoe/yargs/pull/165) expose yargs.terminalWidth() thanks @ensonic (@bcoe) +- [#164](https://github.com/bcoe/yargs/pull/164) better array handling thanks @getify (@bcoe) + +### v3.9.1 (2015/05/20 05:14 +00:00) +- [b6662b6](https://github.com/bcoe/yargs/commit/b6662b6774cfeab4876f41ec5e2f67b7698f4e2f) clarify .config() docs (@linclark) +- [0291360](https://github.com/bcoe/yargs/commit/02913606285ce31ce81d7f12c48d8a3029776ec7) fixed tests, switched to nyc for coverage, fixed security issue, added Lin as collaborator (@bcoe) + +### v3.9.0 (2015/05/10 18:32 +00:00) +- [#157](https://github.com/bcoe/yargs/pull/157) Merge pull request #157 from bcoe/command-yargs. allows handling of command specific arguments. Thanks for the suggestion @ohjames (@bcoe) +- [#158](https://github.com/bcoe/yargs/pull/158) Merge pull request #158 from kemitchell/spdx-license. Update license format (@kemitchell) + +### v3.8.0 (2015/04/24 23:10 +00:00) +- [#154](https://github.com/bcoe/yargs/pull/154) showHelp's method signature was misleading fixes #153 (@bcoe) +- [#151](https://github.com/bcoe/yargs/pull/151) refactor yargs' table layout logic to use new helper library (@bcoe) +- [#150](https://github.com/bcoe/yargs/pull/150) Fix README example in argument requirements (@annonymouse) + +### v3.7.2 (2015/04/13 11:52 -07:00) + +* [679fbbf](https://github.com/bcoe/yargs/commit/679fbbf55904030ccee8a2635e8e5f46551ab2f0) updated yargs to use the [standard](https://github.com/feross/standard) style guide (agokjr) +* [22382ee](https://github.com/bcoe/yargs/commit/22382ee9f5b495bc2586c1758cd1091cec3647f9 various bug fixes for $0 (@nylen) + +### v3.7.1 (2015/04/10 11:06 -07:00) + +* [89e1992](https://github.com/bcoe/yargs/commit/89e1992a004ba73609b5f9ee6890c4060857aba4) detect iojs bin along with node bin. (@bcoe) +* [755509e](https://github.com/bcoe/yargs/commit/755509ea90041e5f7833bba3b8c5deffe56f0aab) improvements to example documentation in README.md (@rstacruz) +* [0d2dfc8](https://github.com/bcoe/yargs/commit/0d2dfc822a43418242908ad97ddd5291a1b35dc6) showHelp() no longer requires that .argv has been called (@bcoe) + +### v3.7.0 (2015/04/04 02:29 -07:00) + +* [56cbe2d](https://github.com/bcoe/yargs/commit/56cbe2ddd33dc176dcbf97ba40559864a9f114e4) make .requiresArg() work with type hints. (@bcoe). +* [2f5d562](https://github.com/bcoe/yargs/commit/2f5d5624f736741deeedf6a664d57bc4d857bdd0) serialize arrays and objects in usage strings. (@bcoe). +* [5126304](https://github.com/bcoe/yargs/commit/5126304dd18351fc28f10530616fdd9361e0af98) be more lenient about alias/primary key ordering in chaining API. (@bcoe) + +### v3.6.0 (2015/03/21 01:00 +00:00) +- [4e24e22](https://github.com/bcoe/yargs/commit/4e24e22e6a195e55ab943ede704a0231ac33b99c) support for .js configuration files. (@pirxpilot) + +### v3.5.4 (2015/03/12 05:56 +00:00) +- [c16cc08](https://github.com/bcoe/yargs/commit/c16cc085501155cf7fd853ccdf8584b05ab92b78) message for non-option arguments is now optional, thanks to (@raine) + +### v3.5.3 (2015/03/09 06:14 +00:00) +- [870b428](https://github.com/bcoe/yargs/commit/870b428cf515d560926ca392555b7ad57dba9e3d) completion script was missing in package.json (@bcoe) + +### v3.5.2 (2015/03/09 06:11 +00:00) +- [58a4b24](https://github.com/bcoe/yargs/commit/58a4b2473ebbb326713d522be53e32d3aabb08d2) parse was being called multiple times, resulting in strange behavior (@bcoe) + +### v3.5.1 (2015/03/09 04:55 +00:00) +- [4e588e0](https://github.com/bcoe/yargs/commit/4e588e055afbeb9336533095f051496e3977f515) accidentally left testing logic in (@bcoe) + +### v3.5.0 (2015/03/09 04:49 +00:00) +- [718bacd](https://github.com/bcoe/yargs/commit/718bacd81b9b44f786af76b2afe491fe06274f19) added support for bash completions see #4 (@bcoe) +- [a192882](https://github.com/bcoe/yargs/commit/a19288270fc431396c42af01125eeb4443664528) downgrade to mocha 2.1.0 until https://github.com/mochajs/mocha/issues/1585 can be sorted out (@bcoe) + +### v3.4.7 (2015/03/09 04:09 +00:00) +- [9845e5c](https://github.com/bcoe/yargs/commit/9845e5c1a9c684ba0be3f0bfb40e7b62ab49d9c8) the Argv singleton was not being updated when manually parsing arguments, fixes #114 (@bcoe) + +### v3.4.6 (2015/03/09 04:01 +00:00) +- [45b4c80](https://github.com/bcoe/yargs/commit/45b4c80b890d02770b0a94f326695a8a566e8fe9) set placeholders for all keys fixes #115 (@bcoe) + +### v3.4.5 (2015/03/01 20:31 +00:00) +- [a758e0b](https://github.com/bcoe/yargs/commit/a758e0b2556184f067cf3d9c4ef886d39817ebd2) fix for count consuming too many arguments (@bcoe) + +### v3.4.4 (2015/02/28 04:52 +00:00) +- [0476af7](https://github.com/bcoe/yargs/commit/0476af757966acf980d998b45108221d4888cfcb) added nargs feature, allowing you to specify the number of arguments after an option (@bcoe) +- [092477d](https://github.com/bcoe/yargs/commit/092477d7ab3efbf0ba11cede57f7d8cfc70b024f) updated README with full example of v3.0 API (@bcoe) + +### v3.3.3 (2015/02/28 04:23 +00:00) +- [0c4b769](https://github.com/bcoe/yargs/commit/0c4b769516cd8d93a7c4e5e675628ae0049aa9a8) remove string dependency, which conflicted with other libraries see #106 (@bcoe) + +### v3.3.2 (2015/02/28 04:11 +00:00) +- [2a98906](https://github.com/bcoe/yargs/commit/2a9890675821c0e7a12f146ce008b0562cb8ec9a) add $0 to epilog (@schnittstabil) + +### v3.3.1 (2015/02/24 03:28 +00:00) +- [ad485ce](https://github.com/bcoe/yargs/commit/ad485ce748ebdfce25b88ef9d6e83d97a2f68987) fix for applying defaults to camel-case args (@bcoe) + +### v3.3.0 (2015/02/24 00:49 +00:00) +- [8bfe36d](https://github.com/bcoe/yargs/commit/8bfe36d7fb0f93a799ea3f4c756a7467c320f8c0) fix and document restart() command, as a tool for building nested CLIs (@bcoe) + +### v3.2.1 (2015/02/22 05:45 +00:00) +- [49a6d18](https://github.com/bcoe/yargs/commit/49a6d1822a4ef9b1ea6f90cc366be60912628885) you can now provide a function that generates a default value (@bcoe) + +### v3.2.0 (2015/02/22 05:24 +00:00) +- [7a55886](https://github.com/bcoe/yargs/commit/7a55886c9343cf71a20744ca5cdd56d2ea7412d5) improvements to yargs two-column text layout (@bcoe) +- [b6ab513](https://github.com/bcoe/yargs/commit/b6ab5136a4c3fa6aa496f6b6360382e403183989) Tweak NPM version badge (@nylen) + +### v3.1.0 (2015/02/19 19:37 +00:00) +- [9bd2379](https://github.com/bcoe/yargs/commit/9bd237921cf1b61fd9f32c0e6d23f572fc225861) version now accepts a function, making it easy to load version #s from a package.json (@bcoe) + +### v3.0.4 (2015/02/14 01:40 +00:00) +- [0b7c19b](https://github.com/bcoe/yargs/commit/0b7c19beaecb747267ca4cc10e5cb2a8550bc4b7) various fixes for dot-notation handling (@bcoe) + +### v3.0.3 (2015/02/14 00:59 +00:00) +- [c3f35e9](https://github.com/bcoe/yargs/commit/c3f35e99bd5a0d278073fcadd95e2d778616cc17) make sure dot-notation is applied to aliases (@bcoe) + +### 3.0.2 (2015/02/13 16:50 +00:00) +- [74c8967](https://github.com/bcoe/yargs/commit/74c8967c340c204a0a7edf8a702b6f46c2705435) document epilog shorthand of epilogue. (@bcoe) +- [670110f](https://github.com/bcoe/yargs/commit/670110fc01bedc4831b6fec6afac54517d5a71bc) any non-truthy value now causes check to fail see #76 (@bcoe) +- [0d8f791](https://github.com/bcoe/yargs/commit/0d8f791a33c11ced4cd431ea8d3d3a337d456b56) finished implementing my wish-list of fetures for yargs 3.0. see #88 (@bcoe) +- [5768447](https://github.com/bcoe/yargs/commit/5768447447c4c8e8304f178846206ce86540f063) fix coverage. (@bcoe) +- [82e793f](https://github.com/bcoe/yargs/commit/82e793f3f61c41259eaacb67f0796aea2cf2aaa0) detect console width and perform word-wrapping. (@bcoe) +- [67476b3](https://github.com/bcoe/yargs/commit/67476b37eea07fee55f23f35b9e0c7d76682b86d) refactor two-column table layout so that we can use it for examples and usage (@bcoe) +- [4724cdf](https://github.com/bcoe/yargs/commit/4724cdfcc8e37ae1ca3dcce9d762f476e9ef4bb4) major refactor of index.js, in prep for 3.x release. (@bcoe) + +### v2.3.0 (2015/02/08 20:41 +00:00) +- [d824620](https://github.com/bcoe/yargs/commit/d824620493df4e63664af1fe320764dd1a9244e6) allow for undefined boolean defaults (@ashi009) + +### v2.2.0 (2015/02/08 20:07 +00:00) +- [d6edd98](https://github.com/bcoe/yargs/commit/d6edd9848826e7389ed1393858c45d03961365fd) in-prep for further refactoring, and a 3.x release I've shuffled some things around and gotten test-coverage to 100%. (@bcoe) + +### v2.1.2 (2015/02/08 06:05 +00:00) +- [d640745](https://github.com/bcoe/yargs/commit/d640745a7b9f8d476e0223879d056d18d9c265c4) switch to path.relative (@bcoe) +- [3bfd41f](https://github.com/bcoe/yargs/commit/3bfd41ff262a041f29d828b88936a79c63cad594) remove mocha.opts. (@bcoe) +- [47a2f35](https://github.com/bcoe/yargs/commit/47a2f357091db70903a402d6765501c1d63f15fe) document using .string('_') for string ids. see #56 (@bcoe) +- [#57](https://github.com/bcoe/yargs/pull/57) Merge pull request #57 from eush77/option-readme (@eush77) + +### v2.1.1 (2015/02/06 08:08 +00:00) +- [01c6c61](https://github.com/bcoe/yargs/commit/01c6c61d67b4ebf88f41f0b32a345ec67f0ac17d) fix for #71, 'newAliases' of undefined (@bcoe) + +### v2.1.0 (2015/02/06 07:59 +00:00) +- [6a1a3fa](https://github.com/bcoe/yargs/commit/6a1a3fa731958e26ccd56885f183dd8985cc828f) try to guess argument types, and apply sensible defaults see #73 (@bcoe) + +### v2.0.1 (2015/02/06 07:54 +00:00) +- [96a06b2](https://github.com/bcoe/yargs/commit/96a06b2650ff1d085a52b7328d8bba614c20cc12) Fix for strange behavior with --sort option, see #51 (@bcoe) + +### v2.0.0 (2015/02/06 07:45 +00:00) +- [0250517](https://github.com/bcoe/yargs/commit/0250517c9643e53f431b824e8ccfa54937414011) - [108fb84](https://github.com/bcoe/yargs/commit/108fb8409a3a63dcaf99d917fe4dfcfaa1de236d) fixed bug with boolean parsing, when bools separated by = see #66 (@bcoe) +- [a465a59](https://github.com/bcoe/yargs/commit/a465a5915f912715738de890982e4f8395958b10) Add `files` field to the package.json (@shinnn) +- [31043de](https://github.com/bcoe/yargs/commit/31043de7a38a17c4c97711f1099f5fb164334db3) fix for yargs.argv having the same keys added multiple times see #63 (@bcoe) +- [2d68c5b](https://github.com/bcoe/yargs/commit/2d68c5b91c976431001c4863ce47c9297850f1ad) Disable process.exit calls using .exitProcess(false) (@cianclarke) +- [45da9ec](https://github.com/bcoe/yargs/commit/45da9ec4c55a7bd394721bc6a1db0dabad7bc52a) Mention .option in README (@eush77) + +### v1.3.2 (2014/10/06 21:56 +00:00) +- [b8d3472](https://github.com/bcoe/yargs/commit/b8d34725482e5821a3cc809c0df71378f282f526) 1.3.2 (@chevex) + +### list (2014/08/30 18:41 +00:00) +- [fbc777f](https://github.com/bcoe/yargs/commit/fbc777f416eeefd37c84e44d27d7dfc7c1925721) Now that yargs is the successor to optimist, I'm changing the README language to be more universal. Pirate speak isn't very accessible to non-native speakers. (@chevex) +- [a54d068](https://github.com/bcoe/yargs/commit/a54d0682ae2efc2394d407ab171cc8a8bbd135ea) version output will not print extra newline (@boneskull) +- [1cef5d6](https://github.com/bcoe/yargs/commit/1cef5d62a9d6d61a3948a49574892e01932cc6ae) Added contributors section to package.json (@chrisn) +- [cc295c0](https://github.com/bcoe/yargs/commit/cc295c0a80a2de267e0155b60d315fc4b6f7c709) Added 'require' and 'required' as synonyms for 'demand' (@chrisn) +- [d0bf951](https://github.com/bcoe/yargs/commit/d0bf951d949066b6280101ed606593d079ee15c8) Updating minimist. (@chevex) +- [c15f8e7](https://github.com/bcoe/yargs/commit/c15f8e7f245b261e542cf205ce4f4313630cbdb4) Fix #31 (bad interaction between camelCase options and strict mode) (@nylen) +- [d991b9b](https://github.com/bcoe/yargs/commit/d991b9be687a68812dee1e3b185ba64b7778b82d) Added .help() and .version() methods (@chrisn) +- [e8c8aa4](https://github.com/bcoe/yargs/commit/e8c8aa46268379357cb11e9fc34b8c403037724b) Added .showHelpOnFail() method (@chrisn) +- [e855af4](https://github.com/bcoe/yargs/commit/e855af4a933ea966b5bbdd3c4c6397a4bac1a053) Allow boolean flag with .demand() (@chrisn) +- [14dbec2](https://github.com/bcoe/yargs/commit/14dbec24fb7380683198e2b20c4deb8423e64bea) Fixes issue #22. Arguments are no longer printed to the console when using .config. (@chevex) +- [bef74fc](https://github.com/bcoe/yargs/commit/bef74fcddc1544598a804f80d0a3728459f196bf) Informing users that Yargs is the official optimist successor. (@chevex) +- [#24](https://github.com/bcoe/yargs/pull/24) Merge pull request #24 from chrisn/strict (@chrisn) +- [889a2b2](https://github.com/bcoe/yargs/commit/889a2b28eb9768801b05163360a470d0fd6c8b79) Added requiresArg option, for options that require values (@chrisn) +- [eb16369](https://github.com/bcoe/yargs/commit/eb163692262be1fe80b992fd8803d5923c5a9b18) Added .strict() method, to report error if unknown arguments are given (@chrisn) +- [0471c3f](https://github.com/bcoe/yargs/commit/0471c3fd999e1ad4e6cded88b8aa02013b66d14f) Changed optimist to yargs in usage-options.js example (@chrisn) +- [5c88f74](https://github.com/bcoe/yargs/commit/5c88f74e3cf031b17c54b4b6606c83e485ff520e) Change optimist to yargs in examples (@chrisn) +- [66f12c8](https://github.com/bcoe/yargs/commit/66f12c82ba3c943e4de8ca862980e835da8ecb3a) Fix a couple of bad interactions between aliases and defaults (@nylen) +- [8fa1d80](https://github.com/bcoe/yargs/commit/8fa1d80f14b03eb1f2898863a61f1d1615bceb50) Document second argument of usage(message, opts) (@Gobie) +- [56e6528](https://github.com/bcoe/yargs/commit/56e6528cf674ff70d63083fb044ff240f608448e) For "--some-option", also set argv.someOption (@nylen) +- [ed5f6d3](https://github.com/bcoe/yargs/commit/ed5f6d33f57ad1086b11c91b51100f7c6c7fa8ee) Finished porting unit tests to Mocha. (@chevex) + +### v1.0.15 (2014/02/05 23:18 +00:00) +- [e2b1fc0](https://github.com/bcoe/yargs/commit/e2b1fc0c4a59cf532ae9b01b275e1ef57eeb64d2) 1.0.15 update to badges (@chevex) + +### v1.0.14 (2014/02/05 23:17 +00:00) +- [f33bbb0](https://github.com/bcoe/yargs/commit/f33bbb0f00fe18960f849cc8e15a7428a4cd59b8) Revert "Fixed issue which caused .demand function not to work correctly." (@chevex) + +### v1.0.13 (2014/02/05 22:13 +00:00) +- [6509e5e](https://github.com/bcoe/yargs/commit/6509e5e7dee6ef1a1f60eea104be0faa1a045075) Fixed issue which caused .demand function not to work correctly. (@chevex) + +### v1.0.12 (2013/12/13 00:09 +00:00) +- [05eb267](https://github.com/bcoe/yargs/commit/05eb26741c9ce446b33ff006e5d33221f53eaceb) 1.0.12 (@chevex) + +### v1.0.11 (2013/12/13 00:07 +00:00) +- [c1bde46](https://github.com/bcoe/yargs/commit/c1bde46e37318a68b87d17a50c130c861d6ce4a9) 1.0.11 (@chevex) + +### v1.0.10 (2013/12/12 23:57 +00:00) +- [dfebf81](https://github.com/bcoe/yargs/commit/dfebf8164c25c650701528ee581ca483a99dc21c) Fixed formatting in README (@chevex) + +### v1.0.9 (2013/12/12 23:47 +00:00) +- [0b4e34a](https://github.com/bcoe/yargs/commit/0b4e34af5e6d84a9dbb3bb6d02cd87588031c182) Update README.md (@chevex) + +### v1.0.8 (2013/12/06 16:36 +00:00) +- [#1](https://github.com/bcoe/yargs/pull/1) fix error caused by check() see #1 (@martinheidegger) + +### v1.0.7 (2013/11/24 18:01 +00:00) +- [a247d88](https://github.com/bcoe/yargs/commit/a247d88d6e46644cbb7303c18b1bb678fc132d72) Modified Pirate Joe image. (@chevex) + +### v1.0.6 (2013/11/23 19:21 +00:00) +- [d7f69e1](https://github.com/bcoe/yargs/commit/d7f69e1d34bc929736a8bdccdc724583e21b7eab) Updated Pirate Joe image. (@chevex) + +### v1.0.5 (2013/11/23 19:09 +00:00) +- [ece809c](https://github.com/bcoe/yargs/commit/ece809cf317cc659175e1d66d87f3ca68c2760be) Updated readme notice again. (@chevex) + +### v1.0.4 (2013/11/23 19:05 +00:00) +- [9e81e81](https://github.com/bcoe/yargs/commit/9e81e81654028f83ba86ffc3ac772a0476084e5e) Updated README with a notice about yargs being a fork of optimist and what that implies. (@chevex) + +### v1.0.3 (2013/11/23 17:43 +00:00) +- [65e7a78](https://github.com/bcoe/yargs/commit/65e7a782c86764944d63d084416aba9ee6019c5f) Changed some small wording in README.md. (@chevex) +- [459e20e](https://github.com/bcoe/yargs/commit/459e20e539b366b85128dd281ccd42221e96c7da) Fix a bug in the options function, when string and boolean options weren't applied to aliases. (@shockone) + +### v1.0.2 (2013/11/23 09:46 +00:00) +- [3d80ebe](https://github.com/bcoe/yargs/commit/3d80ebed866d3799224b6f7d596247186a3898a9) 1.0.2 (@chevex) + +### v1.0.1 (2013/11/23 09:39 +00:00) +- [f80ff36](https://github.com/bcoe/yargs/commit/f80ff3642d580d4b68bf9f5a94277481bd027142) Updated image. (@chevex) + +### v1.0.0 (2013/11/23 09:33 +00:00) +- [54e31d5](https://github.com/bcoe/yargs/commit/54e31d505f820b80af13644e460894b320bf25a3) Rebranded from optimist to yargs in the spirit of the fork :D (@chevex) +- [4ebb6c5](https://github.com/bcoe/yargs/commit/4ebb6c59f44787db7c24c5b8fe2680f01a23f498) Added documentation for demandCount(). (@chevex) +- [4561ce6](https://github.com/bcoe/yargs/commit/4561ce66dcffa95f49e8b4449b25b94cd68acb25) Simplified the error messages returned by .check(). (@chevex) +- [661c678](https://github.com/bcoe/yargs/commit/661c67886f479b16254a830b7e1db3be29e6b7a6) Fixed an issue with demand not accepting a zero value. (@chevex) +- [731dd3c](https://github.com/bcoe/yargs/commit/731dd3c37624790490bd6df4d5f1da8f4348279e) Add .fail(fn) so death isn't the only option. Should fix issue #39. (@chevex) +- [fa15417](https://github.com/bcoe/yargs/commit/fa15417ff9e70dace0d726627a5818654824c1d8) Added a few missing 'return self' (@chevex) +- [e655e4d](https://github.com/bcoe/yargs/commit/e655e4d99d1ae1d3695ef755d51c2de08d669761) Fix showing help in certain JS environments. (@chevex) +- [a746a31](https://github.com/bcoe/yargs/commit/a746a31cd47c87327028e6ea33762d6187ec5c87) Better string representation of default values. (@chevex) +- [6134619](https://github.com/bcoe/yargs/commit/6134619a7e90b911d5443230b644c5d447c1a68c) Implies: conditional demands (@chevex) +- [046b93b](https://github.com/bcoe/yargs/commit/046b93b5d40a27367af4cb29726e4d781d934639) Added support for JSON config files. (@chevex) +- [a677ec0](https://github.com/bcoe/yargs/commit/a677ec0a0ecccd99c75e571d03323f950688da03) Add .example(cmd, desc) feature. (@chevex) +- [1bd4375](https://github.com/bcoe/yargs/commit/1bd4375e11327ba1687d4bb6e5e9f3c30c1be2af) Added 'defaults' as alias to 'default' so as to avoid usage of a reserved keyword. (@chevex) +- [6b753c1](https://github.com/bcoe/yargs/commit/6b753c16ca09e723060e70b773b430323b29c45c) add .normalize(args..) support for normalizing paths (@chevex) +- [33d7d59](https://github.com/bcoe/yargs/commit/33d7d59341d364f03d3a25f0a55cb99004dbbe4b) Customize error messages with demand(key, msg) (@chevex) +- [647d37f](https://github.com/bcoe/yargs/commit/647d37f164c20f4bafbf67dd9db6cd6e2cd3b49f) Merge branch 'rewrite-duplicate-test' of github.com:isbadawi/node-optimist (@chevex) +- [9059d1a](https://github.com/bcoe/yargs/commit/9059d1ad5e8aea686c2a01c89a23efdf929fff2e) Pass aliases object to check functions for greater versatility. (@chevex) +- [623dc26](https://github.com/bcoe/yargs/commit/623dc26c7331abff2465ef8532e3418996d42fe6) Added ability to count boolean options and rolled minimist library back into project. (@chevex) +- [49f0dce](https://github.com/bcoe/yargs/commit/49f0dcef35de4db544c3966350d36eb5838703f6) Fixed small typo. (@chevex) +- [79ec980](https://github.com/bcoe/yargs/commit/79ec9806d9ca6eb0014cfa4b6d1849f4f004baf2) Removed dependency on wordwrap module. (@chevex) +- [ea14630](https://github.com/bcoe/yargs/commit/ea14630feddd69d1de99dd8c0e08948f4c91f00a) Merge branch 'master' of github.com:chbrown/node-optimist (@chevex) +- [2b75da2](https://github.com/bcoe/yargs/commit/2b75da2624061e0f4f3107d20303c06ec9054906) Merge branch 'master' of github.com:seanzhou1023/node-optimist (@chevex) +- [d9bda11](https://github.com/bcoe/yargs/commit/d9bda1116e26f3b40e833ca9ca19263afea53565) Merge branch 'patch-1' of github.com:thefourtheye/node-optimist (@chevex) +- [d6cc606](https://github.com/bcoe/yargs/commit/d6cc6064a4f1bea38a16a4430b8a1334832fbeff) Renamed README. (@chevex) +- [9498d3f](https://github.com/bcoe/yargs/commit/9498d3f59acfb5e102826503e681623c3a64b178) Renamed readme and added .gitignore. (@chevex) +- [bbd1fe3](https://github.com/bcoe/yargs/commit/bbd1fe37fefa366dde0fb3dc44d91fe8b28f57f5) Included examples for ```help``` and ```showHelp``` functions and fixed few formatting issues (@thefourtheye) +- [37fea04](https://github.com/bcoe/yargs/commit/37fea0470a5796a0294c1dcfff68d8041650e622) .alias({}) behaves differently based on mapping direction when generating descriptions (@chbrown) +- [855b20d](https://github.com/bcoe/yargs/commit/855b20d0be567ca121d06b30bea64001b74f3d6d) Documented function signatures are useful for dynamically typed languages. (@chbrown) + +### 0.6.0 (2013/06/25 08:48 +00:00) +- [d37bfe0](https://github.com/bcoe/yargs/commit/d37bfe05ae6d295a0ab481efe4881222412791f4) all tests passing using minimist (@substack) +- [76f1352](https://github.com/bcoe/yargs/commit/76f135270399d01f2bbc621e524a5966e5c422fd) all parse tests now passing (@substack) +- [a7b6754](https://github.com/bcoe/yargs/commit/a7b6754276c38d1565479a5685c3781aeb947816) using minimist, some tests passing (@substack) +- [6655688](https://github.com/bcoe/yargs/commit/66556882aa731cbbbe16cc4d42c85740a2e98099) Give credit where its due (@DeadAlready) +- [602a2a9](https://github.com/bcoe/yargs/commit/602a2a92a459f93704794ad51b115bbb08b535ce) v0.5.3 - Remove wordwrap as dependency (@DeadAlready) + +### 0.5.2 (2013/05/31 03:46 +00:00) +- [4497ca5](https://github.com/bcoe/yargs/commit/4497ca55e332760a37b866ec119ded347ca27a87) fixed the whitespace bug without breaking anything else (@substack) +- [5a3dd1a](https://github.com/bcoe/yargs/commit/5a3dd1a4e0211a38613c6e02f61328e1031953fa) failing test for whitespace arg (@substack) + +### 0.5.1 (2013/05/30 07:17 +00:00) +- [a20228f](https://github.com/bcoe/yargs/commit/a20228f62a454755dd07f628a7c5759113918327) fix parse() to work with functions before it (@substack) +- [b13bd4c](https://github.com/bcoe/yargs/commit/b13bd4cac856a9821d42fa173bdb58f089365a7d) failing test for parse() with modifiers (@substack) + +### 0.5.0 (2013/05/18 21:59 +00:00) +- [c474a64](https://github.com/bcoe/yargs/commit/c474a649231527915c222156e3b40806d365a87c) fixes for dash (@substack) + +### 0.4.0 (2013/04/13 19:03 +00:00) +- [dafe3e1](https://github.com/bcoe/yargs/commit/dafe3e18d7c6e7c2d68e06559df0e5cbea3adb14) failing short test (@substack) + +### 0.3.7 (2013/04/04 04:07 +00:00) +- [6c7a0ec](https://github.com/bcoe/yargs/commit/6c7a0ec94ce4199a505f0518b4d6635d4e47cc81) Fix for windows. On windows there is no _ in environment. (@hdf) + +### 0.3.6 (2013/04/04 04:04 +00:00) +- [e72346a](https://github.com/bcoe/yargs/commit/e72346a727b7267af5aa008b418db89970873f05) Add support for newlines in -a="" arguments (@danielbeardsley) +- [71e1fb5](https://github.com/bcoe/yargs/commit/71e1fb55ea9987110a669ac6ec12338cfff3821c) drop 0.4, add 0.8 to travis (@substack) + +### 0.3.5 (2012/10/10 11:09 +00:00) +- [ee692b3](https://github.com/bcoe/yargs/commit/ee692b37554c70a0bb16389a50a26b66745cbbea) Fix parsing booleans (@vojtajina) +- [5045122](https://github.com/bcoe/yargs/commit/5045122664c3f5b4805addf1be2148d5856f7ce8) set $0 properly in the tests (@substack) + +### 0.3.4 (2012/04/30 06:54 +00:00) +- [f28c0e6](https://github.com/bcoe/yargs/commit/f28c0e62ca94f6e0bb2e6d82fc3d91a55e69b903) bump for string "true" params (@substack) +- [8f44aeb](https://github.com/bcoe/yargs/commit/8f44aeb74121ddd689580e2bf74ef86a605e9bf2) Fix failing test for aliased booleans. (@coderarity) +- [b9f7b61](https://github.com/bcoe/yargs/commit/b9f7b613b1e68e11e6c23fbda9e555a517dcc976) Add failing test for short aliased booleans. (@coderarity) + +### 0.3.3 (2012/04/30 06:45 +00:00) +- [541bac8](https://github.com/bcoe/yargs/commit/541bac8dd787a5f1a5d28f6d8deb1627871705e7) Fixes #37. + +### 0.3.2 (2012/04/12 20:28 +00:00) +- [3a0f014](https://github.com/bcoe/yargs/commit/3a0f014c1451280ac1c9caa1f639d31675586eec) travis badge (@substack) +- [4fb60bf](https://github.com/bcoe/yargs/commit/4fb60bf17845f4ce3293f8ca49c9a1a7c736cfce) Fix boolean aliases. (@coderarity) +- [f14dda5](https://github.com/bcoe/yargs/commit/f14dda546efc4fe06ace04d36919bfbb7634f79b) Adjusted package.json to use tap (@jfhbrook) +- [88e5d32](https://github.com/bcoe/yargs/commit/88e5d32295be6e544c8d355ff84e355af38a1c74) test/usage.js no longer hangs (@jfhbrook) +- [e1e740c](https://github.com/bcoe/yargs/commit/e1e740c27082f3ce84deca2093d9db2ef735d0e5) two tests for combined boolean/alias opts parsing (@jfhbrook) + +### 0.3.1 (2011/12/31 08:44 +00:00) +- [d09b719](https://github.com/bcoe/yargs/commit/d09b71980ef711b6cf3918cd19beec8257e40e82) If "default" is set to false it was not passed on, fixed. (@wolframkriesing) + +### 0.3.0 (2011/12/09 06:03 +00:00) +- [6e74aa7](https://github.com/bcoe/yargs/commit/6e74aa7b46a65773e20c0cb68d2d336d4a0d553d) bump and documented dot notation (@substack) + +### 0.2.7 (2011/10/20 02:25 +00:00) +- [94adee2](https://github.com/bcoe/yargs/commit/94adee20e17b58d0836f80e8b9cdbe9813800916) argv._ can be told 'Hey! argv._! Don't be messing with my args.', and it WILL obey (@colinta) +- [c46fdd5](https://github.com/bcoe/yargs/commit/c46fdd56a05410ae4a1e724a4820c82e77ff5469) optimistic critter image (@substack) +- [5c95c73](https://github.com/bcoe/yargs/commit/5c95c73aedf4c7482bd423e10c545e86d7c8a125) alias options() to option() (@substack) +- [f7692ea](https://github.com/bcoe/yargs/commit/f7692ea8da342850af819367833abb685fde41d8) [fix] Fix for parsing boolean edge case (@indexzero) +- [d1f92d1](https://github.com/bcoe/yargs/commit/d1f92d1425bd7f356055e78621b30cdf9741a3c2) +- [b01bda8](https://github.com/bcoe/yargs/commit/b01bda8d86e455bbf74ce497864cb8ab5b9fb847) [fix test] Update to ensure optimist is aware of default booleans. Associated tests included (@indexzero) +- [aa753e7](https://github.com/bcoe/yargs/commit/aa753e7c54fb3a12f513769a0ff6d54aa0f63943) [dist test] Update devDependencies in package.json. Update test pathing to be more npm and require.paths future-proof (@indexzero) +- [7bfce2f](https://github.com/bcoe/yargs/commit/7bfce2f3b3c98e6539e7549d35fbabced7e9341e) s/sys/util/ (@substack) +- [d420a7a](https://github.com/bcoe/yargs/commit/d420a7a9c890d2cdb11acfaf3ea3f43bc3e39f41) update usage output (@substack) +- [cf86eed](https://github.com/bcoe/yargs/commit/cf86eede2e5fc7495b6ec15e6d137d9ac814f075) some sage readme protips about parsing rules (@substack) +- [5da9f7a](https://github.com/bcoe/yargs/commit/5da9f7a5c0e1758ec7c5801fb3e94d3f6e970513) documented all the methods finally (@substack) +- [8ca6879](https://github.com/bcoe/yargs/commit/8ca6879311224b25933642987300f6a29de5c21b) fenced syntax highlighting (@substack) +- [b72bacf](https://github.com/bcoe/yargs/commit/b72bacf1d02594778c1935405bc8137eb61761dc) right-alignment of wrapped extra params (@substack) +- [2b980bf](https://github.com/bcoe/yargs/commit/2b980bf2656b4ee8fc5134dc5f56a48855c35198) now with .wrap() (@substack) +- [d614f63](https://github.com/bcoe/yargs/commit/d614f639654057d1b7e35e3f5a306e88ec2ad1e4) don't show 'Options:' when there aren't any (@substack) +- [691eda3](https://github.com/bcoe/yargs/commit/691eda354df97b5a86168317abcbcaabdc08a0fb) failing test for multi-aliasing (@substack) +- [0826c9f](https://github.com/bcoe/yargs/commit/0826c9f462109feab2bc7a99346d22e72bf774b7) "Options:" > "options:" (@substack) +- [72f7490](https://github.com/bcoe/yargs/commit/72f749025d01b7f295738ed370a669d885fbada0) [minor] Update formatting for `.showHelp()` (@indexzero) +- [75aecce](https://github.com/bcoe/yargs/commit/75aeccea74329094072f95800e02c275e7d999aa) options works again, too lazy to write a proper test right now (@substack) +- [f742e54](https://github.com/bcoe/yargs/commit/f742e5439817c662dc3bd8734ddd6467e6018cfd) line_count_options example, which breaks (@substack) +- [4ca06b8](https://github.com/bcoe/yargs/commit/4ca06b8b4ea99b5d5714b315a2a8576bee6e5537) line count example (@substack) +- [eeb8423](https://github.com/bcoe/yargs/commit/eeb8423e0a5ecc9dc3eb1e6df9f3f8c1c88f920b) remove self.argv setting in boolean (@substack) +- [6903412](https://github.com/bcoe/yargs/commit/69034126804660af9cc20ea7f4457b50338ee3d7) removed camel case for now (@substack) +- [5a0d88b](https://github.com/bcoe/yargs/commit/5a0d88bf23e9fa79635dd034e2a1aa992acc83cd) remove dead longest checking code (@substack) +- [d782170](https://github.com/bcoe/yargs/commit/d782170babf7284b1aa34f5350df0dd49c373fa8) .help() too (@substack) +- [622ec17](https://github.com/bcoe/yargs/commit/622ec17379bb5374fdbb190404c82bc600975791) rm old help generator (@substack) +- [7c8baac](https://github.com/bcoe/yargs/commit/7c8baac4d66195e9f5158503ea9ebfb61153dab7) nub keys (@substack) +- [8197785](https://github.com/bcoe/yargs/commit/8197785ad4762465084485b041abd722f69bf344) generate help message based on the previous calls, todo: nub (@substack) +- [3ffbdc3](https://github.com/bcoe/yargs/commit/3ffbdc33c8f5e83d4ea2ac60575ce119570c7ede) stub out new showHelp, better checks (@substack) +- [d4e21f5](https://github.com/bcoe/yargs/commit/d4e21f56a4830f7de841900d3c79756fb9886184) let .options() take single options too (@substack) +- [3c4cf29](https://github.com/bcoe/yargs/commit/3c4cf2901a29bac119cca8e983028d8669230ec6) .options() is now heaps simpler (@substack) +- [89f0d04](https://github.com/bcoe/yargs/commit/89f0d043cbccd302f10ab30c2069e05d2bf817c9) defaults work again, all tests pass (@substack) +- [dd87333](https://github.com/bcoe/yargs/commit/dd8733365423006a6e4156372ebb55f98323af58) update test error messages, down to 2 failing tests (@substack) +- [53f7bc6](https://github.com/bcoe/yargs/commit/53f7bc626b9875f2abdfc5dd7a80bde7f14143a3) fix for bools doubling up, passes the parse test again, others fail (@substack) +- [2213e2d](https://github.com/bcoe/yargs/commit/2213e2ddc7263226fba717fb041dc3fde9bc2ee4) refactored for an argv getter, failing several tests (@substack) +- [d1e7379](https://github.com/bcoe/yargs/commit/d1e737970f15c6c006bebdd8917706827ff2f0f2) just rescan for now, alias test passes (@substack) +- [b2f8c99](https://github.com/bcoe/yargs/commit/b2f8c99cc477a8eb0fdf4cf178e1785b63185cfd) failing alias test (@substack) +- [d0c0174](https://github.com/bcoe/yargs/commit/d0c0174daa144bfb6dc7290fdc448c393c475e15) .alias() (@substack) +- [d85f431](https://github.com/bcoe/yargs/commit/d85f431ad7d07b058af3f2a57daa51495576c164) [api] Remove `.describe()` in favor of building upon the existing `.usage()` API (@indexzero) +- [edbd527](https://github.com/bcoe/yargs/commit/edbd5272a8e213e71acd802782135c7f9699913a) [doc api] Add `.describe()`, `.options()`, and `.showHelp()` methods along with example. (@indexzero) +- [be4902f](https://github.com/bcoe/yargs/commit/be4902ff0961ae8feb9093f2c0a4066463ded2cf) updates for coffee since it now does argv the node way (@substack) +- [e24cb23](https://github.com/bcoe/yargs/commit/e24cb23798ee64e53b60815e7fda78b87f42390c) more general coffeescript detection (@substack) +- [78ac753](https://github.com/bcoe/yargs/commit/78ac753e5d0ec32a96d39d893272afe989e42a4d) Don't trigger the CoffeeScript hack when running under node_g. (@papandreou) +- [bcfe973](https://github.com/bcoe/yargs/commit/bcfe9731d7f90d4632281b8a52e8d76eb0195ae6) .string() but failing test (@substack) +- [1987aca](https://github.com/bcoe/yargs/commit/1987aca28c7ba4e8796c07bbc547cb984804c826) test hex strings (@substack) +- [ef36db3](https://github.com/bcoe/yargs/commit/ef36db32259b0b0d62448dc907c760e5554fb7e7) more keywords (@substack) +- [cc53c56](https://github.com/bcoe/yargs/commit/cc53c56329960bed6ab077a79798e991711ba01d) Added camelCase function that converts --multi-word-option to camel case (so it becomes argv.multiWordOption). (@papandreou) +- [60b57da](https://github.com/bcoe/yargs/commit/60b57da36797716e5783a633c6d5c79099016d45) fixed boolean bug by rescanning (@substack) +- [dff6d07](https://github.com/bcoe/yargs/commit/dff6d078d97f8ac503c7d18dcc7b7a8c364c2883) boolean examples (@substack) +- [0e380b9](https://github.com/bcoe/yargs/commit/0e380b92c4ef4e3c8dac1da18b5c31d85b1d02c9) boolean() with passing test (@substack) +- [62644d4](https://github.com/bcoe/yargs/commit/62644d4bffbb8d1bbf0c2baf58a1d14a6359ef07) coffee compatibility with node regex for versions too (@substack) +- [430fafc](https://github.com/bcoe/yargs/commit/430fafcf1683d23774772826581acff84b456827) argv._ fixed by fixing the coffee detection (@substack) +- [343b8af](https://github.com/bcoe/yargs/commit/343b8afefd98af274ebe21b5a16b3a949ec5429f) whichNodeArgs test fails too (@substack) +- [63df2f3](https://github.com/bcoe/yargs/commit/63df2f371f31e63d7f1dec2cbf0022a5f08da9d2) replicated mnot's bug in whichNodeEmpty test (@substack) +- [35473a4](https://github.com/bcoe/yargs/commit/35473a4d93a45e5e7e512af8bb54ebb532997ae1) test for ./bin usage (@substack) +- [13df151](https://github.com/bcoe/yargs/commit/13df151e44228eed10e5441c7cd163e086c458a4) don't coerce booleans to numbers (@substack) +- [85f8007](https://github.com/bcoe/yargs/commit/85f8007e93b8be7124feea64b1f1916d8ba1894a) package bump for automatic number conversion (@substack) +- [8f17014](https://github.com/bcoe/yargs/commit/8f170141cded4ccc0c6d67a849c5bf996aa29643) updated readme and examples with new auto-numberification goodness (@substack) +- [73dc901](https://github.com/bcoe/yargs/commit/73dc9011ac968e39b55e19e916084a839391b506) auto number conversion works yay (@substack) +- [bcec56b](https://github.com/bcoe/yargs/commit/bcec56b3d031e018064cbb691539ccc4f28c14ad) failing test for not-implemented auto numification (@substack) +- [ebd2844](https://github.com/bcoe/yargs/commit/ebd2844d683feeac583df79af0e5124a7a7db04e) odd that eql doesn't check types careflly (@substack) +- [fd854b0](https://github.com/bcoe/yargs/commit/fd854b02e512ce854b76386d395672a7969c1bc4) package author + keywords (@substack) +- [656a1d5](https://github.com/bcoe/yargs/commit/656a1d5a1b7c0e49d72e80cb13f20671d56f76c6) updated readme with .default() stuff (@substack) +- [cd7f8c5](https://github.com/bcoe/yargs/commit/cd7f8c55f0b82b79b690d14c5f806851236998a1) passing tests for new .default() behavior (@substack) +- [932725e](https://github.com/bcoe/yargs/commit/932725e39ce65bc91a0385a5fab659a5fa976ac2) new default() thing for setting default key/values (@substack) +- [4e6c7ab](https://github.com/bcoe/yargs/commit/4e6c7aba6374ac9ebc6259ecf91f13af7bce40e3) test for coffee usage (@substack) +- [d54ffcc](https://github.com/bcoe/yargs/commit/d54ffccf2a5a905f51ed5108f7c647f35d64ae23) new --key value style with passing tests. NOTE: changes existing behavior (@substack) +- [ed2a2d5](https://github.com/bcoe/yargs/commit/ed2a2d5d828100ebeef6385c0fb88d146a5cfe9b) package bump for summatix's coffee script fix (@substack) +- [75a975e](https://github.com/bcoe/yargs/commit/75a975eed8430d28e2a79dc9e6d819ad545f4587) Added support for CoffeeScript (@summatix) +- [56b2b1d](https://github.com/bcoe/yargs/commit/56b2b1de8d11f8a2b91979d8ae2d6db02d8fe64d) test coverage for the falsy check() usage (@substack) +- [a4843a9](https://github.com/bcoe/yargs/commit/a4843a9f0e69ffb4afdf6a671d89eb6f218be35d) check bug fixed plus a handy string (@substack) +- [857bd2d](https://github.com/bcoe/yargs/commit/857bd2db933a5aaa9cfecba0ced2dc9b415f8111) tests for demandCount, back up to 100% coverage (@substack) +- [073b776](https://github.com/bcoe/yargs/commit/073b7768ebd781668ef05c13f9003aceca2f5c35) call demandCount from demand (@substack) +- [4bd4b7a](https://github.com/bcoe/yargs/commit/4bd4b7a085c8b6ce1d885a0f486cc9865cee2db1) add demandCount to check for the number of arguments in the _ list (@marshall) +- [b8689ac](https://github.com/bcoe/yargs/commit/b8689ac68dacf248119d242bba39a41cb0adfa07) Rebase checks. That will be its own module eventually. (@substack) +- [e688370](https://github.com/bcoe/yargs/commit/e688370b576f0aa733c3f46183df69e1b561668e) a $0 like in perl (@substack) +- [2e5e196](https://github.com/bcoe/yargs/commit/2e5e1960fc19afb21fb3293752316eaa8bcd3609) usage test hacking around process and console (@substack) +- [fcc3521](https://github.com/bcoe/yargs/commit/fcc352163fbec6a1dfe8caf47a0df39de24fe016) description pun (@substack) +- [87a1fe2](https://github.com/bcoe/yargs/commit/87a1fe29037ca2ca5fefda85141aaeb13e8ce761) mit/x11 license (@substack) +- [8d089d2](https://github.com/bcoe/yargs/commit/8d089d24cd687c0bde3640a96c09b78f884900dd) bool example is more consistent and also shows off short option grouping (@substack) +- [448d747](https://github.com/bcoe/yargs/commit/448d7473ac68e8e03d8befc9457b0d9e21725be0) start of the readme and examples (@substack) +- [da74dea](https://github.com/bcoe/yargs/commit/da74dea799a9b59dbf022cbb8001bfdb0d52eec9) more tests for long and short captures (@substack) +- [ab6387e](https://github.com/bcoe/yargs/commit/ab6387e6769ca4af82ca94c4c67c7319f0d9fcfa) silly bug in the tests with s/not/no/, all tests pass now (@substack) +- [102496a](https://github.com/bcoe/yargs/commit/102496a319e8e06f6550d828fc2f72992c7d9ecc) hack an instance for process.argv onto Argv so the export can be called to create an instance or used for argv, which is the most common case (@substack) +- [a01caeb](https://github.com/bcoe/yargs/commit/a01caeb532546d19f68f2b2b87f7036cfe1aaedd) divide example (@substack) +- [443da55](https://github.com/bcoe/yargs/commit/443da55736acbaf8ff8b04d1b9ce19ab016ddda2) start of the lib with a package.json (@substack) diff --git a/wrt/node_modules/yargs/LICENSE b/wrt/node_modules/yargs/LICENSE new file mode 100644 index 0000000..432d1ae --- /dev/null +++ b/wrt/node_modules/yargs/LICENSE @@ -0,0 +1,21 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/wrt/node_modules/yargs/README.md b/wrt/node_modules/yargs/README.md new file mode 100644 index 0000000..a310d31 --- /dev/null +++ b/wrt/node_modules/yargs/README.md @@ -0,0 +1,1071 @@ +yargs +======== + +Yargs be a node.js library fer hearties tryin' ter parse optstrings. + +With yargs, ye be havin' a map that leads straight to yer treasure! Treasure of course, being a simple option hash. + +[![Build Status][travis-image]][travis-url] +[![Dependency Status][gemnasium-image]][gemnasium-url] +[![Coverage Status][coveralls-image]][coveralls-url] +[![NPM version][npm-image]][npm-url] + +> Yargs is the official successor to optimist. Please feel free to submit issues and pull requests. If you'd like to contribute and don't know where to start, have a look at [the issue list](https://github.com/bcoe/yargs/issues) :) + +examples +======== + +With yargs, the options be just a hash! +------------------------------------------------------------------- + +plunder.js: + +````javascript +#!/usr/bin/env node +var argv = require('yargs').argv; + +if (argv.ships > 3 && argv.distance < 53.5) { + console.log('Plunder more riffiwobbles!'); +} +else { + console.log('Retreat from the xupptumblers!'); +} +```` + +*** + + $ ./plunder.js --ships=4 --distance=22 + Plunder more riffiwobbles! + + $ ./plunder.js --ships 12 --distance 98.7 + Retreat from the xupptumblers! + +![Joe was one optimistic pirate.](http://i.imgur.com/4WFGVJ9.png) + +But don't walk the plank just yet! There be more! You can do short options: +------------------------------------------------- + +short.js: + +````javascript +#!/usr/bin/env node +var argv = require('yargs').argv; +console.log('(%d,%d)', argv.x, argv.y); +```` + +*** + + $ ./short.js -x 10 -y 21 + (10,21) + +And booleans, both long, short, and even grouped: +---------------------------------- + +bool.js: + +````javascript +#!/usr/bin/env node +var util = require('util'); +var argv = require('yargs').argv; + +if (argv.s) { + process.stdout.write(argv.fr ? 'Le perroquet dit: ' : 'The parrot says: '); +} +console.log( + (argv.fr ? 'couac' : 'squawk') + (argv.p ? '!' : '') +); +```` + +*** + + $ ./bool.js -s + The parrot says: squawk + + $ ./bool.js -sp + The parrot says: squawk! + + $ ./bool.js -sp --fr + Le perroquet dit: couac! + +And non-hyphenated options too! Just use `argv._`! +------------------------------------------------- + +nonopt.js: + +````javascript +#!/usr/bin/env node +var argv = require('yargs').argv; +console.log('(%d,%d)', argv.x, argv.y); +console.log(argv._); +```` + +*** + + $ ./nonopt.js -x 6.82 -y 3.35 rum + (6.82,3.35) + [ 'rum' ] + + $ ./nonopt.js "me hearties" -x 0.54 yo -y 1.12 ho + (0.54,1.12) + [ 'me hearties', 'yo', 'ho' ] + +Yargs even counts your booleans! +---------------------------------------------------------------------- + +count.js: + +````javascript +#!/usr/bin/env node +var argv = require('yargs') + .count('verbose') + .alias('v', 'verbose') + .argv; + +VERBOSE_LEVEL = argv.verbose; + +function WARN() { VERBOSE_LEVEL >= 0 && console.log.apply(console, arguments); } +function INFO() { VERBOSE_LEVEL >= 1 && console.log.apply(console, arguments); } +function DEBUG() { VERBOSE_LEVEL >= 2 && console.log.apply(console, arguments); } + +WARN("Showing only important stuff"); +INFO("Showing semi-important stuff too"); +DEBUG("Extra chatty mode"); +```` + +*** + $ node count.js + Showing only important stuff + + $ node count.js -v + Showing only important stuff + Showing semi-important stuff too + + $ node count.js -vv + Showing only important stuff + Showing semi-important stuff too + Extra chatty mode + + $ node count.js -v --verbose + Showing only important stuff + Showing semi-important stuff too + Extra chatty mode + +Tell users how to use yer options and make demands. +------------------------------------------------- + +area.js: + +````javascript +#!/usr/bin/env node +var argv = require('yargs') + .usage('Usage: $0 -w [num] -h [num]') + .demand(['w','h']) + .argv; + +console.log("The area is:", argv.w * argv.h); +```` + +*** + + $ ./area.js -w 55 -h 11 + The area is: 605 + + $ node ./area.js -w 4.91 -w 2.51 + Usage: area.js -w [num] -h [num] + + Options: + -w [required] + -h [required] + + Missing required arguments: h + +After yer demands have been met, demand more! Ask for non-hypenated arguments! +----------------------------------------- + +demand_count.js: + +````javascript +#!/usr/bin/env node +var argv = require('yargs') + .demand(2) + .argv; +console.dir(argv); +```` + +*** + + $ ./demand_count.js a + + Not enough non-option arguments: got 1, need at least 2 + + $ ./demand_count.js a b + { _: [ 'a', 'b' ], '$0': 'demand_count.js' } + + $ ./demand_count.js a b c + { _: [ 'a', 'b', 'c' ], '$0': 'demand_count.js' } + +EVEN MORE SHIVER ME TIMBERS! +------------------ + +default_singles.js: + +````javascript +#!/usr/bin/env node +var argv = require('yargs') + .default('x', 10) + .default('y', 10) + .argv +; +console.log(argv.x + argv.y); +```` + +*** + + $ ./default_singles.js -x 5 + 15 + +default_hash.js: + +````javascript +#!/usr/bin/env node +var argv = require('yargs') + .default({ x : 10, y : 10 }) + .argv +; +console.log(argv.x + argv.y); +```` + +*** + + $ ./default_hash.js -y 7 + 17 + +And if you really want to get all descriptive about it... +--------------------------------------------------------- + +boolean_single.js: + +````javascript +#!/usr/bin/env node +var argv = require('yargs') + .boolean('v') + .argv +; +console.dir(argv.v); +console.dir(argv._); +```` + +*** + + $ ./boolean_single.js -v "me hearties" yo ho + true + [ 'me hearties', 'yo', 'ho' ] + + +boolean_double.js: + +````javascript +#!/usr/bin/env node +var argv = require('yargs') + .boolean(['x','y','z']) + .argv +; +console.dir([ argv.x, argv.y, argv.z ]); +console.dir(argv._); +```` + +*** + + $ ./boolean_double.js -x -z one two three + [ true, false, true ] + [ 'one', 'two', 'three' ] + +Yargs is here to help you... +--------------------------- + +Ye can describe parameters fer help messages and set aliases. Yargs figures +out how ter format a handy help string automatically. + +line_count.js: + +````javascript +#!/usr/bin/env node +var argv = require('yargs') + .usage('Usage: $0 [options]') + .command('count', 'Count the lines in a file') + .demand(1) + .example('$0 count -f foo.js', 'count the lines in the given file') + .demand('f') + .alias('f', 'file') + .nargs('f', 1) + .describe('f', 'Load a file') + .help('h') + .alias('h', 'help') + .epilog('copyright 2015') + .argv; + +var fs = require('fs'); +var s = fs.createReadStream(argv.file); + +var lines = 0; +s.on('data', function (buf) { + lines += buf.toString().match(/\n/g).length; +}); + +s.on('end', function () { + console.log(lines); +}); +```` + +*** + $ node line_count.js count + Usage: line_count.js [options] + + Commands: + count Count the lines in a file + + Options: + -f, --file Load a file [required] + -h, --help Show help [boolean] + + Examples: + line_count.js count -f foo.js count the lines in the given file + + copyright 2015 + + Missing required arguments: f + + $ node line_count.js count --file line_count.js + 26 + + $ node line_count.js count -f line_count.js + 26 + +methods +======= + +By itself, + +````javascript +require('yargs').argv +```` + +will use the `process.argv` array to construct the `argv` object. + +You can pass in the `process.argv` yourself: + +````javascript +require('yargs')([ '-x', '1', '-y', '2' ]).argv +```` + +or use `.parse()` to do the same thing: + +````javascript +require('yargs').parse([ '-x', '1', '-y', '2' ]) +```` + +The rest of these methods below come in just before the terminating `.argv`. + +.alias(key, alias) +------------------ + +Set key names as equivalent such that updates to a key will propagate to aliases +and vice-versa. + +Optionally `.alias()` can take an object that maps keys to aliases. +Each key of this object should be the canonical version of the option, and each +value should be a string or an array of strings. + +.argv +----- + +Get the arguments as a plain old object. + +Arguments without a corresponding flag show up in the `argv._` array. + +The script name or node command is available at `argv.$0` similarly to how `$0` +works in bash or perl. + +If `yargs` is executed in an environment that embeds node and there's no script name (e.g. [Electron] +(http://electron.atom.io/) or [nw.js](http://nwjs.io/)), it will ignore the first parameter since it +expects it to be the script name. In order to override this behavior, use `.parse(process.argv.slice(1))` +instead of `.argv` and the first parameter won't be ignored. + +.array(key) +---------- + +Tell the parser to interpret `key` as an array. If `.array('foo')` is set, +`--foo foo bar` will be parsed as `['foo', 'bar']` rather than as `'foo'`. + +.boolean(key) +------------- + +Interpret `key` as a boolean. If a non-flag option follows `key` in +`process.argv`, that string won't get set as the value of `key`. + +`key` will default to `false`, unless a `default(key, undefined)` is +explicitly set. + +If `key` is an array, interpret all the elements as booleans. + +.check(fn) +---------- + +Check that certain conditions are met in the provided arguments. + +`fn` is called with two arguments, the parsed `argv` hash and an array of options and their aliases. + +If `fn` throws or returns a non-truthy value, show the thrown error, usage information, and +exit. + +.choices(key, choices) +---------------------- + +Limit valid values for `key` to a predefined set of `choices`, given as an array +or as an individual value. + +```js +var argv = require('yargs') + .alias('i', 'ingredient') + .describe('i', 'choose your sandwich ingredients') + .choices('i', ['peanut-butter', 'jelly', 'banana', 'pickles']) + .help('help') + .argv +``` + +If this method is called multiple times, all enumerated values will be merged +together. Choices are generally strings or numbers, and value matching is +case-sensitive. + +Optionally `.choices()` can take an object that maps multiple keys to their +choices. + +Choices can also be specified as `choices` in the object given to `option()`. + +```js +var argv = require('yargs') + .option('size', { + alias: 's', + describe: 'choose a size', + choices: ['xs', 's', 'm', 'l', 'xl'] + }) + .argv +``` + +.command(cmd, desc, [fn]) +------------------- + +Document the commands exposed by your application. + +Use `desc` to provide a description for each command your application accepts (the +values stored in `argv._`). Set `desc` to `false` to create a hidden command. +Hidden commands don't show up in the help output and aren't available for +completion. + +Optionally, you can provide a handler `fn` which will be executed when +a given command is provided. The handler will be executed with an instance +of `yargs`, which can be used to compose nested commands. + +Here's an example of top-level and nested commands in action: + +```js +var argv = require('yargs') + .usage('npm ') + .command('install', 'tis a mighty fine package to install') + .command('publish', 'shiver me timbers, should you be sharing all that', function (yargs) { + argv = yargs.option('f', { + alias: 'force', + description: 'yar, it usually be a bad idea' + }) + .help('help') + .argv + }) + .help('help') + .argv; +``` + +.completion(cmd, [description], [fn]); +------------- + +Enable bash-completion shortcuts for commands and options. + +`cmd`: When present in `argv._`, will result in the `.bashrc` completion script +being outputted. To enable bash completions, concat the generated script to your +`.bashrc` or `.bash_profile`. + +`description`: Provide a description in your usage instructions for the command +that generates bash completion scripts. + +`fn`: Rather than relying on yargs' default completion functionality, which +shiver me timbers is pretty awesome, you can provide your own completion +method. + +```js +var argv = require('yargs') + .completion('completion', function(current, argv) { + // 'current' is the current command being completed. + // 'argv' is the parsed arguments so far. + // simply return an array of completions. + return [ + 'foo', + 'bar' + ]; + }) + .argv; +``` + +But wait, there's more! You can provide asynchronous completions. + +```js +var argv = require('yargs') + .completion('completion', function(current, argv, done) { + setTimeout(function() { + done([ + 'apple', + 'banana' + ]); + }, 500); + }) + .argv; +``` + +.config(key, [description]) +------------ + +Tells the parser that if the option specified by `key` is passed in, it +should be interpreted as a path to a JSON config file. The file is loaded +and parsed, and its properties are set as arguments. If present, the +`description` parameter customizes the description of the config (`key`) option +in the usage string. + +.default(key, value, [description]) +-------------------- + +Set `argv[key]` to `value` if no option was specified in `process.argv`. + +Optionally `.default()` can take an object that maps keys to default values. + +But wait, there's more! The default value can be a `function` which returns +a value. The name of the function will be used in the usage string: + +```js +var argv = require('yargs') + .default('random', function randomValue() { + return Math.random() * 256; + }).argv; +``` + +Optionally, `description` can also be provided and will take precedence over +displaying the value in the usage instructions: + +```js +.default('timeout', 60000, '(one-minute)') +``` + +.demand(key, [msg | boolean]) +------------------------------ +.demand(count, [max], [msg]) +------------------------------ + +If `key` is a string, show the usage information and exit if `key` wasn't +specified in `process.argv`. + +If `key` is a number, demand at least as many non-option arguments, which show +up in `argv._`. A second number can also optionally be provided, which indicates +the maximum number of non-option arguments. + +If `key` is an array, demand each element. + +If a `msg` string is given, it will be printed when the argument is missing, +instead of the standard error message. This is especially helpful for the non-option arguments in `argv._`. + +If a `boolean` value is given, it controls whether the option is demanded; +this is useful when using `.options()` to specify command line parameters. + +.describe(key, desc) +-------------------- + +Describe a `key` for the generated usage information. + +Optionally `.describe()` can take an object that maps keys to descriptions. + +.epilog(str) +------------ +.epilogue(str) +-------------- + +A message to print at the end of the usage instructions, e.g. + +```js +var argv = require('yargs') + .epilogue('for more information, find our manual at http://example.com'); +``` + +.example(cmd, desc) +------------------- + +Give some example invocations of your program. Inside `cmd`, the string +`$0` will get interpolated to the current script name or node command for the +present script similar to how `$0` works in bash or perl. +Examples will be printed out as part of the help message. + +.exitProcess(enable) +---------------------------------- + +By default, yargs exits the process when the user passes a help flag, uses the +`.version` functionality, or when validation fails. Calling +`.exitProcess(false)` disables this behavior, enabling further actions after +yargs have been validated. + +.fail(fn) +--------- + +Method to execute when a failure occurs, rather than printing the failure message. + +`fn` is called with the failure message that would have been printed. + +.help([option, [description]]) +------------------------------ + +Add an option (e.g. `--help`) that displays the usage string and exits the +process. If present, the `description` parameter customizes the description of +the help option in the usage string. + +If invoked without parameters, `.help()` returns the generated usage string. + +Example: + +```js +var yargs = require("yargs") + .usage("$0 -operand1 number -operand2 number -operation [add|subtract]"); +console.log(yargs.help()); +``` + +Later on, `argv` can be retrieved with `yargs.argv`. + +.implies(x, y) +-------------- + +Given the key `x` is set, it is required that the key `y` is set. + +Optionally `.implies()` can accept an object specifying multiple implications. + +.locale(locale) +--------------- + +Set a locale other than the default `en` locale: + +```js +var argv = require('yargs') + .usage('./$0 - follow ye instructions true') + .option('option', { + alias: 'o', + describe: "'tis a mighty fine option", + demand: true + }) + .command('run', "Arrr, ya best be knowin' what yer doin'") + .example('$0 run foo', "shiver me timbers, here's an example for ye") + .help('help') + .wrap(70) + .locale('pirate') + .argv +``` + +*** + +```shell +./test.js - follow ye instructions true + +Choose yer command: + run Arrr, ya best be knowin' what yer doin' + +Options for me hearties! + --option, -o 'tis a mighty fine option [requi-yar-ed] + --help Parlay this here code of conduct [boolean] + +Ex. marks the spot: + test.js run foo shiver me timbers, here's an example for ye + +Ye be havin' to set the followin' argument land lubber: option +``` + +Locales currently supported: + +* **en:** American English. +* **es:** Spanish. +* **fr:** French. +* **pt:** Portuguese. +* **pirate:** American Pirate. + +To submit a new translation for yargs: + +1. use `./locales/en.json` as a starting point. +2. submit a pull request with the new locale file. + +.nargs(key, count) +----------- + +The number of arguments that should be consumed after a key. This can be a +useful hint to prevent parsing ambiguity. For example: + +```js +var argv = require('yargs') + .nargs('token', 1) + .parse(['--token', '-my-token']); +``` + +parses as: + +`{ _: [], token: '-my-token', '$0': 'node test' }` + +Optionally `.nargs()` can take an object of `key`/`narg` pairs. + +.option(key, opt) +----------------- +.options(key, opt) +------------------ + +Instead of chaining together `.alias().demand().default().describe().string()`, you can specify +keys in `opt` for each of the chainable methods. + +For example: + +````javascript +var argv = require('yargs') + .option('f', { + alias: 'file', + demand: true, + default: '/etc/passwd', + describe: 'x marks the spot', + type: 'string' + }) + .argv +; +```` + +is the same as + +````javascript +var argv = require('yargs') + .alias('f', 'file') + .demand('f') + .default('f', '/etc/passwd') + .describe('f', 'x marks the spot') + .string('f') + .argv +; +```` + +Optionally `.options()` can take an object that maps keys to `opt` parameters. + +````javascript +var argv = require('yargs') + .options({ + 'f': { + alias: 'file', + demand: true, + default: '/etc/passwd', + describe: 'x marks the spot', + type: 'string' + } + }) + .argv +; +```` + +.parse(args) +------------ + +Parse `args` instead of `process.argv`. Returns the `argv` object. + +.require(key, [msg | boolean]) +------------------------------ +.required(key, [msg | boolean]) +------------------------------ + +An alias for [`demand()`](#demand-key-msg-boolean). See docs there. + +.requiresArg(key) +----------------- + +Specifies either a single option key (string), or an array of options that +must be followed by option values. If any option value is missing, show the +usage information and exit. + +The default behavior is to set the value of any key not followed by an +option value to `true`. + +.reset() +-------- + +Reset the argument object built up so far. This is useful for +creating nested command line interfaces. + +```js +var yargs = require('yargs') + .usage('$0 command') + .command('hello', 'hello command') + .command('world', 'world command') + .demand(1, 'must provide a valid command'), + argv = yargs.argv, + command = argv._[0]; + +if (command === 'hello') { + yargs.reset() + .usage('$0 hello') + .help('h') + .example('$0 hello', 'print the hello message!') + .argv + + console.log('hello!'); +} else if (command === 'world'){ + yargs.reset() + .usage('$0 world') + .help('h') + .example('$0 world', 'print the world message!') + .argv + + console.log('world!'); +} else { + yargs.showHelp(); +} +``` + +.showCompletionScript() +---------------------- + +Generate a bash completion script. Users of your application can install this +script in their `.bashrc`, and yargs will provide completion shortcuts for +commands and options. + +.showHelp(consoleLevel='error') +--------------------------- + +Print the usage data using the [`console`](https://nodejs.org/api/console.html) function `consoleLevel` for printing. + +Example: + +```js +var yargs = require("yargs") + .usage("$0 -operand1 number -operand2 number -operation [add|subtract]"); +yargs.showHelp(); //prints to stderr using console.error() +``` + +Or, to print the usage data to `stdout` instead, you can specify the use of `console.log`: + +```js +yargs.showHelp("log"); //prints to stdout using console.log() +``` + +Later on, `argv` can be retrieved with `yargs.argv`. + +.showHelpOnFail(enable, [message]) +---------------------------------- + +By default, yargs outputs a usage string if any error is detected. Use the +`.showHelpOnFail()` method to customize this behavior. If `enable` is `false`, +the usage string is not output. If the `message` parameter is present, this +message is output after the error message. + +line_count.js: + +````javascript +#!/usr/bin/env node +var argv = require('yargs') + .usage('Count the lines in a file.\nUsage: $0 -f ') + .demand('f') + .alias('f', 'file') + .describe('f', 'Load a file') + .string('f') + .showHelpOnFail(false, 'Specify --help for available options') + .help('help') + .argv; + +// etc. +```` + +*** + +``` +$ node line_count.js +Missing argument value: f + +Specify --help for available options +``` + +.strict() +--------- + +Any command-line argument given that is not demanded, or does not have a +corresponding description, will be reported as an error. + +.string(key) +------------ + +Tell the parser logic not to interpret `key` as a number or boolean. +This can be useful if you need to preserve leading zeros in an input. + +If `key` is an array, interpret all the elements as strings. + +`.string('_')` will result in non-hyphenated arguments being interpreted as strings, +regardless of whether they resemble numbers. + +.updateLocale(obj) +------------------ +.updateStrings(obj) +------------------ + +Override the default strings used by yargs with the key/value +pairs provided in `obj`: + +```js +var argv = require('yargs') + .command('run', 'the run command') + .help('help') + .updateStrings({ + 'Commands:': 'My Commands -->\n' + }) + .wrap(null) + .argv +``` + +*** + +```shell +My Commands --> + + run the run command + +Options: + --help Show help [boolean] +``` + +If you explicitly specify a `locale()`, you should do so *before* calling +`updateStrings()`. + +.usage(message, [opts]) +--------------------- + +Set a usage message to show which commands to use. Inside `message`, the string +`$0` will get interpolated to the current script name or node command for the +present script similar to how `$0` works in bash or perl. + +`opts` is optional and acts like calling `.options(opts)`. + +.version(version, [option], [description]) +---------------------------------------- + +Add an option (e.g. `--version`) that displays the version number (given by the +`version` parameter) and exits the process. If present, the `description` +parameter customizes the description of the version option in the usage string. + +You can provide a `function` for version, rather than a string. +This is useful if you want to use the version from your package.json: + +```js +var argv = require('yargs') + .version(function() { + return require('../package').version; + }) + .argv; +``` + +.wrap(columns) +-------------- + +Format usage output to wrap at `columns` many columns. + +By default wrap will be set to `Math.min(80, windowWidth)`. Use `.wrap(null)` to +specify no column limit (no right-align). Use `.wrap(yargs.terminalWidth())` to +maximize the width of yargs' usage instructions. + +parsing tricks +============== + +stop parsing +------------ + +Use `--` to stop parsing flags and stuff the remainder into `argv._`. + + $ node examples/reflect.js -a 1 -b 2 -- -c 3 -d 4 + { _: [ '-c', '3', '-d', '4' ], + a: 1, + b: 2, + '$0': 'examples/reflect.js' } + +negate fields +------------- + +If you want to explicity set a field to false instead of just leaving it +undefined or to override a default you can do `--no-key`. + + $ node examples/reflect.js -a --no-b + { _: [], a: true, b: false, '$0': 'examples/reflect.js' } + +numbers +------- + +Every argument that looks like a number (`!isNaN(Number(arg))`) is converted to +one. This way you can just `net.createConnection(argv.port)` and you can add +numbers out of `argv` with `+` without having that mean concatenation, +which is super frustrating. + +duplicates +---------- + +If you specify a flag multiple times it will get turned into an array containing +all the values in order. + + $ node examples/reflect.js -x 5 -x 8 -x 0 + { _: [], x: [ 5, 8, 0 ], '$0': 'examples/reflect.js' } + +dot notation +------------ + +When you use dots (`.`s) in argument names, an implicit object path is assumed. +This lets you organize arguments into nested objects. + + $ node examples/reflect.js --foo.bar.baz=33 --foo.quux=5 + { _: [], + foo: { bar: { baz: 33 }, quux: 5 }, + '$0': 'examples/reflect.js' } + +short numbers +------------- + +Short numeric `-n5` style arguments work too: + + $ node examples/reflect.js -n123 -m456 + { _: [], n: 123, m: 456, '$0': 'examples/reflect.js' } + +installation +============ + +With [npm](http://github.com/isaacs/npm), just do: + + npm install yargs + +or clone this project on github: + + git clone http://github.com/bcoe/yargs.git + +To run the tests with npm, just do: + + npm test + +inspired by +=========== + +This module is loosely inspired by Perl's +[Getopt::Casual](http://search.cpan.org/~photo/Getopt-Casual-0.13.1/Casual.pm). + + + +[travis-url]: https://travis-ci.org/bcoe/yargs +[travis-image]: https://img.shields.io/travis/bcoe/yargs.svg +[gemnasium-url]: https://gemnasium.com/bcoe/yargs +[gemnasium-image]: https://img.shields.io/gemnasium/bcoe/yargs.svg +[coveralls-url]: https://coveralls.io/github/bcoe/yargs +[coveralls-image]: https://img.shields.io/coveralls/bcoe/yargs.svg +[npm-url]: https://npmjs.org/package/yargs +[npm-image]: https://img.shields.io/npm/v/yargs.svg diff --git a/wrt/node_modules/yargs/completion.sh.hbs b/wrt/node_modules/yargs/completion.sh.hbs new file mode 100644 index 0000000..8392ad5 --- /dev/null +++ b/wrt/node_modules/yargs/completion.sh.hbs @@ -0,0 +1,28 @@ +###-begin-{{app_name}}-completions-### +# +# yargs command completion script +# +# Installation: {{app_path}} completion >> ~/.bashrc +# or {{app_path}} completion >> ~/.bash_profile on OSX. +# +_yargs_completions() +{ + local cur_word args type_list + + cur_word="${COMP_WORDS[COMP_CWORD]}" + args=$(printf "%s " "${COMP_WORDS[@]}") + + # ask yargs to generate completions. + type_list=`{{app_path}} --get-yargs-completions $args` + + COMPREPLY=( $(compgen -W "${type_list}" -- ${cur_word}) ) + + # if no match was found, fall back to filename completion + if [ ${#COMPREPLY[@]} -eq 0 ]; then + COMPREPLY=( $(compgen -f -- "${cur_word}" ) ) + fi + + return 0 +} +complete -F _yargs_completions {{app_name}} +###-end-{{app_name}}-completions-### diff --git a/wrt/node_modules/yargs/index.js b/wrt/node_modules/yargs/index.js new file mode 100644 index 0000000..0376469 --- /dev/null +++ b/wrt/node_modules/yargs/index.js @@ -0,0 +1,564 @@ +var assert = require('assert') +var Completion = require('./lib/completion') +var Parser = require('./lib/parser') +var path = require('path') +var Usage = require('./lib/usage') +var Validation = require('./lib/validation') +var Y18n = require('y18n') + +Argv(process.argv.slice(2)) + +var exports = module.exports = Argv +function Argv (processArgs, cwd) { + processArgs = processArgs || [] // handle calling yargs(). + + var self = {} + var completion = null + var usage = null + var validation = null + var y18n = Y18n({ + directory: path.resolve(__dirname, './locales'), + locale: 'en', + updateFiles: false + }) + + if (!cwd) cwd = process.cwd() + + self.$0 = process.argv + .slice(0, 2) + .map(function (x, i) { + // ignore the node bin, specify this in your + // bin file with #!/usr/bin/env node + if (i === 0 && /\b(node|iojs)$/.test(x)) return + var b = rebase(cwd, x) + return x.match(/^\//) && b.length < x.length + ? b : x + }) + .join(' ').trim() + + if (process.env._ !== undefined && process.argv[1] === process.env._) { + self.$0 = process.env._.replace( + path.dirname(process.execPath) + '/', '' + ) + } + + var options + self.resetOptions = self.reset = function () { + // put yargs back into its initial + // state, this is useful for creating a + // nested CLI. + options = { + array: [], + boolean: [], + string: [], + narg: {}, + key: {}, + alias: {}, + default: {}, + defaultDescription: {}, + choices: {}, + requiresArg: [], + count: [], + normalize: [], + config: [] + } + + usage = Usage(self, y18n) // handle usage output. + validation = Validation(self, usage, y18n) // handle arg validation. + completion = Completion(self, usage) + + demanded = {} + + exitProcess = true + strict = false + helpOpt = null + versionOpt = null + commandHandlers = {} + self.parsed = false + + return self + } + self.resetOptions() + + self.boolean = function (bools) { + options.boolean.push.apply(options.boolean, [].concat(bools)) + return self + } + + self.array = function (arrays) { + options.array.push.apply(options.array, [].concat(arrays)) + return self + } + + self.nargs = function (key, n) { + if (typeof key === 'object') { + Object.keys(key).forEach(function (k) { + self.nargs(k, key[k]) + }) + } else { + options.narg[key] = n + } + return self + } + + self.choices = function (key, values) { + if (typeof key === 'object') { + Object.keys(key).forEach(function (k) { + self.choices(k, key[k]) + }) + } else { + options.choices[key] = (options.choices[key] || []).concat(values) + } + return self + } + + self.normalize = function (strings) { + options.normalize.push.apply(options.normalize, [].concat(strings)) + return self + } + + self.config = function (key, msg) { + self.describe(key, msg || usage.deferY18nLookup('Path to JSON config file')) + options.config.push.apply(options.config, [].concat(key)) + return self + } + + self.example = function (cmd, description) { + usage.example(cmd, description) + return self + } + + self.command = function (cmd, description, fn) { + if (description !== false) { + usage.command(cmd, description) + } + if (fn) commandHandlers[cmd] = fn + return self + } + + var commandHandlers = {} + self.getCommandHandlers = function () { + return commandHandlers + } + + self.string = function (strings) { + options.string.push.apply(options.string, [].concat(strings)) + return self + } + + self.default = function (key, value, defaultDescription) { + if (typeof key === 'object') { + Object.keys(key).forEach(function (k) { + self.default(k, key[k]) + }) + } else { + if (typeof value === 'function') { + defaultDescription = usage.functionDescription(value, defaultDescription) + value = value.call() + } + options.defaultDescription[key] = defaultDescription + options.default[key] = value + } + return self + } + + self.alias = function (x, y) { + if (typeof x === 'object') { + Object.keys(x).forEach(function (key) { + self.alias(key, x[key]) + }) + } else { + options.alias[x] = (options.alias[x] || []).concat(y) + } + return self + } + + self.count = function (counts) { + options.count.push.apply(options.count, [].concat(counts)) + return self + } + + var demanded = {} + self.demand = self.required = self.require = function (keys, max, msg) { + // you can optionally provide a 'max' key, + // which will raise an exception if too many '_' + // options are provided. + if (typeof max !== 'number') { + msg = max + max = Infinity + } + + if (typeof keys === 'number') { + if (!demanded._) demanded._ = { count: 0, msg: null, max: max } + demanded._.count = keys + demanded._.msg = msg + } else if (Array.isArray(keys)) { + keys.forEach(function (key) { + self.demand(key, msg) + }) + } else { + if (typeof msg === 'string') { + demanded[keys] = { msg: msg } + } else if (msg === true || typeof msg === 'undefined') { + demanded[keys] = { msg: undefined } + } + } + + return self + } + self.getDemanded = function () { + return demanded + } + + self.requiresArg = function (requiresArgs) { + options.requiresArg.push.apply(options.requiresArg, [].concat(requiresArgs)) + return self + } + + self.implies = function (key, value) { + validation.implies(key, value) + return self + } + + self.usage = function (msg, opts) { + if (!opts && typeof msg === 'object') { + opts = msg + msg = null + } + + usage.usage(msg) + + if (opts) self.options(opts) + + return self + } + + self.epilogue = self.epilog = function (msg) { + usage.epilog(msg) + return self + } + + self.fail = function (f) { + usage.failFn(f) + return self + } + + self.check = function (f) { + validation.check(f) + return self + } + + self.defaults = self.default + + self.describe = function (key, desc) { + options.key[key] = true + usage.describe(key, desc) + return self + } + + self.parse = function (args) { + return parseArgs(args) + } + + self.option = self.options = function (key, opt) { + if (typeof key === 'object') { + Object.keys(key).forEach(function (k) { + self.options(k, key[k]) + }) + } else { + assert(typeof opt === 'object', 'second argument to option must be an object') + + options.key[key] = true // track manually set keys. + + if (opt.alias) self.alias(key, opt.alias) + + var demand = opt.demand || opt.required || opt.require + + if (demand) { + self.demand(key, demand) + } if ('config' in opt) { + self.config(key) + } if ('default' in opt) { + self.default(key, opt.default) + } if ('nargs' in opt) { + self.nargs(key, opt.nargs) + } if ('choices' in opt) { + self.choices(key, opt.choices) + } if (opt.boolean || opt.type === 'boolean') { + self.boolean(key) + if (opt.alias) self.boolean(opt.alias) + } if (opt.array || opt.type === 'array') { + self.array(key) + if (opt.alias) self.array(opt.alias) + } if (opt.string || opt.type === 'string') { + self.string(key) + if (opt.alias) self.string(opt.alias) + } if (opt.count || opt.type === 'count') { + self.count(key) + } + + var desc = opt.describe || opt.description || opt.desc + if (desc) { + self.describe(key, desc) + } + + if (opt.requiresArg) { + self.requiresArg(key) + } + } + + return self + } + self.getOptions = function () { + return options + } + + self.wrap = function (cols) { + usage.wrap(cols) + return self + } + + var strict = false + self.strict = function () { + strict = true + return self + } + self.getStrict = function () { + return strict + } + + self.showHelp = function (level) { + if (!self.parsed) parseArgs(processArgs) // run parser, if it has not already been executed. + usage.showHelp(level) + return self + } + + var versionOpt = null + self.version = function (ver, opt, msg) { + versionOpt = opt || 'version' + usage.version(ver) + self.boolean(versionOpt) + self.describe(versionOpt, msg || usage.deferY18nLookup('Show version number')) + return self + } + + var helpOpt = null + self.addHelpOpt = function (opt, msg) { + helpOpt = opt + self.boolean(opt) + self.describe(opt, msg || usage.deferY18nLookup('Show help')) + return self + } + + self.showHelpOnFail = function (enabled, message) { + usage.showHelpOnFail(enabled, message) + return self + } + + var exitProcess = true + self.exitProcess = function (enabled) { + if (typeof enabled !== 'boolean') { + enabled = true + } + exitProcess = enabled + return self + } + self.getExitProcess = function () { + return exitProcess + } + + self.help = function () { + if (arguments.length > 0) return self.addHelpOpt.apply(self, arguments) + + if (!self.parsed) parseArgs(processArgs) // run parser, if it has not already been executed. + + return usage.help() + } + + var completionCommand = null + self.completion = function (cmd, desc, fn) { + // a function to execute when generating + // completions can be provided as the second + // or third argument to completion. + if (typeof desc === 'function') { + fn = desc + desc = null + } + + // register the completion command. + completionCommand = cmd || 'completion' + if (!desc && desc !== false) { + desc = 'generate bash completion script' + } + self.command(completionCommand, desc) + + // a function can be provided + if (fn) completion.registerFunction(fn) + + return self + } + + self.showCompletionScript = function ($0) { + $0 = $0 || self.$0 + console.log(completion.generateCompletionScript($0)) + return self + } + + self.locale = function (locale) { + y18n.setLocale(locale) + return self + } + + self.updateStrings = self.updateLocale = function (obj) { + y18n.updateLocale(obj) + return self + } + + self.getUsageInstance = function () { + return usage + } + + self.getValidationInstance = function () { + return validation + } + + self.terminalWidth = function () { + return require('window-size').width + } + + Object.defineProperty(self, 'argv', { + get: function () { + var args = null + + try { + args = parseArgs(processArgs) + } catch (err) { + usage.fail(err.message) + } + + return args + }, + enumerable: true + }) + + function parseArgs (args) { + var parsed = Parser(args, options, y18n) + var argv = parsed.argv + var aliases = parsed.aliases + + argv.$0 = self.$0 + + self.parsed = parsed + + // while building up the argv object, there + // are two passes through the parser. If completion + // is being performed short-circuit on the first pass. + if (completionCommand && + (process.argv.join(' ')).indexOf(completion.completionKey) !== -1 && + !argv[completion.completionKey]) { + return argv + } + + // if there's a handler associated with a + // command defer processing to it. + var handlerKeys = Object.keys(self.getCommandHandlers()) + for (var i = 0, command; (command = handlerKeys[i]) !== undefined; i++) { + if (~argv._.indexOf(command)) { + self.getCommandHandlers()[command](self.reset()) + return self.argv + } + } + + // generate a completion script for adding to ~/.bashrc. + if (completionCommand && ~argv._.indexOf(completionCommand) && !argv[completion.completionKey]) { + self.showCompletionScript() + if (exitProcess) { + process.exit(0) + } + } + + // we must run completions first, a user might + // want to complete the --help or --version option. + if (completion.completionKey in argv) { + // we allow for asynchronous completions, + // e.g., loading in a list of commands from an API. + completion.getCompletion(function (completions) { + ;(completions || []).forEach(function (completion) { + console.log(completion) + }) + + if (exitProcess) { + process.exit(0) + } + }) + return + } + + Object.keys(argv).forEach(function (key) { + if (key === helpOpt && argv[key]) { + self.showHelp('log') + if (exitProcess) { + process.exit(0) + } + } else if (key === versionOpt && argv[key]) { + usage.showVersion() + if (exitProcess) { + process.exit(0) + } + } + }) + + if (parsed.error) throw parsed.error + + // if we're executed via bash completion, don't + // bother with validation. + if (!argv[completion.completionKey]) { + validation.nonOptionCount(argv) + validation.missingArgumentValue(argv) + validation.requiredArguments(argv) + if (strict) validation.unknownArguments(argv, aliases) + validation.customChecks(argv, aliases) + validation.limitedChoices(argv) + validation.implications(argv) + } + + setPlaceholderKeys(argv) + + return argv + } + + function setPlaceholderKeys (argv) { + Object.keys(options.key).forEach(function (key) { + if (typeof argv[key] === 'undefined') argv[key] = undefined + }) + } + + sigletonify(self) + return self +} + +// rebase an absolute path to a relative one with respect to a base directory +// exported for tests +exports.rebase = rebase +function rebase (base, dir) { + return path.relative(base, dir) +} + +/* Hack an instance of Argv with process.argv into Argv + so people can do + require('yargs')(['--beeble=1','-z','zizzle']).argv + to parse a list of args and + require('yargs').argv + to get a parsed version of process.argv. +*/ +function sigletonify (inst) { + Object.keys(inst).forEach(function (key) { + if (key === 'argv') { + Argv.__defineGetter__(key, inst.__lookupGetter__(key)) + } else { + Argv[key] = typeof inst[key] === 'function' + ? inst[key].bind(inst) + : inst[key] + } + }) +} diff --git a/wrt/node_modules/yargs/lib/completion.js b/wrt/node_modules/yargs/lib/completion.js new file mode 100644 index 0000000..33e9b75 --- /dev/null +++ b/wrt/node_modules/yargs/lib/completion.js @@ -0,0 +1,80 @@ +var fs = require('fs') +var path = require('path') + +// add bash completions to your +// yargs-powered applications. +module.exports = function (yargs, usage) { + var self = { + completionKey: 'get-yargs-completions' + } + + // get a list of completion commands. + self.getCompletion = function (done) { + var completions = [] + var current = process.argv[process.argv.length - 1] + var previous = process.argv.slice(process.argv.indexOf('--' + self.completionKey) + 1) + var argv = yargs.parse(previous) + + // a custom completion function can be provided + // to completion(). + if (completionFunction) { + if (completionFunction.length < 3) { + // synchronous completion function. + return done(completionFunction(current, argv)) + } else { + // asynchronous completion function + return completionFunction(current, argv, function (completions) { + done(completions) + }) + } + } + + var handlers = yargs.getCommandHandlers() + for (var i = 0, ii = previous.length; i < ii; ++i) { + if (handlers[previous[i]]) { + return handlers[previous[i]](yargs.reset()) + } + } + + if (!current.match(/^-/)) { + usage.getCommands().forEach(function (command) { + if (previous.indexOf(command[0]) === -1) { + completions.push(command[0]) + } + }) + } + + if (current.match(/^-/)) { + Object.keys(yargs.getOptions().key).forEach(function (key) { + completions.push('--' + key) + }) + } + + done(completions) + } + + // generate the completion script to add to your .bashrc. + self.generateCompletionScript = function ($0) { + var script = fs.readFileSync( + path.resolve(__dirname, '../completion.sh.hbs'), + 'utf-8' + ) + var name = path.basename($0) + + // add ./to applications not yet installed as bin. + if ($0.match(/\.js$/)) $0 = './' + $0 + + script = script.replace(/{{app_name}}/g, name) + return script.replace(/{{app_path}}/g, $0) + } + + // register a function to perform your own custom + // completions., this function can be either + // synchrnous or asynchronous. + var completionFunction = null + self.registerFunction = function (fn) { + completionFunction = fn + } + + return self +} diff --git a/wrt/node_modules/yargs/lib/parser.js b/wrt/node_modules/yargs/lib/parser.js new file mode 100644 index 0000000..145c57e --- /dev/null +++ b/wrt/node_modules/yargs/lib/parser.js @@ -0,0 +1,467 @@ +// fancy-pants parsing of argv, originally forked +// from minimist: https://www.npmjs.com/package/minimist +var camelCase = require('camelcase') +var path = require('path') + +function increment (orig) { + return orig !== undefined ? orig + 1 : 0 +} + +module.exports = function (args, opts, y18n) { + if (!opts) opts = {} + + var __ = y18n.__ + var error = null + var flags = { arrays: {}, bools: {}, strings: {}, counts: {}, normalize: {}, configs: {}, defaulted: {} } + + ;[].concat(opts['array']).filter(Boolean).forEach(function (key) { + flags.arrays[key] = true + }) + + ;[].concat(opts['boolean']).filter(Boolean).forEach(function (key) { + flags.bools[key] = true + }) + + ;[].concat(opts.string).filter(Boolean).forEach(function (key) { + flags.strings[key] = true + }) + + ;[].concat(opts.count).filter(Boolean).forEach(function (key) { + flags.counts[key] = true + }) + + ;[].concat(opts.normalize).filter(Boolean).forEach(function (key) { + flags.normalize[key] = true + }) + + ;[].concat(opts.config).filter(Boolean).forEach(function (key) { + flags.configs[key] = true + }) + + var aliases = {} + var newAliases = {} + + extendAliases(opts.key) + extendAliases(opts.alias) + + var defaults = opts['default'] || {} + Object.keys(defaults).forEach(function (key) { + if (/-/.test(key) && !opts.alias[key]) { + aliases[key] = aliases[key] || [] + } + (aliases[key] || []).forEach(function (alias) { + defaults[alias] = defaults[key] + }) + }) + + var argv = { _: [] } + + Object.keys(flags.bools).forEach(function (key) { + setArg(key, !(key in defaults) ? false : defaults[key]) + setDefaulted(key) + }) + + var notFlags = [] + if (args.indexOf('--') !== -1) { + notFlags = args.slice(args.indexOf('--') + 1) + args = args.slice(0, args.indexOf('--')) + } + + for (var i = 0; i < args.length; i++) { + var arg = args[i] + var broken + var key + var letters + var m + var next + var value + + // -- seperated by = + if (arg.match(/^--.+=/)) { + // Using [\s\S] instead of . because js doesn't support the + // 'dotall' regex modifier. See: + // http://stackoverflow.com/a/1068308/13216 + m = arg.match(/^--([^=]+)=([\s\S]*)$/) + + // nargs format = '--f=monkey washing cat' + if (checkAllAliases(m[1], opts.narg)) { + args.splice(i + 1, m[1], m[2]) + i = eatNargs(i, m[1], args) + // arrays format = '--f=a b c' + } else if (checkAllAliases(m[1], flags.arrays) && args.length > i + 1) { + args.splice(i + 1, m[1], m[2]) + i = eatArray(i, m[1], args) + } else { + setArg(m[1], m[2]) + } + } else if (arg.match(/^--no-.+/)) { + key = arg.match(/^--no-(.+)/)[1] + setArg(key, false) + + // -- seperated by space. + } else if (arg.match(/^--.+/)) { + key = arg.match(/^--(.+)/)[1] + + // nargs format = '--foo a b c' + if (checkAllAliases(key, opts.narg)) { + i = eatNargs(i, key, args) + // array format = '--foo a b c' + } else if (checkAllAliases(key, flags.arrays) && args.length > i + 1) { + i = eatArray(i, key, args) + } else { + next = args[i + 1] + + if (next !== undefined && !next.match(/^-/) && + !checkAllAliases(key, flags.bools) && + !checkAllAliases(key, flags.counts)) { + setArg(key, next) + i++ + } else if (/^(true|false)$/.test(next)) { + setArg(key, next) + i++ + } else { + setArg(key, defaultForType(guessType(key, flags))) + } + } + + // dot-notation flag seperated by '='. + } else if (arg.match(/^-.\..+=/)) { + m = arg.match(/^-([^=]+)=([\s\S]*)$/) + setArg(m[1], m[2]) + + // dot-notation flag seperated by space. + } else if (arg.match(/^-.\..+/)) { + next = args[i + 1] + key = arg.match(/^-(.\..+)/)[1] + + if (next !== undefined && !next.match(/^-/) && + !checkAllAliases(key, flags.bools) && + !checkAllAliases(key, flags.counts)) { + setArg(key, next) + i++ + } else { + setArg(key, defaultForType(guessType(key, flags))) + } + } else if (arg.match(/^-[^-]+/)) { + letters = arg.slice(1, -1).split('') + broken = false + + for (var j = 0; j < letters.length; j++) { + next = arg.slice(j + 2) + + if (letters[j + 1] && letters[j + 1] === '=') { + value = arg.slice(j + 3) + key = letters[j] + + // nargs format = '-f=monkey washing cat' + if (checkAllAliases(letters[j], opts.narg)) { + args.splice(i + 1, 0, value) + i = eatNargs(i, key, args) + // array format = '-f=a b c' + } else if (checkAllAliases(key, flags.arrays) && args.length > i + 1) { + args.splice(i + 1, 0, value) + i = eatArray(i, key, args) + } else { + setArg(key, value) + } + + broken = true + break + } + + if (next === '-') { + setArg(letters[j], next) + continue + } + + if (/[A-Za-z]/.test(letters[j]) && + /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) { + setArg(letters[j], next) + broken = true + break + } + + if (letters[j + 1] && letters[j + 1].match(/\W/)) { + setArg(letters[j], arg.slice(j + 2)) + broken = true + break + } else { + setArg(letters[j], defaultForType(guessType(letters[j], flags))) + } + } + + key = arg.slice(-1)[0] + + if (!broken && key !== '-') { + // nargs format = '-f a b c' + if (checkAllAliases(key, opts.narg)) { + i = eatNargs(i, key, args) + // array format = '-f a b c' + } else if (checkAllAliases(key, flags.arrays) && args.length > i + 1) { + i = eatArray(i, key, args) + } else { + if (args[i + 1] && !/^(-|--)[^-]/.test(args[i + 1]) && + !checkAllAliases(key, flags.bools) && + !checkAllAliases(key, flags.counts)) { + setArg(key, args[i + 1]) + i++ + } else if (args[i + 1] && /true|false/.test(args[i + 1])) { + setArg(key, args[i + 1]) + i++ + } else { + setArg(key, defaultForType(guessType(key, flags))) + } + } + } + } else { + argv._.push( + flags.strings['_'] || !isNumber(arg) ? arg : Number(arg) + ) + } + } + + setConfig(argv) + applyDefaultsAndAliases(argv, aliases, defaults) + + Object.keys(flags.counts).forEach(function (key) { + setArg(key, defaults[key]) + }) + + notFlags.forEach(function (key) { + argv._.push(key) + }) + + // how many arguments should we consume, based + // on the nargs option? + function eatNargs (i, key, args) { + var toEat = checkAllAliases(key, opts.narg) + + if (args.length - (i + 1) < toEat) error = Error(__('Not enough arguments following: %s', key)) + + for (var ii = i + 1; ii < (toEat + i + 1); ii++) { + setArg(key, args[ii]) + } + + return (i + toEat) + } + + // if an option is an array, eat all non-hyphenated arguments + // following it... YUM! + // e.g., --foo apple banana cat becomes ["apple", "banana", "cat"] + function eatArray (i, key, args) { + for (var ii = i + 1; ii < args.length; ii++) { + if (/^-/.test(args[ii])) break + i = ii + setArg(key, args[ii]) + } + + return i + } + + function setArg (key, val) { + unsetDefaulted(key) + + // handle parsing boolean arguments --foo=true --bar false. + if (checkAllAliases(key, flags.bools) || checkAllAliases(key, flags.counts)) { + if (typeof val === 'string') val = val === 'true' + } + + if (/-/.test(key) && !(aliases[key] && aliases[key].length)) { + var c = camelCase(key) + aliases[key] = [c] + newAliases[c] = true + } + + var value = !checkAllAliases(key, flags.strings) && isNumber(val) ? Number(val) : val + + if (checkAllAliases(key, flags.counts)) { + value = increment + } + + var splitKey = key.split('.') + setKey(argv, splitKey, value) + + ;(aliases[splitKey[0]] || []).forEach(function (x) { + x = x.split('.') + + // handle populating dot notation for both + // the key and its aliases. + if (splitKey.length > 1) { + var a = [].concat(splitKey) + a.shift() // nuke the old key. + x = x.concat(a) + } + + setKey(argv, x, value) + }) + + var keys = [key].concat(aliases[key] || []) + for (var i = 0, l = keys.length; i < l; i++) { + if (flags.normalize[keys[i]]) { + keys.forEach(function (key) { + argv.__defineSetter__(key, function (v) { + val = path.normalize(v) + }) + + argv.__defineGetter__(key, function () { + return typeof val === 'string' ? + path.normalize(val) : val + }) + }) + break + } + } + } + + // set args from config.json file, this should be + // applied last so that defaults can be applied. + function setConfig (argv) { + var configLookup = {} + + // expand defaults/aliases, in-case any happen to reference + // the config.json file. + applyDefaultsAndAliases(configLookup, aliases, defaults) + + Object.keys(flags.configs).forEach(function (configKey) { + var configPath = argv[configKey] || configLookup[configKey] + if (configPath) { + try { + var config = require(path.resolve(process.cwd(), configPath)) + + Object.keys(config).forEach(function (key) { + // setting arguments via CLI takes precedence over + // values within the config file. + if (argv[key] === undefined || (flags.defaulted[key])) { + delete argv[key] + setArg(key, config[key]) + } + }) + } catch (ex) { + if (argv[configKey]) error = Error(__('Invalid JSON config file: %s', configPath)) + } + } + }) + } + + function applyDefaultsAndAliases (obj, aliases, defaults) { + Object.keys(defaults).forEach(function (key) { + if (!hasKey(obj, key.split('.'))) { + setKey(obj, key.split('.'), defaults[key]) + + ;(aliases[key] || []).forEach(function (x) { + setKey(obj, x.split('.'), defaults[key]) + }) + } + }) + } + + function hasKey (obj, keys) { + var o = obj + keys.slice(0, -1).forEach(function (key) { + o = (o[key] || {}) + }) + + var key = keys[keys.length - 1] + return key in o + } + + function setKey (obj, keys, value) { + var o = obj + keys.slice(0, -1).forEach(function (key) { + if (o[key] === undefined) o[key] = {} + o = o[key] + }) + + var key = keys[keys.length - 1] + if (value === increment) { + o[key] = increment(o[key]) + } else if (o[key] === undefined && checkAllAliases(key, flags.arrays)) { + o[key] = Array.isArray(value) ? value : [value] + } else if (o[key] === undefined || typeof o[key] === 'boolean') { + o[key] = value + } else if (Array.isArray(o[key])) { + o[key].push(value) + } else { + o[key] = [ o[key], value ] + } + } + + // extend the aliases list with inferred aliases. + function extendAliases (obj) { + Object.keys(obj || {}).forEach(function (key) { + aliases[key] = [].concat(opts.alias[key] || []) + // For "--option-name", also set argv.optionName + aliases[key].concat(key).forEach(function (x) { + if (/-/.test(x)) { + var c = camelCase(x) + aliases[key].push(c) + newAliases[c] = true + } + }) + aliases[key].forEach(function (x) { + aliases[x] = [key].concat(aliases[key].filter(function (y) { + return x !== y + })) + }) + }) + } + + // check if a flag is set for any of a key's aliases. + function checkAllAliases (key, flag) { + var isSet = false + var toCheck = [].concat(aliases[key] || [], key) + + toCheck.forEach(function (key) { + if (flag[key]) isSet = flag[key] + }) + + return isSet + } + + function setDefaulted (key) { + [].concat(aliases[key] || [], key).forEach(function (k) { + flags.defaulted[k] = true + }) + } + + function unsetDefaulted (key) { + [].concat(aliases[key] || [], key).forEach(function (k) { + delete flags.defaulted[k] + }) + } + + // return a default value, given the type of a flag., + // e.g., key of type 'string' will default to '', rather than 'true'. + function defaultForType (type) { + var def = { + boolean: true, + string: '', + array: [] + } + + return def[type] + } + + // given a flag, enforce a default type. + function guessType (key, flags) { + var type = 'boolean' + + if (flags.strings && flags.strings[key]) type = 'string' + else if (flags.arrays && flags.arrays[key]) type = 'array' + + return type + } + + function isNumber (x) { + if (typeof x === 'number') return true + if (/^0x[0-9a-f]+$/i.test(x)) return true + return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x) + } + + return { + argv: argv, + aliases: aliases, + error: error, + newAliases: newAliases + } +} diff --git a/wrt/node_modules/yargs/lib/usage.js b/wrt/node_modules/yargs/lib/usage.js new file mode 100644 index 0000000..e0af2be --- /dev/null +++ b/wrt/node_modules/yargs/lib/usage.js @@ -0,0 +1,339 @@ +// this file handles outputting usage instructions, +// failures, etc. keeps logging in one place. +var cliui = require('cliui') +var decamelize = require('decamelize') +var wsize = require('window-size') + +module.exports = function (yargs, y18n) { + var __ = y18n.__ + var self = {} + + // methods for ouputting/building failure message. + var fails = [] + self.failFn = function (f) { + fails.push(f) + } + + var failMessage = null + var showHelpOnFail = true + self.showHelpOnFail = function (enabled, message) { + if (typeof enabled === 'string') { + message = enabled + enabled = true + } else if (typeof enabled === 'undefined') { + enabled = true + } + failMessage = message + showHelpOnFail = enabled + return self + } + + self.fail = function (msg) { + if (fails.length) { + fails.forEach(function (f) { + f(msg) + }) + } else { + if (showHelpOnFail) yargs.showHelp('error') + if (msg) console.error(msg) + if (failMessage) { + if (msg) console.error('') + console.error(failMessage) + } + if (yargs.getExitProcess()) { + process.exit(1) + } else { + throw new Error(msg) + } + } + } + + // methods for ouputting/building help (usage) message. + var usage + self.usage = function (msg) { + usage = msg + } + + var examples = [] + self.example = function (cmd, description) { + examples.push([cmd, description || '']) + } + + var commands = [] + self.command = function (cmd, description) { + commands.push([cmd, description || '']) + } + self.getCommands = function () { + return commands + } + + var descriptions = {} + self.describe = function (key, desc) { + if (typeof key === 'object') { + Object.keys(key).forEach(function (k) { + self.describe(k, key[k]) + }) + } else { + descriptions[key] = desc + } + } + self.getDescriptions = function () { + return descriptions + } + + var epilog + self.epilog = function (msg) { + epilog = msg + } + + var wrap = windowWidth() + self.wrap = function (cols) { + wrap = cols + } + + var deferY18nLookupPrefix = '__yargsString__:' + self.deferY18nLookup = function (str) { + return deferY18nLookupPrefix + str + } + + self.help = function () { + normalizeAliases() + + var demanded = yargs.getDemanded() + var options = yargs.getOptions() + var keys = Object.keys( + Object.keys(descriptions) + .concat(Object.keys(demanded)) + .concat(Object.keys(options.default)) + .reduce(function (acc, key) { + if (key !== '_') acc[key] = true + return acc + }, {}) + ) + var ui = cliui({ + width: wrap, + wrap: !!wrap + }) + + // the usage string. + if (usage) { + var u = usage.replace(/\$0/g, yargs.$0) + ui.div(u + '\n') + } + + // your application's commands, i.e., non-option + // arguments populated in '_'. + if (commands.length) { + ui.div(__('Commands:')) + + commands.forEach(function (command) { + ui.div( + {text: command[0], padding: [0, 2, 0, 2], width: maxWidth(commands) + 4}, + {text: command[1]} + ) + }) + + ui.div() + } + + // the options table. + var aliasKeys = (Object.keys(options.alias) || []) + .concat(Object.keys(yargs.parsed.newAliases) || []) + + keys = keys.filter(function (key) { + return !yargs.parsed.newAliases[key] && aliasKeys.every(function (alias) { + return (options.alias[alias] || []).indexOf(key) === -1 + }) + }) + + var switches = keys.reduce(function (acc, key) { + acc[key] = [ key ].concat(options.alias[key] || []) + .map(function (sw) { + return (sw.length > 1 ? '--' : '-') + sw + }) + .join(', ') + + return acc + }, {}) + + if (keys.length) { + ui.div(__('Options:')) + + keys.forEach(function (key) { + var kswitch = switches[key] + var desc = descriptions[key] || '' + var type = null + + if (~desc.lastIndexOf(deferY18nLookupPrefix)) desc = __(desc.substring(deferY18nLookupPrefix.length)) + + if (~options.boolean.indexOf(key)) type = '[' + __('boolean') + ']' + if (~options.count.indexOf(key)) type = '[' + __('count') + ']' + if (~options.string.indexOf(key)) type = '[' + __('string') + ']' + if (~options.normalize.indexOf(key)) type = '[' + __('string') + ']' + if (~options.array.indexOf(key)) type = '[' + __('array') + ']' + + var extra = [ + type, + demanded[key] ? '[' + __('required') + ']' : null, + options.choices && options.choices[key] ? '[' + __('choices:') + ' ' + + self.stringifiedValues(options.choices[key]) + ']' : null, + defaultString(options.default[key], options.defaultDescription[key]) + ].filter(Boolean).join(' ') + + ui.span( + {text: kswitch, padding: [0, 2, 0, 2], width: maxWidth(switches) + 4}, + desc + ) + + if (extra) ui.div({text: extra, padding: [0, 0, 0, 2], align: 'right'}) + else ui.div() + }) + + ui.div() + } + + // describe some common use-cases for your application. + if (examples.length) { + ui.div(__('Examples:')) + + examples.forEach(function (example) { + example[0] = example[0].replace(/\$0/g, yargs.$0) + }) + + examples.forEach(function (example) { + ui.div( + {text: example[0], padding: [0, 2, 0, 2], width: maxWidth(examples) + 4}, + example[1] + ) + }) + + ui.div() + } + + // the usage string. + if (epilog) { + var e = epilog.replace(/\$0/g, yargs.$0) + ui.div(e + '\n') + } + + return ui.toString() + } + + // return the maximum width of a string + // in the left-hand column of a table. + function maxWidth (table) { + var width = 0 + + // table might be of the form [leftColumn], + // or {key: leftColumn}} + if (!Array.isArray(table)) { + table = Object.keys(table).map(function (key) { + return [table[key]] + }) + } + + table.forEach(function (v) { + width = Math.max(v[0].length, width) + }) + + // if we've enabled 'wrap' we should limit + // the max-width of the left-column. + if (wrap) width = Math.min(width, parseInt(wrap * 0.5, 10)) + + return width + } + + // make sure any options set for aliases, + // are copied to the keys being aliased. + function normalizeAliases () { + var demanded = yargs.getDemanded() + var options = yargs.getOptions() + + ;(Object.keys(options.alias) || []).forEach(function (key) { + options.alias[key].forEach(function (alias) { + // copy descriptions. + if (descriptions[alias]) self.describe(key, descriptions[alias]) + // copy demanded. + if (demanded[alias]) yargs.demand(key, demanded[alias].msg) + + // type messages. + if (~options.boolean.indexOf(alias)) yargs.boolean(key) + if (~options.count.indexOf(alias)) yargs.count(key) + if (~options.string.indexOf(alias)) yargs.string(key) + if (~options.normalize.indexOf(alias)) yargs.normalize(key) + if (~options.array.indexOf(alias)) yargs.array(key) + }) + }) + } + + self.showHelp = function (level) { + level = level || 'error' + console[level](self.help()) + } + + self.functionDescription = function (fn, defaultDescription) { + if (defaultDescription) { + return defaultDescription + } + var description = fn.name ? decamelize(fn.name, '-') : __('generated-value') + return ['(', description, ')'].join('') + } + + self.stringifiedValues = function (values, separator) { + var string = '' + var sep = separator || ', ' + var array = [].concat(values) + + if (!values || !array.length) return string + + array.forEach(function (value) { + if (string.length) string += sep + string += JSON.stringify(value) + }) + + return string + } + + // format the default-value-string displayed in + // the right-hand column. + function defaultString (value, defaultDescription) { + var string = '[' + __('default:') + ' ' + + if (value === undefined) return null + + if (defaultDescription) { + string += defaultDescription + } else { + switch (typeof value) { + case 'string': + string += JSON.stringify(value) + break + case 'object': + string += JSON.stringify(value) + break + default: + string += value + } + } + + return string + ']' + } + + // guess the width of the console window, max-width 80. + function windowWidth () { + return wsize.width ? Math.min(80, wsize.width) : null + } + + // logic for displaying application version. + var version = null + self.version = function (ver, opt, msg) { + version = ver + } + + self.showVersion = function () { + if (typeof version === 'function') console.log(version()) + else console.log(version) + } + + return self +} diff --git a/wrt/node_modules/yargs/lib/validation.js b/wrt/node_modules/yargs/lib/validation.js new file mode 100644 index 0000000..514bbff --- /dev/null +++ b/wrt/node_modules/yargs/lib/validation.js @@ -0,0 +1,249 @@ +// validation-type-stuff, missing params, +// bad implications, custom checks. +module.exports = function (yargs, usage, y18n) { + var __ = y18n.__ + var __n = y18n.__n + var self = {} + + // validate appropriate # of non-option + // arguments were provided, i.e., '_'. + self.nonOptionCount = function (argv) { + var demanded = yargs.getDemanded() + var _s = argv._.length + + if (demanded._ && (_s < demanded._.count || _s > demanded._.max)) { + if (demanded._.msg !== undefined) { + usage.fail(demanded._.msg) + } else if (_s < demanded._.count) { + usage.fail( + __('Not enough non-option arguments: got %s, need at least %s', argv._.length, demanded._.count) + ) + } else { + usage.fail( + __('Too many non-option arguments: got %s, maximum of %s', argv._.length, demanded._.max) + ) + } + } + } + + // make sure that any args that require an + // value (--foo=bar), have a value. + self.missingArgumentValue = function (argv) { + var defaultValues = [true, false, ''] + var options = yargs.getOptions() + + if (options.requiresArg.length > 0) { + var missingRequiredArgs = [] + + options.requiresArg.forEach(function (key) { + var value = argv[key] + + // if a value is explicitly requested, + // flag argument as missing if it does not + // look like foo=bar was entered. + if (~defaultValues.indexOf(value) || + (Array.isArray(value) && !value.length)) { + missingRequiredArgs.push(key) + } + }) + + if (missingRequiredArgs.length > 0) { + usage.fail(__n( + 'Missing argument value: %s', + 'Missing argument values: %s', + missingRequiredArgs.length, + missingRequiredArgs.join(', ') + )) + } + } + } + + // make sure all the required arguments are present. + self.requiredArguments = function (argv) { + var demanded = yargs.getDemanded() + var missing = null + + Object.keys(demanded).forEach(function (key) { + if (!argv.hasOwnProperty(key)) { + missing = missing || {} + missing[key] = demanded[key] + } + }) + + if (missing) { + var customMsgs = [] + Object.keys(missing).forEach(function (key) { + var msg = missing[key].msg + if (msg && customMsgs.indexOf(msg) < 0) { + customMsgs.push(msg) + } + }) + + var customMsg = customMsgs.length ? '\n' + customMsgs.join('\n') : '' + + usage.fail(__n( + 'Missing required argument: %s', + 'Missing required arguments: %s', + Object.keys(missing).length, + Object.keys(missing).join(', ') + customMsg + )) + } + } + + // check for unknown arguments (strict-mode). + self.unknownArguments = function (argv, aliases) { + var aliasLookup = {} + var descriptions = usage.getDescriptions() + var demanded = yargs.getDemanded() + var unknown = [] + + Object.keys(aliases).forEach(function (key) { + aliases[key].forEach(function (alias) { + aliasLookup[alias] = key + }) + }) + + Object.keys(argv).forEach(function (key) { + if (key !== '$0' && key !== '_' && + !descriptions.hasOwnProperty(key) && + !demanded.hasOwnProperty(key) && + !aliasLookup.hasOwnProperty(key)) { + unknown.push(key) + } + }) + + if (unknown.length > 0) { + usage.fail(__n( + 'Unknown argument: %s', + 'Unknown arguments: %s', + unknown.length, + unknown.join(', ') + )) + } + } + + // validate arguments limited to enumerated choices + self.limitedChoices = function (argv) { + var options = yargs.getOptions() + var invalid = {} + + if (!Object.keys(options.choices).length) return + + Object.keys(argv).forEach(function (key) { + if (key !== '$0' && key !== '_' && + options.choices.hasOwnProperty(key)) { + [].concat(argv[key]).forEach(function (value) { + // TODO case-insensitive configurability + if (options.choices[key].indexOf(value) === -1) { + invalid[key] = (invalid[key] || []).concat(value) + } + }) + } + }) + + var invalidKeys = Object.keys(invalid) + + if (!invalidKeys.length) return + + var msg = __('Invalid values:') + invalidKeys.forEach(function (key) { + msg += '\n ' + __( + 'Argument: %s, Given: %s, Choices: %s', + key, + usage.stringifiedValues(invalid[key]), + usage.stringifiedValues(options.choices[key]) + ) + }) + usage.fail(msg) + } + + // custom checks, added using the `check` option on yargs. + var checks = [] + self.check = function (f) { + checks.push(f) + } + + self.customChecks = function (argv, aliases) { + checks.forEach(function (f) { + try { + var result = f(argv, aliases) + if (!result) { + usage.fail(__('Argument check failed: %s', f.toString())) + } else if (typeof result === 'string') { + usage.fail(result) + } + } catch (err) { + usage.fail(err.message ? err.message : err) + } + }) + } + + // check implications, argument foo implies => argument bar. + var implied = {} + self.implies = function (key, value) { + if (typeof key === 'object') { + Object.keys(key).forEach(function (k) { + self.implies(k, key[k]) + }) + } else { + implied[key] = value + } + } + self.getImplied = function () { + return implied + } + + self.implications = function (argv) { + var implyFail = [] + + Object.keys(implied).forEach(function (key) { + var num + var origKey = key + var value = implied[key] + + // convert string '1' to number 1 + num = Number(key) + key = isNaN(num) ? key : num + + if (typeof key === 'number') { + // check length of argv._ + key = argv._.length >= key + } else if (key.match(/^--no-.+/)) { + // check if key doesn't exist + key = key.match(/^--no-(.+)/)[1] + key = !argv[key] + } else { + // check if key exists + key = argv[key] + } + + num = Number(value) + value = isNaN(num) ? value : num + + if (typeof value === 'number') { + value = argv._.length >= value + } else if (value.match(/^--no-.+/)) { + value = value.match(/^--no-(.+)/)[1] + value = !argv[value] + } else { + value = argv[value] + } + + if (key && !value) { + implyFail.push(origKey) + } + }) + + if (implyFail.length) { + var msg = __('Implications failed:') + '\n' + + implyFail.forEach(function (key) { + msg += (' ' + key + ' -> ' + implied[key]) + }) + + usage.fail(msg) + } + } + + return self +} diff --git a/wrt/node_modules/yargs/locales/en.json b/wrt/node_modules/yargs/locales/en.json new file mode 100644 index 0000000..ce19199 --- /dev/null +++ b/wrt/node_modules/yargs/locales/en.json @@ -0,0 +1,36 @@ +{ + "Commands:": "Commands:", + "Options:": "Options:", + "Examples:": "Examples:", + "boolean": "boolean", + "count": "count", + "string": "string", + "array": "array", + "required": "required", + "default:": "default:", + "choices:": "choices:", + "generated-value": "generated-value", + "Not enough non-option arguments: got %s, need at least %s": "Not enough non-option arguments: got %s, need at least %s", + "Too many non-option arguments: got %s, maximum of %s": "Too many non-option arguments: got %s, maximum of %s", + "Missing argument value: %s": { + "one": "Missing argument value: %s", + "other": "Missing argument values: %s" + }, + "Missing required argument: %s": { + "one": "Missing required argument: %s", + "other": "Missing required arguments: %s" + }, + "Unknown argument: %s": { + "one": "Unknown argument: %s", + "other": "Unknown arguments: %s" + }, + "Invalid values:": "Invalid values:", + "Argument: %s, Given: %s, Choices: %s": "Argument: %s, Given: %s, Choices: %s", + "Argument check failed: %s": "Argument check failed: %s", + "Implications failed:": "Implications failed:", + "Not enough arguments following: %s": "Not enough arguments following: %s", + "Invalid JSON config file: %s": "Invalid JSON config file: %s", + "Path to JSON config file": "Path to JSON config file", + "Show help": "Show help", + "Show version number": "Show version number" +} diff --git a/wrt/node_modules/yargs/locales/es.json b/wrt/node_modules/yargs/locales/es.json new file mode 100644 index 0000000..c4f1917 --- /dev/null +++ b/wrt/node_modules/yargs/locales/es.json @@ -0,0 +1,36 @@ +{ + "Commands:": "Comandos:", + "Options:": "Opciones:", + "Examples:": "Ejemplos:", + "boolean": "boolean", + "count": "cuenta", + "string": "cadena de caracteres", + "array": "tabla", + "required": "requisito", + "default:": "defecto:", + "choices:": "selección:", + "generated-value": "valor-generado", + "Not enough non-option arguments: got %s, need at least %s": "Hacen falta argumentos no-opcionales: Número recibido %s, necesita por lo menos %s", + "Too many non-option arguments: got %s, maximum of %s": "Demasiados argumentos no-opcionales: Número recibido %s, máximo es %s", + "Missing argument value: %s": { + "one": "Falta argumento: %s", + "other": "Faltan argumentos: %s" + }, + "Missing required argument: %s": { + "one": "Falta argumento requerido: %s", + "other": "Faltan argumentos requeridos: %s" + }, + "Unknown argument: %s": { + "one": "Argumento desconocido: %s", + "other": "Argumentos desconocidos: %s" + }, + "Invalid values:": "Valores inválidos:", + "Argument: %s, Given: %s, Choices: %s": "Argumento: %s, Recibido: %s, Selección: %s", + "Argument check failed: %s": "Verificación de argumento ha fracasado: %s", + "Implications failed:": "Implicaciones fracasadas:", + "Not enough arguments following: %s": "No hay suficientes argumentos después de: %s", + "Invalid JSON config file: %s": "Archivo de configuración JSON inválido: %s", + "Path to JSON config file": "Ruta al archivo de configuración JSON", + "Show help": "Muestra ayuda", + "Show version number": "Muestra número de versión" +} diff --git a/wrt/node_modules/yargs/locales/fr.json b/wrt/node_modules/yargs/locales/fr.json new file mode 100644 index 0000000..49d068b --- /dev/null +++ b/wrt/node_modules/yargs/locales/fr.json @@ -0,0 +1,36 @@ +{ + "Commands:": "Commandes:", + "Options:": "Options:", + "Examples:": "Exemples:", + "boolean": "booléen", + "count": "comptage", + "string": "chaine de caractère", + "array": "tableau", + "required": "requis", + "default:": "défaut:", + "choices:": "choix:", + "generated-value": "valeur générée", + "Not enough non-option arguments: got %s, need at least %s": "Pas assez d'arguments non-option: reçu %s, besoin d'au moins %s", + "Too many non-option arguments: got %s, maximum of %s": "Trop d'arguments non-option: reçu %s, maximum %s", + "Missing argument value: %s": { + "one": "Argument manquant: %s", + "other": "Arguments manquants: %s" + }, + "Missing required argument: %s": { + "one": "Argument requis manquant: %s", + "other": "Arguments requis manquants: %s" + }, + "Unknown argument: %s": { + "one": "Argument inconnu: %s", + "other": "Arguments inconnus: %s" + }, + "Invalid values:": "Valeurs invalides:", + "Argument: %s, Given: %s, Choices: %s": "Argument: %s, Donné: %s, Choix: %s", + "Argument check failed: %s": "Echec de la vérification de l'argument: %s", + "Implications failed:": "Implications échouées:", + "Not enough arguments following: %s": "Pas assez d'arguments suivant: %s", + "Invalid JSON config file: %s": "Fichier de configuration JSON invalide: %s", + "Path to JSON config file": "Chemin du fichier de configuration JSON", + "Show help": "Affiche de l'aide", + "Show version number": "Affiche le numéro de version" +} diff --git a/wrt/node_modules/yargs/locales/pirate.json b/wrt/node_modules/yargs/locales/pirate.json new file mode 100644 index 0000000..1f4e19e --- /dev/null +++ b/wrt/node_modules/yargs/locales/pirate.json @@ -0,0 +1,12 @@ +{ + "Commands:": "Choose yer command:", + "Options:": "Options for me hearties!", + "Examples:": "Ex. marks the spot:", + "required": "requi-yar-ed", + "Missing required argument: %s": { + "one": "Ye be havin' to set the followin' argument land lubber: %s", + "other": "Ye be havin' to set the followin' arguments land lubber: %s" + }, + "Show help": "Parlay this here code of conduct", + "Show version number": "'Tis the version ye be askin' fer" +} diff --git a/wrt/node_modules/yargs/locales/pt.json b/wrt/node_modules/yargs/locales/pt.json new file mode 100644 index 0000000..6abbcd4 --- /dev/null +++ b/wrt/node_modules/yargs/locales/pt.json @@ -0,0 +1,36 @@ +{ + "Commands:": "Comandos:", + "Options:": "Opções:", + "Examples:": "Exemplos:", + "boolean": "boolean", + "count": "contagem", + "string": "cadeia de caracteres", + "array": "arranjo", + "required": "requerido", + "default:": "padrão:", + "choices:": "escolhas:", + "generated-value": "valor-gerado", + "Not enough non-option arguments: got %s, need at least %s": "Argumentos insuficientes não opcionais: Argumento %s, necessário pelo menos %s", + "Too many non-option arguments: got %s, maximum of %s": "Excesso de argumentos não opcionais: recebido %s, máximo de %s", + "Missing argument value: %s": { + "one": "Falta valor de argumento: %s", + "other": "Falta valores de argumento: %s" + }, + "Missing required argument: %s": { + "one": "Falta argumento obrigatório: %s", + "other": "Faltando argumentos obrigatórios: %s" + }, + "Unknown argument: %s": { + "one": "Argumento desconhecido: %s", + "other": "Argumentos desconhecidos: %s" + }, + "Invalid values:": "Valores inválidos:", + "Argument: %s, Given: %s, Choices: %s": "Argumento: %s, Dado: %s, Escolhas: %s", + "Argument check failed: %s": "Verificação de argumento falhou: %s", + "Implications failed:": "Implicações falharam:", + "Not enough arguments following: %s": "Insuficientes argumentos a seguir: %s", + "Invalid JSON config file: %s": "Arquivo de configuração em JSON esta inválido: %s", + "Path to JSON config file": "Caminho para o arquivo de configuração em JSON", + "Show help": "Mostra ajuda", + "Show version number": "Mostra número de versão" +} diff --git a/wrt/node_modules/yargs/package.json b/wrt/node_modules/yargs/package.json new file mode 100644 index 0000000..a98701c --- /dev/null +++ b/wrt/node_modules/yargs/package.json @@ -0,0 +1,167 @@ +{ + "_args": [ + [ + { + "raw": "yargs@3.19.0", + "scope": null, + "escapedName": "yargs", + "name": "yargs", + "rawSpec": "3.19.0", + "spec": "3.19.0", + "type": "version" + }, + "/home/sources/5.0/crosswalk-tizen/wrt" + ] + ], + "_from": "yargs@3.19.0", + "_id": "yargs@3.19.0", + "_inCache": true, + "_location": "/yargs", + "_nodeVersion": "2.0.2", + "_npmUser": { + "name": "bcoe", + "email": "ben@npmjs.com" + }, + "_npmVersion": "2.13.2", + "_phantomChildren": {}, + "_requested": { + "raw": "yargs@3.19.0", + "scope": null, + "escapedName": "yargs", + "name": "yargs", + "rawSpec": "3.19.0", + "spec": "3.19.0", + "type": "version" + }, + "_requiredBy": [ + "#DEV:/" + ], + "_resolved": "https://registry.npmjs.org/yargs/-/yargs-3.19.0.tgz", + "_shasum": "35a5a841a6fe70f3fabbb88dd6d9ebfb56db5320", + "_shrinkwrap": null, + "_spec": "yargs@3.19.0", + "_where": "/home/sources/5.0/crosswalk-tizen/wrt", + "author": { + "name": "Alex Ford", + "email": "Alex.Ford@CodeTunnel.com", + "url": "http://CodeTunnel.com" + }, + "bugs": { + "url": "https://github.com/bcoe/yargs/issues" + }, + "contributors": [ + { + "name": "Benjamin Coe", + "email": "ben@npmjs.com", + "url": "https://github.com/bcoe" + }, + { + "name": "Andrew Goode", + "url": "https://github.com/nexdrew" + }, + { + "name": "Chris Needham", + "email": "chris@chrisneedham.com", + "url": "http://chrisneedham.com" + }, + { + "name": "James Nylen", + "email": "jnylen@gmail.com", + "url": "https://github.com/nylen" + }, + { + "name": "Benjamin Horsleben", + "url": "https://github.com/fizker" + }, + { + "name": "Lin Clark", + "url": "https://github.com/linclark" + }, + { + "name": "Tim Schaub", + "url": "https://github.com/tschaub" + } + ], + "dependencies": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "^0.1.1", + "y18n": "^3.0.0" + }, + "description": "Light-weight option parsing with an argv hash. No optstrings attached.", + "devDependencies": { + "chai": "^3.0.0", + "coveralls": "^2.11.2", + "hashish": "0.0.4", + "mocha": "^2.2.1", + "nyc": "^3.1.0", + "standard": "^5.0.2" + }, + "directories": {}, + "dist": { + "shasum": "35a5a841a6fe70f3fabbb88dd6d9ebfb56db5320", + "tarball": "https://registry.npmjs.org/yargs/-/yargs-3.19.0.tgz" + }, + "engine": { + "node": ">=0.4" + }, + "files": [ + "index.js", + "lib", + "locales", + "completion.sh.hbs", + "LICENSE" + ], + "gitHead": "c17c3b41ddeab725d1c7d7646342bb85fc2280ef", + "homepage": "https://github.com/bcoe/yargs#readme", + "keywords": [ + "argument", + "args", + "option", + "parser", + "parsing", + "cli", + "command" + ], + "license": "MIT", + "main": "./index.js", + "maintainers": [ + { + "name": "chevex", + "email": "alex.ford@codetunnel.com" + }, + { + "name": "bcoe", + "email": "ben@npmjs.com" + }, + { + "name": "nylen", + "email": "jnylen@gmail.com" + }, + { + "name": "abg", + "email": "andrewbgoode@gmail.com" + } + ], + "name": "yargs", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/bcoe/yargs.git" + }, + "scripts": { + "coverage": "nyc report --reporter=text-lcov | coveralls", + "test": "standard && nyc mocha --check-leaks" + }, + "standard": { + "ignore": [ + "**/example/**" + ], + "globals": [ + "it" + ] + }, + "version": "3.19.0" +} -- 2.7.4 From fd80b9a284b4e8fcbf0787ce457a0e1c93498bc0 Mon Sep 17 00:00:00 2001 From: deepti Date: Tue, 20 Mar 2018 12:08:50 +0530 Subject: [PATCH 02/16] Handling App Control Data Change-Id: I42374c5f69b6ed749889dfc14f04240924309639 Signed-off-by: deepti --- atom/app/ui_runtime.cc | 6 ++++++ atom/browser/browser.cc | 16 +++++++++++++++- atom/browser/browser.h | 8 ++++++-- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/atom/app/ui_runtime.cc b/atom/app/ui_runtime.cc index c85a63f..44cacf7 100644 --- a/atom/app/ui_runtime.cc +++ b/atom/app/ui_runtime.cc @@ -67,6 +67,12 @@ void UiRuntime::OnAppControl(app_control_h app_control) { common::AppDB* appdb = common::AppDB::GetInstance(); appdb->Set(kAppDBRuntimeSection, kAppDBRuntimeBundle, appcontrol->encoded_bundle()); + atom::Browser *browser_model = atom::Browser::Get(); + if (browser_model->is_ready()) { + browser_model->AppControl(std::move(appcontrol)); + } else { + browser_model->Launch(std::move(appcontrol)); + } } void UiRuntime::OnLanguageChanged(const std::string& language) { diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 42cc787..6de6ca1 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -15,7 +15,7 @@ #include "base/run_loop.h" #include "base/threading/thread_task_runner_handle.h" #include "brightray/browser/brightray_paths.h" - +#include "tizen/common/resource_manager.h" namespace atom { Browser::Browser() @@ -222,5 +222,19 @@ void Browser::Show() { for (BrowserObserver& observer : observers_) observer.OnResume(); } +void Browser::AppControl( + std::unique_ptr appcontrol) { + std::unique_ptr res = + resource_manager_->GetStartResource(appcontrol.get()); + + bool do_reset = res->should_reset(); +//To do +} +void Browser::Launch(std::unique_ptr appcontrol) { +//To do +} + + + } // namespace atom diff --git a/atom/browser/browser.h b/atom/browser/browser.h index fc674dd..08de521 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -16,7 +16,9 @@ #include "base/strings/string16.h" #include "base/values.h" #include "native_mate/arguments.h" - +#include "tizen/common/app_control.h" +#include "tizen/common/application_data.h" +#include "tizen/common/resource_manager.h" #if defined(OS_WIN) #include "base/files/file_path.h" #endif @@ -41,7 +43,7 @@ class Browser : public WindowListObserver { ~Browser(); static Browser* Get(); - + std::unique_ptr resource_manager_; // Try to close all windows and quit the application. void Quit(); @@ -106,6 +108,8 @@ class Browser : public WindowListObserver { void Hide(); void Show(); + void AppControl(std::unique_ptr appcontrol); + void Launch(std::unique_ptr appcontrol); #if defined(OS_MACOSX) // Hide the application. void Hide(); -- 2.7.4 From 8052db6ce78c7428a17bc98784b063519e6467b9 Mon Sep 17 00:00:00 2001 From: jaekuk lee Date: Tue, 27 Mar 2018 05:15:14 +0000 Subject: [PATCH 03/16] Revert "Handling App Control Data" This reverts commit fd80b9a284b4e8fcbf0787ce457a0e1c93498bc0. Change-Id: Ifdbad4f988f46c92ea5ffbde5a61ac4c69006c03 --- atom/app/ui_runtime.cc | 6 ------ atom/browser/browser.cc | 16 +--------------- atom/browser/browser.h | 8 ++------ 3 files changed, 3 insertions(+), 27 deletions(-) diff --git a/atom/app/ui_runtime.cc b/atom/app/ui_runtime.cc index 44cacf7..c85a63f 100644 --- a/atom/app/ui_runtime.cc +++ b/atom/app/ui_runtime.cc @@ -67,12 +67,6 @@ void UiRuntime::OnAppControl(app_control_h app_control) { common::AppDB* appdb = common::AppDB::GetInstance(); appdb->Set(kAppDBRuntimeSection, kAppDBRuntimeBundle, appcontrol->encoded_bundle()); - atom::Browser *browser_model = atom::Browser::Get(); - if (browser_model->is_ready()) { - browser_model->AppControl(std::move(appcontrol)); - } else { - browser_model->Launch(std::move(appcontrol)); - } } void UiRuntime::OnLanguageChanged(const std::string& language) { diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 6de6ca1..42cc787 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -15,7 +15,7 @@ #include "base/run_loop.h" #include "base/threading/thread_task_runner_handle.h" #include "brightray/browser/brightray_paths.h" -#include "tizen/common/resource_manager.h" + namespace atom { Browser::Browser() @@ -222,19 +222,5 @@ void Browser::Show() { for (BrowserObserver& observer : observers_) observer.OnResume(); } -void Browser::AppControl( - std::unique_ptr appcontrol) { - std::unique_ptr res = - resource_manager_->GetStartResource(appcontrol.get()); - - bool do_reset = res->should_reset(); -//To do -} -void Browser::Launch(std::unique_ptr appcontrol) { -//To do -} - - - } // namespace atom diff --git a/atom/browser/browser.h b/atom/browser/browser.h index 08de521..fc674dd 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -16,9 +16,7 @@ #include "base/strings/string16.h" #include "base/values.h" #include "native_mate/arguments.h" -#include "tizen/common/app_control.h" -#include "tizen/common/application_data.h" -#include "tizen/common/resource_manager.h" + #if defined(OS_WIN) #include "base/files/file_path.h" #endif @@ -43,7 +41,7 @@ class Browser : public WindowListObserver { ~Browser(); static Browser* Get(); - std::unique_ptr resource_manager_; + // Try to close all windows and quit the application. void Quit(); @@ -108,8 +106,6 @@ class Browser : public WindowListObserver { void Hide(); void Show(); - void AppControl(std::unique_ptr appcontrol); - void Launch(std::unique_ptr appcontrol); #if defined(OS_MACOSX) // Hide the application. void Hide(); -- 2.7.4 From 4acf39405c71b9eb3248d13a9ee77ac8ce7d7807 Mon Sep 17 00:00:00 2001 From: SangYong Park Date: Tue, 27 Mar 2018 21:52:19 +0900 Subject: [PATCH 04/16] Cleanup build script and gyp files Minimize change of electron's code (Later patch will be fixed brightray's gyp files.) Change-Id: I2cae341abeddd812c0997d91b90e94ff36aab46e Signed-off-by: SangYong Park --- atom/app/atom_main_delegate.cc | 2 +- common.gypi | 27 --- efl/build/system.gyp | 4 +- electron.gyp | 141 ++----------- filenames.gypi | 23 -- packaging/electron-efl.manifest | 2 +- packaging/electron-efl.spec | 23 +- script/bootstrap.py | 21 +- script/build-libchromiumcontent.py | 2 +- script/build.py | 7 +- script/clean.py | 3 +- script/update.py | 9 +- tizen/common.gypi | 43 ++++ tizen/loader/wrt_loader.cc | 2 +- tizen/script/build | 1 - tizen/src/wrt_main.cc | 231 +++++++++++++++++++++ tizen/src/wrt_main.h | 10 + vendor/brightray/brightray.gyp | 4 +- vendor/brightray/brightray.gypi | 5 - vendor/brightray/script/bootstrap | 20 +- .../vendor/libchromiumcontent/script/build | 3 +- .../vendor/libchromiumcontent/script/create-dist | 3 +- .../vendor/libchromiumcontent/script/download | 15 +- .../vendor/libchromiumcontent/script/update | 12 +- .../tools/generate_filenames_gypi.py | 37 +--- wrt.gyp | 201 ++++++++++++++++++ 26 files changed, 565 insertions(+), 286 deletions(-) create mode 100644 tizen/common.gypi create mode 100644 tizen/src/wrt_main.cc create mode 100644 tizen/src/wrt_main.h create mode 100644 wrt.gyp diff --git a/atom/app/atom_main_delegate.cc b/atom/app/atom_main_delegate.cc index e102cc3..9f9ac69 100644 --- a/atom/app/atom_main_delegate.cc +++ b/atom/app/atom_main_delegate.cc @@ -114,7 +114,7 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) { void AtomMainDelegate::PreSandboxStartup() { brightray::MainDelegate::PreSandboxStartup(); - PathService::Override(base::FILE_EXE, base::FilePath("/usr/bin/electron")); + PathService::Override(base::FILE_EXE, base::FilePath("/usr/bin/wrt")); // Set google API key. std::unique_ptr env(base::Environment::Create()); diff --git a/common.gypi b/common.gypi index 125bcb1..9f0a6f0 100644 --- a/common.gypi +++ b/common.gypi @@ -1,7 +1,6 @@ { 'includes': [ 'vendor/brightray/brightray.gypi', - 'efl/features.gypi', ], 'conditions': [ ['use_efl!=1', { @@ -22,10 +21,6 @@ 'python': 'python', 'openssl_fips': '', 'openssl_no_asm': 1, - 'use_efl%': 0, - 'desktop_linux%': 0, - 'is_tizen%': 0, - 'tizen_product_tv%': 0, 'use_openssl_def': 0, 'OPENSSL_PRODUCT': 'libopenssl.a', 'node_release_urlbase': 'https://atom.io/download/atom-shell', @@ -141,7 +136,6 @@ }], ['_target_name=="node"', { 'include_dirs': [ - '/usr/include/v8', '<(libchromiumcontent_src_dir)', '<(libchromiumcontent_src_dir)/third_party/icu/source/common', '<(libchromiumcontent_src_dir)/third_party/icu/source/i18n', @@ -280,26 +274,5 @@ }, }, }], # OS=="mac" - ['is_tizen==1', { - 'target_defaults': { - 'defines': [ - 'OS_TIZEN', - ], - }, - }], # is_tizen==1 - ['tizen_product_tv==1', { - 'target_defaults': { - 'defines': [ - 'OS_TIZEN_TV_PRODUCT', - ], - }, - }], # tizen_product_tv==1 - ['use_efl==1', { - 'target_defaults': { - 'defines': [ - 'USE_EFL', - ], - }, - }], # is_tizen==1 ], } diff --git a/efl/build/system.gyp b/efl/build/system.gyp index 3e0f94f..32c429f 100644 --- a/efl/build/system.gyp +++ b/efl/build/system.gyp @@ -32,7 +32,7 @@ 'target_name': 'ecore-x', 'type': 'none', 'conditions': [ - ['desktop_linux==1', { + ['is_tizen!=1', { 'direct_dependent_settings': { 'cflags': [ ' - + diff --git a/packaging/electron-efl.spec b/packaging/electron-efl.spec index 67b8cef..f26da7c 100755 --- a/packaging/electron-efl.spec +++ b/packaging/electron-efl.spec @@ -70,8 +70,7 @@ cp %{SOURCE1001} . %define _xmldir %TZ_SYS_RO_PACKAGES %define _out out.tizen/out/D -export DEFINE_ARGS=" - desktop_linux=0 +DEFINE_ARGS=" libchromiumcontent_component=1 use_efl=1 is_tizen=1 @@ -84,14 +83,16 @@ DEFINE_ARGS+=" %if "%{?skipbootstrap}" != "1" ./script/bootstrap.py \ - --libcc_chromium_efl_path /usr/lib \ + --libcc_source_path ./vendor/brightray/vendor/libchromiumcontent/src \ + --libcc_shared_library_path /usr/lib \ + --libcc_static_library_path /usr/lib \ --define "${DEFINE_ARGS}" \ --dev \ --disable_clang \ -v %endif -./script/build.py -c D +./script/build.py -c D -t wrt %install install -d %{_out}/packaging @@ -116,18 +117,17 @@ install -d %{buildroot}/%{_icondir} install -d %{buildroot}/%{_libdir} install -d %{buildroot}/%{_bindir} install -m 0644 packaging/%{_pkgid}.png %{buildroot}/%{_icondir} -install -m 0755 %{_out}/libnode.so %{buildroot}/%{_libdir} +install -m 0755 %{_out}/lib/libnode.so %{buildroot}/%{_libdir} install -m 0755 %{_out}/wrt-loader %{buildroot}/%{_bindir} -install -m 0755 %{_out}/electron %{buildroot}/%{_bindir} +install -m 0755 %{_out}/wrt %{buildroot}/%{_bindir} + +ln -s %{_bindir}/wrt %{buildroot}%{_bindir}/wrt-client +ln -s %{_bindir}/wrt %{buildroot}%{_bindir}/xwalk_runtime # install resource. -mkdir -p %{buildroot}/opt/usr/home/owner/data/org.tizen.electron-efl/wrt_release +mkdir -p %{buildroot}/opt/usr/home/owner/data/org.tizen.electron-efl install -m 0755 %{_out}/resources/electron.asar %{buildroot}/opt/usr/home/owner/data/org.tizen.electron-efl -ln -s %{_bindir}/electron %{buildroot}%{_bindir}/wrt -ln -s %{_bindir}/electron %{buildroot}%{_bindir}/wrt-client -ln -s %{_bindir}/electron %{buildroot}%{_bindir}/xwalk_runtime - ./node_modules/asar/bin/asar p wrt %{_out}/resources/app.asar install -m 0755 %{_out}/resources/app.asar %{buildroot}/opt/usr/home/owner/data/org.tizen.electron-efl @@ -155,7 +155,6 @@ rm -fr %{buildroot} %{_icondir}/%{_pkgid}.png %{_libdir}/libnode.so %{_xmldir}/%{_pkgid}.xml -%attr(755,root,root) %{_bindir}/electron %attr(755,root,root) %{_bindir}/wrt %attr(755,root,root) %{_bindir}/wrt-client %attr(755,root,root) %{_bindir}/wrt-loader diff --git a/script/bootstrap.py b/script/bootstrap.py index ba7f31a..20de36b 100755 --- a/script/bootstrap.py +++ b/script/bootstrap.py @@ -31,7 +31,8 @@ def main(): if sys.platform == 'cygwin': update_win32_python() - if args.libcc_chromium_efl_path == None: + use_efl = 'use_efl=1' in [d.strip() for d in defines.split(' ')] + if not use_efl: update_submodules() libcc_source_path = args.libcc_source_path @@ -47,26 +48,26 @@ def main(): libcc_shared_library_path = os.path.join(dist_dir, 'shared_library') libcc_static_library_path = os.path.join(dist_dir, 'static_library') - if PLATFORM != 'win32' and args.libcc_chromium_efl_path == None: + if PLATFORM != 'win32': if not args.disable_clang and args.clang_dir == '': # Download prebuilt clang binaries. update_clang() - if os.path.isfile('/etc/tizen-release') != True: + if PLATFORM != 'tizen': setup_python_libs() - if args.libcc_chromium_efl_path == None: + if not use_efl: update_node_modules('.') bootstrap_brightray(args.dev, args.url, args.target_arch, libcc_source_path, libcc_shared_library_path, - libcc_static_library_path, args.libcc_chromium_efl_path) + libcc_static_library_path) - if PLATFORM == 'linux' and args.libcc_chromium_efl_path == None: + if PLATFORM == 'linux' and not use_efl: download_sysroot(args.target_arch) create_chrome_version_h() touch_config_gypi() run_update(defines, args.msvs) - if args.libcc_chromium_efl_path == None: + if not use_efl: update_electron_modules('spec', args.target_arch) @@ -106,8 +107,6 @@ def parse_args(): help='The static library path of libchromiumcontent.') parser.add_argument('--defines', default='', help='The build variables passed to gyp') - parser.add_argument('--libcc_chromium_efl_path', required=False, - help='The shared library path of chromium-efl.') return parser.parse_args() @@ -142,7 +141,7 @@ def setup_python_libs(): def bootstrap_brightray(is_dev, url, target_arch, libcc_source_path, libcc_shared_library_path, - libcc_static_library_path, libcc_chromium_efl_path): + libcc_static_library_path): bootstrap = os.path.join(VENDOR_DIR, 'brightray', 'script', 'bootstrap') args = [ '--commit', LIBCHROMIUMCONTENT_COMMIT, @@ -157,8 +156,6 @@ def bootstrap_brightray(is_dev, url, target_arch, libcc_source_path, args += ['--libcc_source_path', libcc_source_path, '--libcc_shared_library_path', libcc_shared_library_path, '--libcc_static_library_path', libcc_static_library_path] - if libcc_chromium_efl_path != None: - args += ['--libcc_chromium_efl_path', libcc_chromium_efl_path] execute_stdout([sys.executable, bootstrap] + args) diff --git a/script/build-libchromiumcontent.py b/script/build-libchromiumcontent.py index e04a3b6..e0a95f6 100755 --- a/script/build-libchromiumcontent.py +++ b/script/build-libchromiumcontent.py @@ -29,7 +29,7 @@ def main(): build = os.path.join(script_dir, 'build') create_dist = os.path.join(script_dir, 'create-dist') execute_stdout([sys.executable, bootstrap]) - execute_stdout([sys.executable, update, '-t', args.target_arch, '-N', + execute_stdout([sys.executable, update, '-t', args.target_arch, '--defines', args.defines]) execute_stdout([sys.executable, build, '-R', '-t', args.target_arch]) execute_stdout([sys.executable, create_dist, '-c', 'static_library', diff --git a/script/build.py b/script/build.py index b130211..80f266d 100755 --- a/script/build.py +++ b/script/build.py @@ -5,7 +5,7 @@ import os import subprocess import sys -from lib.config import get_target_arch +from lib.config import PLATFORM, get_target_arch from lib.util import electron_gyp, import_vs_env @@ -20,13 +20,14 @@ def main(): import_vs_env(get_target_arch()) ninja = os.path.join('vendor', 'depot_tools', 'ninja') - ninja = 'ninja' if sys.platform == 'win32': ninja += '.exe' + if PLATFORM == 'tizen': + ninja = 'ninja' args = parse_args() for config in args.configuration: - if os.path.isfile('/etc/tizen-release'): + if PLATFORM == 'tizen': build_path = os.path.join('out.tizen', 'out', config[0]) else: build_path = os.path.join('out', config[0]) diff --git a/script/clean.py b/script/clean.py index 703a2b4..aaa77ea 100755 --- a/script/clean.py +++ b/script/clean.py @@ -4,6 +4,7 @@ import argparse import os import sys +from lib.config import PLATFORM from lib.util import rm_rf @@ -16,7 +17,7 @@ def main(): args = parse_args() remove_directory('dist') - if os.path.isfile('/etc/tizen-release'): + if PLATFORM == 'tizen': remove_directory('out.tizen') else: remove_directory('out') diff --git a/script/update.py b/script/update.py index e172c4c..5c9c957 100755 --- a/script/update.py +++ b/script/update.py @@ -41,7 +41,6 @@ def update_external_binaries(): def update_gyp(): - print 'update gyp !!!' # Since gyp doesn't support specify link_settings for each configuration, # we are not able to link to different libraries in "Debug" and "Release" # configurations. @@ -89,18 +88,18 @@ def run_gyp(target_arch, component): # Add the defines passed from command line. args = parse_args() - use_efl=0 for define in [d.strip() for d in args.defines.split(' ')]: if define: - if define == 'use_efl=1': - use_efl=1 defines += ['-D' + define] generator = 'ninja' if args.msvs: generator = 'msvs-ninja' - print "GYP defines ::: ", defines + if 'use_efl=1' in [d.strip() for d in args.defines.split(' ')]: + return subprocess.call([python, gyp, '-f', generator, '--depth', '.', + 'wrt.gyp', '-I' + os.path.join('tizen', 'common.gypi')] + defines, env=env) + return subprocess.call([python, gyp, '-f', generator, '--depth', '.', 'electron.gyp', '-Icommon.gypi'] + defines, env=env) diff --git a/tizen/common.gypi b/tizen/common.gypi new file mode 100644 index 0000000..b0c2055 --- /dev/null +++ b/tizen/common.gypi @@ -0,0 +1,43 @@ +{ + 'includes': [ + '../common.gypi', + '../efl/features.gypi', + ], + 'variables': { + 'clang%': 0, + 'use_efl%': 0, + 'is_tizen%': 0, + 'tizen_product_tv%': 0, + }, + 'conditions': [ + ['use_efl==1', { + 'target_defaults': { + 'defines': [ + 'USE_EFL', + ], + }, + 'variables': { + 'js_sources': [ + '<(DEPTH)/lib/browser/api/pwrt.js', + ], + }, + }], # use_efl==1 + ['is_tizen==1', { + 'target_defaults': { + 'defines': [ + 'OS_TIZEN', + ], + }, + 'variables': { + 'libchromiumcontent_libraries': '/usr/lib/libchromium-ewk.so', + }, + }], # is_tizen==1 + ['tizen_product_tv==1', { + 'target_defaults': { + 'defines': [ + 'OS_TIZEN_TV_PRODUCT', + ], + }, + }], # tizen_product_tv==1 + ], +} diff --git a/tizen/loader/wrt_loader.cc b/tizen/loader/wrt_loader.cc index bb91449..1e756e0 100644 --- a/tizen/loader/wrt_loader.cc +++ b/tizen/loader/wrt_loader.cc @@ -20,7 +20,7 @@ // with "System::Privileged" label. int main(int argc, char* argv[]) { dlog_print(DLOG_INFO, "CHROMIUM", "Begin wrt-loader"); - void* handle = dlopen("/usr/bin/electron", RTLD_NOW); + void* handle = dlopen("/usr/bin/wrt", RTLD_NOW); if (!handle) { dlog_print(DLOG_ERROR, "CHROMIUM", "Failed to load electorn"); return false; diff --git a/tizen/script/build b/tizen/script/build index 5ef809c..22091bd 100755 --- a/tizen/script/build +++ b/tizen/script/build @@ -172,7 +172,6 @@ def run_bootstrap(chromium_path, verbose): defines = [ 'libchromiumcontent_component=1', - 'desktop_linux=1', 'use_efl=1' ] diff --git a/tizen/src/wrt_main.cc b/tizen/src/wrt_main.cc new file mode 100644 index 0000000..799621c --- /dev/null +++ b/tizen/src/wrt_main.cc @@ -0,0 +1,231 @@ +// Copyright (c) 2013 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "wrt_main.h" + +#include + +#if defined(OS_WIN) +#include // windows.h must be included first + +#include +#include +#include + +#include "atom/app/atom_main_delegate.h" +#include "atom/common/crash_reporter/win/crash_service_main.h" +#include "base/environment.h" +#include "base/process/launch.h" +#include "base/win/windows_version.h" +#include "content/public/app/sandbox_helper_win.h" +#include "sandbox/win/src/sandbox_types.h" +#elif defined(OS_LINUX) // defined(OS_WIN) +#include "atom/app/atom_main_delegate.h" // NOLINT +#include "content/public/app/content_main.h" +#else // defined(OS_LINUX) +#include "atom/app/atom_library_main.h" +#endif // defined(OS_MACOSX) + +#if defined(USE_EFL) +#include "efl/init.h" +#endif + +#include "atom/app/node_main.h" +#include "atom/common/atom_command_line.h" +#include "base/at_exit.h" +#include "base/i18n/icu_util.h" + +#if defined(OS_TIZEN) +#include + +#include "atom/app/runtime.h" +#include "base/logging.h" +#include "tizen/common/application_data.h" +#include "tizen/common/command_line.h" +#include "tizen/loader/prelauncher.h" +#endif + +namespace { + +const char* kRunAsNode = "ELECTRON_RUN_AS_NODE"; + +// Default command line flags for all profiles and platforms +const char* kDefaultCommandLineFlags[] = { + "allow-file-access-from-files", + "enable-tizen-app-container", +}; + +bool IsEnvSet(const char* name) { +#if defined(OS_WIN) + size_t required_size; + getenv_s(&required_size, nullptr, 0, name); + return required_size != 0; +#else + char* indicator = getenv(name); + return indicator && indicator[0] != '\0'; +#endif +} + +} // namespace + +#if defined(OS_WIN) +int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) { + int argc = 0; + wchar_t** wargv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + + bool run_as_node = IsEnvSet(kRunAsNode); + + // Make sure the output is printed to console. + if (run_as_node || !IsEnvSet("ELECTRON_NO_ATTACH_CONSOLE")) + base::RouteStdioToConsole(false); + + // Convert argv to to UTF8 + char** argv = new char*[argc]; + for (int i = 0; i < argc; i++) { + // Compute the size of the required buffer + DWORD size = WideCharToMultiByte(CP_UTF8, + 0, + wargv[i], + -1, + NULL, + 0, + NULL, + NULL); + if (size == 0) { + // This should never happen. + fprintf(stderr, "Could not convert arguments to utf8."); + exit(1); + } + // Do the actual conversion + argv[i] = new char[size]; + DWORD result = WideCharToMultiByte(CP_UTF8, + 0, + wargv[i], + -1, + argv[i], + size, + NULL, + NULL); + if (result == 0) { + // This should never happen. + fprintf(stderr, "Could not convert arguments to utf8."); + exit(1); + } + } + + if (run_as_node) { + // Now that argv conversion is done, we can finally start. + base::AtExitManager atexit_manager; + base::i18n::InitializeICU(); + return atom::NodeMain(argc, argv); + } else if (IsEnvSet("ELECTRON_INTERNAL_CRASH_SERVICE")) { + return crash_service::Main(cmd); + } + + sandbox::SandboxInterfaceInfo sandbox_info = {0}; + content::InitializeSandboxInfo(&sandbox_info); + atom::AtomMainDelegate delegate; + + content::ContentMainParams params(&delegate); + params.instance = instance; + params.sandbox_info = &sandbox_info; + atom::AtomCommandLine::Init(argc, argv); + atom::AtomCommandLine::InitW(argc, wargv); + return content::ContentMain(params); +} + +#elif defined(OS_LINUX) // defined(OS_WIN) + +#if defined(OS_TIZEN) +// For debug purpose only. +// TODO: To be removed later +bool hasTizenPackageID(int argc, const char* const* argv) { + if (argc > 3) { + if (0 == strncmp(argv[0], "/opt/usr/globalapps/", strlen("/opt/usr/globalapps/"))) { + return true; + } + } + return false; +} + +int real_main(int argc, char* argv[]) { +#else +int main(int argc, char* argv[]) { +#endif + if (IsEnvSet(kRunAsNode)) { + base::i18n::InitializeICU(); + base::AtExitManager atexit_manager; + return atom::NodeMain(argc, const_cast(argv)); + } + +#if defined(USE_EFL) + common::CommandLine::Init(argc, argv); + common::CommandLine* runtime_cmd = common::CommandLine::ForCurrentProcess(); + std::string appid = runtime_cmd->GetAppIdFromCommandLine("/usr/bin/wrt"); + + // load manifest + if (appid != "wrt") { // TODO: Any better way to distinguish? + auto appdata_manager = common::ApplicationDataManager::GetInstance(); + common::ApplicationData* appdata = appdata_manager->GetApplicationData(appid); + if (!appdata->LoadManifestData()) { + return false; + } + } + + if (efl::Initialize(argc, const_cast(argv))) + return 1; + + // Add params for EFL port + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + + static std::vector flags; + for (auto arg : kDefaultCommandLineFlags) + command_line->AppendSwitch(const_cast(arg)); + efl::AppendPortParams(*command_line); +#endif + + atom::AtomMainDelegate delegate; + content::ContentMainParams params(&delegate); + params.argc = argc; + params.argv = const_cast(argv); + atom::AtomCommandLine::Init(argc, argv); +#if defined(OS_TIZEN) + if (hasTizenPackageID(argc,argv)) { // TODO: Check to be removed later + elm_init(argc, argv); + std::unique_ptr runtime = runtime::Runtime::MakeRuntime(¶ms); + return runtime->Exec(); + } +#endif + return content::ContentMain(params); +} + +#if defined(OS_TIZEN) +__attribute__((visibility("default"))) +int main(int argc, const char* argv[]) { + if (strcmp(argv[0], "/usr/bin/wrt-loader") == 0) { + LOG(INFO) << "run with wrt-loader"; + auto preload = [argv](void) { + }; + auto did_launch = [](const std::string& app_path) { + }; + auto prelaunch = runtime::PreLauncher::Prelaunch; + return prelaunch(argc, const_cast(argv), preload, did_launch, real_main); + } else { + LOG(INFO) << "run without wrt-loader"; + return real_main(argc, const_cast(argv)); + } +} +#endif + +#else // defined(OS_LINUX) + +int main(int argc, const char* argv[]) { + if (IsEnvSet(kRunAsNode)) { + return AtomInitializeICUandStartNode(argc, const_cast(argv)); + } + + return AtomMain(argc, argv); +} + +#endif // defined(OS_MACOSX) diff --git a/tizen/src/wrt_main.h b/tizen/src/wrt_main.h new file mode 100644 index 0000000..30663a4 --- /dev/null +++ b/tizen/src/wrt_main.h @@ -0,0 +1,10 @@ +// Copyright (c) 2013 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_APP_ATOM_MAIN_H_ +#define ATOM_APP_ATOM_MAIN_H_ + +#include "content/public/app/content_main.h" + +#endif // ATOM_APP_ATOM_MAIN_H_ diff --git a/vendor/brightray/brightray.gyp b/vendor/brightray/brightray.gyp index def490d..018a859 100644 --- a/vendor/brightray/brightray.gyp +++ b/vendor/brightray/brightray.gyp @@ -1,6 +1,6 @@ { 'conditions': [ - ['desktop_linux==0', { + ['is_tizen==1', { 'variables': { # The libraries brightray will be compiled to. 'linux_system_libraries': 'chromium-efl dbus-1 evas gmodule-2.0 nss icu-i18n icu-uc' @@ -72,8 +72,6 @@ 'link_settings': { 'libraries': [ '<@(libchromiumcontent_libraries)', - '<@(libchromiumcontent_shared_root_libraries)', -# ' Date: Tue, 3 Apr 2018 20:05:00 +0900 Subject: [PATCH 05/16] Implement Hardware Backkey action Hardware Backkey callback was already registered and called but inside of it, there was nothing implemented related with WebApp. Now hardware backkey work as it should be, like going back history and App quit when there is no history to go back. Change-Id: Ib95be89c8dc4da0628b7c69c531f36ff921c1b04 Signed-off-by: ws29.jung --- atom/app/ui_runtime.cc | 1 - atom/browser/browser.cc | 2 ++ atom/browser/native_window_efl.cc | 5 ++++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/atom/app/ui_runtime.cc b/atom/app/ui_runtime.cc index c85a63f..2593e32 100644 --- a/atom/app/ui_runtime.cc +++ b/atom/app/ui_runtime.cc @@ -45,7 +45,6 @@ bool UiRuntime::OnCreate() { void UiRuntime::OnTerminate() { atom::Browser *browser_model = atom::Browser::Get(); - browser_model->Shutdown(); } void UiRuntime::OnPause() { diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 42cc787..2678b1c 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -5,6 +5,7 @@ #include "atom/browser/browser.h" #include +#include #include "atom/browser/atom_browser_main_parts.h" #include "atom/browser/browser_observer.h" @@ -87,6 +88,7 @@ void Browser::Shutdown() { if (base::ThreadTaskRunnerHandle::IsSet()) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); + ui_app_exit(); } else { // There is no message loop available so we are in early stage. exit(0); diff --git a/atom/browser/native_window_efl.cc b/atom/browser/native_window_efl.cc index 209e49c..af0b862 100644 --- a/atom/browser/native_window_efl.cc +++ b/atom/browser/native_window_efl.cc @@ -145,7 +145,6 @@ void NativeWindowEfl::Close() { } void NativeWindowEfl::CloseImmediately() { - NOTIMPLEMENTED(); if(window_) evas_object_del(window_); window_ = nullptr; @@ -419,6 +418,10 @@ void NativeWindowEfl::HWBackKeyCallback(void* data, Evas_Object*, void*) { rfh->ExecuteJavaScriptWithUserGestureForTests( base::UTF8ToUTF16(kBackKeyEventScript)); } + if (thiz->web_contents()->GetController().CanGoBack()) + thiz->web_contents()->GetController().GoBack(); + else + thiz->Close(); } // static -- 2.7.4 From 085877491630a1e60d7f14d6b743e0ba6ea13894 Mon Sep 17 00:00:00 2001 From: deepti Date: Wed, 28 Mar 2018 11:46:09 +0530 Subject: [PATCH 06/16] Handling app Control Data 1)Take decision whether to launch or send app control data. 2)Parsing of config file to check whether to reload or not. Change-Id: I51f0d48aba58ca62d185b994beca12abb9344578 Signed-off-by: deepti --- atom/app/ui_runtime.cc | 7 +++++++ atom/browser/browser.cc | 31 +++++++++++++++++++++++++++++-- atom/browser/browser.h | 14 ++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/atom/app/ui_runtime.cc b/atom/app/ui_runtime.cc index 2593e32..c773aca 100644 --- a/atom/app/ui_runtime.cc +++ b/atom/app/ui_runtime.cc @@ -66,6 +66,13 @@ void UiRuntime::OnAppControl(app_control_h app_control) { common::AppDB* appdb = common::AppDB::GetInstance(); appdb->Set(kAppDBRuntimeSection, kAppDBRuntimeBundle, appcontrol->encoded_bundle()); + atom::Browser *browser_model = atom::Browser::Get(); + if (browser_model->launched()) { + browser_model->AppControl(std::move(appcontrol)); + } else { + browser_model->Initialize(); + browser_model->Launch(std::move(appcontrol)); + } } void UiRuntime::OnLanguageChanged(const std::string& language) { diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 2678b1c..2a36143 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -16,14 +16,16 @@ #include "base/run_loop.h" #include "base/threading/thread_task_runner_handle.h" #include "brightray/browser/brightray_paths.h" - +#include "tizen/common/command_line.h" namespace atom { Browser::Browser() : is_quiting_(false), is_exiting_(false), is_ready_(false), - is_shutdown_(false) { + is_shutdown_(false), + launched_(false), + locale_manager_(new common::LocaleManager()) { WindowList::AddObserver(this); } @@ -225,4 +227,29 @@ void Browser::Show() { observer.OnResume(); } +void Browser::Initialize() { + common::CommandLine* runtime_cmd = common::CommandLine::ForCurrentProcess(); + std::string appid = runtime_cmd->GetAppIdFromCommandLine("/usr/bin/electron"); + //TODO: update the appid from binary name to electron + if (appid != "electron") { + auto appdata_manager = common::ApplicationDataManager::GetInstance(); + common::ApplicationData* appdata = appdata_manager->GetApplicationData(appid); + + resource_manager_.reset( + new common::ResourceManager(appdata, locale_manager_.get())); + } +} + +void Browser::AppControl(std::unique_ptr appcontrol) { + std::unique_ptr res = + resource_manager_->GetStartResource(appcontrol.get()); + bool do_reset = res->should_reset(); +//To do: Implementation of reset case according to parsed config file parameter. +} + +void Browser::Launch(std::unique_ptr appcontrol) { + launched_ = true; +//To do:Implementation of relaunching of app +} + } // namespace atom diff --git a/atom/browser/browser.h b/atom/browser/browser.h index fc674dd..286ba29 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -16,6 +16,10 @@ #include "base/strings/string16.h" #include "base/values.h" #include "native_mate/arguments.h" +#include "tizen/common/app_control.h" +#include "tizen/common/application_data.h" +#include "tizen/common/resource_manager.h" +#include "tizen/common/locale_manager.h" #if defined(OS_WIN) #include "base/files/file_path.h" @@ -42,6 +46,10 @@ class Browser : public WindowListObserver { static Browser* Get(); + std::unique_ptr resource_manager_; + std::unique_ptr locale_manager_; + + void Initialize(); // Try to close all windows and quit the application. void Quit(); @@ -89,6 +97,7 @@ class Browser : public WindowListObserver { // Set/Get the badge count. bool SetBadgeCount(int count); + bool launched() const { return launched_; } int GetBadgeCount(); // Set/Get the login item settings of the app @@ -106,6 +115,9 @@ class Browser : public WindowListObserver { void Hide(); void Show(); + void AppControl(std::unique_ptr appcontrol); + void Launch(std::unique_ptr appcontrol); + #if defined(OS_MACOSX) // Hide the application. void Hide(); @@ -226,6 +238,8 @@ class Browser : public WindowListObserver { bool is_quiting_; + bool launched_; + private: // WindowListObserver implementations: void OnWindowCloseCancelled(NativeWindow* window) override; -- 2.7.4 From 5f0fea7f7d8d9ce15680d45c76614081ece6845b Mon Sep 17 00:00:00 2001 From: "ws29.jung" Date: Tue, 27 Mar 2018 16:41:37 +0900 Subject: [PATCH 07/16] Initial Implementation of Node prelaunch This patch is created to reduce WebApp launching time by using method of Node environment prelaunching. Prelaunch will load and run electron.asar and app.asar then it will wait until onCreate event emit. onCreate event will be triggered when actual WebApp is launched. Change-Id: I42f198e9755dd8e017691c22edf96eef15cb3eb5 Signed-off-by: ws29.jung --- atom/app/runtime.h | 4 +- atom/app/ui_runtime.cc | 11 ++++++ atom/app/ui_runtime.h | 1 + atom/browser/api/atom_api_app.cc | 3 +- atom/browser/api/atom_api_pwrt.cc | 31 ++++++++------- atom/browser/api/trackable_object.cc | 3 +- atom/browser/atom_browser_main_parts.cc | 69 +++++++++++++++++++++++++++++++-- atom/browser/atom_browser_main_parts.h | 3 ++ atom/browser/browser.cc | 5 ++- lib/browser/init.js | 4 +- tizen/common/command_line.cc | 4 +- tizen/common/command_line.h | 2 +- tizen/src/wrt_main.cc | 49 ++++++++++++++++++----- wrt/src/web_window.js | 7 +++- 14 files changed, 162 insertions(+), 34 deletions(-) diff --git a/atom/app/runtime.h b/atom/app/runtime.h index baf9001..a5bcbc2 100644 --- a/atom/app/runtime.h +++ b/atom/app/runtime.h @@ -31,9 +31,11 @@ class Runtime { virtual int Exec() = 0; + virtual void SetParam(content::ContentMainParams *params) = 0; + static std::unique_ptr MakeRuntime(content::ContentMainParams *params); }; } // namespace runtime -#endif // RUNTIME_H_ \ No newline at end of file +#endif // RUNTIME_H_ diff --git a/atom/app/ui_runtime.cc b/atom/app/ui_runtime.cc index c773aca..7091bff 100644 --- a/atom/app/ui_runtime.cc +++ b/atom/app/ui_runtime.cc @@ -22,6 +22,7 @@ #include "atom/app/ui_runtime.h" #include "atom/browser/browser.h" #include "atom/browser/atom_browser_client.h" +#include "atom/browser/atom_browser_main_parts.h" #include "atom/common/atom_command_line.h" #include "base/logging.h" #include "content/public/app/content_main.h" @@ -29,15 +30,25 @@ #include "tizen/common/app_control.h" #include "tizen/common/constants.h" +#include "gin/v8_initializer.h" + namespace runtime { UiRuntime::UiRuntime(content::ContentMainParams *params) { _params = params; + + atom::AtomBrowserMainParts::SetNodeEnvironment(); } UiRuntime::~UiRuntime() { } +void UiRuntime::SetParam(content::ContentMainParams *params) { + if (_params) + LOG(ERROR) << "Use SetParam only when params is null"; + else + _params = params; +} bool UiRuntime::OnCreate() { return true; diff --git a/atom/app/ui_runtime.h b/atom/app/ui_runtime.h index 1c8ec22..f32086b 100644 --- a/atom/app/ui_runtime.h +++ b/atom/app/ui_runtime.h @@ -30,6 +30,7 @@ class UiRuntime : public Runtime { virtual ~UiRuntime(); virtual int Exec(); + virtual void SetParam(content::ContentMainParams *params); protected: virtual bool OnCreate(); diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 115041d..638a769 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -491,7 +491,8 @@ void OnIconDataAvailable(v8::Isolate* isolate, } // namespace App::App(v8::Isolate* isolate) { - static_cast(AtomBrowserClient::Get())->set_delegate(this); + if (AtomBrowserClient::Get()) + static_cast(AtomBrowserClient::Get())->set_delegate(this); Browser::Get()->AddObserver(this); content::GpuDataManager::GetInstance()->AddObserver(this); Init(isolate); diff --git a/atom/browser/api/atom_api_pwrt.cc b/atom/browser/api/atom_api_pwrt.cc index e8a75a6..e89b1dd 100644 --- a/atom/browser/api/atom_api_pwrt.cc +++ b/atom/browser/api/atom_api_pwrt.cc @@ -14,32 +14,35 @@ namespace atom { namespace api { PWRT::PWRT(v8::Isolate* isolate) { - LOG(INFO) << "PWRT::PWRT"; + LOG(ERROR) << "PWRT::PWRT"; Init(isolate); } PWRT::~PWRT() { - LOG(INFO) << "PWRT::~PWRT"; + LOG(ERROR) << "PWRT::~PWRT"; } std::string PWRT::GetMessage() { - LOG(INFO) << "PWRT::GetMessage"; + LOG(ERROR) << "PWRT::GetMessage"; return "message from C++"; } std::string PWRT::GetPath() { - LOG(INFO) << "PWRT::GetPath"; + LOG(ERROR) << "PWRT::GetPath"; common::CommandLine* runtime_cmd = common::CommandLine::ForCurrentProcess(); - std::string appid = runtime_cmd->GetAppIdFromCommandLine("/usr/bin/electron"); - auto appdata_manager = common::ApplicationDataManager::GetInstance(); - common::ApplicationData* app_data = appdata_manager->GetApplicationData(appid); - // TODO: Use resource-manager's GetStartResource() for localized urls - std::string app_path = "file://" + app_data->application_path() + app_data->content_info()->src(); - return app_path; + if (runtime_cmd) { + std::string appid = runtime_cmd->GetAppIdFromCommandLine("/usr/bin/electron"); + auto appdata_manager = common::ApplicationDataManager::GetInstance(); + common::ApplicationData* app_data = appdata_manager->GetApplicationData(appid); + // TODO: Use resource-manager's GetStartResource() for localized urls + std::string app_path = "file://" + app_data->application_path() + app_data->content_info()->src(); + return app_path; + } + return ""; } bool PWRT::isTizenWebApp() { - LOG(INFO) << "PWRT::isTizenWebApp"; + LOG(ERROR) << "PWRT::isTizenWebApp"; common::CommandLine* runtime_cmd = common::CommandLine::ForCurrentProcess(); std::string appid = runtime_cmd->GetAppIdFromCommandLine("/usr/bin/electron"); if (appid != "electron") { // TODO: Any better distinguishing feature? @@ -56,14 +59,14 @@ void PWRT::Log(const std::string& message) { // static mate::Handle PWRT::Create(v8::Isolate* isolate) { - LOG(INFO) << "PWRT::Create"; + LOG(ERROR) << "PWRT::Create"; return mate::CreateHandle(isolate, new PWRT(isolate)); } // static void PWRT::BuildPrototype( v8::Isolate* isolate, v8::Local prototype) { - LOG(INFO) << "PWRT::BuildPrototype"; + LOG(ERROR) << "PWRT::BuildPrototype"; prototype->SetClassName(mate::StringToV8(isolate, "PWRT")); // TODO: Needs adding necessary interface methods mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) @@ -82,7 +85,7 @@ namespace { void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { - LOG(INFO) << "PWRT::Initialize"; + LOG(ERROR) << "PWRT::Initialize"; v8::Isolate* isolate = context->GetIsolate(); mate::Dictionary dict(isolate, exports); // TODO: Expose this attribute only for Tizen web apps diff --git a/atom/browser/api/trackable_object.cc b/atom/browser/api/trackable_object.cc index 502757a..59e43b2 100644 --- a/atom/browser/api/trackable_object.cc +++ b/atom/browser/api/trackable_object.cc @@ -61,7 +61,8 @@ int32_t TrackableObjectBase::GetIDFromWrappedClass(base::SupportsUserData* w) { // static base::Closure TrackableObjectBase::RegisterDestructionCallback( const base::Closure& c) { - return atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(c); + if (atom::AtomBrowserMainParts::Get()) + return atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(c); } } // namespace mate diff --git a/atom/browser/atom_browser_main_parts.cc b/atom/browser/atom_browser_main_parts.cc index c5155be..f718f86 100644 --- a/atom/browser/atom_browser_main_parts.cc +++ b/atom/browser/atom_browser_main_parts.cc @@ -18,6 +18,7 @@ #include "atom/common/node_bindings.h" #include "atom/common/node_includes.h" #include "base/command_line.h" +#include "base/feature_list.h" #include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/browser_process.h" #include "content/public/browser/child_process_security_policy.h" @@ -25,6 +26,8 @@ #include "device/geolocation/geolocation_provider.h" #include "v8/include/v8-debug.h" +#include "gin/v8_initializer.h" + #if defined(USE_X11) #include "chrome/browser/ui/libgtkui/gtk_util.h" #include "ui/events/devices/x11/touch_factory_x11.h" @@ -61,16 +64,36 @@ void Erase(T* container, typename T::iterator iter) { } // namespace // static +bool g_prelaunch = false; AtomBrowserMainParts* AtomBrowserMainParts::self_ = nullptr; +node::Environment* env_ = nullptr; +scoped_refptr self_bridge_task_runner; +std::unique_ptr self_browser; +std::unique_ptr self_js_env; +std::unique_ptr self_node_bindings; +std::unique_ptr self_atom_bindings; +std::unique_ptr self_node_env; +std::unique_ptr self_node_debugger; AtomBrowserMainParts::AtomBrowserMainParts() : fake_browser_process_(new BrowserProcess), exit_code_(nullptr), - browser_(new Browser), - node_bindings_(NodeBindings::Create(NodeBindings::BROWSER)), - atom_bindings_(new AtomBindings(uv_default_loop())), gc_timer_(true, true) { DCHECK(!self_) << "Cannot have two AtomBrowserMainParts"; + if (g_prelaunch) { + browser_ = std::move(self_browser); + node_bindings_ = std::move(self_node_bindings); + atom_bindings_ = std::move(self_atom_bindings); + + js_env_ = std::move(self_js_env); + node_debugger_ = std::move(self_node_debugger); + bridge_task_runner_ = self_bridge_task_runner; + node_env_ = std::move(self_node_env); + } else { + browser_.reset(new Browser); + node_bindings_.reset(NodeBindings::Create(NodeBindings::BROWSER)); + atom_bindings_.reset(new AtomBindings(uv_default_loop())); + } self_ = this; // Register extension scheme as web safe scheme. content::ChildProcessSecurityPolicy::GetInstance()-> @@ -95,6 +118,44 @@ AtomBrowserMainParts* AtomBrowserMainParts::Get() { return self_; } +Browser* AtomBrowserMainParts::GetStaticBrowser() { + return self_browser.get(); +} + +void AtomBrowserMainParts::SetNodeEnvironment() { + if (g_prelaunch) + return; + + std::unique_ptr feature_list(new base::FeatureList); + feature_list->InitializeFromCommandLine("", ""); + base::FeatureList::SetInstance(std::move(feature_list)); + + gin::V8Initializer::LoadV8Snapshot(); + gin::V8Initializer::LoadV8Natives(); + + self_browser.reset(new atom::Browser); + self_bridge_task_runner = new atom::BridgeTaskRunner; + base::ThreadTaskRunnerHandle handle(self_bridge_task_runner); + + self_js_env.reset(new atom::JavascriptEnvironment); + self_node_bindings.reset(atom::NodeBindings::Create(atom::NodeBindings::BROWSER)); + self_atom_bindings.reset(new atom::AtomBindings(uv_default_loop())); + self_node_bindings->Initialize(); + + self_node_debugger.reset(new atom::NodeDebugger(self_js_env->isolate())); + env_ = self_node_bindings->CreateEnvironment(self_js_env->context()); + self_node_env.reset(new atom::NodeEnvironment(env_)); + + if (self_node_debugger->IsRunning()) + env_->AssignToContext(v8::Debug::GetDebugContext(self_js_env->isolate())); + + self_atom_bindings->BindTo(self_js_env->isolate(), env_->process_object()); + + self_node_bindings->LoadEnvironment(env_); + self_node_bindings->set_uv_env(env_); + g_prelaunch = true; +} + bool AtomBrowserMainParts::SetExitCode(int code) { if (!exit_code_) return false; @@ -122,6 +183,8 @@ void AtomBrowserMainParts::PreEarlyInitialization() { void AtomBrowserMainParts::PostEarlyInitialization() { brightray::BrowserMainParts::PostEarlyInitialization(); + if (g_prelaunch) + return; // Temporary set the bridge_task_runner_ as current thread's task runner, // so we can fool gin::PerIsolateData to use it as its task runner, instead diff --git a/atom/browser/atom_browser_main_parts.h b/atom/browser/atom_browser_main_parts.h index 2ba7d34..ca505f7 100644 --- a/atom/browser/atom_browser_main_parts.h +++ b/atom/browser/atom_browser_main_parts.h @@ -43,7 +43,10 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts { // Returns a closure that can be used to remove |callback| from the list. base::Closure RegisterDestructionCallback(const base::Closure& callback); + static void SetNodeEnvironment(); + Browser* browser() { return browser_.get(); } + static Browser* GetStaticBrowser(); protected: // content::BrowserMainParts: diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 2a36143..dea0bf2 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -35,7 +35,10 @@ Browser::~Browser() { // static Browser* Browser::Get() { - return AtomBrowserMainParts::Get()->browser(); + if (AtomBrowserMainParts::Get()) + return AtomBrowserMainParts::Get()->browser(); + else + return AtomBrowserMainParts::GetStaticBrowser(); } void Browser::Quit() { diff --git a/lib/browser/init.js b/lib/browser/init.js index a220069..6c8ac89 100644 --- a/lib/browser/init.js +++ b/lib/browser/init.js @@ -169,7 +169,9 @@ app.setPath('userCache', path.join(app.getPath('cache'), app.getName())) app.setAppPath(packagePath) // Load the chrome extension support. -require('./chrome-extension') +// FIXME: When prelaunch, initializing electron modules +// in chrome-extension cause segmentation fault. +//require('./chrome-extension') // Load internal desktop-capturer module. // FIXME: This is guard for bringup. diff --git a/tizen/common/command_line.cc b/tizen/common/command_line.cc index 6ee518a..ecf6d3c 100644 --- a/tizen/common/command_line.cc +++ b/tizen/common/command_line.cc @@ -131,10 +131,12 @@ void CommandLine::Reset() { } // static -void CommandLine::Init(int argc, char* argv[]) { +bool CommandLine::Init(int argc, char* argv[]) { if (!current_process_commandline_) { current_process_commandline_ = new CommandLine(argc, argv); + return true; } + return false; } // static diff --git a/tizen/common/command_line.h b/tizen/common/command_line.h index 6854808..1c7bae0 100644 --- a/tizen/common/command_line.h +++ b/tizen/common/command_line.h @@ -30,7 +30,7 @@ class CommandLine { // Arguments which except for option strings typedef std::vector Arguments; - static void Init(int argc, char* argv[]); + static bool Init(int argc, char* argv[]); static CommandLine* ForCurrentProcess(); static void Reset(); diff --git a/tizen/src/wrt_main.cc b/tizen/src/wrt_main.cc index 799621c..0bf3635 100644 --- a/tizen/src/wrt_main.cc +++ b/tizen/src/wrt_main.cc @@ -138,6 +138,9 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) { #elif defined(OS_LINUX) // defined(OS_WIN) #if defined(OS_TIZEN) +bool g_initialized_ = false; +std::unique_ptr runtime_; + // For debug purpose only. // TODO: To be removed later bool hasTizenPackageID(int argc, const char* const* argv) { @@ -153,6 +156,8 @@ int real_main(int argc, char* argv[]) { #else int main(int argc, char* argv[]) { #endif + for (int i = 0; i < argc; ++i) + LOG(ERROR) << "argv[" << i << "] : " << argv[i]; if (IsEnvSet(kRunAsNode)) { base::i18n::InitializeICU(); base::AtExitManager atexit_manager; @@ -160,7 +165,15 @@ int main(int argc, char* argv[]) { } #if defined(USE_EFL) - common::CommandLine::Init(argc, argv); + if (!common::CommandLine::Init(argc, argv)) { + common::CommandLine::Reset(); + common::CommandLine::Init(argc, argv); + } + + if (!base::CommandLine::Init(argc, argv)) { + base::CommandLine::Reset(); + base::CommandLine::Init(argc, argv); + } common::CommandLine* runtime_cmd = common::CommandLine::ForCurrentProcess(); std::string appid = runtime_cmd->GetAppIdFromCommandLine("/usr/bin/wrt"); @@ -172,9 +185,10 @@ int main(int argc, char* argv[]) { return false; } } - - if (efl::Initialize(argc, const_cast(argv))) - return 1; + if (!g_initialized_) { + if (efl::Initialize(argc, const_cast(argv))) + return 1; + } // Add params for EFL port base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); @@ -193,8 +207,12 @@ int main(int argc, char* argv[]) { #if defined(OS_TIZEN) if (hasTizenPackageID(argc,argv)) { // TODO: Check to be removed later elm_init(argc, argv); - std::unique_ptr runtime = runtime::Runtime::MakeRuntime(¶ms); - return runtime->Exec(); + if (!g_initialized_) { + runtime_ = runtime::Runtime::MakeRuntime(¶ms); + } else { + runtime_->SetParam(¶ms); + } + return runtime_->Exec(); } #endif return content::ContentMain(params); @@ -203,16 +221,29 @@ int main(int argc, char* argv[]) { #if defined(OS_TIZEN) __attribute__((visibility("default"))) int main(int argc, const char* argv[]) { + for (int i = 0; i < argc; ++i) + LOG(ERROR) << "argv[" << i << "] : " << argv[i]; if (strcmp(argv[0], "/usr/bin/wrt-loader") == 0) { - LOG(INFO) << "run with wrt-loader"; - auto preload = [argv](void) { + LOG(ERROR) << "run with wrt-loader"; + auto preload = [argc, argv](void) { + g_initialized_ = true; + if (efl::Initialize(argc, const_cast(argv))) + return 1; + + atom::AtomMainDelegate delegate; + content::ContentMainParams params(&delegate); + params.argc = argc; + params.argv = const_cast(argv); + atom::AtomCommandLine::Init(argc, argv); + runtime_ = runtime::Runtime::MakeRuntime(nullptr); + return 0; }; auto did_launch = [](const std::string& app_path) { }; auto prelaunch = runtime::PreLauncher::Prelaunch; return prelaunch(argc, const_cast(argv), preload, did_launch, real_main); } else { - LOG(INFO) << "run without wrt-loader"; + LOG(ERROR) << "run without wrt-loader"; return real_main(argc, const_cast(argv)); } } diff --git a/wrt/src/web_window.js b/wrt/src/web_window.js index 9c552be..5258234 100644 --- a/wrt/src/web_window.js +++ b/wrt/src/web_window.js @@ -212,7 +212,12 @@ class WebWindow { }); } setUrl(path) { -        this.mainWindow.loadURL(path); + if (path && (path.trim() != '')) { + this.mainWindow.loadURL(path); + } else { + const {pwrt} = require('electron'); +        this.mainWindow.loadURL(pwrt.getPath()); + } } show() { this.mainWindow.show(); -- 2.7.4 From 3b958ed34caa5d2f0eb26d2faa391382064dc1f6 Mon Sep 17 00:00:00 2001 From: "jaekuk, lee" Date: Fri, 13 Apr 2018 14:07:21 +0900 Subject: [PATCH 08/16] Add CRX type to Addon manager Change-Id: I883ac2de7230f9801758728ccad6e024f2f079e0 Signed-off-by: jaekuk, lee --- wrt/src/extension_manager.js | 4 ++++ 1 file changed, 4 insertions(+) mode change 100644 => 100755 wrt/src/extension_manager.js diff --git a/wrt/src/extension_manager.js b/wrt/src/extension_manager.js old mode 100644 new mode 100755 index 78934ab..21c8cd0 --- a/wrt/src/extension_manager.js +++ b/wrt/src/extension_manager.js @@ -291,6 +291,7 @@ class ExtensionManager { extension_debug('extension.deactivate not defined!'); } } else if (this.extensions_[T_CRX] !== undefined && this.extensions_[T_CRX][name] !== undefined) { + extension_path = this.extensions_[T_CRX][name]; try { BrowserWindow.removeExtension(name); } catch (e) { @@ -320,6 +321,9 @@ class ExtensionManager { for (var name in this.extensions_[T_WRT]) { this.deactivate(event_emitter, name); } + for (var name in this.extensions_[T_CRX]) { + this.deactivate(event_emitter, name); + } } static getManifestFile() { -- 2.7.4 From ec47f1bbaccb47747432e51b2ba0c2a352cfb887 Mon Sep 17 00:00:00 2001 From: "ws29.jung" Date: Tue, 10 Apr 2018 11:13:36 +0900 Subject: [PATCH 09/16] Implement window rotation When mobile device is rotated, webapp did not follow the rotation. Now window will properly rotate as mobile device rotates. Change-Id: I27f45277188d119dc87e5e912607ffec26607373 Signed-off-by: ws29.jung --- atom/browser/native_window_efl.cc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/atom/browser/native_window_efl.cc b/atom/browser/native_window_efl.cc index af0b862..2f214b7 100644 --- a/atom/browser/native_window_efl.cc +++ b/atom/browser/native_window_efl.cc @@ -92,6 +92,21 @@ NativeWindowEfl::NativeWindowEfl( &HWBackKeyCallback, this); eext_object_event_callback_add(web_view_, EEXT_CALLBACK_MORE, &HWMoreKeyCallback, this); + + if (elm_win_wm_rotation_supported_get(window_)) { + int rots[4] = {0, 90, 180, 270}; + elm_win_wm_rotation_available_rotations_set(window_, + (const int *)(&rots), 4); + + // Registering nullptr as Callback, but window will rotate without error. + // Is it right action? + evas_object_smart_callback_add(window_, + "wm,rotation,changed", + nullptr, + this); + } else { + LOG(ERROR) << __func__ << " Window does not support rotation"; + } #endif #if defined(OS_TIZEN_TV_PRODUCT) -- 2.7.4 From ba3836c993b5a128cd7d9fe21a3bd49e3f5b3acc Mon Sep 17 00:00:00 2001 From: prathmeshm Date: Fri, 23 Mar 2018 12:16:03 +0530 Subject: [PATCH 10/16] Added Injected Bundle and extension server and client - Added injected bundle in electron - Added extension server and client - Set injected bundle path to chromium for init - related patch https://review.tizen.org/gerrit/#/c/174986/ Change-Id: Iee1717b760cb68576ad02c7cab657b099e54b913 Signed-off-by: prathmeshm --- atom/app/atom_main_delegate.cc | 13 + packaging/electron-efl.spec | 12 + tizen/build/common.gypi | 12 +- tizen/extensions/common/constants.cc | 30 ++ tizen/extensions/common/constants.h | 32 ++ tizen/extensions/common/xwalk_extension.cc | 125 +++++ tizen/extensions/common/xwalk_extension.h | 82 +++ tizen/extensions/common/xwalk_extension_adapter.cc | 323 ++++++++++++ tizen/extensions/common/xwalk_extension_adapter.h | 96 ++++ .../extensions/common/xwalk_extension_instance.cc | 63 +++ tizen/extensions/common/xwalk_extension_instance.h | 47 ++ tizen/extensions/common/xwalk_extension_manager.cc | 260 +++++++++ tizen/extensions/common/xwalk_extension_manager.h | 47 ++ tizen/extensions/common/xwalk_extension_server.cc | 229 ++++++++ tizen/extensions/common/xwalk_extension_server.h | 57 ++ tizen/extensions/extensions.gyp | 60 +++ .../internal/splash_screen/splash_screen.json | 7 + .../internal/splash_screen/splash_screen_api.js | 22 + .../splash_screen/splash_screen_extension.cc | 95 ++++ tizen/extensions/internal/widget/widget.json | 7 + tizen/extensions/internal/widget/widget_api.js | 93 ++++ .../extensions/internal/widget/widget_extension.cc | 95 ++++ tizen/extensions/public/XW_Extension.h | 185 +++++++ tizen/extensions/public/XW_Extension_EntryPoints.h | 49 ++ tizen/extensions/public/XW_Extension_Message_2.h | 64 +++ tizen/extensions/public/XW_Extension_Permissions.h | 41 ++ tizen/extensions/public/XW_Extension_Runtime.h | 44 ++ tizen/extensions/public/XW_Extension_SyncMessage.h | 48 ++ tizen/extensions/renderer/object_tools_module.cc | 114 ++++ tizen/extensions/renderer/object_tools_module.h | 36 ++ tizen/extensions/renderer/runtime_ipc_client.cc | 238 +++++++++ tizen/extensions/renderer/runtime_ipc_client.h | 100 ++++ tizen/extensions/renderer/widget_module.cc | 581 +++++++++++++++++++++ tizen/extensions/renderer/widget_module.h | 75 +++ .../extensions/renderer/xwalk_extension_client.cc | 131 +++++ tizen/extensions/renderer/xwalk_extension_client.h | 71 +++ .../extensions/renderer/xwalk_extension_module.cc | 514 ++++++++++++++++++ tizen/extensions/renderer/xwalk_extension_module.h | 84 +++ .../xwalk_extension_renderer_controller.cc | 132 +++++ .../renderer/xwalk_extension_renderer_controller.h | 45 ++ tizen/extensions/renderer/xwalk_module_system.cc | 524 +++++++++++++++++++ tizen/extensions/renderer/xwalk_module_system.h | 116 ++++ tizen/extensions/renderer/xwalk_v8tools_module.cc | 98 ++++ tizen/extensions/renderer/xwalk_v8tools_module.h | 28 + tizen/renderer/injected_bundle.cc | 190 +++++++ tizen/renderer/injected_bundle.gyp | 23 + vendor/brightray/browser/browser_context.cc | 15 + wrt.gyp | 2 + 48 files changed, 5349 insertions(+), 6 deletions(-) create mode 100644 tizen/extensions/common/constants.cc create mode 100644 tizen/extensions/common/constants.h create mode 100644 tizen/extensions/common/xwalk_extension.cc create mode 100644 tizen/extensions/common/xwalk_extension.h create mode 100644 tizen/extensions/common/xwalk_extension_adapter.cc create mode 100644 tizen/extensions/common/xwalk_extension_adapter.h create mode 100644 tizen/extensions/common/xwalk_extension_instance.cc create mode 100644 tizen/extensions/common/xwalk_extension_instance.h create mode 100644 tizen/extensions/common/xwalk_extension_manager.cc create mode 100644 tizen/extensions/common/xwalk_extension_manager.h create mode 100644 tizen/extensions/common/xwalk_extension_server.cc create mode 100644 tizen/extensions/common/xwalk_extension_server.h create mode 100644 tizen/extensions/extensions.gyp create mode 100644 tizen/extensions/internal/splash_screen/splash_screen.json create mode 100644 tizen/extensions/internal/splash_screen/splash_screen_api.js create mode 100644 tizen/extensions/internal/splash_screen/splash_screen_extension.cc create mode 100644 tizen/extensions/internal/widget/widget.json create mode 100644 tizen/extensions/internal/widget/widget_api.js create mode 100644 tizen/extensions/internal/widget/widget_extension.cc create mode 100644 tizen/extensions/public/XW_Extension.h create mode 100644 tizen/extensions/public/XW_Extension_EntryPoints.h create mode 100644 tizen/extensions/public/XW_Extension_Message_2.h create mode 100644 tizen/extensions/public/XW_Extension_Permissions.h create mode 100644 tizen/extensions/public/XW_Extension_Runtime.h create mode 100644 tizen/extensions/public/XW_Extension_SyncMessage.h create mode 100644 tizen/extensions/renderer/object_tools_module.cc create mode 100644 tizen/extensions/renderer/object_tools_module.h create mode 100644 tizen/extensions/renderer/runtime_ipc_client.cc create mode 100644 tizen/extensions/renderer/runtime_ipc_client.h create mode 100644 tizen/extensions/renderer/widget_module.cc create mode 100644 tizen/extensions/renderer/widget_module.h create mode 100644 tizen/extensions/renderer/xwalk_extension_client.cc create mode 100644 tizen/extensions/renderer/xwalk_extension_client.h create mode 100644 tizen/extensions/renderer/xwalk_extension_module.cc create mode 100644 tizen/extensions/renderer/xwalk_extension_module.h create mode 100644 tizen/extensions/renderer/xwalk_extension_renderer_controller.cc create mode 100644 tizen/extensions/renderer/xwalk_extension_renderer_controller.h create mode 100644 tizen/extensions/renderer/xwalk_module_system.cc create mode 100644 tizen/extensions/renderer/xwalk_module_system.h create mode 100644 tizen/extensions/renderer/xwalk_v8tools_module.cc create mode 100644 tizen/extensions/renderer/xwalk_v8tools_module.h create mode 100644 tizen/renderer/injected_bundle.cc create mode 100644 tizen/renderer/injected_bundle.gyp diff --git a/atom/app/atom_main_delegate.cc b/atom/app/atom_main_delegate.cc index 9f9ac69..f840690 100644 --- a/atom/app/atom_main_delegate.cc +++ b/atom/app/atom_main_delegate.cc @@ -25,6 +25,11 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" +#if defined(OS_TIZEN) +#include "tizen/common/command_line.h" +#include "atom/common/atom_command_line.h" +#endif + namespace atom { namespace { @@ -141,6 +146,14 @@ void AtomMainDelegate::PreSandboxStartup() { // Allow file:// URIs to read other file:// URIs by default. command_line->AppendSwitch(::switches::kAllowFileAccessFromFiles); +#if defined(OS_TIZEN) + LOG (ERROR) << "Set Injected bundle path to engine"; + command_line->AppendSwitchASCII("injected-bundle-path","/usr/lib/libxwalk_injected_bundle.so"); + std::vector cmdAgrs = atom::AtomCommandLine::argv(); + std::string app_id = cmdAgrs[1]; + command_line->AppendSwitchASCII("widget-id",app_id); +#endif + #if defined(OS_MACOSX) // Enable AVFoundation. command_line->AppendSwitch("enable-avfoundation"); diff --git a/packaging/electron-efl.spec b/packaging/electron-efl.spec index f26da7c..7f48f8b 100755 --- a/packaging/electron-efl.spec +++ b/packaging/electron-efl.spec @@ -53,6 +53,7 @@ BuildRequires: pkgconfig(ttrace) BuildRequires: pkgconfig(vd-win-util) %endif BuildRequires: pkgconfig(wgt-manifest-handlers) +BuildRequires: pkgconfig(jsoncpp) Requires: /usr/bin/systemctl @@ -74,6 +75,8 @@ DEFINE_ARGS=" libchromiumcontent_component=1 use_efl=1 is_tizen=1 + injected_bundle_path=%{_libdir}/libxwalk_injected_bundle.so + extension_path=%{_libdir}/tizen-extensions-crosswalk " %if "%{?TIZEN_PRODUCT_TV}" == "1" DEFINE_ARGS+=" @@ -131,6 +134,13 @@ install -m 0755 %{_out}/resources/electron.asar %{buildroot}/opt/usr/home/ow ./node_modules/asar/bin/asar p wrt %{_out}/resources/app.asar install -m 0755 %{_out}/resources/app.asar %{buildroot}/opt/usr/home/owner/data/org.tizen.electron-efl +# injected bundle and extensions +mkdir -p %{buildroot}%{extension_path} +# xwalk extension shared +install -p -m 644 %{_out}/lib/libxwalk_extension_shared.so %{buildroot}%{_libdir} +# xwalk_injected_bundle +install -p -m 755 %{_out}/lib/libxwalk_injected_bundle.so %{buildroot}%{_libdir} + %post # Owner account can't write /opt/usr/home/owner/data/org.tizen.electron-efl # which is created in 'install'. So we should copy resources in 'post'. @@ -161,3 +171,5 @@ rm -fr %{buildroot} %attr(755,root,root) %{_bindir}/xwalk_runtime %attr(644,root,root) %{_datadir}/aul/wrt.loader %attr(644,root,root) %{_libdir}/libwrt_common.so +%attr(644,root,root) %{_libdir}/libxwalk_extension_shared.so +%attr(644,root,root) %{_libdir}/libxwalk_injected_bundle.so diff --git a/tizen/build/common.gypi b/tizen/build/common.gypi index 587a0ad..5f90ec5 100644 --- a/tizen/build/common.gypi +++ b/tizen/build/common.gypi @@ -1,8 +1,8 @@ { 'variables': { 'build_type%': 'Debug', -# 'extension_path%': '<(extension_path)', -# 'injected_bundle_path%': '<(injected_bundle_path)', + 'extension_path%': '<(extension_path)', + 'injected_bundle_path%': '<(injected_bundle_path)', }, 'target_defaults': { 'variables': { @@ -36,10 +36,10 @@ '../', '<(SHARED_INTERMEDIATE_DIR)', ], -# 'defines': [ -# 'EXTENSION_PATH="<(extension_path)"', -# 'INJECTED_BUNDLE_PATH="<(injected_bundle_path)"', -# ], + 'defines': [ + 'EXTENSION_PATH="<(extension_path)"', + 'INJECTED_BUNDLE_PATH="<(injected_bundle_path)"', + ], 'cflags': [ '-std=c++0x', '-fPIC', diff --git a/tizen/extensions/common/constants.cc b/tizen/extensions/common/constants.cc new file mode 100644 index 0000000..cfc9fa4 --- /dev/null +++ b/tizen/extensions/common/constants.cc @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "extensions/common/constants.h" + +namespace extensions { + +const char kMethodGetExtensions[] = "xwalk://GetExtensions"; +const char kMethodCreateInstance[] = "xwalk://CreateInstance"; +const char kMethodDestroyInstance[] = "xwalk://DestroyInstance"; +const char kMethodSendSyncMessage[] = "xwalk://SendSyncMessage"; +const char kMethodPostMessage[] = "xwalk://PostMessage"; +const char kMethodGetAPIScript[] = "xwalk://GetAPIScript"; +const char kMethodPostMessageToJS[] = "xwalk://PostMessageToJS"; + + +} // namespace extensions diff --git a/tizen/extensions/common/constants.h b/tizen/extensions/common/constants.h new file mode 100644 index 0000000..588f09b --- /dev/null +++ b/tizen/extensions/common/constants.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef XWALK_EXTENSIONS_COMMON_CONSTANTS_H_ +#define XWALK_EXTENSIONS_COMMON_CONSTANTS_H_ + +namespace extensions { + +extern const char kMethodGetExtensions[]; +extern const char kMethodCreateInstance[]; +extern const char kMethodDestroyInstance[]; +extern const char kMethodSendSyncMessage[]; +extern const char kMethodPostMessage[]; +extern const char kMethodGetAPIScript[]; +extern const char kMethodPostMessageToJS[]; + +} // namespace extensions + +#endif // XWALK_EXTENSIONS_COMMON_CONSTANTS_H_ diff --git a/tizen/extensions/common/xwalk_extension.cc b/tizen/extensions/common/xwalk_extension.cc new file mode 100644 index 0000000..d41af24 --- /dev/null +++ b/tizen/extensions/common/xwalk_extension.cc @@ -0,0 +1,125 @@ +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/common/xwalk_extension.h" + +#include +#include + +#include "common/logger.h" +#include "extensions/common/xwalk_extension_adapter.h" +#include "extensions/public/XW_Extension.h" + +namespace extensions { + +XWalkExtension::XWalkExtension(const std::string& path, + XWalkExtensionDelegate* delegate) + : initialized_(false), + library_path_(path), + xw_extension_(0), + lazy_loading_(false), + delegate_(delegate), + created_instance_callback_(NULL), + destroyed_instance_callback_(NULL), + shutdown_callback_(NULL), + handle_msg_callback_(NULL), + handle_sync_msg_callback_(NULL), + handle_binary_msg_callback_(NULL) { +} + +XWalkExtension::XWalkExtension(const std::string& path, + const std::string& name, + const StringVector& entry_points, + XWalkExtensionDelegate* delegate) + : initialized_(false), + library_path_(path), + xw_extension_(0), + name_(name), + entry_points_(entry_points), + lazy_loading_(true), + delegate_(delegate), + created_instance_callback_(NULL), + destroyed_instance_callback_(NULL), + shutdown_callback_(NULL), + handle_msg_callback_(NULL), + handle_sync_msg_callback_(NULL), + handle_binary_msg_callback_(NULL) { +} + +XWalkExtension::~XWalkExtension() { + if (!initialized_) + return; + if (shutdown_callback_) + shutdown_callback_(xw_extension_); + XWalkExtensionAdapter::GetInstance()->UnregisterExtension(this); +} + +bool XWalkExtension::Initialize() { + if (initialized_) + return true; + + LOGGER(DEBUG) << "XWalkExtension:Initialize"; + void* handle = dlopen(library_path_.c_str(), RTLD_LAZY); + if (!handle) { + LOGGER(ERROR) << "Error loading extension '" + << library_path_ << "' : " << dlerror(); + return false; + } + + XW_Initialize_Func initialize = reinterpret_cast( + dlsym(handle, "XW_Initialize")); + if (!initialize) { + LOGGER(ERROR) << "Error loading extension '" << library_path_ + << "' : couldn't get XW_Initialize function."; + dlclose(handle); + return false; + } + + XWalkExtensionAdapter* adapter = XWalkExtensionAdapter::GetInstance(); + xw_extension_ = adapter->GetNextXWExtension(); + adapter->RegisterExtension(this); + + int ret = initialize(xw_extension_, XWalkExtensionAdapter::GetInterface); + if (ret != XW_OK) { + LOGGER(ERROR) << "Error loading extension '" << library_path_ + << "' : XW_Initialize() returned error value."; + dlclose(handle); + return false; + } + + initialized_ = true; + return true; +} + +XWalkExtensionInstance* XWalkExtension::CreateInstance() { + Initialize(); + XWalkExtensionAdapter* adapter = XWalkExtensionAdapter::GetInstance(); + XW_Instance xw_instance = adapter->GetNextXWInstance(); + return new XWalkExtensionInstance(this, xw_instance); +} + +std::string XWalkExtension::GetJavascriptCode() { + Initialize(); + return javascript_api_; +} + +void XWalkExtension::GetRuntimeVariable(const char* key, char* value, + size_t value_len) { + if (delegate_) { + delegate_->GetRuntimeVariable(key, value, value_len); + } +} +int XWalkExtension::CheckAPIAccessControl(const char* /*api_name*/) { + // Not Supported + return XW_OK; +} + +int XWalkExtension::RegisterPermissions(const char* /*perm_table*/) { + // Not Supported + return XW_OK; +} + +} // namespace extensions + diff --git a/tizen/extensions/common/xwalk_extension.h b/tizen/extensions/common/xwalk_extension.h new file mode 100644 index 0000000..c7aaf83 --- /dev/null +++ b/tizen/extensions/common/xwalk_extension.h @@ -0,0 +1,82 @@ +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef XWALK_EXTENSIONS_XWALK_EXTENSION_H_ +#define XWALK_EXTENSIONS_XWALK_EXTENSION_H_ + +#include +#include + +#include "extensions/common/xwalk_extension_instance.h" +#include "extensions/public/XW_Extension.h" +#include "extensions/public/XW_Extension_SyncMessage.h" +#include "extensions/public/XW_Extension_Message_2.h" + +namespace extensions { + +class XWalkExtensionAdapter; +class XWalkExtensionInstance; + +class XWalkExtension { + public: + typedef std::vector StringVector; + + class XWalkExtensionDelegate { + public: + virtual void GetRuntimeVariable(const char* key, char* value, + size_t value_len) = 0; + }; + + XWalkExtension(const std::string& path, XWalkExtensionDelegate* delegate); + XWalkExtension(const std::string& path, + const std::string& name, + const StringVector& entry_points, + XWalkExtensionDelegate* delegate); + virtual ~XWalkExtension(); + + bool Initialize(); + XWalkExtensionInstance* CreateInstance(); + std::string GetJavascriptCode(); + + std::string name() const { return name_; } + + const StringVector& entry_points() const { + return entry_points_; + } + + bool lazy_loading() const { + return lazy_loading_; + } + + private: + friend class XWalkExtensionAdapter; + friend class XWalkExtensionInstance; + + void GetRuntimeVariable(const char* key, char* value, size_t value_len); + int CheckAPIAccessControl(const char* api_name); + int RegisterPermissions(const char* perm_table); + + bool initialized_; + std::string library_path_; + XW_Extension xw_extension_; + + std::string name_; + std::string javascript_api_; + StringVector entry_points_; + bool lazy_loading_; + + XWalkExtensionDelegate* delegate_; + + XW_CreatedInstanceCallback created_instance_callback_; + XW_DestroyedInstanceCallback destroyed_instance_callback_; + XW_ShutdownCallback shutdown_callback_; + XW_HandleMessageCallback handle_msg_callback_; + XW_HandleSyncMessageCallback handle_sync_msg_callback_; + XW_HandleBinaryMessageCallback handle_binary_msg_callback_; +}; + +} // namespace extensions + +#endif // XWALK_EXTENSIONS_XWALK_EXTENSION_H_ diff --git a/tizen/extensions/common/xwalk_extension_adapter.cc b/tizen/extensions/common/xwalk_extension_adapter.cc new file mode 100644 index 0000000..ef693ff --- /dev/null +++ b/tizen/extensions/common/xwalk_extension_adapter.cc @@ -0,0 +1,323 @@ +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/common/xwalk_extension_adapter.h" + +#include + +#include "common/logger.h" + +namespace extensions { + +XWalkExtensionAdapter::XWalkExtensionAdapter() + : next_xw_extension_(1), + next_xw_instance_(1) { +} + +XWalkExtensionAdapter::~XWalkExtensionAdapter() { +} + +XWalkExtensionAdapter* XWalkExtensionAdapter::GetInstance() { + static XWalkExtensionAdapter self; + return &self; +} + +XW_Extension XWalkExtensionAdapter::GetNextXWExtension() { + return next_xw_extension_++; +} + +XW_Instance XWalkExtensionAdapter::GetNextXWInstance() { + return next_xw_instance_++; +} + +void XWalkExtensionAdapter::RegisterExtension(XWalkExtension* extension) { + XW_Extension xw_extension = extension->xw_extension_; + if (!(xw_extension > 0 && xw_extension < next_xw_extension_)) { + LOGGER(WARN) << "xw_extension (" << xw_extension << ") is invalid."; + return; + } + if (extension_map_.find(xw_extension) == extension_map_.end()) + extension_map_[xw_extension] = extension; +} + +void XWalkExtensionAdapter::UnregisterExtension(XWalkExtension* extension) { + XW_Extension xw_extension = extension->xw_extension_; + if (!(xw_extension > 0 && xw_extension < next_xw_extension_)) { + LOGGER(WARN) << "xw_extension (" << xw_extension << ") is invalid."; + return; + } + auto it = extension_map_.find(xw_extension); + if (it != extension_map_.end()) { + extension_map_.erase(it); + } +} + +void XWalkExtensionAdapter::RegisterInstance( + XWalkExtensionInstance* instance) { + XW_Instance xw_instance = instance->xw_instance_; + if (!(xw_instance > 0 && xw_instance < next_xw_instance_)) { + LOGGER(WARN) << "xw_instance (" << xw_instance << ") is invalid."; + return; + } + if (instance_map_.find(xw_instance) == instance_map_.end()) + instance_map_[xw_instance] = instance; +} + +void XWalkExtensionAdapter::UnregisterInstance( + XWalkExtensionInstance* instance) { + XW_Instance xw_instance = instance->xw_instance_; + if (!(xw_instance > 0 && xw_instance < next_xw_instance_)) { + LOGGER(WARN) << "xw_instance (" << xw_instance << ") is invalid."; + return; + } + auto it = instance_map_.find(xw_instance); + if (it != instance_map_.end()) { + instance_map_.erase(it); + } +} + +const void* XWalkExtensionAdapter::GetInterface(const char* name) { + if (!strcmp(name, XW_CORE_INTERFACE_1)) { + static const XW_CoreInterface_1 coreInterface1 = { + CoreSetExtensionName, + CoreSetJavaScriptAPI, + CoreRegisterInstanceCallbacks, + CoreRegisterShutdownCallback, + CoreSetInstanceData, + CoreGetInstanceData + }; + return &coreInterface1; + } + + if (!strcmp(name, XW_MESSAGING_INTERFACE_1)) { + static const XW_MessagingInterface_1 messagingInterface1 = { + MessagingRegister, + MessagingPostMessage + }; + return &messagingInterface1; + } + + if (!strcmp(name, XW_MESSAGING_INTERFACE_2)) { + static const XW_MessagingInterface_2 messagingInterface2 = { + MessagingRegister, + MessagingPostMessage, + MessagingRegisterBinaryMessageCallback, + MessagingPostBinaryMessage + }; + return &messagingInterface2; + } + + if (!strcmp(name, XW_INTERNAL_SYNC_MESSAGING_INTERFACE_1)) { + static const XW_Internal_SyncMessagingInterface_1 + syncMessagingInterface1 = { + SyncMessagingRegister, + SyncMessagingSetSyncReply + }; + return &syncMessagingInterface1; + } + + if (!strcmp(name, XW_INTERNAL_ENTRY_POINTS_INTERFACE_1)) { + static const XW_Internal_EntryPointsInterface_1 entryPointsInterface1 = { + EntryPointsSetExtraJSEntryPoints + }; + return &entryPointsInterface1; + } + + if (!strcmp(name, XW_INTERNAL_RUNTIME_INTERFACE_1)) { + static const XW_Internal_RuntimeInterface_1 runtimeInterface1 = { + RuntimeGetStringVariable + }; + return &runtimeInterface1; + } + + if (!strcmp(name, XW_INTERNAL_PERMISSIONS_INTERFACE_1)) { + static const XW_Internal_PermissionsInterface_1 permissionsInterface1 = { + PermissionsCheckAPIAccessControl, + PermissionsRegisterPermissions + }; + return &permissionsInterface1; + } + + LOGGER(WARN) << "Interface '" << name << "' is not supported."; + return NULL; +} + +XWalkExtension* XWalkExtensionAdapter::GetExtension(XW_Extension xw_extension) { + XWalkExtensionAdapter* adapter = XWalkExtensionAdapter::GetInstance(); + ExtensionMap::iterator it = adapter->extension_map_.find(xw_extension); + if (it == adapter->extension_map_.end()) + return NULL; + return it->second; +} + +XWalkExtensionInstance* XWalkExtensionAdapter::GetExtensionInstance( + XW_Instance xw_instance) { + XWalkExtensionAdapter* adapter = XWalkExtensionAdapter::GetInstance(); + InstanceMap::iterator it = adapter->instance_map_.find(xw_instance); + if (it == adapter->instance_map_.end()) + return NULL; + return it->second; +} + +#define CHECK(x, xw) \ + if (!x) { \ + LOGGER(WARN) << "Ignoring call. Invalid " << #xw << " = " << xw; \ + return; \ + } + +#define RETURN_IF_INITIALIZED(x) \ + if (x->initialized_) \ + return; + +void XWalkExtensionAdapter::CoreSetExtensionName( + XW_Extension xw_extension, + const char* name) { + XWalkExtension* extension = GetExtension(xw_extension); + CHECK(extension, xw_extension); + RETURN_IF_INITIALIZED(extension); + extension->name_ = name; +} + +void XWalkExtensionAdapter::CoreSetJavaScriptAPI( + XW_Extension xw_extension, + const char* javascript_api) { + XWalkExtension* extension = GetExtension(xw_extension); + CHECK(extension, xw_extension); + RETURN_IF_INITIALIZED(extension); + extension->javascript_api_ = javascript_api; +} + +void XWalkExtensionAdapter::CoreRegisterInstanceCallbacks( + XW_Extension xw_extension, + XW_CreatedInstanceCallback created, + XW_DestroyedInstanceCallback destroyed) { + XWalkExtension* extension = GetExtension(xw_extension); + CHECK(extension, xw_extension); + RETURN_IF_INITIALIZED(extension); + extension->created_instance_callback_ = created; + extension->destroyed_instance_callback_ = destroyed; +} + +void XWalkExtensionAdapter::CoreRegisterShutdownCallback( + XW_Extension xw_extension, + XW_ShutdownCallback shutdown) { + XWalkExtension* extension = GetExtension(xw_extension); + CHECK(extension, xw_extension); + RETURN_IF_INITIALIZED(extension); + extension->shutdown_callback_ = shutdown; +} + +void XWalkExtensionAdapter::CoreSetInstanceData( + XW_Instance xw_instance, + void* data) { + XWalkExtensionInstance* instance = GetExtensionInstance(xw_instance); + CHECK(instance, xw_instance); + instance->instance_data_ = data; +} + +void* XWalkExtensionAdapter::CoreGetInstanceData( + XW_Instance xw_instance) { + XWalkExtensionInstance* instance = GetExtensionInstance(xw_instance); + if (instance) + return instance->instance_data_; + else + return NULL; +} + +void XWalkExtensionAdapter::MessagingRegister( + XW_Extension xw_extension, + XW_HandleMessageCallback handle_message) { + XWalkExtension* extension = GetExtension(xw_extension); + CHECK(extension, xw_extension); + RETURN_IF_INITIALIZED(extension); + extension->handle_msg_callback_ = handle_message; +} + +void XWalkExtensionAdapter::MessagingPostMessage( + XW_Instance xw_instance, + const char* message) { + XWalkExtensionInstance* instance = GetExtensionInstance(xw_instance); + CHECK(instance, xw_instance); + instance->PostMessageToJS(message); +} + +void XWalkExtensionAdapter::SyncMessagingRegister( + XW_Extension xw_extension, + XW_HandleSyncMessageCallback handle_sync_message) { + XWalkExtension* extension = GetExtension(xw_extension); + CHECK(extension, xw_extension); + RETURN_IF_INITIALIZED(extension); + extension->handle_sync_msg_callback_ = handle_sync_message; +} + +void XWalkExtensionAdapter::SyncMessagingSetSyncReply( + XW_Instance xw_instance, + const char* reply) { + XWalkExtensionInstance* instance = GetExtensionInstance(xw_instance); + CHECK(instance, xw_instance); + instance->SyncReplyToJS(reply); +} + +void XWalkExtensionAdapter::EntryPointsSetExtraJSEntryPoints( + XW_Extension xw_extension, + const char** entry_points) { + XWalkExtension* extension = GetExtension(xw_extension); + CHECK(extension, xw_extension); + RETURN_IF_INITIALIZED(extension); + + for (int i=0; entry_points[i]; ++i) { + extension->entry_points_.push_back(std::string(entry_points[i])); + } +} + +void XWalkExtensionAdapter::RuntimeGetStringVariable( + XW_Extension xw_extension, + const char* key, + char* value, + unsigned int value_len) { + XWalkExtension* extension = GetExtension(xw_extension); + CHECK(extension, xw_extension); + extension->GetRuntimeVariable(key, value, value_len); +} + +int XWalkExtensionAdapter::PermissionsCheckAPIAccessControl( + XW_Extension xw_extension, + const char* api_name) { + XWalkExtension* extension = GetExtension(xw_extension); + if (extension) + return extension->CheckAPIAccessControl(api_name); + else + return XW_ERROR; +} + +int XWalkExtensionAdapter::PermissionsRegisterPermissions( + XW_Extension xw_extension, + const char* perm_table) { + XWalkExtension* extension = GetExtension(xw_extension); + if (extension) + return extension->RegisterPermissions(perm_table); + else + return XW_ERROR; +} + +void XWalkExtensionAdapter::MessagingRegisterBinaryMessageCallback( + XW_Extension xw_extension, XW_HandleBinaryMessageCallback handle_message) { + XWalkExtension* extension = GetExtension(xw_extension); + CHECK(extension, xw_extension); + RETURN_IF_INITIALIZED(extension); + extension->handle_binary_msg_callback_ = handle_message; +} + +void XWalkExtensionAdapter::MessagingPostBinaryMessage( + XW_Instance xw_instance, const char* message, size_t size) { + XWalkExtensionInstance* instance = GetExtensionInstance(xw_instance); + CHECK(instance, xw_instance); + instance->PostMessageToJS(message); +} + +#undef CHECK +#undef RETURN_IF_INITIALIZED + +} // namespace extensions diff --git a/tizen/extensions/common/xwalk_extension_adapter.h b/tizen/extensions/common/xwalk_extension_adapter.h new file mode 100644 index 0000000..9a29c35 --- /dev/null +++ b/tizen/extensions/common/xwalk_extension_adapter.h @@ -0,0 +1,96 @@ +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef XWALK_EXTENSIONS_XWALK_EXTENSION_ADAPTER_H_ +#define XWALK_EXTENSIONS_XWALK_EXTENSION_ADAPTER_H_ + +#include + +#include "extensions/common/xwalk_extension.h" +#include "extensions/common/xwalk_extension_instance.h" +#include "extensions/public/XW_Extension.h" +#include "extensions/public/XW_Extension_EntryPoints.h" +#include "extensions/public/XW_Extension_Permissions.h" +#include "extensions/public/XW_Extension_Runtime.h" +#include "extensions/public/XW_Extension_SyncMessage.h" +#include "extensions/public/XW_Extension_Message_2.h" + +namespace extensions { + +class XWalkExtensionAdapter { + public: + typedef std::map ExtensionMap; + typedef std::map InstanceMap; + + static XWalkExtensionAdapter* GetInstance(); + + XW_Extension GetNextXWExtension(); + XW_Instance GetNextXWInstance(); + + void RegisterExtension(XWalkExtension* extension); + void UnregisterExtension(XWalkExtension* extension); + + void RegisterInstance(XWalkExtensionInstance* instance); + void UnregisterInstance(XWalkExtensionInstance* instance); + + // Returns the correct struct according to interface asked. This is + // passed to external extensions in XW_Initialize() call. + static const void* GetInterface(const char* name); + + private: + XWalkExtensionAdapter(); + virtual ~XWalkExtensionAdapter(); + + static XWalkExtension* GetExtension(XW_Extension xw_extension); + static XWalkExtensionInstance* GetExtensionInstance(XW_Instance xw_instance); + + static void CoreSetExtensionName( + XW_Extension xw_extension, const char* name); + static void CoreSetJavaScriptAPI( + XW_Extension xw_extension, const char* javascript_api); + static void CoreRegisterInstanceCallbacks( + XW_Extension xw_extension, + XW_CreatedInstanceCallback created, + XW_DestroyedInstanceCallback destroyed); + static void CoreRegisterShutdownCallback( + XW_Extension xw_extension, + XW_ShutdownCallback shutdown); + static void CoreSetInstanceData( + XW_Instance xw_instance, void* data); + static void* CoreGetInstanceData(XW_Instance xw_instance); + static void MessagingRegister( + XW_Extension xw_extension, + XW_HandleMessageCallback handle_message); + static void MessagingPostMessage( + XW_Instance xw_instance, const char* message); + static void SyncMessagingRegister( + XW_Extension xw_extension, + XW_HandleSyncMessageCallback handle_sync_message); + static void SyncMessagingSetSyncReply( + XW_Instance xw_instance, const char* reply); + static void EntryPointsSetExtraJSEntryPoints( + XW_Extension xw_extension, const char** entry_points); + static void RuntimeGetStringVariable( + XW_Extension xw_extension, + const char* key, char* value, unsigned int value_len); + static int PermissionsCheckAPIAccessControl( + XW_Extension xw_extension, const char* api_name); + static int PermissionsRegisterPermissions( + XW_Extension xw_extension, const char* perm_table); + static void MessagingRegisterBinaryMessageCallback( + XW_Extension xw_extension, XW_HandleBinaryMessageCallback handle_message); + static void MessagingPostBinaryMessage( + XW_Instance xw_instance, const char* message, size_t size); + + ExtensionMap extension_map_; + InstanceMap instance_map_; + + XW_Extension next_xw_extension_; + XW_Instance next_xw_instance_; +}; + +} // namespace extensions + +#endif // XWALK_EXTENSIONS_XWALK_EXTENSION_ADAPTER_H_ diff --git a/tizen/extensions/common/xwalk_extension_instance.cc b/tizen/extensions/common/xwalk_extension_instance.cc new file mode 100644 index 0000000..c86bb59 --- /dev/null +++ b/tizen/extensions/common/xwalk_extension_instance.cc @@ -0,0 +1,63 @@ +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/common/xwalk_extension_instance.h" + +#include "extensions/common/xwalk_extension_adapter.h" +#include "extensions/public/XW_Extension_SyncMessage.h" + +namespace extensions { + +XWalkExtensionInstance::XWalkExtensionInstance( + XWalkExtension* extension, XW_Instance xw_instance) + : extension_(extension), + xw_instance_(xw_instance), + instance_data_(NULL) { + XWalkExtensionAdapter::GetInstance()->RegisterInstance(this); + XW_CreatedInstanceCallback callback = extension_->created_instance_callback_; + if (callback) + callback(xw_instance_); +} + +XWalkExtensionInstance::~XWalkExtensionInstance() { + XW_DestroyedInstanceCallback callback = + extension_->destroyed_instance_callback_; + if (callback) + callback(xw_instance_); + XWalkExtensionAdapter::GetInstance()->UnregisterInstance(this); +} + +void XWalkExtensionInstance::HandleMessage(const std::string& msg) { + XW_HandleMessageCallback callback = extension_->handle_msg_callback_; + if (callback) + callback(xw_instance_, msg.c_str()); +} + +void XWalkExtensionInstance::HandleSyncMessage(const std::string& msg) { + XW_HandleSyncMessageCallback callback = extension_->handle_sync_msg_callback_; + if (callback) { + callback(xw_instance_, msg.c_str()); + } +} + +void XWalkExtensionInstance::SetPostMessageCallback( + MessageCallback callback) { + post_message_callback_ = callback; +} + +void XWalkExtensionInstance::SetSendSyncReplyCallback( + MessageCallback callback) { + send_sync_reply_callback_ = callback; +} + +void XWalkExtensionInstance::PostMessageToJS(const std::string& msg) { + post_message_callback_(msg); +} + +void XWalkExtensionInstance::SyncReplyToJS(const std::string& reply) { + send_sync_reply_callback_(reply); +} + +} // namespace extensions diff --git a/tizen/extensions/common/xwalk_extension_instance.h b/tizen/extensions/common/xwalk_extension_instance.h new file mode 100644 index 0000000..9efe2db --- /dev/null +++ b/tizen/extensions/common/xwalk_extension_instance.h @@ -0,0 +1,47 @@ +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef XWALK_EXTENSIONS_XWALK_EXTENSION_INSTANCE_H_ +#define XWALK_EXTENSIONS_XWALK_EXTENSION_INSTANCE_H_ + +#include +#include + +#include "extensions/public/XW_Extension.h" + +namespace extensions { + +class XWalkExtension; + +class XWalkExtensionInstance { + public: + typedef std::function MessageCallback; + + XWalkExtensionInstance(XWalkExtension* extension, XW_Instance xw_instance); + virtual ~XWalkExtensionInstance(); + + void HandleMessage(const std::string& msg); + void HandleSyncMessage(const std::string& msg); + + void SetPostMessageCallback(MessageCallback callback); + void SetSendSyncReplyCallback(MessageCallback callback); + + private: + friend class XWalkExtensionAdapter; + + void PostMessageToJS(const std::string& msg); + void SyncReplyToJS(const std::string& reply); + + XWalkExtension* extension_; + XW_Instance xw_instance_; + void* instance_data_; + + MessageCallback post_message_callback_; + MessageCallback send_sync_reply_callback_; +}; + +} // namespace extensions + +#endif // XWALK_EXTENSIONS_XWALK_EXTENSION_INSTANCE_H_ diff --git a/tizen/extensions/common/xwalk_extension_manager.cc b/tizen/extensions/common/xwalk_extension_manager.cc new file mode 100644 index 0000000..130eca8 --- /dev/null +++ b/tizen/extensions/common/xwalk_extension_manager.cc @@ -0,0 +1,260 @@ +// Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/common/xwalk_extension_manager.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include "common/app_db.h" +#include "common/logger.h" +#include "common/picojson.h" +#include "common/file_utils.h" +#include "common/string_utils.h" + +#include "extensions/common/constants.h" +#include "extensions/common/xwalk_extension.h" + +#ifndef EXTENSION_PATH + #error EXTENSION_PATH is not set. +#endif + +namespace extensions { + +namespace { + +const char kAppDBRuntimeSection[] = "Runtime"; + +const char kExtensionPrefix[] = "lib"; +const char kExtensionSuffix[] = ".so"; +const char kExtensionMetadataSuffix[] = ".json"; + +static const char* kPreloadLibs[] = { + EXTENSION_PATH"/libtizen.so", + EXTENSION_PATH"/libtizen_common.so", + EXTENSION_PATH"/libtizen_application.so", + EXTENSION_PATH"/libtizen_utils.so", + NULL +}; + +const char kUserPluginsDirectory[] = "plugin/"; +const char kArchArmv7l[] = "armv7l"; +const char kArchI586[] = "i586"; +const char kArchDefault[] = "default"; + +} // namespace + +XWalkExtensionManager::XWalkExtensionManager() { +} + +XWalkExtensionManager::~XWalkExtensionManager() { +} + +void XWalkExtensionManager::PreloadExtensions() { + for (int i = 0; kPreloadLibs[i]; i++) { + LOGGER(DEBUG) << "Preload libs : " << kPreloadLibs[i]; + void* handle = dlopen(kPreloadLibs[i], RTLD_NOW|RTLD_GLOBAL); + if (handle == nullptr) { + LOGGER(WARN) << "Fail to load libs : " << dlerror(); + } + } +} + +void XWalkExtensionManager::LoadExtensions(bool meta_only) { + if (!extensions_.empty()) { + return; + } + + std::string extension_path(EXTENSION_PATH); + + // Gets all extension files in the EXTENSION_PATH + std::string ext_pattern(extension_path); + ext_pattern.append("/"); + ext_pattern.append(kExtensionPrefix); + ext_pattern.append("*"); + ext_pattern.append(kExtensionSuffix); + + StringSet files; + { + glob_t glob_result; + glob(ext_pattern.c_str(), GLOB_TILDE, NULL, &glob_result); + for (unsigned int i = 0; i < glob_result.gl_pathc; ++i) { + files.insert(glob_result.gl_pathv[i]); + } + } + + // Gets all metadata files in the EXTENSION_PATH + // Loads information from the metadata files and remove the loaded file from + // the set 'files' + std::string meta_pattern(extension_path); + meta_pattern.append("/"); + meta_pattern.append("*"); + meta_pattern.append(kExtensionMetadataSuffix); + { + glob_t glob_result; + glob(meta_pattern.c_str(), GLOB_TILDE, NULL, &glob_result); + for (unsigned int i = 0; i < glob_result.gl_pathc; ++i) { + RegisterExtensionsByMeta(glob_result.gl_pathv[i], &files); + } + } + + // Load extensions in the remained files of the set 'files' + if (!meta_only) { + for (auto it = files.begin(); it != files.end(); ++it) { + XWalkExtension* ext = new XWalkExtension(*it, this); + RegisterExtension(ext); + } + } +} + +void XWalkExtensionManager::LoadUserExtensions(const std::string app_path) { + if (app_path.empty()) { + LOGGER(ERROR) << "Failed to get package root path"; + return; + } + std::string app_ext_pattern(app_path); + app_ext_pattern.append(kUserPluginsDirectory); + struct utsname u; + if (0 == uname(&u)) { + std::string machine = u.machine; + if (!machine.empty()) { + if (machine == kArchArmv7l) { + app_ext_pattern.append(kArchArmv7l); + } else if (machine == kArchI586) { + app_ext_pattern.append(kArchI586); + } else { + app_ext_pattern.append(kArchDefault); + } + } else { + LOGGER(ERROR) << "cannot get machine info"; + app_ext_pattern.append(kArchDefault); + } + app_ext_pattern.append("/"); + } + app_ext_pattern.append("*"); + app_ext_pattern.append(kExtensionSuffix); + + StringSet files; + { + glob_t glob_result; + glob(app_ext_pattern.c_str(), GLOB_TILDE, NULL, &glob_result); + for (unsigned int i = 0; i < glob_result.gl_pathc; ++i) { + files.insert(glob_result.gl_pathv[i]); + } + } + for (auto it = files.begin(); it != files.end(); ++it) { + XWalkExtension* ext = new XWalkExtension(*it, this); + RegisterExtension(ext); + } + LOGGER(DEBUG) << "finish load user extension plugins"; +} + +void XWalkExtensionManager::UnloadExtensions() { + for (auto it = extensions_.begin(); it != extensions_.end(); ++it) { + delete it->second; + } + extensions_.clear(); +} + +bool XWalkExtensionManager::RegisterSymbols(XWalkExtension* extension) { + std::string name = extension->name(); + + if (extension_symbols_.find(name) != extension_symbols_.end()) { + LOGGER(WARN) << "Ignoring extension with name already registred. '" + << name << "'"; + return false; + } + + XWalkExtension::StringVector entry_points = extension->entry_points(); + for (auto it = entry_points.begin(); it != entry_points.end(); ++it) { + if (extension_symbols_.find(*it) != extension_symbols_.end()) { + LOGGER(WARN) << "Ignoring extension with entry_point already registred. '" + << (*it) << "'"; + return false; + } + } + + for (auto it = entry_points.begin(); it != entry_points.end(); ++it) { + extension_symbols_.insert(*it); + } + + extension_symbols_.insert(name); + + return true; +} + +void XWalkExtensionManager::RegisterExtension(XWalkExtension* extension) { + if (!extension->lazy_loading() && !extension->Initialize()) { + delete extension; + return; + } + + if (!RegisterSymbols(extension)) { + delete extension; + return; + } + + extensions_[extension->name()] = extension; + LOGGER(DEBUG) << extension->name() << " is registered."; +} + +void XWalkExtensionManager::RegisterExtensionsByMeta( + const std::string& meta_path, StringSet* files) { + std::string extension_path(EXTENSION_PATH); + + std::ifstream metafile(meta_path.c_str()); + if (!metafile.is_open()) { + LOGGER(ERROR) << "Fail to open the plugin metadata file :" << meta_path; + return; + } + + picojson::value metadata; + metafile >> metadata; + if (metadata.is()) { + auto& plugins = metadata.get(); + for (auto plugin = plugins.begin(); plugin != plugins.end(); ++plugin) { + if (!plugin->is()) + continue; + + std::string name = plugin->get("name").to_str(); + std::string lib = plugin->get("lib").to_str(); + if (!common::utils::StartsWith(lib, "/")) { + lib = extension_path + "/" + lib; + } + + std::vector entries; + auto& entry_points_value = plugin->get("entry_points"); + if (entry_points_value.is()) { + auto& entry_points = entry_points_value.get(); + for (auto entry = entry_points.begin(); entry != entry_points.end(); + ++entry) { + entries.push_back(entry->to_str()); + } + } + XWalkExtension* extension = new XWalkExtension(lib, name, entries, this); + RegisterExtension(extension); + files->erase(lib); + } + } else { + LOGGER(ERROR) << meta_path << " is not a valid metadata file."; + } + metafile.close(); +} + +// override +void XWalkExtensionManager::GetRuntimeVariable( + const char* key, char* value, size_t value_len) { + common::AppDB* db = common::AppDB::GetInstance(); + std::string ret = db->Get(kAppDBRuntimeSection, key); + strncpy(value, ret.c_str(), value_len); +} + + +} // namespace extensions diff --git a/tizen/extensions/common/xwalk_extension_manager.h b/tizen/extensions/common/xwalk_extension_manager.h new file mode 100644 index 0000000..cfbdede --- /dev/null +++ b/tizen/extensions/common/xwalk_extension_manager.h @@ -0,0 +1,47 @@ +// Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef XWALK_EXTENSIONS_XWALK_EXTENSION_MANAGER_H_ +#define XWALK_EXTENSIONS_XWALK_EXTENSION_MANAGER_H_ + +#include +#include +#include + +#include "extensions/common/xwalk_extension.h" + +namespace extensions { + +class XWalkExtensionManager : public XWalkExtension::XWalkExtensionDelegate { + public: + typedef std::set StringSet; + typedef std::map ExtensionMap; + + XWalkExtensionManager(); + virtual ~XWalkExtensionManager(); + + ExtensionMap extensions() const { return extensions_; } + + void LoadExtensions(bool meta_only = true); + void LoadUserExtensions(const std::string app_path); + void PreloadExtensions(); + + void UnloadExtensions(); + + private: + // override + void GetRuntimeVariable(const char* key, char* value, size_t value_len); + + bool RegisterSymbols(XWalkExtension* extension); + void RegisterExtension(XWalkExtension* extension); + void RegisterExtensionsByMeta(const std::string& meta_path, + StringSet* files); + + StringSet extension_symbols_; + ExtensionMap extensions_; +}; + +} // namespace extensions + +#endif // XWALK_EXTENSIONS_XWALK_EXTENSION_MANAGER_H_ diff --git a/tizen/extensions/common/xwalk_extension_server.cc b/tizen/extensions/common/xwalk_extension_server.cc new file mode 100644 index 0000000..fc50396 --- /dev/null +++ b/tizen/extensions/common/xwalk_extension_server.cc @@ -0,0 +1,229 @@ +// Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/common/xwalk_extension_server.h" + +#include + +#include + +#include "common/logger.h" +#include "common/profiler.h" +#include "common/string_utils.h" +#include "extensions/common/constants.h" +#include "extensions/common/xwalk_extension_manager.h" + +namespace extensions { + +// static +XWalkExtensionServer* XWalkExtensionServer::GetInstance() { + static XWalkExtensionServer self; + return &self; +} + +XWalkExtensionServer::XWalkExtensionServer() { + manager_.LoadExtensions(); +} + +XWalkExtensionServer::~XWalkExtensionServer() { +} + +void XWalkExtensionServer::SetupIPC(Ewk_Context* ewk_context) { + ewk_context_ = ewk_context; +} + +void XWalkExtensionServer::Preload() { + manager_.PreloadExtensions(); +} + +void XWalkExtensionServer::Shutdown() { + for (auto it = instances_.begin(); it != instances_.end(); ++it) { + delete it->second; + } + instances_.clear(); + manager_.UnloadExtensions(); +} + +Json::Value XWalkExtensionServer::GetExtensions() { + Json::Value out; + auto extensions = manager_.extensions(); + for (auto it = extensions.begin(); it != extensions.end(); ++it) { + Json::Value ext; + ext["name"] = it->second->name(); + // ext["api"] = it->second->GetJavascriptCode(); + auto entry_points = it->second->entry_points(); + for (auto ite = entry_points.begin(); ite != entry_points.end(); ++ite) { + ext["entry_points"].append(*ite); + } + out.append(ext); + } + return out; +} + +std::string XWalkExtensionServer::GetAPIScript( + const std::string& extension_name) { + auto extensions = manager_.extensions(); + auto it = extensions.find(extension_name); + if (it == extensions.end()) { + LOGGER(ERROR) << "No such extension '" << extension_name << "'"; + return std::string(); + } + + return it->second->GetJavascriptCode(); +} + +std::string XWalkExtensionServer::CreateInstance( + const std::string& extension_name) { + std::string instance_id; + + auto extensions = manager_.extensions(); + auto it = extensions.find(extension_name); + if (it != extensions.end()) { + XWalkExtensionInstance* instance = it->second->CreateInstance(); + if (instance) { + instance_id = common::utils::GenerateUUID(); + instance->SetPostMessageCallback( + [this, instance_id](const std::string& msg) { + Ewk_IPC_Wrt_Message_Data* ans = ewk_ipc_wrt_message_data_new(); + ewk_ipc_wrt_message_data_type_set(ans, kMethodPostMessageToJS); + ewk_ipc_wrt_message_data_id_set(ans, instance_id.c_str()); + ewk_ipc_wrt_message_data_value_set(ans, msg.c_str()); + if (!ewk_ipc_wrt_message_send(ewk_context_, ans)) { + LOGGER(ERROR) << "Failed to send response"; + } + ewk_ipc_wrt_message_data_del(ans); + }); + + instances_[instance_id] = instance; + } else { + LOGGER(ERROR) << "Failed to create instance of the extension '" + << extension_name << "'"; + } + } else { + LOGGER(ERROR) << "No such extension '" << extension_name << "'"; + } + return instance_id; +} + +void XWalkExtensionServer::HandleIPCMessage(Ewk_IPC_Wrt_Message_Data* data) { + if (!data) { + LOGGER(ERROR) << "Invalid parameter. data is NULL."; + return; + } + + if (!ewk_context_) { + LOGGER(WARN) << "IPC is not ready yet."; + return; + } + + Eina_Stringshare* msg_type = ewk_ipc_wrt_message_data_type_get(data); + #define TYPE_IS(x) (!strcmp(msg_type, x)) + + if (TYPE_IS(kMethodGetExtensions)) { + HandleGetExtensions(data); + } else if (TYPE_IS(kMethodCreateInstance)) { + HandleCreateInstance(data); + } else if (TYPE_IS(kMethodDestroyInstance)) { + HandleDestroyInstance(data); + } else if (TYPE_IS(kMethodPostMessage)) { + HandlePostMessageToNative(data); + } else if (TYPE_IS(kMethodSendSyncMessage)) { + HandleSendSyncMessageToNative(data); + } else if (TYPE_IS(kMethodGetAPIScript)) { + HandleGetAPIScript(data); + } + + eina_stringshare_del(msg_type); + #undef TYPE_IS +} + +void XWalkExtensionServer::HandleGetExtensions(Ewk_IPC_Wrt_Message_Data* data) { + Json::Value reply = GetExtensions(); + Json::FastWriter writer; + std::string reply_str = writer.write(reply); + ewk_ipc_wrt_message_data_value_set(data, reply_str.c_str()); +} + +void XWalkExtensionServer::HandleCreateInstance( + Ewk_IPC_Wrt_Message_Data* data) { + Eina_Stringshare* extension_name = ewk_ipc_wrt_message_data_value_get(data); + + std::string instance_id = CreateInstance(extension_name); + + ewk_ipc_wrt_message_data_value_set(data, instance_id.c_str()); + + eina_stringshare_del(extension_name); +} + +void XWalkExtensionServer::HandleDestroyInstance( + Ewk_IPC_Wrt_Message_Data* data) { + Eina_Stringshare* instance_id = ewk_ipc_wrt_message_data_id_get(data); + + auto it = instances_.find(instance_id); + if (it != instances_.end()) { + XWalkExtensionInstance* instance = it->second; + delete instance; + instances_.erase(it); + } else { + LOGGER(ERROR) << "No such instance '" << instance_id << "'"; + } + + eina_stringshare_del(instance_id); +} + +void XWalkExtensionServer::HandlePostMessageToNative( + Ewk_IPC_Wrt_Message_Data* data) { + Eina_Stringshare* instance_id = ewk_ipc_wrt_message_data_id_get(data); + + auto it = instances_.find(instance_id); + if (it != instances_.end()) { + Eina_Stringshare* msg = ewk_ipc_wrt_message_data_value_get(data); + XWalkExtensionInstance* instance = it->second; + instance->HandleMessage(msg); + eina_stringshare_del(msg); + } else { + LOGGER(ERROR) << "No such instance '" << instance_id << "'"; + } + + eina_stringshare_del(instance_id); +} + +void XWalkExtensionServer::HandleSendSyncMessageToNative( + Ewk_IPC_Wrt_Message_Data* data) { + Eina_Stringshare* instance_id = ewk_ipc_wrt_message_data_id_get(data); + + auto it = instances_.find(instance_id); + if (it != instances_.end()) { + Eina_Stringshare* msg = ewk_ipc_wrt_message_data_value_get(data); + XWalkExtensionInstance* instance = it->second; + std::string reply; + instance->SetSendSyncReplyCallback([&reply](const std::string& msg) { + reply = msg; + }); + instance->HandleSyncMessage(msg); + ewk_ipc_wrt_message_data_value_set(data, reply.c_str()); + eina_stringshare_del(msg); + } else { + LOGGER(ERROR) << "No such instance '" << instance_id << "'"; + } + + eina_stringshare_del(instance_id); +} + +void XWalkExtensionServer::HandleGetAPIScript( + Ewk_IPC_Wrt_Message_Data* data) { + Eina_Stringshare* extension_name = ewk_ipc_wrt_message_data_value_get(data); + + std::string api = GetAPIScript(extension_name); + + ewk_ipc_wrt_message_data_value_set(data, api.c_str()); + + eina_stringshare_del(extension_name); +} + +void XWalkExtensionServer::LoadUserExtensions(const std::string app_path) { + manager_.LoadUserExtensions(app_path); +} + +} // namespace extensions diff --git a/tizen/extensions/common/xwalk_extension_server.h b/tizen/extensions/common/xwalk_extension_server.h new file mode 100644 index 0000000..3cd67bf --- /dev/null +++ b/tizen/extensions/common/xwalk_extension_server.h @@ -0,0 +1,57 @@ +// Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef XWALK_EXTENSIONS_XWALK_EXTENSION_SERVER_H_ +#define XWALK_EXTENSIONS_XWALK_EXTENSION_SERVER_H_ + +#include +#include +#include + +#include +#include + +#include "extensions/common/xwalk_extension_manager.h" +#include "extensions/common/xwalk_extension_instance.h" + +namespace extensions { + +class XWalkExtensionServer { + public: + static XWalkExtensionServer* GetInstance(); + + void SetupIPC(Ewk_Context* ewk_context); + void Preload(); + Json::Value GetExtensions(); + std::string GetAPIScript(const std::string& extension_name); + std::string CreateInstance(const std::string& extension_name); + + void HandleIPCMessage(Ewk_IPC_Wrt_Message_Data* data); + + void Shutdown(); + void LoadUserExtensions(const std::string app_path); + + private: + XWalkExtensionServer(); + virtual ~XWalkExtensionServer(); + + void HandleGetExtensions(Ewk_IPC_Wrt_Message_Data* data); + void HandleCreateInstance(Ewk_IPC_Wrt_Message_Data* data); + void HandleDestroyInstance(Ewk_IPC_Wrt_Message_Data* data); + void HandlePostMessageToNative(Ewk_IPC_Wrt_Message_Data* data); + void HandleSendSyncMessageToNative(Ewk_IPC_Wrt_Message_Data* data); + void HandleGetAPIScript(Ewk_IPC_Wrt_Message_Data* data); + + typedef std::map InstanceMap; + + Ewk_Context* ewk_context_; + + XWalkExtensionManager manager_; + + InstanceMap instances_; +}; + +} // namespace extensions + +#endif // XWALK_EXTENSIONS_XWALK_EXTENSION_SERVER_H_ diff --git a/tizen/extensions/extensions.gyp b/tizen/extensions/extensions.gyp new file mode 100644 index 0000000..165271b --- /dev/null +++ b/tizen/extensions/extensions.gyp @@ -0,0 +1,60 @@ +{ + 'includes':[ + '../build/common.gypi', + ], + 'targets': [ + { + 'target_name': 'xwalk_extension_shared', + 'type': 'shared_library', + 'sources': [ + 'common/constants.h', + 'common/constants.cc', + 'common/xwalk_extension.h', + 'common/xwalk_extension.cc', + 'common/xwalk_extension_instance.h', + 'common/xwalk_extension_instance.cc', + 'common/xwalk_extension_adapter.h', + 'common/xwalk_extension_adapter.cc', + 'common/xwalk_extension_manager.h', + 'common/xwalk_extension_manager.cc', + 'common/xwalk_extension_server.h', + 'common/xwalk_extension_server.cc', + 'renderer/xwalk_extension_client.h', + 'renderer/xwalk_extension_client.cc', + 'renderer/xwalk_extension_module.h', + 'renderer/xwalk_extension_module.cc', + 'renderer/xwalk_extension_renderer_controller.h', + 'renderer/xwalk_extension_renderer_controller.cc', + 'renderer/xwalk_module_system.h', + 'renderer/xwalk_module_system.cc', + 'renderer/xwalk_v8tools_module.h', + 'renderer/xwalk_v8tools_module.cc', + 'renderer/widget_module.h', + 'renderer/widget_module.cc', + 'renderer/object_tools_module.h', + 'renderer/object_tools_module.cc', + 'renderer/runtime_ipc_client.h', + 'renderer/runtime_ipc_client.cc', + ], + 'cflags': [ + '-fvisibility=default', + ], + 'variables': { + 'packages': [ + 'chromium-efl', + 'elementary', + ], + }, + 'direct_dependent_settings': { +# 'libraries': [ +# '-lxwalk_extension_shared', +# ], + 'variables': { + 'packages': [ + 'jsoncpp', + ], + }, + }, + }, # end of target 'xwalk_extension_static' + ], # end of targets +} diff --git a/tizen/extensions/internal/splash_screen/splash_screen.json b/tizen/extensions/internal/splash_screen/splash_screen.json new file mode 100644 index 0000000..e7a565d --- /dev/null +++ b/tizen/extensions/internal/splash_screen/splash_screen.json @@ -0,0 +1,7 @@ +[ + { + "name":"SplashScreen", + "lib":"libsplash_screen_plugin.so", + "entry_points":["window.screen.show"] + } +] diff --git a/tizen/extensions/internal/splash_screen/splash_screen_api.js b/tizen/extensions/internal/splash_screen/splash_screen_api.js new file mode 100644 index 0000000..551a72d --- /dev/null +++ b/tizen/extensions/internal/splash_screen/splash_screen_api.js @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var sendRuntimeMessage = extension.sendRuntimeMessage || function() { + console.error('Runtime did not implement extension.sendRuntimeMessage!'); +}; +window.screen.show = function() { + sendRuntimeMessage('tizen://hide_splash_screen'); +}; diff --git a/tizen/extensions/internal/splash_screen/splash_screen_extension.cc b/tizen/extensions/internal/splash_screen/splash_screen_extension.cc new file mode 100644 index 0000000..19823e5 --- /dev/null +++ b/tizen/extensions/internal/splash_screen/splash_screen_extension.cc @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "extensions/public/XW_Extension.h" +#include "extensions/public/XW_Extension_EntryPoints.h" +#include "extensions/public/XW_Extension_Permissions.h" +#include "extensions/public/XW_Extension_Runtime.h" +#include "extensions/public/XW_Extension_SyncMessage.h" + +#include "common/application_data.h" +#include "common/locale_manager.h" +#include "common/logger.h" +#include "common/string_utils.h" + +XW_Extension g_xw_extension = 0; +const XW_CoreInterface* g_core = NULL; +const XW_MessagingInterface* g_messaging = NULL; +const XW_Internal_SyncMessagingInterface* g_sync_messaging = NULL; +const XW_Internal_EntryPointsInterface* g_entry_points = NULL; +const XW_Internal_RuntimeInterface* g_runtime = NULL; + +extern const char kSource_splash_screen_api[]; + +extern "C" int32_t XW_Initialize(XW_Extension extension, + XW_GetInterface get_interface) { + g_xw_extension = extension; + g_core = reinterpret_cast( + get_interface(XW_CORE_INTERFACE)); + if (!g_core) { + LOGGER(ERROR) + << "Can't initialize extension: error getting Core interface."; + return XW_ERROR; + } + + g_messaging = reinterpret_cast( + get_interface(XW_MESSAGING_INTERFACE)); + if (!g_messaging) { + LOGGER(ERROR) + << "Can't initialize extension: error getting Messaging interface."; + return XW_ERROR; + } + + g_sync_messaging = + reinterpret_cast( + get_interface(XW_INTERNAL_SYNC_MESSAGING_INTERFACE)); + if (!g_sync_messaging) { + LOGGER(ERROR) + << "Can't initialize extension: " + << "error getting SyncMessaging interface."; + return XW_ERROR; + } + + g_entry_points = reinterpret_cast( + get_interface(XW_INTERNAL_ENTRY_POINTS_INTERFACE)); + if (!g_entry_points) { + LOGGER(ERROR) + << "NOTE: Entry points interface not available in this version " + << "of Crosswalk, ignoring entry point data for extensions.\n"; + return XW_ERROR; + } + + g_runtime = reinterpret_cast( + get_interface(XW_INTERNAL_RUNTIME_INTERFACE)); + if (!g_runtime) { + LOGGER(ERROR) + << "NOTE: runtime interface not available in this version " + << "of Crosswalk, ignoring runtime variables for extensions.\n"; + return XW_ERROR; + } + + g_core->SetExtensionName(g_xw_extension, "SplashScreen"); + const char* entry_points[] = {"window.screen.show", NULL}; + g_entry_points->SetExtraJSEntryPoints(g_xw_extension, entry_points); + g_core->SetJavaScriptAPI(g_xw_extension, kSource_splash_screen_api); + + return XW_OK; +} diff --git a/tizen/extensions/internal/widget/widget.json b/tizen/extensions/internal/widget/widget.json new file mode 100644 index 0000000..ae1dbbd --- /dev/null +++ b/tizen/extensions/internal/widget/widget.json @@ -0,0 +1,7 @@ +[ + { + "name":"Widget", + "lib":"libwidget_plugin.so", + "entry_points":["widget"] + } +] diff --git a/tizen/extensions/internal/widget/widget_api.js b/tizen/extensions/internal/widget/widget_api.js new file mode 100644 index 0000000..6a5b7a6 --- /dev/null +++ b/tizen/extensions/internal/widget/widget_api.js @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var dispatchStorageEvent = function(key, oldValue, newValue) { + var evt = document.createEvent("CustomEvent"); + evt.initCustomEvent("storage", true, true, null); + evt.key = key; + evt.oldValue = oldValue; + evt.newValue = newValue; + evt.storageArea = window.widget.preference; + document.dispatchEvent(evt); + for (var i=0; i < window.frames.length; i++) { + window.frames[i].document.dispatchEvent(evt); + } +}; + +var widget_info_ = requireNative('WidgetModule'); +var preference_ = widget_info_['preference']; +preference_.__onChanged_WRT__ = dispatchStorageEvent; + +function Widget() { + Object.defineProperties(this, { + "author": { + value: widget_info_[ +"author"], + writable: false + }, + "description": { + value: widget_info_["description"], + writable: false + }, + "name": { + value: widget_info_["name"], + writable: false + }, + "shortName": { + value: widget_info_["shortName"], + writable: false + }, + "version": { + value: widget_info_["version"], + writable: false + }, + "id": { + value: widget_info_["id"], + writable: false + }, + "authorEmail": { + value: widget_info_["authorEmail"], + writable: false + }, + "authorHref": { + value: widget_info_["authorHref"], + writable: false + }, + "height": { + get: function() { + return window && window.innerHeight || 0; + }, + configurable: false + }, + "width": { + get: function() { + return window && window.innerWidth || 0; + }, + configurable: false + }, + "preferences": { + value: preference_, + writable: false + } + }); +}; + +Widget.prototype.toString = function() { + return "[object Widget]"; +}; + +window.widget = new Widget(); +exports = Widget; diff --git a/tizen/extensions/internal/widget/widget_extension.cc b/tizen/extensions/internal/widget/widget_extension.cc new file mode 100644 index 0000000..aab1dab --- /dev/null +++ b/tizen/extensions/internal/widget/widget_extension.cc @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "extensions/public/XW_Extension.h" +#include "extensions/public/XW_Extension_EntryPoints.h" +#include "extensions/public/XW_Extension_Permissions.h" +#include "extensions/public/XW_Extension_Runtime.h" +#include "extensions/public/XW_Extension_SyncMessage.h" + +#include "common/application_data.h" +#include "common/locale_manager.h" +#include "common/logger.h" +#include "common/string_utils.h" + +XW_Extension g_xw_extension = 0; +const XW_CoreInterface* g_core = NULL; +const XW_MessagingInterface* g_messaging = NULL; +const XW_Internal_SyncMessagingInterface* g_sync_messaging = NULL; +const XW_Internal_EntryPointsInterface* g_entry_points = NULL; +const XW_Internal_RuntimeInterface* g_runtime = NULL; + +extern const char kSource_widget_api[]; + +extern "C" int32_t XW_Initialize(XW_Extension extension, + XW_GetInterface get_interface) { + g_xw_extension = extension; + g_core = reinterpret_cast( + get_interface(XW_CORE_INTERFACE)); + if (!g_core) { + LOGGER(ERROR) + << "Can't initialize extension: error getting Core interface."; + return XW_ERROR; + } + + g_messaging = reinterpret_cast( + get_interface(XW_MESSAGING_INTERFACE)); + if (!g_messaging) { + LOGGER(ERROR) + << "Can't initialize extension: error getting Messaging interface."; + return XW_ERROR; + } + + g_sync_messaging = + reinterpret_cast( + get_interface(XW_INTERNAL_SYNC_MESSAGING_INTERFACE)); + if (!g_sync_messaging) { + LOGGER(ERROR) + << "Can't initialize extension: " + << "error getting SyncMessaging interface."; + return XW_ERROR; + } + + g_entry_points = reinterpret_cast( + get_interface(XW_INTERNAL_ENTRY_POINTS_INTERFACE)); + if (!g_entry_points) { + LOGGER(ERROR) + << "NOTE: Entry points interface not available in this version " + << "of Crosswalk, ignoring entry point data for extensions.\n"; + return XW_ERROR; + } + + g_runtime = reinterpret_cast( + get_interface(XW_INTERNAL_RUNTIME_INTERFACE)); + if (!g_runtime) { + LOGGER(ERROR) + << "NOTE: runtime interface not available in this version " + << "of Crosswalk, ignoring runtime variables for extensions.\n"; + return XW_ERROR; + } + + g_core->SetExtensionName(g_xw_extension, "Widget"); + const char* entry_points[] = {"widget", NULL}; + g_entry_points->SetExtraJSEntryPoints(g_xw_extension, entry_points); + g_core->SetJavaScriptAPI(g_xw_extension, kSource_widget_api); + + return XW_OK; +} diff --git a/tizen/extensions/public/XW_Extension.h b/tizen/extensions/public/XW_Extension.h new file mode 100644 index 0000000..174915a --- /dev/null +++ b/tizen/extensions/public/XW_Extension.h @@ -0,0 +1,185 @@ +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_ +#define XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_ + +// Crosswalk Extensions are modules of code loaded by Crosswalk runtime that +// allow extending its capabilities. The extension is expected to define a +// XW_Initialize() function as declared below, get the interfaces it need to +// use and register to whatever callbacks it needs, then return XW_OK. +// +// The Extension is represented by the type XW_Extension. Each extension +// loaded may be used multiple times for different pages, so to each execution +// there will be an associated XW_Instance. A reasonable analogy is that the +// XW_Extension represent a "class", and have concrete instances running. +// +// An interface is a struct with a set of functions, provided by Crosswalk, +// that allow the extension code to interact with the web content. Certain +// functions in an interface are used to register callbacks, so that Crosswalk +// can call the extension at specific situations. +// +// Crosswalk won't call an extension's XW_Initialize() multiple times in the +// same process. + +#ifdef __cplusplus +extern "C" { +#endif + +#if __GNUC__ >= 4 +#define XW_EXPORT __attribute__ ((visibility("default"))) +#elif defined(_MSC_VER) +#define XW_EXPORT __declspec(dllexport) +#endif + +#include + + +// XW_Extension is used to identify your extension when calling functions from +// the API. You should always use the XW_Extension received at XW_Initialize(). +// +// XW_Instance is used to identify different web contents using your +// extension. Each time a new web content is created you can be notified +// registering the XW_CreatedInstanceCallback, that receives the new +// XW_Instance. When interacting with an Instance (for example to post a +// message), you should pass the corresponding XW_Instance. +// +// In both types the zero value is never used by Crosswalk, so can be used to +// initialize variables. +typedef int32_t XW_Extension; +typedef int32_t XW_Instance; + +enum { + XW_OK = 0, + XW_ERROR = -1 +}; + +// Returns a struct containing functions to be used by the extension. Those +// structs can be stored statically and used until the extension is unloaded. +// Extensions should use definitions like XW_CORE_INTERFACE, instead of using +// the versioned definition or the literal string. Returns NULL if the +// interface is not supported. +typedef const void* (*XW_GetInterface)(const char* interface_name); + + +typedef int32_t (*XW_Initialize_Func)(XW_Extension extension, + XW_GetInterface get_interface); + +// XW_Initialize is called after the extension code is loaded. The 'extension' +// value should be used in further calls that expect XW_Extension argument. +// +// The 'get_interface' function should be used to get access to functions that +// interact with the web content. It is only valid during the execution of the +// XW_Initialize() function. +// +// This function should return XW_OK when the extension was succesfully +// loaded, otherwise XW_ERROR. +XW_EXPORT int32_t XW_Initialize(XW_Extension extension, + XW_GetInterface get_interface); + + +// +// XW_CORE_INTERFACE: Basic functionality for Crosswalk Extensions. All +// extensions should use this interface to set at least their name. +// + +#define XW_CORE_INTERFACE_1 "XW_CoreInterface_1" +#define XW_CORE_INTERFACE XW_CORE_INTERFACE_1 + +typedef void (*XW_CreatedInstanceCallback)(XW_Instance instance); +typedef void (*XW_DestroyedInstanceCallback)(XW_Instance instance); +typedef void (*XW_ShutdownCallback)(XW_Extension extension); + +struct XW_CoreInterface_1 { + // Set the name of the extension. It is used as the namespace for the + // JavaScript code exposed by the extension. So extension named + // 'my_extension', will expose its JavaScript functionality inside + // the 'my_extension' namespace. + // + // This function should be called only during XW_Initialize(). + void (*SetExtensionName)(XW_Extension extension, const char* name); + + // Set the JavaScript code loaded in the web content when the extension is + // used. This can be used together with the messaging mechanism to implement + // a higher-level API that posts messages to extensions, see + // XW_MESSAGING_INTERFACE below. + // + // The code will be executed inside a JS function context with the following + // objects available: + // + // - exports: this object should be filled with properties and functions + // that will be exposed in the namespace associated with this + // extension. + // + // - extension.postMessage(): post a string message to the extension native + // code. See below for details. + // - extension.setMessageListener(): allow setting a callback that is called + // when the native code sends a message + // to JavaScript. Callback takes a string. + // + // This function should be called only during XW_Initialize(). + void (*SetJavaScriptAPI)(XW_Extension extension, const char* api); + + // Register callbacks that are called when an instance of this extension + // is created or destroyed. Everytime a new web content is loaded, it will + // get a new associated instance. + // + // This function should be called only during XW_Initialize(). + void (*RegisterInstanceCallbacks)(XW_Extension extension, + XW_CreatedInstanceCallback created, + XW_DestroyedInstanceCallback destroyed); + + // Register a callback to be executed when the extension will be unloaded. + // + // This function should be called only during XW_Initialize(). + void (*RegisterShutdownCallback)(XW_Extension extension, + XW_ShutdownCallback shutdown_callback); + + // These two functions are conveniences used to associated arbitrary data + // with a given XW_Instance. They can be used only with instances that were + // created but not yet completely destroyed. GetInstanceData() can be used + // during the destroyed instance callback. If not instance data was set, + // getting it returns NULL. + void (*SetInstanceData)(XW_Instance instance, void* data); + void* (*GetInstanceData)(XW_Instance instance); +}; + +typedef struct XW_CoreInterface_1 XW_CoreInterface; + + +// +// XW_MESSAGING_INTERFACE: Exchange asynchronous messages with JavaScript +// code provided by extension. +// + +#define XW_MESSAGING_INTERFACE_1 "XW_MessagingInterface_1" +#define XW_MESSAGING_INTERFACE XW_MESSAGING_INTERFACE_1 + +typedef void (*XW_HandleMessageCallback)(XW_Instance instance, + const char* message); + +struct XW_MessagingInterface_1 { + // Register a callback to be called when the JavaScript code associated + // with the extension posts a message. Note that the callback will be called + // with the XW_Instance that posted the message as well as the message + // contents. + void (*Register)(XW_Extension extension, + XW_HandleMessageCallback handle_message); + + // Post a message to the web content associated with the instance. To + // receive this message the extension's JavaScript code should set a + // listener using extension.setMessageListener() function. + // + // This function is thread-safe and can be called until the instance is + // destroyed. + void (*PostMessage)(XW_Instance instance, const char* message); +}; + +typedef struct XW_MessagingInterface_1 XW_MessagingInterface; + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_ diff --git a/tizen/extensions/public/XW_Extension_EntryPoints.h b/tizen/extensions/public/XW_Extension_EntryPoints.h new file mode 100644 index 0000000..54532a9 --- /dev/null +++ b/tizen/extensions/public/XW_Extension_EntryPoints.h @@ -0,0 +1,49 @@ +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_ENTRYPOINTS_H_ +#define XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_ENTRYPOINTS_H_ + +// NOTE: This file and interfaces marked as internal are not considered stable +// and can be modified in incompatible ways between Crosswalk versions. + +#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_ +#error "You should include XW_Extension.h before this file" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define XW_INTERNAL_ENTRY_POINTS_INTERFACE_1 \ + "XW_Internal_EntryPointsInterface_1" +#define XW_INTERNAL_ENTRY_POINTS_INTERFACE \ + XW_INTERNAL_ENTRY_POINTS_INTERFACE_1 + +// +// XW_INTERNAL_ENTRY_POINTS_INTERFACE: provides a way for extensions to add +// more information about its implementation. For now, allow extensions to +// specify more objects that the access should cause the extension to be +// loaded. +// + +struct XW_Internal_EntryPointsInterface_1 { + // Register extra entry points for this extension. An "extra" entry points + // are objects outside the implicit namespace for which the extension should + // be loaded when they are touched. + // + // This function should be called only during XW_Initialize(). + void (*SetExtraJSEntryPoints)(XW_Extension extension, + const char** entry_points); +}; + +typedef struct XW_Internal_EntryPointsInterface_1 + XW_Internal_EntryPointsInterface; + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_ENTRYPOINTS_H_ + diff --git a/tizen/extensions/public/XW_Extension_Message_2.h b/tizen/extensions/public/XW_Extension_Message_2.h new file mode 100644 index 0000000..f417f88 --- /dev/null +++ b/tizen/extensions/public/XW_Extension_Message_2.h @@ -0,0 +1,64 @@ +// Copyright (c) 2015 Intel Corporation. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_MESSAGE_2_H_ +#define XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_MESSAGE_2_H_ + +#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_ +#error "You should include XW_Extension.h before this file" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define XW_MESSAGING_INTERFACE_2 "XW_MessagingInterface_2" + +typedef void (*XW_HandleBinaryMessageCallback)(XW_Instance instance, + const char* message, + const size_t size); + +struct XW_MessagingInterface_2 { + // Register a callback to be called when the JavaScript code associated + // with the extension posts a message. Note that the callback will be called + // with the XW_Instance that posted the message as well as the message + // contents. + void (*Register)(XW_Extension extension, + XW_HandleMessageCallback handle_message); + + // Post a message to the web content associated with the instance. To + // receive this message the extension's JavaScript code should set a + // listener using extension.setMessageListener() function. + // + // This function is thread-safe and can be called until the instance is + // destroyed. + void (*PostMessage)(XW_Instance instance, const char* message); + + // Register a callback to be called when the JavaScript code associated + // with the extension posts a binary message (ArrayBuffer object). + // Note that the callback will be called with the XW_Instance that posted + // the message as well as the message contents. + void (*RegisterBinaryMesssageCallback)( + XW_Extension extension, + XW_HandleBinaryMessageCallback handle_message); + + // Post a binary message to the web content associated with the instance. To + // receive this message the extension's JavaScript code should set a + // listener using extension.setMessageListener() function. + // The JavaScript message listener function would receive the binary message + // in an ArrayBuffer object. + // + // This function is thread-safe and can be called until the instance is + // destroyed. + void (*PostBinaryMessage)(XW_Instance instance, + const char* message, size_t size); +}; + +typedef struct XW_MessagingInterface_2 XW_MessagingInterface2; + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_MESSAGE_2_H_ diff --git a/tizen/extensions/public/XW_Extension_Permissions.h b/tizen/extensions/public/XW_Extension_Permissions.h new file mode 100644 index 0000000..d25484e --- /dev/null +++ b/tizen/extensions/public/XW_Extension_Permissions.h @@ -0,0 +1,41 @@ +// Copyright (c) 2014 Intel Corporation. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_PERMISSIONS_H_ +#define XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_PERMISSIONS_H_ + +// NOTE: This file and interfaces marked as internal are not considered stable +// and can be modified in incompatible ways between Crosswalk versions. + +#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_ +#error "You should include XW_Extension.h before this file" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define XW_INTERNAL_PERMISSIONS_INTERFACE_1 \ + "XW_Internal_PermissionsInterface_1" +#define XW_INTERNAL_PERMISSIONS_INTERFACE \ + XW_INTERNAL_PERMISSIONS_INTERFACE_1 + +// +// XW_INTERNAL_PERMISSIONS_INTERFACE: provides a way for extensions +// check if they have the proper permissions for certain APIs. +// + +struct XW_Internal_PermissionsInterface_1 { + int (*CheckAPIAccessControl)(XW_Extension extension, const char* api_name); + int (*RegisterPermissions)(XW_Extension extension, const char* perm_table); +}; + +typedef struct XW_Internal_PermissionsInterface_1 + XW_Internal_PermissionsInterface; + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_PERMISSIONS_H_ diff --git a/tizen/extensions/public/XW_Extension_Runtime.h b/tizen/extensions/public/XW_Extension_Runtime.h new file mode 100644 index 0000000..11ad307 --- /dev/null +++ b/tizen/extensions/public/XW_Extension_Runtime.h @@ -0,0 +1,44 @@ +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_RUNTIME_H_ +#define XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_RUNTIME_H_ + +// NOTE: This file and interfaces marked as internal are not considered stable +// and can be modified in incompatible ways between Crosswalk versions. + +#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_ +#error "You should include XW_Extension.h before this file" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define XW_INTERNAL_RUNTIME_INTERFACE_1 \ + "XW_Internal_RuntimeInterface_1" +#define XW_INTERNAL_RUNTIME_INTERFACE \ + XW_INTERNAL_RUNTIME_INTERFACE_1 + +// +// XW_INTERNAL_RUNTIME_INTERFACE: allow extensions to gather information +// from the runtime. +// + +struct XW_Internal_RuntimeInterface_1 { + void (*GetRuntimeVariableString)(XW_Extension extension, + const char* key, + char* value, + unsigned int value_len); +}; + +typedef struct XW_Internal_RuntimeInterface_1 + XW_Internal_RuntimeInterface; + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_RUNTIME_H_ + diff --git a/tizen/extensions/public/XW_Extension_SyncMessage.h b/tizen/extensions/public/XW_Extension_SyncMessage.h new file mode 100644 index 0000000..4eddbf9 --- /dev/null +++ b/tizen/extensions/public/XW_Extension_SyncMessage.h @@ -0,0 +1,48 @@ +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_SYNCMESSAGE_H_ +#define XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_SYNCMESSAGE_H_ + +// NOTE: This file and interfaces marked as internal are not considered stable +// and can be modified in incompatible ways between Crosswalk versions. + +#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_ +#error "You should include XW_Extension.h before this file" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// +// XW_INTERNAL_SYNC_MESSAGING_INTERFACE: allow JavaScript code to send a +// synchronous message to extension code and block until response is +// available. The response is made available by calling the SetSyncReply +// function, that can be done from outside the context of the SyncMessage +// handler. +// + +#define XW_INTERNAL_SYNC_MESSAGING_INTERFACE_1 \ + "XW_InternalSyncMessagingInterface_1" +#define XW_INTERNAL_SYNC_MESSAGING_INTERFACE \ + XW_INTERNAL_SYNC_MESSAGING_INTERFACE_1 + +typedef void (*XW_HandleSyncMessageCallback)(XW_Instance instance, + const char* message); + +struct XW_Internal_SyncMessagingInterface_1 { + void (*Register)(XW_Extension extension, + XW_HandleSyncMessageCallback handle_sync_message); + void (*SetSyncReply)(XW_Instance instance, const char* reply); +}; + +typedef struct XW_Internal_SyncMessagingInterface_1 + XW_Internal_SyncMessagingInterface; + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_SYNCMESSAGE_H_ diff --git a/tizen/extensions/renderer/object_tools_module.cc b/tizen/extensions/renderer/object_tools_module.cc new file mode 100644 index 0000000..67cb503 --- /dev/null +++ b/tizen/extensions/renderer/object_tools_module.cc @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "extensions/renderer/object_tools_module.h" + +#include + +#include + +#include "common/logger.h" + +namespace extensions { + +namespace { +const char *kCreateObjectCode = + "(function(object) {" + " var newobject = Object.create(object);" + " Object.getOwnPropertyNames(object).forEach(function(name) {" + " if (object[name] instanceof Function) {" + " newobject[name] = object[name];" + " }" + " });" + " newobject['origin_prototype'] = {};" + " Object.getOwnPropertyNames(object.prototype).forEach(function(name) {" + " if (object.prototype[name] instanceof Function) {" + " newobject['origin_prototype'][name] = object.prototype[name];" + " }" + " });" + " return function() {" + " return newobject;" + " };" + "}(Object));"; + +v8::Handle RunString(const std::string& code) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope handle_scope(isolate); + v8::Handle v8_code( + v8::String::NewFromUtf8(isolate, code.c_str())); + + v8::TryCatch try_catch; + try_catch.SetVerbose(true); + + v8::Handle script(v8::Script::Compile(v8_code)); + if (try_catch.HasCaught()) { + v8::String::Utf8Value exception(try_catch.Exception()); + LOGGER(ERROR) << "Error occurred(script compile):" << *exception; + return handle_scope.Escape( + v8::Local(v8::Undefined(isolate))); + } + + v8::Local result = script->Run(); + if (try_catch.HasCaught()) { + v8::String::Utf8Value exception(try_catch.Exception()); + LOGGER(ERROR) << "Error occurred(script run):" << *exception; + return handle_scope.Escape( + v8::Local(v8::Undefined(isolate))); + } + return handle_scope.Escape(result); +} +} // namespace + + +ObjectToolsModule::ObjectToolsModule() { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope handle_scope(isolate); + + v8::Handle result = RunString(kCreateObjectCode); + if (!result->IsFunction()) { + LOGGER(ERROR) << "Couldn't load Object Create function"; + return; + } + v8::Handle create_function = + v8::Handle::Cast(result); + + create_function_.Reset(isolate, create_function); +} + +ObjectToolsModule::~ObjectToolsModule() { + create_function_.Reset(); +} + +v8::Handle ObjectToolsModule::NewInstance() { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + if (create_function_.IsEmpty()) { + return v8::Object::New(isolate); + } + v8::Handle function = + v8::Local::New(isolate, create_function_); + + v8::Handle context = v8::Context::New(isolate); + v8::TryCatch try_catch; + v8::Handle ret = function->Call(context->Global(), 0, NULL); + if (try_catch.HasCaught()) { + LOGGER(ERROR) << "Exception when running create function: "; + return v8::Object::New(isolate); + } + return v8::Handle::Cast(ret); +} + +} // namespace extensions + diff --git a/tizen/extensions/renderer/object_tools_module.h b/tizen/extensions/renderer/object_tools_module.h new file mode 100644 index 0000000..eb4609b --- /dev/null +++ b/tizen/extensions/renderer/object_tools_module.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef XWALK_EXTENSIONS_RENDERER_OBJECT_TOOLS_MODULE_H_ +#define XWALK_EXTENSIONS_RENDERER_OBJECT_TOOLS_MODULE_H_ + +#include "extensions/renderer/xwalk_module_system.h" + +namespace extensions { + +class ObjectToolsModule : public XWalkNativeModule { + public: + ObjectToolsModule(); + ~ObjectToolsModule() override; + + private: + v8::Handle NewInstance() override; + v8::Persistent create_function_; +}; + +} // namespace extensions + +#endif // XWALK_EXTENSIONS_RENDERER_OBJECT_TOOLS_MODULE_H_ diff --git a/tizen/extensions/renderer/runtime_ipc_client.cc b/tizen/extensions/renderer/runtime_ipc_client.cc new file mode 100644 index 0000000..6b96828 --- /dev/null +++ b/tizen/extensions/renderer/runtime_ipc_client.cc @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "extensions/renderer/runtime_ipc_client.h" +#include "extensions/renderer/xwalk_extension_renderer_controller.h" + +#include "common/logger.h" +#include "common/profiler.h" +#include "common/string_utils.h" + +namespace extensions { + +namespace { + +const int kRoutingIdEmbedderDataIndex = 12; + +} // namespace + +RuntimeIPCClient::JSCallback::JSCallback(v8::Isolate* isolate, + v8::Handle callback) { + callback_.Reset(isolate, callback); +} + +RuntimeIPCClient::JSCallback::~JSCallback() { + callback_.Reset(); +} + +void RuntimeIPCClient::JSCallback::Call(v8::Isolate* isolate, + v8::Handle args[]) { + if (!callback_.IsEmpty()) { + v8::HandleScope handle_scope(isolate); + v8::TryCatch try_catch(isolate); + v8::Handle func = + v8::Local::New(isolate, callback_); + func->Call(func, 1, args); + if (try_catch.HasCaught()) { + LOGGER(ERROR) << "Exception when running Javascript callback"; + v8::String::Utf8Value exception_str(try_catch.Exception()); + LOGGER(ERROR) << (*exception_str); + } + } +} + +// static +RuntimeIPCClient* RuntimeIPCClient::GetInstance() { + static RuntimeIPCClient self; + return &self; +} + +RuntimeIPCClient::RuntimeIPCClient() { +} + +int RuntimeIPCClient::GetRoutingId(v8::Handle context) { + v8::Handle value = + context->GetEmbedderData(kRoutingIdEmbedderDataIndex); + int routing_id = 0; + if (value->IsNumber()) { + routing_id = value->IntegerValue(); + } else { + LOGGER(WARN) << "Failed to get routing index from context."; + } + + return routing_id; +} + +void RuntimeIPCClient::SetRoutingId(v8::Handle context, + int routing_id) { + context->SetEmbedderData(kRoutingIdEmbedderDataIndex, + v8::Integer::New(context->GetIsolate(), routing_id)); +} + +void RuntimeIPCClient::SendMessage(v8::Handle context, + const std::string& type, + const std::string& value) { + SendMessage(context, type, "", "", value); +} + +void RuntimeIPCClient::SendMessage(v8::Handle context, + const std::string& type, + const std::string& id, + const std::string& value) { + SendMessage(context, type, id, "", value); +} + +void RuntimeIPCClient::SendMessage(v8::Handle context, + const std::string& type, + const std::string& id, + const std::string& ref_id, + const std::string& value) { + if (!strcmp(type.c_str(), "tizen://exit")) { + extensions::XWalkExtensionRendererController& controller = + extensions::XWalkExtensionRendererController::GetInstance(); + controller.exit_requested = true; + } + + int routing_id = GetRoutingId(context); + if (routing_id < 1) { + LOGGER(ERROR) << "Invalid routing handle for IPC."; + return; + } + + Ewk_IPC_Wrt_Message_Data* msg = ewk_ipc_wrt_message_data_new(); + ewk_ipc_wrt_message_data_type_set(msg, type.c_str()); + ewk_ipc_wrt_message_data_id_set(msg, id.c_str()); + ewk_ipc_wrt_message_data_reference_id_set(msg, ref_id.c_str()); + ewk_ipc_wrt_message_data_value_set(msg, value.c_str()); + + if (!ewk_ipc_plugins_message_send(routing_id, msg)) { + LOGGER(ERROR) << "Failed to send message to runtime using ewk_ipc."; + } + + ewk_ipc_wrt_message_data_del(msg); +} + +std::string RuntimeIPCClient::SendSyncMessage(v8::Handle context, + const std::string& type, + const std::string& value) { + return SendSyncMessage(context, type, "", "", value); +} + +std::string RuntimeIPCClient::SendSyncMessage(v8::Handle context, + const std::string& type, + const std::string& id, + const std::string& value) { + return SendSyncMessage(context, type, id, "", value); +} + +std::string RuntimeIPCClient::SendSyncMessage(v8::Handle context, + const std::string& type, + const std::string& id, + const std::string& ref_id, + const std::string& value) { + int routing_id = GetRoutingId(context); + if (routing_id < 1) { + LOGGER(ERROR) << "Invalid routing handle for IPC."; + return std::string(); + } + + Ewk_IPC_Wrt_Message_Data* msg = ewk_ipc_wrt_message_data_new(); + ewk_ipc_wrt_message_data_type_set(msg, type.c_str()); + ewk_ipc_wrt_message_data_id_set(msg, id.c_str()); + ewk_ipc_wrt_message_data_reference_id_set(msg, ref_id.c_str()); + ewk_ipc_wrt_message_data_value_set(msg, value.c_str()); + + if (!ewk_ipc_plugins_sync_message_send(routing_id, msg)) { + LOGGER(ERROR) << "Failed to send message to runtime using ewk_ipc."; + ewk_ipc_wrt_message_data_del(msg); + return std::string(); + } + + Eina_Stringshare* msg_value = ewk_ipc_wrt_message_data_value_get(msg); + std::string result(msg_value); + eina_stringshare_del(msg_value); + + ewk_ipc_wrt_message_data_del(msg); + + return result; +} + +void RuntimeIPCClient::SendAsyncMessage(v8::Handle context, + const std::string& type, + const std::string& value, + ReplyCallback callback) { + int routing_id = GetRoutingId(context); + if (routing_id < 1) { + LOGGER(ERROR) << "Invalid routing handle for IPC."; + return; + } + + std::string msg_id = common::utils::GenerateUUID(); + + Ewk_IPC_Wrt_Message_Data* msg = ewk_ipc_wrt_message_data_new(); + ewk_ipc_wrt_message_data_id_set(msg, msg_id.c_str()); + ewk_ipc_wrt_message_data_type_set(msg, type.c_str()); + ewk_ipc_wrt_message_data_value_set(msg, value.c_str()); + + if (!ewk_ipc_plugins_message_send(routing_id, msg)) { + LOGGER(ERROR) << "Failed to send message to runtime using ewk_ipc."; + ewk_ipc_wrt_message_data_del(msg); + return; + } + + callbacks_[msg_id] = callback; + + ewk_ipc_wrt_message_data_del(msg); +} + +void RuntimeIPCClient::HandleMessageFromRuntime( + const Ewk_IPC_Wrt_Message_Data* msg) { + if (msg == NULL) { + LOGGER(ERROR) << "received message is NULL"; + return; + } + + Eina_Stringshare* msg_refid = ewk_ipc_wrt_message_data_reference_id_get(msg); + + if (msg_refid == NULL || !strcmp(msg_refid, "")) { + if (msg_refid) eina_stringshare_del(msg_refid); + LOGGER(ERROR) << "No reference id of received message."; + return; + } + + auto it = callbacks_.find(msg_refid); + if (it == callbacks_.end()) { + eina_stringshare_del(msg_refid); + LOGGER(ERROR) << "No registered callback with reference id : " << msg_refid; + return; + } + + Eina_Stringshare* msg_type = ewk_ipc_wrt_message_data_type_get(msg); + Eina_Stringshare* msg_value = ewk_ipc_wrt_message_data_value_get(msg); + + ReplyCallback func = it->second; + if (func) { + func(msg_type, msg_value); + } + + callbacks_.erase(it); + + eina_stringshare_del(msg_refid); + eina_stringshare_del(msg_type); + eina_stringshare_del(msg_value); +} + +} // namespace extensions diff --git a/tizen/extensions/renderer/runtime_ipc_client.h b/tizen/extensions/renderer/runtime_ipc_client.h new file mode 100644 index 0000000..7f94fb3 --- /dev/null +++ b/tizen/extensions/renderer/runtime_ipc_client.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef XWALK_EXTENSIONS_RENDERER_RUNTIME_IPC_CLIENT_H_ +#define XWALK_EXTENSIONS_RENDERER_RUNTIME_IPC_CLIENT_H_ + +#include +#include +#include + +#include +#include +#include + +namespace extensions { + +class RuntimeIPCClient { + public: + class JSCallback { + public: + explicit JSCallback(v8::Isolate* isolate, + v8::Handle callback); + ~JSCallback(); + + void Call(v8::Isolate* isolate, v8::Handle args[]); + private: + v8::Persistent callback_; + }; + + typedef std::function ReplyCallback; + + static RuntimeIPCClient* GetInstance(); + + // Send message to BrowserProcess without reply + void SendMessage(v8::Handle context, + const std::string& type, + const std::string& value); + + void SendMessage(v8::Handle context, + const std::string& type, + const std::string& id, + const std::string& value); + + void SendMessage(v8::Handle context, + const std::string& type, + const std::string& id, + const std::string& ref_id, + const std::string& value); + + // Send message to BrowserProcess synchronous with reply + std::string SendSyncMessage(v8::Handle context, + const std::string& type, + const std::string& value); + + std::string SendSyncMessage(v8::Handle context, + const std::string& type, + const std::string& id, + const std::string& value); + + std::string SendSyncMessage(v8::Handle context, + const std::string& type, + const std::string& id, + const std::string& ref_id, + const std::string& value); + + // Send message to BrowserProcess asynchronous, + // reply message will be passed to callback function. + void SendAsyncMessage(v8::Handle context, + const std::string& type, const std::string& value, + ReplyCallback callback); + + void HandleMessageFromRuntime(const Ewk_IPC_Wrt_Message_Data* msg); + + int GetRoutingId(v8::Handle context); + + void SetRoutingId(v8::Handle context, int routing_id); + + private: + RuntimeIPCClient(); + + std::map callbacks_; +}; + +} // namespace extensions + +#endif // XWALK_EXTENSIONS_RENDERER_RUNTIME_IPC_CLIENT_H_ diff --git a/tizen/extensions/renderer/widget_module.cc b/tizen/extensions/renderer/widget_module.cc new file mode 100644 index 0000000..2237501 --- /dev/null +++ b/tizen/extensions/renderer/widget_module.cc @@ -0,0 +1,581 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "extensions/renderer/widget_module.h" + +#include + +#include +#include + +#include "common/app_db.h" +#include "common/logger.h" + +namespace extensions { + +namespace { +const char* kOnchangedEventHandler = "__onChanged_WRT__"; +const char* kKeyKey = "key"; +const char* kGetItemKey = "getItem"; +const char* kSetItemKey = "setItem"; +const char* kRemoveItemKey = "removeItem"; +const char* kLengthKey = "length"; +const char* kClearKey = "clear"; +const int kKeyLengthLimit = 80; +const int kValueLengthLimit = 8192; + +std::vector kExcludeList = { + kOnchangedEventHandler, + kKeyKey, + kGetItemKey, + kSetItemKey, + kRemoveItemKey, + kLengthKey, + kClearKey}; + +void DispatchEvent(const v8::Local& This, + v8::Local key, + v8::Local oldvalue, + v8::Local newvalue) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + + v8::Handle function = + This->Get(v8::String::NewFromUtf8(isolate, kOnchangedEventHandler)); + + if (function.IsEmpty() || !function->IsFunction()) { + LOGGER(DEBUG) << "onChanged function not set"; + return; + } + + v8::Handle context = v8::Context::New(isolate); + + const int argc = 3; + v8::Handle argv[argc] = { + key, + oldvalue, + newvalue + }; + + v8::TryCatch try_catch; + v8::Handle::Cast(function)->Call( + context->Global(), argc, argv); + if (try_catch.HasCaught()) + LOGGER(DEBUG) << "Exception when running onChanged callback"; +} + +v8::Handle MakeException(int code, + std::string name, + std::string message) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope handle_scope(isolate); + v8::Local error = v8::Object::New(isolate); + + error->Set( + v8::String::NewFromUtf8(isolate, "code"), + v8::Number::New(isolate, code)); + error->Set( + v8::String::NewFromUtf8(isolate, "name"), + v8::String::NewFromUtf8(isolate, name.c_str())); + error->Set( + v8::String::NewFromUtf8(isolate, "message"), + v8::String::NewFromUtf8(isolate, message.c_str())); + + return handle_scope.Escape(error); +} + +void KeyFunction(const v8::FunctionCallbackInfo& info) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + int idx = info[0]->ToInt32()->Value(); + auto widget = WidgetPreferenceDB::GetInstance(); + std::string keyname; + if (widget->Key(idx, &keyname)) { + info.GetReturnValue().Set( + v8::String::NewFromUtf8(isolate, keyname.c_str())); + } else { + info.GetReturnValue().SetNull(); + } +} + +void GetItemFunction(const v8::FunctionCallbackInfo& info) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + std::string key = *v8::String::Utf8Value(info[0]->ToString()); + auto widget = WidgetPreferenceDB::GetInstance(); + std::string valuestr; + if (widget->GetItem(key, &valuestr)) { + info.GetReturnValue().Set( + v8::String::NewFromUtf8(isolate, valuestr.c_str())); + } else { + info.GetReturnValue().SetNull(); + } +} + +void SetItemFunction(const v8::FunctionCallbackInfo& info) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + std::string key = *v8::String::Utf8Value(info[0]->ToString()); + std::string value = *v8::String::Utf8Value(info[1]->ToString()); + auto widget = WidgetPreferenceDB::GetInstance(); + + v8::Local oldvalue = v8::Null(isolate); + std::string oldvaluestr; + if (widget->GetItem(key, &oldvaluestr)) { + oldvalue = v8::String::NewFromUtf8(isolate, oldvaluestr.c_str()); + } + + if (widget->SetItem(key, value)) { + DispatchEvent(info.This(), + info[0], + oldvalue, + info[1]); + } else { + info.GetReturnValue().Set(isolate->ThrowException(MakeException( + 7, "NoModificationAllowedError", "Read only data"))); + } +} + +void RemoveItemFunction(const v8::FunctionCallbackInfo& info) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + std::string key = *v8::String::Utf8Value(info[0]->ToString()); + auto widget = WidgetPreferenceDB::GetInstance(); + + if (!widget->HasItem(key)) { + return; + } + + v8::Local oldvalue = v8::Null(isolate); + std::string oldvaluestr; + if (widget->GetItem(key, &oldvaluestr)) { + oldvalue = v8::String::NewFromUtf8(isolate, oldvaluestr.c_str()); + } + + if (widget->RemoveItem(key)) { + DispatchEvent(info.This(), + info[0], + oldvalue, + v8::Null(isolate)); + } else { + info.GetReturnValue().Set(isolate->ThrowException(MakeException( + 7, "NoModificationAllowedError", "Read only data"))); + } +} + +void ClearFunction(const v8::FunctionCallbackInfo& info) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + auto widget = WidgetPreferenceDB::GetInstance(); + widget->Clear(); + DispatchEvent(info.This(), + v8::Null(isolate), + v8::Null(isolate), + v8::Null(isolate)); +} + +} // namespace + +WidgetModule::WidgetModule() { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope handle_scope(isolate); + v8::Handle + preference_object_template = v8::ObjectTemplate::New(); + + auto getter = []( + v8::Local property, + const v8::PropertyCallbackInfo& info) { + v8::Isolate* isolate = info.GetIsolate(); + auto widget = WidgetPreferenceDB::GetInstance(); + std::string key = *v8::String::Utf8Value(property); + + if (key == kLengthKey) { + info.GetReturnValue().Set(widget->Length()); + return; + } + + if (std::find(kExcludeList.begin(), kExcludeList.end(), key) + != kExcludeList.end()) { + return; + } + + if (!widget->HasItem(key)) { + return; + } + + std::string value; + if (widget->GetItem(key, &value)) { + info.GetReturnValue().Set( + v8::String::NewFromUtf8(isolate, value.c_str())); + } else { + info.GetReturnValue().SetNull(); + } + }; + + auto setter = []( + v8::Local property, + v8::Local value, + const v8::PropertyCallbackInfo& info) { + v8::Isolate* isolate = info.GetIsolate(); + auto widget = WidgetPreferenceDB::GetInstance(); + std::string key = *v8::String::Utf8Value(property); + std::string nvalue = *v8::String::Utf8Value(value->ToString()); + + if (std::find(kExcludeList.begin(), kExcludeList.end(), key) + != kExcludeList.end()) { + return; + } + + v8::Local oldvalue = v8::Null(isolate); + std::string oldvaluestr; + if (widget->GetItem(key, &oldvaluestr)) { + oldvalue = v8::String::NewFromUtf8(isolate, oldvaluestr.c_str()); + } + if (widget->SetItem(key, nvalue)) { + info.GetReturnValue().Set(value); + DispatchEvent(info.This(), + property, + oldvalue, + value); + } + }; + + auto deleter = []( + v8::Local property, + const v8::PropertyCallbackInfo& info) { + v8::Isolate* isolate = info.GetIsolate(); + auto widget = WidgetPreferenceDB::GetInstance(); + std::string key = *v8::String::Utf8Value(property); + if (!widget->HasItem(key)) { + info.GetReturnValue().Set(false); + return; + } + + v8::Local oldvalue = v8::Null(isolate); + std::string oldvaluestr; + if (widget->GetItem(key, &oldvaluestr)) { + oldvalue = v8::String::NewFromUtf8(isolate, oldvaluestr.c_str()); + } + + if (widget->RemoveItem(key)) { + info.GetReturnValue().Set(true); + DispatchEvent(info.This(), + property, + oldvalue, + v8::Null(isolate)); + } else { + info.GetReturnValue().Set(false); + } + }; + + preference_object_template->SetNamedPropertyHandler( + getter, + setter, + NULL, + deleter, + NULL); + + preference_object_template->Set( + v8::String::NewFromUtf8(isolate, kKeyKey), + v8::FunctionTemplate::New(isolate, KeyFunction)); + + preference_object_template->Set( + v8::String::NewFromUtf8(isolate, kGetItemKey), + v8::FunctionTemplate::New(isolate, GetItemFunction)); + + preference_object_template->Set( + v8::String::NewFromUtf8(isolate, kSetItemKey), + v8::FunctionTemplate::New(isolate, SetItemFunction)); + + preference_object_template->Set( + v8::String::NewFromUtf8(isolate, kRemoveItemKey), + v8::FunctionTemplate::New(isolate, RemoveItemFunction)); + + preference_object_template->Set( + v8::String::NewFromUtf8(isolate, kClearKey), + v8::FunctionTemplate::New(isolate, ClearFunction)); + + + preference_object_template_.Reset(isolate, preference_object_template); +} + +WidgetModule::~WidgetModule() { +} + +v8::Handle WidgetModule::NewInstance() { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope handle_scope(isolate); + + v8::Local widget = v8::Object::New(isolate); + v8::Handle object_template = + v8::Local::New(isolate, preference_object_template_); + + auto widgetdb = WidgetPreferenceDB::GetInstance(); + widgetdb->InitializeDB(); + + widget->Set( + v8::String::NewFromUtf8(isolate, "preference"), + object_template->NewInstance()); + + widget->Set( + v8::String::NewFromUtf8(isolate, "author"), + v8::String::NewFromUtf8(isolate, widgetdb->author().c_str())); + widget->Set( + v8::String::NewFromUtf8(isolate, "description"), + v8::String::NewFromUtf8(isolate, widgetdb->description().c_str())); + widget->Set( + v8::String::NewFromUtf8(isolate, "name"), + v8::String::NewFromUtf8(isolate, widgetdb->name().c_str())); + widget->Set( + v8::String::NewFromUtf8(isolate, "shortName"), + v8::String::NewFromUtf8(isolate, widgetdb->shortName().c_str())); + widget->Set( + v8::String::NewFromUtf8(isolate, "version"), + v8::String::NewFromUtf8(isolate, widgetdb->version().c_str())); + widget->Set( + v8::String::NewFromUtf8(isolate, "id"), + v8::String::NewFromUtf8(isolate, widgetdb->id().c_str())); + widget->Set( + v8::String::NewFromUtf8(isolate, "authorEmail"), + v8::String::NewFromUtf8(isolate, widgetdb->authorEmail().c_str())); + widget->Set( + v8::String::NewFromUtf8(isolate, "authorHref"), + v8::String::NewFromUtf8(isolate, widgetdb->authorHref().c_str())); + + return handle_scope.Escape(widget); +} + + +namespace { + const char* kDbInitedCheckKey = "__WRT_DB_INITED__"; + const char* kDBPublicSection = "public"; + const char* kDBPrivateSection = "private"; + const char* kReadOnlyPrefix = "_READONLY_KEY_"; +} // namespace + + +WidgetPreferenceDB* WidgetPreferenceDB::GetInstance() { + static WidgetPreferenceDB instance; + return &instance; +} + +WidgetPreferenceDB::WidgetPreferenceDB() + : appdata_(nullptr), + locale_manager_(nullptr) { +} +WidgetPreferenceDB::~WidgetPreferenceDB() { +} + +void WidgetPreferenceDB::Initialize( + const common::ApplicationData* appdata, + common::LocaleManager* locale_manager) { + appdata_ = appdata; + locale_manager_ = locale_manager; +} + +void WidgetPreferenceDB::InitializeDB() { + common::AppDB* db = common::AppDB::GetInstance(); + if (db->HasKey(kDBPrivateSection, kDbInitedCheckKey)) { + return; + } + if (appdata_->widget_info() == NULL) { + return; + } + + auto& preferences = appdata_->widget_info()->preferences(); + + for (const auto& pref : preferences) { + if (pref->Name().empty()) + continue; + + // check size limit + std::string key = pref->Name(); + std::string value = pref->Value(); + if (key.length() > kKeyLengthLimit) { + key.resize(kKeyLengthLimit); + } + + if (db->HasKey(kDBPublicSection, key)) + continue; + + // check size limit + if (value.length() > kValueLengthLimit) { + value.resize(kValueLengthLimit); + } + + db->Set(kDBPublicSection, + key, + value); + if (pref->ReadOnly()) { + db->Set(kDBPrivateSection, + kReadOnlyPrefix + key, "true"); + } + } + db->Set(kDBPrivateSection, kDbInitedCheckKey, "true"); +} + +int WidgetPreferenceDB::Length() { + common::AppDB* db = common::AppDB::GetInstance(); + std::list list; + db->GetKeys(kDBPublicSection, &list); + return list.size(); +} + +bool WidgetPreferenceDB::Key(int idx, std::string* key) { + common::AppDB* db = common::AppDB::GetInstance(); + std::list list; + db->GetKeys(kDBPublicSection, &list); + + auto it = list.begin(); + for ( ; it != list.end() && idx >= 0; ++it) { + if (idx == 0) { + *key = *it; + return true; + } + idx--; + } + return false; +} + +bool WidgetPreferenceDB::GetItem(const std::string& key, std::string* value) { + common::AppDB* db = common::AppDB::GetInstance(); + if (!db->HasKey(kDBPublicSection, key)) + return false; + *value = db->Get(kDBPublicSection, key); + return true; +} + +bool WidgetPreferenceDB::SetItem(const std::string& key, + const std::string& value) { + common::AppDB* db = common::AppDB::GetInstance(); + if (db->HasKey(kDBPrivateSection, kReadOnlyPrefix + key)) + return false; + db->Set(kDBPublicSection, key, value); + return true; +} + +bool WidgetPreferenceDB::RemoveItem(const std::string& key) { + common::AppDB* db = common::AppDB::GetInstance(); + if (!db->HasKey(kDBPublicSection, key)) + return false; + if (db->HasKey(kDBPrivateSection, kReadOnlyPrefix + key)) + return false; + db->Remove(kDBPublicSection, key); + return true; +} + +bool WidgetPreferenceDB::HasItem(const std::string& key) { + common::AppDB* db = common::AppDB::GetInstance(); + return db->HasKey(kDBPublicSection, key); +} + +void WidgetPreferenceDB::Clear() { + common::AppDB* db = common::AppDB::GetInstance(); + std::list list; + db->GetKeys(kDBPublicSection, &list); + auto it = list.begin(); + for ( ; it != list.end(); ++it) { + if (db->HasKey(kDBPrivateSection, kReadOnlyPrefix + *it)) + continue; + db->Remove(kDBPublicSection, *it); + } +} + +void WidgetPreferenceDB::GetKeys(std::list* keys) { + common::AppDB* db = common::AppDB::GetInstance(); + db->GetKeys(kDBPublicSection, keys); +} + +std::string WidgetPreferenceDB::author() { + if (appdata_ == NULL || + appdata_->widget_info() == NULL) + return std::string(); + auto widget_info = appdata_->widget_info(); + return widget_info->author(); +} + +std::string WidgetPreferenceDB::description() { + if (appdata_ == NULL || + appdata_->widget_info() == NULL || + locale_manager_ == NULL) + return std::string(); + auto widget_info = appdata_->widget_info(); + return locale_manager_->GetLocalizedString(widget_info->description_set()); +} + +std::string WidgetPreferenceDB::name() { + if (appdata_ == NULL || + appdata_->widget_info() == NULL || + locale_manager_ == NULL) + return std::string(); + + auto widget_info = appdata_->widget_info(); + return locale_manager_->GetLocalizedString(widget_info->name_set()); +} + +std::string WidgetPreferenceDB::shortName() { + if (appdata_ == NULL || + appdata_->widget_info() == NULL || + locale_manager_ == NULL) + return std::string(); + + auto widget_info = appdata_->widget_info(); + return locale_manager_->GetLocalizedString(widget_info->short_name_set()); +} + +std::string WidgetPreferenceDB::version() { + if (appdata_ == NULL || + appdata_->widget_info() == NULL) + return std::string(); + auto widget_info = appdata_->widget_info(); + return widget_info->version(); +} + +std::string WidgetPreferenceDB::id() { + if (appdata_ == NULL || + appdata_->widget_info() == NULL) + return std::string(); + auto widget_info = appdata_->widget_info(); + return widget_info->id(); +} + +std::string WidgetPreferenceDB::authorEmail() { + if (appdata_ == NULL || + appdata_->widget_info() == NULL) + return std::string(); + auto widget_info = appdata_->widget_info(); + return widget_info->author_email(); +} + +std::string WidgetPreferenceDB::authorHref() { + if (appdata_ == NULL || + appdata_->widget_info() == NULL) + return std::string(); + auto widget_info = appdata_->widget_info(); + return widget_info->author_href(); +} + +unsigned int WidgetPreferenceDB::height() { + if (appdata_ == NULL || + appdata_->widget_info() == NULL) + return 0; + auto widget_info = appdata_->widget_info(); + return widget_info->height(); +} + +unsigned int WidgetPreferenceDB::width() { + if (appdata_ == NULL || + appdata_->widget_info() == NULL) + return 0; + auto widget_info = appdata_->widget_info(); + return widget_info->width(); +} + +} // namespace extensions diff --git a/tizen/extensions/renderer/widget_module.h b/tizen/extensions/renderer/widget_module.h new file mode 100644 index 0000000..36acec1 --- /dev/null +++ b/tizen/extensions/renderer/widget_module.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef XWALK_EXTENSIONS_RENDERER_WIDGET_MODULE_H_ +#define XWALK_EXTENSIONS_RENDERER_WIDGET_MODULE_H_ + +#include +#include + +#include "common/application_data.h" +#include "common/locale_manager.h" +#include "extensions/renderer/xwalk_module_system.h" + +namespace extensions { + +// This module provides widget object +class WidgetModule : public XWalkNativeModule { + public: + WidgetModule(); + ~WidgetModule() override; + + private: + v8::Handle NewInstance() override; + v8::Persistent preference_object_template_; +}; + +class WidgetPreferenceDB { + public: + static WidgetPreferenceDB* GetInstance(); + void Initialize(const common::ApplicationData* appdata, + common::LocaleManager* locale_manager); + void InitializeDB(); + int Length(); + bool Key(int idx, std::string* key); + bool GetItem(const std::string& key, std::string* value); + bool SetItem(const std::string& key, const std::string& value); + bool RemoveItem(const std::string& key); + bool HasItem(const std::string& key); + void Clear(); + void GetKeys(std::list* keys); + + std::string author(); + std::string description(); + std::string name(); + std::string shortName(); + std::string version(); + std::string id(); + std::string authorEmail(); + std::string authorHref(); + unsigned int height(); + unsigned int width(); + + private: + WidgetPreferenceDB(); + virtual ~WidgetPreferenceDB(); + const common::ApplicationData* appdata_; + common::LocaleManager* locale_manager_; +}; + +} // namespace extensions + +#endif // XWALK_EXTENSIONS_RENDERER_WIDGET_MODULE_H_ diff --git a/tizen/extensions/renderer/xwalk_extension_client.cc b/tizen/extensions/renderer/xwalk_extension_client.cc new file mode 100644 index 0000000..383473f --- /dev/null +++ b/tizen/extensions/renderer/xwalk_extension_client.cc @@ -0,0 +1,131 @@ +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/renderer/xwalk_extension_client.h" + +#include +#include +#include +#include + +#include + +#include "common/logger.h" +#include "common/profiler.h" +#include "common/string_utils.h" +#include "extensions/common/constants.h" +#include "extensions/common/xwalk_extension_server.h" +#include "extensions/renderer/runtime_ipc_client.h" + +namespace extensions { + +namespace { + void* CreateInstanceInMainloop(void* data) { + const char* extension_name = static_cast(data); + XWalkExtensionServer* server = XWalkExtensionServer::GetInstance(); + std::string instance_id = server->CreateInstance(extension_name); + return static_cast(new std::string(instance_id)); + } +} // namespace + +XWalkExtensionClient::XWalkExtensionClient() { +} + +XWalkExtensionClient::~XWalkExtensionClient() { + for (auto it = extension_apis_.begin(); it != extension_apis_.end(); ++it) { + delete it->second; + } + extension_apis_.clear(); +} + +void XWalkExtensionClient::Initialize() { + SCOPE_PROFILE(); + if (!extension_apis_.empty()) { + return; + } + + XWalkExtensionServer* server = XWalkExtensionServer::GetInstance(); + Json::Value reply = server->GetExtensions(); + for (auto it = reply.begin(); it != reply.end(); ++it) { + ExtensionCodePoints* codepoint = new ExtensionCodePoints; + Json::Value entry_points = (*it)["entry_points"]; + for (auto ep = entry_points.begin(); ep != entry_points.end(); ++ep) { + codepoint->entry_points.push_back((*ep).asString()); + } + std::string name = (*it)["name"].asString(); + extension_apis_[name] = codepoint; + } +} + +std::string XWalkExtensionClient::CreateInstance( + v8::Handle context, + const std::string& extension_name, InstanceHandler* handler) { + void* ret = ecore_main_loop_thread_safe_call_sync( + CreateInstanceInMainloop, + static_cast(const_cast(extension_name.data()))); + std::string* sp = static_cast(ret); + std::string instance_id = *sp; + delete sp; + + handlers_[instance_id] = handler; + return instance_id; +} + +void XWalkExtensionClient::DestroyInstance( + v8::Handle context, const std::string& instance_id) { + auto it = handlers_.find(instance_id); + if (it == handlers_.end()) { + LOGGER(WARN) << "Failed to destory invalid instance id: " << instance_id; + return; + } + RuntimeIPCClient* ipc = RuntimeIPCClient::GetInstance(); + ipc->SendMessage(context, kMethodDestroyInstance, instance_id, ""); + + handlers_.erase(it); +} + +void XWalkExtensionClient::PostMessageToNative( + v8::Handle context, + const std::string& instance_id, const std::string& msg) { + RuntimeIPCClient* ipc = RuntimeIPCClient::GetInstance(); + ipc->SendMessage(context, kMethodPostMessage, instance_id, msg); +} + +std::string XWalkExtensionClient::SendSyncMessageToNative( + v8::Handle context, + const std::string& instance_id, const std::string& msg) { + RuntimeIPCClient* ipc = RuntimeIPCClient::GetInstance(); + std::string reply = + ipc->SendSyncMessage(context, kMethodSendSyncMessage, instance_id, msg); + return reply; +} + +std::string XWalkExtensionClient::GetAPIScript( + v8::Handle context, + const std::string& extension_name) { + XWalkExtensionServer* server = XWalkExtensionServer::GetInstance(); + return server->GetAPIScript(extension_name); +} + +void XWalkExtensionClient::OnReceivedIPCMessage( + const std::string& instance_id, const std::string& msg) { + auto it = handlers_.find(instance_id); + if (it == handlers_.end()) { + LOGGER(WARN) << "Failed to post the message. Invalid instance id."; + return; + } + + if (!it->second) + return; + + it->second->HandleMessageFromNative(msg); +} + +void XWalkExtensionClient::LoadUserExtensions(const std::string app_path) { + XWalkExtensionServer* server = XWalkExtensionServer::GetInstance(); + server->LoadUserExtensions(app_path); +} + +} // namespace extensions diff --git a/tizen/extensions/renderer/xwalk_extension_client.h b/tizen/extensions/renderer/xwalk_extension_client.h new file mode 100644 index 0000000..5b98ee9 --- /dev/null +++ b/tizen/extensions/renderer/xwalk_extension_client.h @@ -0,0 +1,71 @@ +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef XWALK_EXTENSIONS_RENDERER_XWALK_EXTENSION_CLIENT_H_ +#define XWALK_EXTENSIONS_RENDERER_XWALK_EXTENSION_CLIENT_H_ + +#include + +#include +#include +#include +#include + +#include "extensions/renderer/xwalk_module_system.h" + +namespace extensions { + +class XWalkExtensionClient { + public: + struct InstanceHandler { + virtual void HandleMessageFromNative(const std::string& msg) = 0; + protected: + ~InstanceHandler() {} + }; + + XWalkExtensionClient(); + virtual ~XWalkExtensionClient(); + + void Initialize(); + + std::string CreateInstance(v8::Handle context, + const std::string& extension_name, + InstanceHandler* handler); + void DestroyInstance(v8::Handle context, + const std::string& instance_id); + + void PostMessageToNative(v8::Handle context, + const std::string& instance_id, + const std::string& msg); + std::string SendSyncMessageToNative(v8::Handle context, + const std::string& instance_id, + const std::string& msg); + + std::string GetAPIScript(v8::Handle context, + const std::string& extension_name); + + void OnReceivedIPCMessage(const std::string& instance_id, + const std::string& msg); + void LoadUserExtensions(const std::string app_path); + + struct ExtensionCodePoints { + std::string api; + std::vector entry_points; + }; + + typedef std::map ExtensionAPIMap; + + const ExtensionAPIMap& extension_apis() const { return extension_apis_; } + + private: + ExtensionAPIMap extension_apis_; + + typedef std::map HandlerMap; + HandlerMap handlers_; +}; + +} // namespace extensions + +#endif // XWALK_EXTENSIONS_RENDERER_XWALK_EXTENSION_CLIENT_H_ diff --git a/tizen/extensions/renderer/xwalk_extension_module.cc b/tizen/extensions/renderer/xwalk_extension_module.cc new file mode 100644 index 0000000..c222556 --- /dev/null +++ b/tizen/extensions/renderer/xwalk_extension_module.cc @@ -0,0 +1,514 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/renderer/xwalk_extension_module.h" + +#include +#include +#include + +#include + +#include "common/arraysize.h" +#include "common/logger.h" +#include "common/profiler.h" +#include "extensions/renderer/runtime_ipc_client.h" +#include "extensions/renderer/xwalk_extension_client.h" +#include "extensions/renderer/xwalk_module_system.h" + +namespace extensions { + +namespace { + +// This is the key used in the data object passed to our callbacks to store a +// pointer back to kXWalkExtensionModule. +const char* kXWalkExtensionModule = "kXWalkExtensionModule"; + +} // namespace + +XWalkExtensionModule::XWalkExtensionModule(XWalkExtensionClient* client, + XWalkModuleSystem* module_system, + const std::string& extension_name, + const std::string& extension_code) + : extension_name_(extension_name), + extension_code_(extension_code), + client_(client), + module_system_(module_system), + instance_id_("") { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope handle_scope(isolate); + v8::Handle function_data = v8::Object::New(isolate); + function_data->Set(v8::String::NewFromUtf8(isolate, kXWalkExtensionModule), + v8::External::New(isolate, this)); + + v8::Handle object_template = + v8::ObjectTemplate::New(isolate); + // TODO(cmarcelo): Use Template::Set() function that takes isolate, once we + // update the Chromium (and V8) version. + object_template->Set( + v8::String::NewFromUtf8(isolate, "postMessage"), + v8::FunctionTemplate::New(isolate, PostMessageCallback, function_data)); + object_template->Set( + v8::String::NewFromUtf8(isolate, "sendSyncMessage"), + v8::FunctionTemplate::New( + isolate, SendSyncMessageCallback, function_data)); + object_template->Set( + v8::String::NewFromUtf8(isolate, "setMessageListener"), + v8::FunctionTemplate::New( + isolate, SetMessageListenerCallback, function_data)); + object_template->Set( + v8::String::NewFromUtf8(isolate, "sendRuntimeMessage"), + v8::FunctionTemplate::New( + isolate, SendRuntimeMessageCallback, function_data)); + object_template->Set( + v8::String::NewFromUtf8(isolate, "sendRuntimeSyncMessage"), + v8::FunctionTemplate::New( + isolate, SendRuntimeSyncMessageCallback, function_data)); + object_template->Set( + v8::String::NewFromUtf8(isolate, "sendRuntimeAsyncMessage"), + v8::FunctionTemplate::New( + isolate, SendRuntimeAsyncMessageCallback, function_data)); + + function_data_.Reset(isolate, function_data); + object_template_.Reset(isolate, object_template); +} + +XWalkExtensionModule::~XWalkExtensionModule() { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope handle_scope(isolate); + + // Deleting the data will disable the functions, they'll return early. We do + // this because it might be the case that the JS objects we created outlive + // this object (getting references from inside an iframe and then destroying + // the iframe), even if we destroy the references we have. + v8::Handle function_data = + v8::Local::New(isolate, function_data_); + function_data->Delete(v8::String::NewFromUtf8(isolate, + kXWalkExtensionModule)); + + object_template_.Reset(); + function_data_.Reset(); + message_listener_.Reset(); + + if (!instance_id_.empty()) + client_->DestroyInstance(module_system_->GetV8Context(), instance_id_); +} + +namespace { + +std::string CodeToEnsureNamespace(const std::string& extension_name) { + std::string result; + size_t pos = 0; + while (true) { + pos = extension_name.find('.', pos); + if (pos == std::string::npos) { + result += extension_name + " = {};"; + break; + } + std::string ns = extension_name.substr(0, pos); + result += ns + " = " + ns + " || {}; "; + pos++; + } + return result; +} + +// Templatized backend for StringPrintF/StringAppendF. This does not finalize +// the va_list, the caller is expected to do that. +template +static void StringAppendVT(StringType* dst, + const typename StringType::value_type* format, + va_list ap) { + // First try with a small fixed size buffer. + // This buffer size should be kept in sync with StringUtilTest.GrowBoundary + // and StringUtilTest.StringPrintfBounds. + typename StringType::value_type stack_buf[1024]; + + va_list ap_copy; + va_copy(ap_copy, ap); + + int result = vsnprintf(stack_buf, ARRAYSIZE(stack_buf), format, ap_copy); + va_end(ap_copy); + + if (result >= 0 && result < static_cast(ARRAYSIZE(stack_buf))) { + // It fit. + dst->append(stack_buf, result); + return; + } + + // Repeatedly increase buffer size until it fits. + int mem_length = ARRAYSIZE(stack_buf); + while (true) { + if (result < 0) { + if (errno != 0 && errno != EOVERFLOW) + return; + // Try doubling the buffer size. + mem_length *= 2; + } else { + // We need exactly "result + 1" characters. + mem_length = result + 1; + } + + if (mem_length > 32 * 1024 * 1024) { + // That should be plenty, don't try anything larger. This protects + // against huge allocations when using vsnprintfT implementations that + // return -1 for reasons other than overflow without setting errno. + LOGE("Unable to printf the requested string due to size."); + return; + } + + std::vector mem_buf(mem_length); + + // NOTE: You can only use a va_list once. Since we're in a while loop, we + // need to make a new copy each time so we don't use up the original. + va_copy(ap_copy, ap); + result = vsnprintf(&mem_buf[0], mem_length, format, ap_copy); + va_end(ap_copy); + + if ((result >= 0) && (result < mem_length)) { + // It fit. + dst->append(&mem_buf[0], result); + return; + } + } +} + +std::string StringPrintf(const char* format, ...) { + va_list ap; + va_start(ap, format); + std::string result; + StringAppendVT(&result, format, ap); + va_end(ap); + return result; +} + +// Wrap API code into a callable form that takes extension object as parameter. +std::string WrapAPICode(const std::string& extension_code, + const std::string& extension_name) { + // We take care here to make sure that line numbering for api_code after + // wrapping doesn't change, so that syntax errors point to the correct line. + + return StringPrintf( + "var %s; (function(extension, requireNative) { " + "extension.internal = {};" + "extension.internal.sendSyncMessage = extension.sendSyncMessage;" + "delete extension.sendSyncMessage;" + "var Object = requireNative('objecttools');" + "var exports = {}; (function() {'use strict'; %s\n})();" + "%s = exports; });", + CodeToEnsureNamespace(extension_name).c_str(), + extension_code.c_str(), + extension_name.c_str()); +} + +std::string ExceptionToString(const v8::TryCatch& try_catch) { + std::string str; + v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); + v8::String::Utf8Value exception(try_catch.Exception()); + v8::Local message(try_catch.Message()); + if (message.IsEmpty()) { + str.append(StringPrintf("%s\n", *exception)); + } else { + v8::String::Utf8Value filename(message->GetScriptResourceName()); + int linenum = message->GetLineNumber(); + int colnum = message->GetStartColumn(); + str.append(StringPrintf( + "%s:%i:%i %s\n", *filename, linenum, colnum, *exception)); + v8::String::Utf8Value sourceline(message->GetSourceLine()); + str.append(StringPrintf("%s\n", *sourceline)); + } + return str; +} + +v8::Handle RunString(const std::string& code, + std::string* exception) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope handle_scope(isolate); + v8::Handle v8_code( + v8::String::NewFromUtf8(isolate, code.c_str())); + + v8::TryCatch try_catch; + try_catch.SetVerbose(true); + + v8::Handle script(v8::Script::Compile(v8_code)); + if (try_catch.HasCaught()) { + *exception = ExceptionToString(try_catch); + return handle_scope.Escape( + v8::Local(v8::Undefined(isolate))); + } + + v8::Local result = script->Run(); + if (try_catch.HasCaught()) { + *exception = ExceptionToString(try_catch); + return handle_scope.Escape( + v8::Local(v8::Undefined(isolate))); + } + + return handle_scope.Escape(result); +} + +} // namespace + +void XWalkExtensionModule::LoadExtensionCode( + v8::Handle context, v8::Handle require_native) { + instance_id_ = client_->CreateInstance(context, extension_name_, this); + if (instance_id_.empty()) { + LOGGER(ERROR) << "Failed to create an instance of " << extension_name_; + return; + } + + if (extension_code_.empty()) { + extension_code_ = client_->GetAPIScript(context, extension_name_); + if (extension_code_.empty()) { + LOGGER(ERROR) << "Failed to get API script of " << extension_name_; + return; + } + } + + std::string wrapped_api_code = WrapAPICode(extension_code_, extension_name_); + + std::string exception; + v8::Handle result = RunString(wrapped_api_code, &exception); + + if (!result->IsFunction()) { + LOGGER(ERROR) << "Couldn't load JS API code for " + << extension_name_ << " : " << exception; + return; + } + v8::Handle callable_api_code = + v8::Handle::Cast(result); + v8::Handle object_template = + v8::Local::New(context->GetIsolate(), + object_template_); + + const int argc = 2; + v8::Handle argv[argc] = { + object_template->NewInstance(), + require_native + }; + + v8::TryCatch try_catch; + try_catch.SetVerbose(true); + callable_api_code->Call(context->Global(), argc, argv); + if (try_catch.HasCaught()) { + LOGGER(ERROR) << "Exception while loading JS API code for " + << extension_name_ << " : " << ExceptionToString(try_catch); + } +} + +void XWalkExtensionModule::HandleMessageFromNative(const std::string& msg) { + if (message_listener_.IsEmpty()) + return; + + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope handle_scope(isolate); + v8::Handle context = module_system_->GetV8Context(); + v8::Context::Scope context_scope(context); + + v8::Handle args[] = { + v8::String::NewFromUtf8(isolate, msg.c_str()) }; + + v8::Handle message_listener = + v8::Local::New(isolate, message_listener_); + + v8::TryCatch try_catch; + message_listener->Call(context->Global(), 1, args); + if (try_catch.HasCaught()) + LOGGER(ERROR) << "Exception when running message listener: " + << ExceptionToString(try_catch); +} + +// static +void XWalkExtensionModule::PostMessageCallback( + const v8::FunctionCallbackInfo& info) { + v8::ReturnValue result(info.GetReturnValue()); + XWalkExtensionModule* module = GetExtensionModule(info); + if (!module || info.Length() != 1) { + result.Set(false); + return; + } + + v8::String::Utf8Value value(info[0]->ToString()); + + // CHECK(module->instance_id_); + module->client_->PostMessageToNative(module->module_system_->GetV8Context(), + module->instance_id_, + std::string(*value)); + result.Set(true); +} + +// static +void XWalkExtensionModule::SendSyncMessageCallback( + const v8::FunctionCallbackInfo& info) { + v8::ReturnValue result(info.GetReturnValue()); + XWalkExtensionModule* module = GetExtensionModule(info); + if (!module || info.Length() != 1) { + result.Set(false); + return; + } + + v8::String::Utf8Value value(info[0]->ToString()); + + // CHECK(module->instance_id_); + std::string reply = + module->client_->SendSyncMessageToNative( + module->module_system_->GetV8Context(), + module->instance_id_, + std::string(*value)); + + // If we tried to send a message to an instance that became invalid, + // then reply will be NULL. + if (!reply.empty()) { + result.Set(v8::String::NewFromUtf8(info.GetIsolate(), reply.c_str())); + } +} + +// static +void XWalkExtensionModule::SetMessageListenerCallback( + const v8::FunctionCallbackInfo& info) { + v8::ReturnValue result(info.GetReturnValue()); + XWalkExtensionModule* module = GetExtensionModule(info); + if (!module || info.Length() != 1) { + result.Set(false); + return; + } + + if (!info[0]->IsFunction() && !info[0]->IsUndefined()) { + LOGGER(ERROR) << "Trying to set message listener with invalid value."; + result.Set(false); + return; + } + + v8::Isolate* isolate = info.GetIsolate(); + if (info[0]->IsUndefined()) + module->message_listener_.Reset(); + else + module->message_listener_.Reset(isolate, info[0].As()); + + result.Set(true); +} + +// static +void XWalkExtensionModule::SendRuntimeMessageCallback( + const v8::FunctionCallbackInfo& info) { + v8::ReturnValue result(info.GetReturnValue()); + XWalkExtensionModule* module = GetExtensionModule(info); + if (!module || info.Length() < 1) { + result.Set(false); + return; + } + + v8::String::Utf8Value type(info[0]->ToString()); + std::string data_str; + if (info.Length() > 1) { + v8::String::Utf8Value data(info[1]->ToString()); + data_str = std::string(*data); + } + + RuntimeIPCClient* rc = RuntimeIPCClient::GetInstance(); + rc->SendMessage(module->module_system_->GetV8Context(), + std::string(*type), data_str); + + result.Set(true); +} + +// static +void XWalkExtensionModule::SendRuntimeSyncMessageCallback( + const v8::FunctionCallbackInfo& info) { + v8::Isolate* isolate = info.GetIsolate(); + + v8::ReturnValue result(info.GetReturnValue()); + XWalkExtensionModule* module = GetExtensionModule(info); + if (!module || info.Length() < 1) { + result.SetUndefined(); + return; + } + + v8::String::Utf8Value type(info[0]->ToString()); + std::string data_str; + if (info.Length() > 1) { + v8::String::Utf8Value data(info[1]->ToString()); + data_str = std::string(*data); + } + + RuntimeIPCClient* rc = RuntimeIPCClient::GetInstance(); + std::string reply = rc->SendSyncMessage( + module->module_system_->GetV8Context(), + std::string(*type), data_str); + + result.Set(v8::String::NewFromUtf8(isolate, reply.c_str())); +} + +// static +void XWalkExtensionModule::SendRuntimeAsyncMessageCallback( + const v8::FunctionCallbackInfo& info) { + v8::Isolate* isolate = info.GetIsolate(); + v8::HandleScope handle_scope(isolate); + + v8::ReturnValue result(info.GetReturnValue()); + XWalkExtensionModule* module = GetExtensionModule(info); + if (!module || info.Length() < 1) { + result.Set(false); + return; + } + + // type + v8::String::Utf8Value type(info[0]->ToString()); + + // value + std::string value_str; + if (info.Length() > 1) { + v8::String::Utf8Value value(info[1]->ToString()); + value_str = std::string(*value); + } + + // callback + RuntimeIPCClient::JSCallback* js_callback = NULL; + if (info.Length() > 2) { + if (info[2]->IsFunction()) { + v8::Handle func = info[2].As(); + js_callback = new RuntimeIPCClient::JSCallback(isolate, func); + } + } + + auto callback = [js_callback](const std::string& /*type*/, + const std::string& value) -> void { + if (!js_callback) { + LOGGER(ERROR) << "JsCallback is NULL."; + return; + } + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope handle_scope(isolate); + v8::Handle args[] = { + v8::String::NewFromUtf8(isolate, value.c_str()) }; + js_callback->Call(isolate, args); + delete js_callback; + }; + + RuntimeIPCClient* rc = RuntimeIPCClient::GetInstance(); + rc->SendAsyncMessage(module->module_system_->GetV8Context(), + std::string(*type), value_str, callback); + + result.Set(true); +} + +// static +XWalkExtensionModule* XWalkExtensionModule::GetExtensionModule( + const v8::FunctionCallbackInfo& info) { + v8::Isolate* isolate = info.GetIsolate(); + v8::HandleScope handle_scope(isolate); + + v8::Local data = info.Data().As(); + v8::Local module = + data->Get(v8::String::NewFromUtf8(isolate, kXWalkExtensionModule)); + if (module.IsEmpty() || module->IsUndefined()) { + LOGGER(ERROR) << "Trying to use extension from already destroyed context!"; + return NULL; + } + // CHECK(module->IsExternal()); + return static_cast(module.As()->Value()); +} + +} // namespace extensions diff --git a/tizen/extensions/renderer/xwalk_extension_module.h b/tizen/extensions/renderer/xwalk_extension_module.h new file mode 100644 index 0000000..1076f0f --- /dev/null +++ b/tizen/extensions/renderer/xwalk_extension_module.h @@ -0,0 +1,84 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef XWALK_EXTENSIONS_RENDERER_XWALK_EXTENSION_MODULE_H_ +#define XWALK_EXTENSIONS_RENDERER_XWALK_EXTENSION_MODULE_H_ + +#include + +#include +#include + +#include "extensions/renderer/xwalk_extension_client.h" + +namespace extensions { + +class XWalkModuleSystem; + +// Responsible for running the JS code of a Extension. This includes +// creating and exposing an 'extension' object for the execution context of +// the extension JS code. +// +// We'll create one XWalkExtensionModule per extension/frame pair, so +// there'll be a set of different modules per v8::Context. +class XWalkExtensionModule : public XWalkExtensionClient::InstanceHandler { + public: + XWalkExtensionModule(XWalkExtensionClient* client, + XWalkModuleSystem* module_system, + const std::string& extension_name, + const std::string& extension_code); + virtual ~XWalkExtensionModule(); + + // TODO(cmarcelo): Make this return a v8::Handle, and + // let the module system set it to the appropriated object. + void LoadExtensionCode(v8::Handle context, + v8::Handle require_native); + + std::string extension_name() const { return extension_name_; } + + private: + // ExtensionClient::InstanceHandler implementation. + virtual void HandleMessageFromNative(const std::string& msg); + + // Callbacks for JS functions available in 'extension' object. + static void PostMessageCallback( + const v8::FunctionCallbackInfo& info); + static void SendSyncMessageCallback( + const v8::FunctionCallbackInfo& info); + static void SetMessageListenerCallback( + const v8::FunctionCallbackInfo& info); + static void SendRuntimeMessageCallback( + const v8::FunctionCallbackInfo& info); + static void SendRuntimeSyncMessageCallback( + const v8::FunctionCallbackInfo& info); + static void SendRuntimeAsyncMessageCallback( + const v8::FunctionCallbackInfo& info); + + static XWalkExtensionModule* GetExtensionModule( + const v8::FunctionCallbackInfo& info); + + // Template for the 'extension' object exposed to the extension JS code. + v8::Persistent object_template_; + + // This JS object contains a pointer back to the ExtensionModule, it is + // set as data for the function callbacks. + v8::Persistent function_data_; + + // Function to be called when the extension sends a message to its JS code. + // This value is registered by using 'extension.setMessageListener()'. + v8::Persistent message_listener_; + + std::string extension_name_; + std::string extension_code_; + + XWalkExtensionClient* client_; + XWalkModuleSystem* module_system_; + std::string instance_id_; +}; + +} // namespace extensions + +#endif // XWALK_EXTENSIONS_RENDERER_XWALK_EXTENSION_MODULE_H_ diff --git a/tizen/extensions/renderer/xwalk_extension_renderer_controller.cc b/tizen/extensions/renderer/xwalk_extension_renderer_controller.cc new file mode 100644 index 0000000..6c8dd11 --- /dev/null +++ b/tizen/extensions/renderer/xwalk_extension_renderer_controller.cc @@ -0,0 +1,132 @@ +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/renderer/xwalk_extension_renderer_controller.h" + +#include +#include +#include +#include + +#include "common/logger.h" +#include "common/profiler.h" +#include "extensions/renderer/object_tools_module.h" +#include "extensions/renderer/widget_module.h" +#include "extensions/renderer/xwalk_extension_client.h" +#include "extensions/renderer/xwalk_extension_module.h" +#include "extensions/renderer/xwalk_module_system.h" +#include "extensions/renderer/xwalk_v8tools_module.h" +#include "extensions/renderer/runtime_ipc_client.h" + +namespace extensions { + +// static +int XWalkExtensionRendererController::plugin_session_count = 0; + +namespace { + +void CreateExtensionModules(XWalkExtensionClient* client, + XWalkModuleSystem* module_system) { + const XWalkExtensionClient::ExtensionAPIMap& extensions = + client->extension_apis(); + + for (auto it = extensions.begin(); it != extensions.end(); ++it) { + XWalkExtensionClient::ExtensionCodePoints* codepoint = it->second; + std::unique_ptr module( + new XWalkExtensionModule(client, module_system, + it->first, codepoint->api)); + module_system->RegisterExtensionModule(std::move(module), + codepoint->entry_points); + } +} + +} // namespace + +XWalkExtensionRendererController& +XWalkExtensionRendererController::GetInstance() { + static XWalkExtensionRendererController instance; + return instance; +} + +XWalkExtensionRendererController::XWalkExtensionRendererController() + : exit_requested(false), + extensions_client_(new XWalkExtensionClient()) { +} + +XWalkExtensionRendererController::~XWalkExtensionRendererController() { +} + +void XWalkExtensionRendererController::DidCreateScriptContext( + v8::Handle context) { + SCOPE_PROFILE(); + + // Skip plugin loading after application exit request. + if (exit_requested) { + return; + } + + XWalkModuleSystem* module_system = new XWalkModuleSystem(context); + XWalkModuleSystem::SetModuleSystemInContext( + std::unique_ptr(module_system), context); + module_system->RegisterNativeModule( + "v8tools", + std::unique_ptr(new XWalkV8ToolsModule)); + module_system->RegisterNativeModule( + "WidgetModule", + std::unique_ptr(new WidgetModule)); + module_system->RegisterNativeModule( + "objecttools", + std::unique_ptr(new ObjectToolsModule)); + + extensions_client_->Initialize(); + CreateExtensionModules(extensions_client_.get(), module_system); + + module_system->Initialize(); + plugin_session_count++; + LOGGER(DEBUG) << "plugin_session_count : " << plugin_session_count; +} + +void XWalkExtensionRendererController::WillReleaseScriptContext( + v8::Handle context) { + v8::Context::Scope contextScope(context); + XWalkModuleSystem* module_system = XWalkModuleSystem::GetModuleSystemFromContext(context); + if (module_system) { + plugin_session_count--; + LOGGER(DEBUG) << "plugin_session_count : " << plugin_session_count; + } + XWalkModuleSystem::ResetModuleSystemFromContext(context); +} + +void XWalkExtensionRendererController::OnReceivedIPCMessage( + const Ewk_IPC_Wrt_Message_Data* data) { + + Eina_Stringshare* type = ewk_ipc_wrt_message_data_type_get(data); + +#define TYPE_BEGIN(x) (!strncmp(type, x, strlen(x))) + if (TYPE_BEGIN("xwalk://")) { + Eina_Stringshare* id = ewk_ipc_wrt_message_data_id_get(data); + Eina_Stringshare* msg = ewk_ipc_wrt_message_data_value_get(data); + extensions_client_->OnReceivedIPCMessage(id, msg); + eina_stringshare_del(id); + eina_stringshare_del(msg); + } else { + RuntimeIPCClient* ipc = RuntimeIPCClient::GetInstance(); + ipc->HandleMessageFromRuntime(data); + } +#undef TYPE_BEGIN + + eina_stringshare_del(type); +} + +void XWalkExtensionRendererController::InitializeExtensionClient() { + extensions_client_->Initialize(); +} + +void XWalkExtensionRendererController::LoadUserExtensions( + const std::string app_path) { + extensions_client_->LoadUserExtensions(app_path); +} + +} // namespace extensions diff --git a/tizen/extensions/renderer/xwalk_extension_renderer_controller.h b/tizen/extensions/renderer/xwalk_extension_renderer_controller.h new file mode 100644 index 0000000..95e3145 --- /dev/null +++ b/tizen/extensions/renderer/xwalk_extension_renderer_controller.h @@ -0,0 +1,45 @@ +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef XWALK_EXTENSIONS_RENDERER_XWALK_EXTENSION_RENDERER_CONTROLLER_H_ +#define XWALK_EXTENSIONS_RENDERER_XWALK_EXTENSION_RENDERER_CONTROLLER_H_ + +#include +#include +#include + +#include +#include + +namespace extensions { + +class XWalkExtensionClient; + +class XWalkExtensionRendererController { + public: + static XWalkExtensionRendererController& GetInstance(); + static int plugin_session_count; + + void DidCreateScriptContext(v8::Handle context); + void WillReleaseScriptContext(v8::Handle context); + + void OnReceivedIPCMessage(const Ewk_IPC_Wrt_Message_Data* data); + + void InitializeExtensionClient(); + void LoadUserExtensions(const std::string app_path); + + bool exit_requested; + + private: + XWalkExtensionRendererController(); + virtual ~XWalkExtensionRendererController(); + + private: + std::unique_ptr extensions_client_; +}; + +} // namespace extensions + +#endif // XWALK_EXTENSIONS_RENDERER_XWALK_EXTENSION_RENDERER_CONTROLLER_H_ diff --git a/tizen/extensions/renderer/xwalk_module_system.cc b/tizen/extensions/renderer/xwalk_module_system.cc new file mode 100644 index 0000000..2218188 --- /dev/null +++ b/tizen/extensions/renderer/xwalk_module_system.cc @@ -0,0 +1,524 @@ +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/renderer/xwalk_module_system.h" + +#include + +#include + +#include "common/logger.h" +#include "common/profiler.h" +#include "extensions/renderer/xwalk_extension_module.h" + +namespace extensions { + +namespace { + +// Index used to set embedder data into v8::Context, so we can get from a +// context to its corresponding module. Index chosen to not conflict with +// WebCore::V8ContextEmbedderDataField in V8PerContextData.h. +const int kModuleSystemEmbedderDataIndex = 8; + +// This is the key used in the data object passed to our callbacks to store a +// pointer back to XWalkExtensionModule. +const char* kXWalkModuleSystem = "kXWalkModuleSystem"; + +void RequireNativeCallback(const v8::FunctionCallbackInfo& info) { + v8::ReturnValue result(info.GetReturnValue()); + + v8::Isolate* isolate = info.GetIsolate(); + v8::HandleScope handle_scope(isolate); + + v8::Handle data = info.Data().As(); + v8::Handle module_system_value = + data->Get(v8::String::NewFromUtf8(isolate, kXWalkModuleSystem)); + if (module_system_value.IsEmpty() || module_system_value->IsUndefined()) { + LOGGER(ERROR) << "Trying to use requireNative from already " + << "destroyed module system!"; + result.SetUndefined(); + return; + } + + XWalkModuleSystem* module_system = static_cast( + module_system_value.As()->Value()); + + if (info.Length() < 1) { + // TODO(cmarcelo): Throw appropriate exception or warning. + result.SetUndefined(); + return; + } + if (!module_system) { + result.SetUndefined(); + return; + } + v8::Handle object = + module_system->RequireNative(*v8::String::Utf8Value(info[0])); + if (object.IsEmpty()) { + // TODO(cmarcelo): Throw appropriate exception or warning. + result.SetUndefined(); + return; + } + result.Set(object); +} + +} // namespace + +XWalkModuleSystem::XWalkModuleSystem(v8::Handle context) { + v8::Isolate* isolate = context->GetIsolate(); + v8_context_.Reset(isolate, context); + + v8::HandleScope handle_scope(isolate); + v8::Handle function_data = v8::Object::New(isolate); + function_data->Set(v8::String::NewFromUtf8(isolate, kXWalkModuleSystem), + v8::External::New(isolate, this)); + v8::Handle require_native_template = + v8::FunctionTemplate::New(isolate, RequireNativeCallback, function_data); + + function_data_.Reset(isolate, function_data); + require_native_template_.Reset(isolate, require_native_template); +} + +XWalkModuleSystem::~XWalkModuleSystem() { + DeleteExtensionModules(); + auto it = native_modules_.begin(); + for ( ; it != native_modules_.end(); ++it) { + delete it->second; + } + native_modules_.clear(); + + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope handle_scope(isolate); + + require_native_template_.Reset(); + function_data_.Reset(); + v8_context_.Reset(); +} + +// static +XWalkModuleSystem* XWalkModuleSystem::GetModuleSystemFromContext( + v8::Handle context) { + return reinterpret_cast( + context->GetAlignedPointerFromEmbedderData( + kModuleSystemEmbedderDataIndex)); +} + +// static +void XWalkModuleSystem::SetModuleSystemInContext( + std::unique_ptr module_system, + v8::Handle context) { + context->SetAlignedPointerInEmbedderData(kModuleSystemEmbedderDataIndex, + module_system.release()); +} + +// static +void XWalkModuleSystem::ResetModuleSystemFromContext( + v8::Handle context) { + XWalkModuleSystem* module_system = GetModuleSystemFromContext(context); + if (module_system) { + delete module_system; + SetModuleSystemInContext(std::unique_ptr(), context); + } +} + +void XWalkModuleSystem::RegisterExtensionModule( + std::unique_ptr module, + const std::vector& entry_points) { + const std::string& extension_name = module->extension_name(); + if (ContainsEntryPoint(extension_name)) { + LOGGER(ERROR) << "Can't register Extension Module named for extension '" + << extension_name << "' in the Module System because name " + << " was already registered."; + return; + } + + std::vector::const_iterator it = entry_points.begin(); + for (; it != entry_points.end(); ++it) { + if (ContainsEntryPoint(*it)) { + LOGGER(ERROR) << "Can't register Extension Module named for extension '" + << extension_name << "' in the Module System because " + << "another extension has the entry point '" + << (*it) << "'."; + return; + } + } + + extension_modules_.push_back( + ExtensionModuleEntry(extension_name, module.release(), entry_points)); +} + +void XWalkModuleSystem::RegisterNativeModule( + const std::string& name, std::unique_ptr module) { + if (native_modules_.find(name) != native_modules_.end()) { + return; + } + native_modules_[name] = module.release(); +} + + +namespace { + +v8::Handle EnsureTargetObjectForTrampoline( + v8::Handle context, const std::vector& path, + std::string* error) { + v8::Handle object = context->Global(); + v8::Isolate* isolate = context->GetIsolate(); + + std::vector::const_iterator it = path.begin(); + for (; it != path.end(); ++it) { + v8::Handle part = + v8::String::NewFromUtf8(isolate, it->c_str()); + v8::Handle value = object->Get(part); + + if (value->IsUndefined()) { + v8::Handle next_object = v8::Object::New(isolate); + object->Set(part, next_object); + object = next_object; + continue; + } + + if (!value->IsObject()) { + *error = "the property '" + *it + "' in the path is undefined"; + return v8::Undefined(isolate); + } + + object = value.As(); + } + return object; +} + +v8::Handle GetObjectForPath(v8::Handle context, + const std::vector& path, + std::string* error) { + v8::Handle object = context->Global(); + v8::Isolate* isolate = context->GetIsolate(); + + std::vector::const_iterator it = path.begin(); + for (; it != path.end(); ++it) { + v8::Handle part = + v8::String::NewFromUtf8(isolate, it->c_str()); + v8::Handle value = object->Get(part); + + if (!value->IsObject()) { + *error = "the property '" + *it + "' in the path is undefined"; + return v8::Undefined(isolate); + } + + object = value.As(); + } + return object; +} + +} // namespace + +template +void SplitString(const STR& str, const typename STR::value_type s, + std::vector* r) { + r->clear(); + size_t last = 0; + size_t c = str.size(); + for (size_t i = 0; i <= c; ++i) { + if (i == c || str[i] == s) { + STR tmp(str, last, i - last); + if (i != c || !r->empty() || !tmp.empty()) + r->push_back(tmp); + last = i + 1; + } + } +} + +bool XWalkModuleSystem::SetTrampolineAccessorForEntryPoint( + v8::Handle context, + const std::string& entry_point, + v8::Local user_data) { + std::vector path; + SplitString(entry_point, '.', &path); + std::string basename = path.back(); + path.pop_back(); + + std::string error; + v8::Handle value = + EnsureTargetObjectForTrampoline(context, path, &error); + if (value->IsUndefined()) { + LOGGER(ERROR) << "Error installing trampoline for " << entry_point + << " : " << error; + return false; + } + + v8::Isolate* isolate = context->GetIsolate(); + v8::Local params = v8::Array::New(isolate); + v8::Local entry = + v8::String::NewFromUtf8(isolate, entry_point.c_str()); + params->Set(v8::Integer::New(isolate, 0), user_data); + params->Set(v8::Integer::New(isolate, 1), entry); + + // FIXME(cmarcelo): ensure that trampoline is readonly. + value.As()->SetAccessor(context, + v8::String::NewFromUtf8(isolate, basename.c_str()), + TrampolineCallback, TrampolineSetterCallback, params); + return true; +} + +// static +bool XWalkModuleSystem::DeleteAccessorForEntryPoint( + v8::Handle context, + const std::string& entry_point) { + std::vector path; + SplitString(entry_point, '.', &path); + std::string basename = path.back(); + path.pop_back(); + + std::string error; + v8::Handle value = GetObjectForPath(context, path, &error); + if (value->IsUndefined()) { + LOGGER(ERROR) << "Error retrieving object for " << entry_point + << " : " << error; + return false; + } + + value.As()->Delete( + v8::String::NewFromUtf8(context->GetIsolate(), basename.c_str())); + return true; +} + +bool XWalkModuleSystem::InstallTrampoline(v8::Handle context, + ExtensionModuleEntry* entry) { + v8::Local entry_ptr = + v8::External::New(context->GetIsolate(), entry); + bool ret = SetTrampolineAccessorForEntryPoint(context, entry->name, + entry_ptr); + if (!ret) { + LOGGER(ERROR) << "Error installing trampoline for " << entry->name; + return false; + } + + std::vector::const_iterator it = entry->entry_points.begin(); + for (; it != entry->entry_points.end(); ++it) { + ret = SetTrampolineAccessorForEntryPoint(context, *it, entry_ptr); + if (!ret) { + // TODO(vcgomes): Remove already added trampolines when it fails. + LOGGER(ERROR) << "Error installing trampoline for " << entry->name; + return false; + } + } + return true; +} + +v8::Handle XWalkModuleSystem::RequireNative( + const std::string& name) { + NativeModuleMap::iterator it = native_modules_.find(name); + if (it == native_modules_.end()) + return v8::Handle(); + return it->second->NewInstance(); +} + +void XWalkModuleSystem::Initialize() { + SCOPE_PROFILE(); + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope handle_scope(isolate); + v8::Handle context = GetV8Context(); + v8::Handle require_native_template = + v8::Local::New(isolate, require_native_template_); + v8::Handle require_native = + require_native_template->GetFunction(); + + MarkModulesWithTrampoline(); + + ExtensionModules::iterator it = extension_modules_.begin(); + for (; it != extension_modules_.end(); ++it) { + if (it->use_trampoline && InstallTrampoline(context, &*it)) + continue; + it->module->LoadExtensionCode(context, require_native); + EnsureExtensionNamespaceIsReadOnly(context, it->name); + } +} + +v8::Handle XWalkModuleSystem::GetV8Context() { + return v8::Local::New(v8::Isolate::GetCurrent(), v8_context_); +} + +bool XWalkModuleSystem::ContainsEntryPoint( + const std::string& entry) { + auto it = extension_modules_.begin(); + for (; it != extension_modules_.end(); ++it) { + if (it->name == entry) + return true; + + auto entry_it = std::find( + it->entry_points.begin(), it->entry_points.end(), entry); + if (entry_it != it->entry_points.end()) { + return true; + } + } + return false; +} + +void XWalkModuleSystem::DeleteExtensionModules() { + for (ExtensionModules::iterator it = extension_modules_.begin(); + it != extension_modules_.end(); ++it) { + delete it->module; + } + extension_modules_.clear(); +} + +// static +void XWalkModuleSystem::LoadExtensionForTrampoline( + v8::Isolate* isolate, + v8::Local data) { + v8::HandleScope handle_scope(isolate); + v8::Local params = data.As(); + void* ptr = params->Get( + v8::Integer::New(isolate, 0)).As()->Value(); + + ExtensionModuleEntry* entry = static_cast(ptr); + + if (!entry) + return; + + v8::Handle context = isolate->GetCurrentContext(); + + DeleteAccessorForEntryPoint(context, entry->name); + + auto it = entry->entry_points.begin(); + for (; it != entry->entry_points.end(); ++it) { + DeleteAccessorForEntryPoint(context, *it); + } + + XWalkModuleSystem* module_system = GetModuleSystemFromContext(context); + v8::Handle require_native_template = + v8::Local::New( + isolate, + module_system->require_native_template_); + + XWalkExtensionModule* module = entry->module; + module->LoadExtensionCode(module_system->GetV8Context(), + require_native_template->GetFunction()); + + module_system->EnsureExtensionNamespaceIsReadOnly(context, entry->name); +} + +// static +v8::Handle XWalkModuleSystem::RefetchHolder( + v8::Isolate* isolate, + v8::Local data) { + v8::Local params = data.As(); + const std::string entry_point = *v8::String::Utf8Value( + params->Get(v8::Integer::New(isolate, 1)).As()); + + std::vector path; + SplitString(entry_point, '.', &path); + path.pop_back(); + + std::string error; + return GetObjectForPath(isolate->GetCurrentContext(), path, &error); +} + +// static +void XWalkModuleSystem::TrampolineCallback( + v8::Local property, + const v8::PropertyCallbackInfo& info) { + XWalkModuleSystem::LoadExtensionForTrampoline(info.GetIsolate(), info.Data()); + v8::Handle holder = RefetchHolder(info.GetIsolate(), info.Data()); + if (holder->IsUndefined()) + return; + + info.GetReturnValue().Set(holder.As()->Get(property)); +} + +// static +void XWalkModuleSystem::TrampolineSetterCallback( + v8::Local property, + v8::Local value, + const v8::PropertyCallbackInfo& info) { + XWalkModuleSystem::LoadExtensionForTrampoline(info.GetIsolate(), info.Data()); + v8::Handle holder = RefetchHolder(info.GetIsolate(), info.Data()); + if (holder->IsUndefined()) + return; + + holder.As()->Set(property, value); +} + +XWalkModuleSystem::ExtensionModuleEntry::ExtensionModuleEntry( + const std::string& name, + XWalkExtensionModule* module, + const std::vector& entry_points) : + name(name), module(module), use_trampoline(true), + entry_points(entry_points) { +} + +XWalkModuleSystem::ExtensionModuleEntry::~ExtensionModuleEntry() { +} + +// Returns whether the name of first is prefix of the second, considering "." +// character as a separator. So "a" is prefix of "a.b" but not of "ab". +bool XWalkModuleSystem::ExtensionModuleEntry::IsPrefix( + const ExtensionModuleEntry& first, + const ExtensionModuleEntry& second) { + const std::string& p = first.name; + const std::string& s = second.name; + return s.size() > p.size() && s[p.size()] == '.' + && std::mismatch(p.begin(), p.end(), s.begin()).first == p.end(); +} + +// Mark the extension modules that we want to setup "trampolines" +// instead of loading the code directly. The current algorithm is very +// simple: we only create trampolines for extensions that are leaves +// in the namespace tree. +// +// For example, if there are two extensions "tizen" and "tizen.time", +// the first one won't be marked with trampoline, but the second one +// will. So we'll only load code for "tizen" extension. +void XWalkModuleSystem::MarkModulesWithTrampoline() { + std::sort(extension_modules_.begin(), extension_modules_.end()); + { + ExtensionModules::iterator it = extension_modules_.begin(); + while (it != extension_modules_.end()) { + it = std::adjacent_find(it, extension_modules_.end(), + &ExtensionModuleEntry::IsPrefix); + if (it == extension_modules_.end()) + break; + it->use_trampoline = false; + ++it; + } + } + + // NOTE: Special Case for Security Reason + // xwalk module should not be trampolined even it does not have any children. + { + ExtensionModules::iterator it = extension_modules_.begin(); + while (it != extension_modules_.end()) { + if ("xwalk" == (*it).name) { + it->use_trampoline = false; + break; + } + ++it; + } + } +} + +void XWalkModuleSystem::EnsureExtensionNamespaceIsReadOnly( + v8::Handle context, + const std::string& extension_name) { + std::vector path; + SplitString(extension_name, '.', &path); + std::string basename = path.back(); + path.pop_back(); + + std::string error; + v8::Handle value = GetObjectForPath(context, path, &error); + if (value->IsUndefined()) { + LOGGER(ERROR) << "Error retrieving object for " << extension_name << " : " + << error; + return; + } + + v8::Handle v8_extension_name( + v8::String::NewFromUtf8(context->GetIsolate(), basename.c_str())); + value.As()->ForceSet( + v8_extension_name, value.As()->Get(v8_extension_name), + v8::ReadOnly); +} + +} // namespace extensions diff --git a/tizen/extensions/renderer/xwalk_module_system.h b/tizen/extensions/renderer/xwalk_module_system.h new file mode 100644 index 0000000..e8bf6bf --- /dev/null +++ b/tizen/extensions/renderer/xwalk_module_system.h @@ -0,0 +1,116 @@ +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef XWALK_EXTENSIONS_RENDERER_XWALK_MODULE_SYSTEM_H_ +#define XWALK_EXTENSIONS_RENDERER_XWALK_MODULE_SYSTEM_H_ + +#include + +#include +#include +#include +#include + +namespace extensions { + +class XWalkExtensionModule; + +// Interface used to expose objects via the requireNative() function in JS API +// code. Native modules should be registered with the module system. +class XWalkNativeModule { + public: + virtual v8::Handle NewInstance() = 0; + virtual ~XWalkNativeModule() {} +}; + + +class XWalkModuleSystem { + public: + explicit XWalkModuleSystem(v8::Handle context); + ~XWalkModuleSystem(); + + static XWalkModuleSystem* GetModuleSystemFromContext( + v8::Handle context); + static void SetModuleSystemInContext( + std::unique_ptr module_system, + v8::Handle context); + static void ResetModuleSystemFromContext(v8::Handle context); + + void RegisterExtensionModule(std::unique_ptr module, + const std::vector& entry_points); + void RegisterNativeModule(const std::string& name, + std::unique_ptr module); + v8::Handle RequireNative(const std::string& name); + + void Initialize(); + + v8::Handle GetV8Context(); + + private: + struct ExtensionModuleEntry { + ExtensionModuleEntry(const std::string& name, XWalkExtensionModule* module, + const std::vector& entry_points); + ~ExtensionModuleEntry(); + std::string name; + XWalkExtensionModule* module; + bool use_trampoline; + std::vector entry_points; + bool operator<(const ExtensionModuleEntry& other) const { + return name < other.name; + } + + static bool IsPrefix(const ExtensionModuleEntry& first, + const ExtensionModuleEntry& second); + }; + + bool SetTrampolineAccessorForEntryPoint( + v8::Handle context, + const std::string& entry_point, + v8::Local user_data); + + static bool DeleteAccessorForEntryPoint(v8::Handle context, + const std::string& entry_point); + + bool InstallTrampoline(v8::Handle context, + ExtensionModuleEntry* entry); + + static void TrampolineCallback( + v8::Local property, + const v8::PropertyCallbackInfo& info); + static void TrampolineSetterCallback( + v8::Local property, + v8::Local value, + const v8::PropertyCallbackInfo& info); + static void LoadExtensionForTrampoline( + v8::Isolate* isolate, + v8::Local data); + static v8::Handle RefetchHolder( + v8::Isolate* isolate, + v8::Local data); + + bool ContainsEntryPoint(const std::string& entry_point); + void MarkModulesWithTrampoline(); + void DeleteExtensionModules(); + + void EnsureExtensionNamespaceIsReadOnly(v8::Handle context, + const std::string& extension_name); + + typedef std::vector ExtensionModules; + ExtensionModules extension_modules_; + typedef std::map NativeModuleMap; + NativeModuleMap native_modules_; + + v8::Persistent require_native_template_; + v8::Persistent function_data_; + + // Points back to the current context, used when native wants to callback + // JavaScript. When WillReleaseScriptContext() is called, we dispose this + // persistent. + v8::Persistent v8_context_; +}; + +} // namespace extensions + +#endif // XWALK_EXTENSIONS_RENDERER_XWALK_MODULE_SYSTEM_H_ diff --git a/tizen/extensions/renderer/xwalk_v8tools_module.cc b/tizen/extensions/renderer/xwalk_v8tools_module.cc new file mode 100644 index 0000000..4fcad37 --- /dev/null +++ b/tizen/extensions/renderer/xwalk_v8tools_module.cc @@ -0,0 +1,98 @@ +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/renderer/xwalk_v8tools_module.h" + +#include + +#include "common/logger.h" + +namespace extensions { + +namespace { + +void ForceSetPropertyCallback( + const v8::FunctionCallbackInfo& info) { + if (info.Length() != 3 || !info[0]->IsObject() || !info[1]->IsString()) { + return; + } + info[0].As()->ForceSet(info[1], info[2]); +} + +// ================ +// lifecycleTracker +// ================ +struct LifecycleTrackerWrapper { + v8::Global handle; + v8::Global destructor; +}; + +void LifecycleTrackerCleanup( + const v8::WeakCallbackInfo& data) { + LifecycleTrackerWrapper* wrapper = data.GetParameter(); + + if (!wrapper->destructor.IsEmpty()) { + v8::HandleScope handle_scope(data.GetIsolate()); + v8::Local context = v8::Context::New(data.GetIsolate()); + v8::Context::Scope scope(context); + + v8::Local destructor = + wrapper->destructor.Get(data.GetIsolate()); + + v8::MicrotasksScope microtasks( + data.GetIsolate(), v8::MicrotasksScope::kDoNotRunMicrotasks); + + v8::TryCatch try_catch(data.GetIsolate()); + destructor->Call(context->Global(), 0, nullptr); + + if (try_catch.HasCaught()) { + LOGGER(WARN) << "Exception when running LifecycleTracker destructor"; + } + } +} + +void LifecycleTracker(const v8::FunctionCallbackInfo& info) { + v8::Isolate* isolate = info.GetIsolate(); + v8::HandleScope handle_scope(info.GetIsolate()); + + v8::Local tracker = v8::Object::New(isolate); + LifecycleTrackerWrapper* wrapper = new LifecycleTrackerWrapper; + wrapper->handle.Reset(isolate, tracker); + wrapper->handle.SetWeak(wrapper, LifecycleTrackerCleanup, + v8::WeakCallbackType::kParameter); + info.GetReturnValue().Set(wrapper->handle); +} + +} // namespace + +XWalkV8ToolsModule::XWalkV8ToolsModule() { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope handle_scope(isolate); + v8::Handle object_template = v8::ObjectTemplate::New(); + + // TODO(cmarcelo): Use Template::Set() function that takes isolate, once we + // update the Chromium (and V8) version. + object_template->Set(v8::String::NewFromUtf8(isolate, "forceSetProperty"), + v8::FunctionTemplate::New( + isolate, ForceSetPropertyCallback)); + object_template->Set(v8::String::NewFromUtf8(isolate, "lifecycleTracker"), + v8::FunctionTemplate::New(isolate, LifecycleTracker)); + + object_template_.Reset(isolate, object_template); +} + +XWalkV8ToolsModule::~XWalkV8ToolsModule() { + object_template_.Reset(); +} + +v8::Handle XWalkV8ToolsModule::NewInstance() { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope handle_scope(isolate); + v8::Handle object_template = + v8::Local::New(isolate, object_template_); + return handle_scope.Escape(object_template->NewInstance()); +} + +} // namespace extensions diff --git a/tizen/extensions/renderer/xwalk_v8tools_module.h b/tizen/extensions/renderer/xwalk_v8tools_module.h new file mode 100644 index 0000000..5b31dce --- /dev/null +++ b/tizen/extensions/renderer/xwalk_v8tools_module.h @@ -0,0 +1,28 @@ +// Copyright (c) 2013 Intel Corporation. All rights reserved. +// Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef XWALK_EXTENSIONS_RENDERER_XWALK_V8TOOLS_MODULE_H_ +#define XWALK_EXTENSIONS_RENDERER_XWALK_V8TOOLS_MODULE_H_ + +#include "extensions/renderer/xwalk_module_system.h" + +namespace extensions { + +// This module provides extra JS functions that help writing JS API code for +// extensions, for example: allowing setting a read-only property of an object. +class XWalkV8ToolsModule : public XWalkNativeModule { + public: + XWalkV8ToolsModule(); + ~XWalkV8ToolsModule() override; + + private: + v8::Handle NewInstance() override; + + v8::Persistent object_template_; +}; + +} // namespace extensions + +#endif // XWALK_EXTENSIONS_RENDERER_XWALK_V8TOOLS_MODULE_H_ diff --git a/tizen/renderer/injected_bundle.cc b/tizen/renderer/injected_bundle.cc new file mode 100644 index 0000000..a030975 --- /dev/null +++ b/tizen/renderer/injected_bundle.cc @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "common/application_data.h" +#include "common/locale_manager.h" +#include "common/logger.h" +#include "common/profiler.h" +#include "common/resource_manager.h" +#include "common/string_utils.h" +#include "extensions/renderer/runtime_ipc_client.h" +#include "extensions/renderer/widget_module.h" +#include "extensions/renderer/xwalk_extension_renderer_controller.h" +#include "extensions/renderer/xwalk_module_system.h" + +namespace runtime { + +class BundleGlobalData { + public: + static BundleGlobalData* GetInstance() { + static BundleGlobalData instance; + return &instance; + } + void PreInitialize() { + if (preInitialized) + return; + preInitialized = true; + locale_manager_.reset(new common::LocaleManager); + } + void Initialize(const std::string& app_id) { + PreInitialize(); + + auto appdata_manager = common::ApplicationDataManager::GetInstance(); + common::ApplicationData* app_data = + appdata_manager->GetApplicationData(app_id); + + app_data->LoadManifestData(); + // PreInitialized locale_manager_.reset(new common::LocaleManager); + locale_manager_->EnableAutoUpdate(true); + if (app_data->widget_info() != NULL && + !app_data->widget_info()->default_locale().empty()) { + locale_manager_->SetDefaultLocale( + app_data->widget_info()->default_locale()); + } + resource_manager_.reset(new common::ResourceManager(app_data, + locale_manager_.get())); + resource_manager_->set_base_resource_path( + app_data->application_path()); + + auto widgetdb = extensions::WidgetPreferenceDB::GetInstance(); + widgetdb->Initialize(app_data, + locale_manager_.get()); + } + + common::ResourceManager* resource_manager() { + return resource_manager_.get(); + } + + private: + BundleGlobalData() : preInitialized(false) {} + ~BundleGlobalData() {} + std::unique_ptr resource_manager_; + std::unique_ptr locale_manager_; + + bool preInitialized; +}; + +} // namespace runtime + +extern "C" unsigned int DynamicPluginVersion(void) { + return 1; +} + +extern "C" void DynamicSetWidgetInfo(const char* tizen_id) { + SCOPE_PROFILE(); + ecore_init(); + + runtime::BundleGlobalData::GetInstance()->Initialize(tizen_id); + extensions::XWalkExtensionRendererController& controller = + extensions::XWalkExtensionRendererController::GetInstance(); + auto appdata_manager = common::ApplicationDataManager::GetInstance(); + common::ApplicationData* app_data = + appdata_manager->GetApplicationData(tizen_id); + controller.LoadUserExtensions(app_data->application_path()); +} + +extern "C" void DynamicPluginStartSession(const char* tizen_id, + v8::Handle context, + int routing_handle, + const char* base_url) { + SCOPE_PROFILE(); + + // Initialize context's aligned pointer in embedder data with null + extensions::XWalkModuleSystem::SetModuleSystemInContext( + std::unique_ptr(), context); + + if (base_url == NULL || common::utils::StartsWith(base_url, "http")) { + LOGGER(ERROR) << "External url not allowed plugin loading."; + return; + } + + // Initialize RuntimeIPCClient + extensions::RuntimeIPCClient* rc = + extensions::RuntimeIPCClient::GetInstance(); + rc->SetRoutingId(context, routing_handle); + + extensions::XWalkExtensionRendererController& controller = + extensions::XWalkExtensionRendererController::GetInstance(); + controller.DidCreateScriptContext(context); +} + +extern "C" void DynamicPluginStopSession( + const char* tizen_id, v8::Handle context) { + SCOPE_PROFILE(); + extensions::XWalkExtensionRendererController& controller = + extensions::XWalkExtensionRendererController::GetInstance(); + controller.WillReleaseScriptContext(context); +} + +extern "C" void DynamicUrlParsing( + std::string* old_url, std::string* new_url, const char* /*tizen_id*/) { + LOGGER(DEBUG) << "DynamicUrlParsing"; + auto res_manager = + runtime::BundleGlobalData::GetInstance()->resource_manager(); + if (res_manager == NULL) { + LOGGER(ERROR) << "Widget Info was not set, Resource Manager is NULL"; + *new_url = *old_url; + return; + } + // Check Access control + if (!res_manager->AllowedResource(*old_url)) { + // To maintain backward compatibility, we shoudn't explicitly set URL "about:blank" + *new_url = std::string(); + LOGGER(ERROR) << "request was blocked by WARP"; + return; + } + // convert to localized path + if (common::utils::StartsWith(*old_url, "file:/") || + common::utils::StartsWith(*old_url, "app:/")) { + *new_url = res_manager->GetLocalizedPath(*old_url); + } else { + *new_url = *old_url; + } + // check encryption + if (res_manager->IsEncrypted(*new_url)) { + *new_url = res_manager->DecryptResource(*new_url); + } +} + +extern "C" void DynamicDatabaseAttach(int /*attach*/) { + // LOGGER(DEBUG) << "InjectedBundle::DynamicDatabaseAttach !!"; +} + +extern "C" void DynamicOnIPCMessage(const Ewk_IPC_Wrt_Message_Data& data) { + SCOPE_PROFILE(); + extensions::XWalkExtensionRendererController& controller = + extensions::XWalkExtensionRendererController::GetInstance(); + controller.OnReceivedIPCMessage(&data); +} + +extern "C" void DynamicPreloading() { + LOGGER(ERROR) << "DynamicPreloading"; + SCOPE_PROFILE(); + runtime::BundleGlobalData::GetInstance()->PreInitialize(); + extensions::XWalkExtensionRendererController& controller = + extensions::XWalkExtensionRendererController::GetInstance(); + controller.InitializeExtensionClient(); +} diff --git a/tizen/renderer/injected_bundle.gyp b/tizen/renderer/injected_bundle.gyp new file mode 100644 index 0000000..f6ab6d7 --- /dev/null +++ b/tizen/renderer/injected_bundle.gyp @@ -0,0 +1,23 @@ +{ + 'includes':[ + '../build/common.gypi', + ], + 'targets': [ + { + 'target_name': 'xwalk_injected_bundle', + 'type': 'shared_library', + 'sources': [ + 'injected_bundle.cc', + ], + 'cflags': [ + '-fvisibility=default', + ], + 'variables': { + 'packages': [ + 'chromium-efl', + 'elementary', + ], + }, + }, # end of target 'xwalk_injected_bundle' + ], +} diff --git a/vendor/brightray/browser/browser_context.cc b/vendor/brightray/browser/browser_context.cc index 46f7630..4ab07e4 100644 --- a/vendor/brightray/browser/browser_context.cc +++ b/vendor/brightray/browser/browser_context.cc @@ -28,6 +28,13 @@ #include "content/public/browser/storage_partition.h" #include "net/base/escape.h" +#if defined(OS_TIZEN) +#include "content/browser/zygote_host/zygote_communication_linux.h" +#include "content/public/browser/zygote_handle_linux.h" +#include "content/public/common/content_switches.h" +#include "base/command_line.h" +#endif + using content::BrowserThread; namespace brightray { @@ -100,6 +107,14 @@ BrowserContext::BrowserContext(const std::string& partition, bool in_memory) content::BrowserContext::Initialize(this, path_); browser_context_map_[PartitionKey(partition, in_memory)] = GetWeakPtr(); +#if defined(OS_TIZEN) + auto command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch("injected-bundle-path")) { + std::string injected_bundle_path = command_line->GetSwitchValueASCII("injected-bundle-path"); + (*content::GetGenericZygote())-> + LoadInjectedBundlePath(injected_bundle_path); + } +#endif } BrowserContext::~BrowserContext() { diff --git a/wrt.gyp b/wrt.gyp index a24edb4..6ea31d4 100644 --- a/wrt.gyp +++ b/wrt.gyp @@ -13,6 +13,8 @@ 'wrt_lib', '<(DEPTH)/tizen/common/common.gyp:wrt_common', '<(DEPTH)/tizen/loader/loader.gyp:wrt-loader', + '<(DEPTH)/tizen/extensions/extensions.gyp:xwalk_extension_shared', + '<(DEPTH)/tizen/renderer/injected_bundle.gyp:xwalk_injected_bundle', '<(DEPTH)/efl/build/system.gyp:ecore', '<(DEPTH)/efl/build/system.gyp:launchpad', '<(DEPTH)/efl/build/system.gyp:capi-appfw-application', -- 2.7.4 From e2f189e3b5d49c98f44ff11b11ec58201712423a Mon Sep 17 00:00:00 2001 From: "k2.nagaraju" Date: Thu, 5 Apr 2018 20:14:03 +0530 Subject: [PATCH 11/16] IPC bring up and removing ewk dependency to support webdevice API. - Modified the exising xwalk extension server and client to work in multiprocess - related patch https://review.tizen.org/gerrit/#/c/173694/ Change-Id: I5675b9fc3f2aad7d477b8a7dd60a3639e3d9b757 Signed-off-by: k2.nagaraju --- atom/app/atom_main_delegate.cc | 7 +- atom/app/runtime.cc | 2 +- atom/browser/api/atom_api_pwrt.cc | 2 +- atom/browser/api/atom_api_web_contents.cc | 38 ++++- atom/browser/api/atom_api_web_contents.h | 6 +- atom/browser/atom_browser_client.cc | 7 +- atom/common/api/api_messages.h | 26 ++++ atom/common/options_switches.cc | 7 + atom/common/options_switches.h | 5 + atom/renderer/atom_renderer_client.cc | 50 +++++++ atom/renderer/atom_renderer_client.h | 5 +- packaging/electron-efl.spec | 4 +- tizen/build/common.gypi | 2 +- tizen/common/common.gyp | 3 + tizen/common/wrt_message_data.cc | 38 +++++ tizen/common/wrt_message_data.h | 26 ++++ tizen/extensions/common/constants.cc | 2 +- tizen/extensions/common/constants.h | 1 + .../extensions/common/xwalk_extension_instance.cc | 1 + tizen/extensions/common/xwalk_extension_server.cc | 67 ++++----- tizen/extensions/common/xwalk_extension_server.h | 21 +-- tizen/extensions/extensions.gyp | 9 ++ tizen/extensions/renderer/runtime_ipc_client.cc | 78 +++++----- tizen/extensions/renderer/runtime_ipc_client.h | 5 +- .../extensions/renderer/xwalk_extension_client.cc | 53 +++++-- tizen/extensions/renderer/xwalk_extension_client.h | 2 +- .../xwalk_extension_renderer_controller.cc | 12 +- .../renderer/xwalk_extension_renderer_controller.h | 5 +- tizen/renderer/injected_bundle.cc | 5 +- tizen/wrt/chromium_wrt.gyp | 55 +++++++ tizen/wrt/dynamicplugin.cc | 89 +++++++++++ tizen/wrt/dynamicplugin.h | 46 ++++++ tizen/wrt/v8widget.cc | 92 ++++++++++++ tizen/wrt/v8widget.h | 41 ++++++ tizen/wrt/wrt_dynamicplugin.cc | 164 +++++++++++++++++++++ tizen/wrt/wrt_dynamicplugin.h | 71 +++++++++ tizen/wrt/wrt_file_protocol_handler.cc | 110 ++++++++++++++ tizen/wrt/wrt_file_protocol_handler.h | 46 ++++++ tizen/wrt/wrt_widget_host.cc | 164 +++++++++++++++++++++ tizen/wrt/wrt_widget_host.h | 89 +++++++++++ tizen/wrt/wrtwidget.cc | 97 ++++++++++++ tizen/wrt/wrtwidget.h | 45 ++++++ vendor/brightray/browser/browser_context.cc | 41 +++++- vendor/brightray/browser/browser_context.h | 4 + .../src/base/trace_event/trace_event.h | 2 +- wrt.gyp | 2 + 46 files changed, 1508 insertions(+), 139 deletions(-) create mode 100644 tizen/common/wrt_message_data.cc create mode 100644 tizen/common/wrt_message_data.h create mode 100644 tizen/wrt/chromium_wrt.gyp create mode 100644 tizen/wrt/dynamicplugin.cc create mode 100644 tizen/wrt/dynamicplugin.h create mode 100644 tizen/wrt/v8widget.cc create mode 100644 tizen/wrt/v8widget.h create mode 100644 tizen/wrt/wrt_dynamicplugin.cc create mode 100644 tizen/wrt/wrt_dynamicplugin.h create mode 100644 tizen/wrt/wrt_file_protocol_handler.cc create mode 100644 tizen/wrt/wrt_file_protocol_handler.h create mode 100644 tizen/wrt/wrt_widget_host.cc create mode 100644 tizen/wrt/wrt_widget_host.h create mode 100644 tizen/wrt/wrtwidget.cc create mode 100644 tizen/wrt/wrtwidget.h diff --git a/atom/app/atom_main_delegate.cc b/atom/app/atom_main_delegate.cc index f840690..32e6ecf 100644 --- a/atom/app/atom_main_delegate.cc +++ b/atom/app/atom_main_delegate.cc @@ -148,9 +148,10 @@ void AtomMainDelegate::PreSandboxStartup() { #if defined(OS_TIZEN) LOG (ERROR) << "Set Injected bundle path to engine"; - command_line->AppendSwitchASCII("injected-bundle-path","/usr/lib/libxwalk_injected_bundle.so"); - std::vector cmdAgrs = atom::AtomCommandLine::argv(); - std::string app_id = cmdAgrs[1]; + command_line->AppendSwitchASCII( + "injected-bundle-path","/usr/lib/libxwalk_injected_bundle.so"); + std::string app_id = common::CommandLine::ForCurrentProcess()-> + GetAppIdFromCommandLine("/usr/bin/wrt"); command_line->AppendSwitchASCII("widget-id",app_id); #endif diff --git a/atom/app/runtime.cc b/atom/app/runtime.cc index a14e842..ad61e2d 100644 --- a/atom/app/runtime.cc +++ b/atom/app/runtime.cc @@ -42,4 +42,4 @@ std::unique_ptr Runtime::MakeRuntime(content::ContentMainParams *params //} } -} // namespace runtime \ No newline at end of file +} // namespace runtime diff --git a/atom/browser/api/atom_api_pwrt.cc b/atom/browser/api/atom_api_pwrt.cc index e89b1dd..b63ef51 100644 --- a/atom/browser/api/atom_api_pwrt.cc +++ b/atom/browser/api/atom_api_pwrt.cc @@ -54,7 +54,7 @@ bool PWRT::isTizenWebApp() { void PWRT::Log(const std::string& message) { std::string output = "[JS LOG] " + message; - dlog_print(DLOG_INFO, "WRT", output.c_str()); + dlog_print(DLOG_ERROR, "WRT", output.c_str()); } // static diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 8c473c5..8474a5b 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -4,6 +4,7 @@ #include "atom/browser/api/atom_api_web_contents.h" +#include #include #include @@ -77,6 +78,10 @@ #include "third_party/WebKit/public/web/WebFindOptions.h" #include "ui/display/screen.h" +#if defined(USE_EFL) +#include "tizen/extensions/common/xwalk_extension_server.h" +#endif + #if !defined(OS_MACOSX) && !defined(USE_EFL) #include "ui/aura/window.h" #endif @@ -434,7 +439,8 @@ bool WebContents::DidAddMessageToConsole(content::WebContents* source, int32_t line_no, const base::string16& source_id) { if (type_ == BROWSER_WINDOW || type_ == OFF_SCREEN) { - return false; + LOG(ERROR) << "Console Message : " << message << ", source:" << source_id << " (" << line_no << ")"; + return true; } else { Emit("console-message", level, message, line_no, source_id); return true; @@ -897,6 +903,33 @@ void WebContents::DevToolsClosed() { Emit("devtools-closed"); } +void WebContents::OnWrtPluginMessage(const Wrt_Message_Data& data) { + Wrt_Message_Data tmp = data; + HandleWrtPluginMessage(&tmp); +} + +void WebContents::OnWrtPluginSyncMessage(const Wrt_Message_Data& data, + IPC::Message* reply) { + Wrt_Message_Data tmp = data; + HandleWrtPluginMessage(&tmp); + EwkHostMsg_WrtSyncMessage::WriteReplyParams(reply, tmp.value); + Send(reply); +} + +void WebContents::HandleWrtPluginMessage(Wrt_Message_Data* msg) { + Eina_Stringshare* msg_type = msg->GetType(); + +#define TYPE_BEGIN(x) (!strncmp(msg_type, x, strlen(x))) +#define TYPE_IS(x) (!strcmp(msg_type, x)) + + if (TYPE_BEGIN("xwalk://")) { + auto extension_server = extensions::XWalkExtensionServer::GetInstance(); + extension_server->HandleIPCMessage(msg); + } else { + // implement in future + } +} + bool WebContents::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(WebContents, message) @@ -907,7 +940,8 @@ bool WebContents::OnMessageReceived(const IPC::Message& message) { OnSetTemporaryZoomLevel) IPC_MESSAGE_HANDLER_DELAY_REPLY(AtomViewHostMsg_GetZoomLevel, OnGetZoomLevel) - + IPC_MESSAGE_HANDLER(EwkHostMsg_WrtMessage, OnWrtPluginMessage) + IPC_MESSAGE_HANDLER_DELAY_REPLY(EwkHostMsg_WrtSyncMessage, OnWrtPluginSyncMessage) // FIXME: Disable OnCursorChange due to stach_chk_fail crash. // IPC_MESSAGE_HANDLER_CODE(ViewHostMsg_SetCursor, OnCursorChange, // handled = false) diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 1301ed1..4407b3c 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -18,6 +18,7 @@ #include "content/public/browser/web_contents_observer.h" #include "content/public/common/favicon_url.h" #include "native_mate/handle.h" +#include "tizen/common/wrt_message_data.h" #include "ui/gfx/image/image.h" namespace blink { @@ -217,7 +218,10 @@ class WebContents : public mate::TrackableObject, v8::Local Debugger(v8::Isolate* isolate); WebContentsZoomController* GetZoomController() { return zoom_controller_; } - + void OnWrtPluginMessage(const Wrt_Message_Data& data); + void OnWrtPluginSyncMessage(const Wrt_Message_Data& data, + IPC::Message* reply); + void HandleWrtPluginMessage(Wrt_Message_Data* msg); protected: WebContents(v8::Isolate* isolate, content::WebContents* web_contents, diff --git a/atom/browser/atom_browser_client.cc b/atom/browser/atom_browser_client.cc index 77c3212..ebbd54a 100644 --- a/atom/browser/atom_browser_client.cc +++ b/atom/browser/atom_browser_client.cc @@ -215,7 +215,12 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches( static const char* const kCommonSwitchNames[] = { switches::kStandardSchemes, switches::kEnableSandbox, - switches::kSecureSchemes + switches::kSecureSchemes, + switches::kInjectedBundlePath, + switches::kTizenAppId, + switches::kWidgetScale, + switches::kWidgetTheme, + switches::kWidgetEncodedBundle }; command_line->CopySwitchesFrom( *base::CommandLine::ForCurrentProcess(), diff --git a/atom/common/api/api_messages.h b/atom/common/api/api_messages.h index ef945d9..cffc9df 100644 --- a/atom/common/api/api_messages.h +++ b/atom/common/api/api_messages.h @@ -9,6 +9,7 @@ #include "base/values.h" #include "content/public/common/common_param_traits.h" #include "ipc/ipc_message_macros.h" +#include "tizen/common/wrt_message_data.h" #include "ui/gfx/ipc/gfx_param_traits.h" // The message starter should be declared in ipc/ipc_message_start.h. Since @@ -21,6 +22,13 @@ IPC_STRUCT_TRAITS_BEGIN(atom::DraggableRegion) IPC_STRUCT_TRAITS_MEMBER(bounds) IPC_STRUCT_TRAITS_END() +IPC_STRUCT_TRAITS_BEGIN(Wrt_Message_Data) + IPC_STRUCT_TRAITS_MEMBER(type) + IPC_STRUCT_TRAITS_MEMBER(value) + IPC_STRUCT_TRAITS_MEMBER(id) + IPC_STRUCT_TRAITS_MEMBER(reference_id) +IPC_STRUCT_TRAITS_END() + IPC_MESSAGE_ROUTED2(AtomViewHostMsg_Message, base::string16 /* channel */, base::ListValue /* arguments */) @@ -49,3 +57,21 @@ IPC_SYNC_MESSAGE_ROUTED1_1(AtomViewHostMsg_SetTemporaryZoomLevel, // Sent by renderer to get the zoom level. IPC_SYNC_MESSAGE_ROUTED0_1(AtomViewHostMsg_GetZoomLevel, double /* result */) + +IPC_MESSAGE_ROUTED1(EwkHostMsg_WrtMessage, + Wrt_Message_Data /* data */) + +IPC_MESSAGE_CONTROL1(WrtMsg_SendWrtMessage, + Wrt_Message_Data /* data */) + +IPC_MESSAGE_CONTROL2(WrtMsg_ParseUrl, + int, // result: request_id + GURL) // result: url + +IPC_MESSAGE_CONTROL2(WrtMsg_ParseUrlResponse, + int, // result: request_id + GURL) // result: url + +IPC_SYNC_MESSAGE_ROUTED1_1(EwkHostMsg_WrtSyncMessage, + Wrt_Message_Data /* data */, + std::string /*result*/) diff --git a/atom/common/options_switches.cc b/atom/common/options_switches.cc index 2f1c036..a2b394e 100644 --- a/atom/common/options_switches.cc +++ b/atom/common/options_switches.cc @@ -182,6 +182,13 @@ const char kWidevineCdmPath[] = "widevine-cdm-path"; // Widevine CDM version. const char kWidevineCdmVersion[] = "widevine-cdm-version"; +const char kInjectedBundlePath[] = "injected-bundle-path"; +// Widget Info +const char kTizenAppId[] = "widget-id"; +const char kWidgetScale[] = "widget-scale"; +const char kWidgetTheme[] = "widget-theme"; +const char kWidgetEncodedBundle[] = "widget-encoded-bundle"; + } // namespace switches } // namespace atom diff --git a/atom/common/options_switches.h b/atom/common/options_switches.h index 69e7af0..6aecbf8 100644 --- a/atom/common/options_switches.h +++ b/atom/common/options_switches.h @@ -97,6 +97,11 @@ extern const char kNodeIntegrationInWorker[]; extern const char kWidevineCdmPath[]; extern const char kWidevineCdmVersion[]; +extern const char kInjectedBundlePath[]; +extern const char kTizenAppId[]; +extern const char kWidgetScale[]; +extern const char kWidgetTheme[]; +extern const char kWidgetEncodedBundle[]; } // namespace switches } // namespace atom diff --git a/atom/renderer/atom_renderer_client.cc b/atom/renderer/atom_renderer_client.cc index 1a9343e..77b5eb0 100644 --- a/atom/renderer/atom_renderer_client.cc +++ b/atom/renderer/atom_renderer_client.cc @@ -9,6 +9,11 @@ #if defined(USE_EFL) #include "atom/common/atom_command_line.h" +#include "base/strings/string_number_conversions.h" +#include "content/common/wrt/wrt_url_parse.h" +#include "content/public/renderer/render_thread.h" +#include "content/public/renderer/render_view.h" +#include "third_party/WebKit/public/web/WebView.h" #endif #include "atom_natives.h" // NOLINT: This file is generated with js2c @@ -53,6 +58,22 @@ const char** StringVectorToArgArray( } // namespace +class WrtUrlParseImpl : public content::WrtUrlParseBase { + public: + WrtUrlParseImpl(WrtWidget* wrt_widget) : wrt_widget_(wrt_widget) {} + GURL parseUrl(const GURL& old_url) const override { + if (!wrt_widget_->IsWidgetInfoSet()) + return old_url; + GURL new_url; + bool is_decrypted_file = false; + wrt_widget_->ParseUrl(old_url, new_url, is_decrypted_file); + return new_url; + } + + private: + WrtWidget* wrt_widget_; +}; + AtomRendererClient::AtomRendererClient() : node_integration_initialized_(false), node_bindings_(NodeBindings::Create(NodeBindings::RENDERER)), @@ -74,6 +95,24 @@ void AtomRendererClient::RenderThreadStarted() { base::CommandLine::StringVector argv = command_line->argv(); const char** c_argv = StringVectorToArgArray(argv); atom::AtomCommandLine::Init(argv.size(), c_argv); + std::string tizen_app_id = command_line->GetSwitchValueASCII( + "widget-id"); + + WrtWidget* wrt_widget = new WrtWidget; + if (wrt_widget == nullptr) { + return; + } + widget_.reset(wrt_widget); + content::RenderThread* thread = content::RenderThread::Get(); + thread->AddObserver(wrt_widget->GetObserver()); + wrt_url_parser_.reset(new WrtUrlParseImpl(wrt_widget)); + std::string theme = command_line->GetSwitchValueASCII("widget-theme"); + std::string encoded_bundle = command_line->GetSwitchValueASCII("widget-encoded-bundle"); + std::string scale = command_line->GetSwitchValueASCII("widget-scale"); + double scale_factor = 0; + base::StringToDouble(scale, &scale_factor); + wrt_widget->SetWidgetInfo(tizen_app_id, scale_factor, theme, + encoded_bundle); #endif OverrideNodeArrayBuffer(); RendererClientBase::RenderThreadStarted(); @@ -140,6 +179,13 @@ void AtomRendererClient::DidCreateScriptContext( // Give the node loop a run to make sure everything is ready. node_bindings_->RunMessageLoop(); } +#if defined(USE_EFL) + if (widget_) { + const content::RenderView* render_view = render_frame->GetRenderView(); + widget_->StartSession(context, render_view->GetRoutingID(), + render_frame->GetWebFrame()->document().baseURL().string().utf8().c_str()); + } +#endif } void AtomRendererClient::WillReleaseScriptContext( @@ -160,6 +206,10 @@ void AtomRendererClient::WillReleaseScriptContext( // Destroy the node environment. node::FreeEnvironment(env); atom_bindings_->EnvironmentDestroyed(env); +#if defined(USE_EFL) + if (widget_) + widget_->StopSession(context); +#endif } bool AtomRendererClient::ShouldFork(blink::WebLocalFrame* frame, diff --git a/atom/renderer/atom_renderer_client.h b/atom/renderer/atom_renderer_client.h index c9ffb29..0e623b5 100644 --- a/atom/renderer/atom_renderer_client.h +++ b/atom/renderer/atom_renderer_client.h @@ -9,11 +9,13 @@ #include #include "atom/renderer/renderer_client_base.h" +#include "tizen/wrt/wrtwidget.h" namespace atom { class AtomBindings; class NodeBindings; +class WrtUrlParseImpl; class AtomRendererClient : public RendererClientBase { public: @@ -41,7 +43,8 @@ class AtomRendererClient : public RendererClientBase { MANUAL_ENABLE_IFRAME, DISABLE, }; - + std::unique_ptr widget_; + std::unique_ptr wrt_url_parser_; // content::ContentRendererClient: void RenderThreadStarted() override; void RenderFrameCreated(content::RenderFrame*) override; diff --git a/packaging/electron-efl.spec b/packaging/electron-efl.spec index 7f48f8b..bafe82b 100755 --- a/packaging/electron-efl.spec +++ b/packaging/electron-efl.spec @@ -140,7 +140,8 @@ mkdir -p %{buildroot}%{extension_path} install -p -m 644 %{_out}/lib/libxwalk_extension_shared.so %{buildroot}%{_libdir} # xwalk_injected_bundle install -p -m 755 %{_out}/lib/libxwalk_injected_bundle.so %{buildroot}%{_libdir} - +# wrt chromium shared +install -p -m 644 %{_out}/lib/libchromium_wrt_shared.so %{buildroot}%{_libdir} %post # Owner account can't write /opt/usr/home/owner/data/org.tizen.electron-efl # which is created in 'install'. So we should copy resources in 'post'. @@ -173,3 +174,4 @@ rm -fr %{buildroot} %attr(644,root,root) %{_libdir}/libwrt_common.so %attr(644,root,root) %{_libdir}/libxwalk_extension_shared.so %attr(644,root,root) %{_libdir}/libxwalk_injected_bundle.so +%attr(644,root,root) %{_libdir}/libchromium_wrt_shared.so diff --git a/tizen/build/common.gypi b/tizen/build/common.gypi index 5f90ec5..8b70ac2 100644 --- a/tizen/build/common.gypi +++ b/tizen/build/common.gypi @@ -50,4 +50,4 @@ '-L./lib', ], }, -} \ No newline at end of file +} diff --git a/tizen/common/common.gyp b/tizen/common/common.gyp index dfc2494..be5a8ec 100644 --- a/tizen/common/common.gyp +++ b/tizen/common/common.gyp @@ -34,6 +34,8 @@ 'resource_manager.cc', 'platform_info.h', 'platform_info.cc', + 'wrt_message_data.h', + 'wrt_message_data.cc', ], 'cflags': [ '-fvisibility=default', @@ -49,6 +51,7 @@ 'capi-system-info', 'cynara-client', 'dlog', + 'elementary', 'uuid', 'libwebappenc', 'manifest-parser', diff --git a/tizen/common/wrt_message_data.cc b/tizen/common/wrt_message_data.cc new file mode 100644 index 0000000..7b60902 --- /dev/null +++ b/tizen/common/wrt_message_data.cc @@ -0,0 +1,38 @@ +#include "wrt_message_data.h" + +Wrt_Message_Data::Wrt_Message_Data() {} + +Wrt_Message_Data::~Wrt_Message_Data() {} + +Eina_Stringshare* Wrt_Message_Data::GetType() const { + return eina_stringshare_add(type.c_str()); +} + +void Wrt_Message_Data::SetType(const char* val) { + type = val; +} + +Eina_Stringshare* Wrt_Message_Data::GetValue() const { + return eina_stringshare_add(value.c_str()); +} + +void Wrt_Message_Data::SetValue(const char* val) { + value = val; +} + +Eina_Stringshare* Wrt_Message_Data::GetId() const { + return eina_stringshare_add(id.c_str()); +} + +void Wrt_Message_Data::SetId(const char* val) { + id = val; +} + +Eina_Stringshare* Wrt_Message_Data::GetReferenceId() const { + return eina_stringshare_add(reference_id.c_str()); +} + +void Wrt_Message_Data::SetReferenceId(const char* val) { + reference_id = val; +} + diff --git a/tizen/common/wrt_message_data.h b/tizen/common/wrt_message_data.h new file mode 100644 index 0000000..81e7213 --- /dev/null +++ b/tizen/common/wrt_message_data.h @@ -0,0 +1,26 @@ +#ifndef WRT_MESSAGE_DATA_H +#define WRT_MESSAGE_DATA_H + +#include +#include + +struct Wrt_Message_Data { + std::string type; + std::string value; + std::string id; + std::string reference_id; + + Wrt_Message_Data(); + ~Wrt_Message_Data(); + const Eina_Stringshare* GetType() const; + void SetType(const char* val); + const Eina_Stringshare* GetValue() const; + void SetValue(const char* val); + const Eina_Stringshare* GetId() const; + void SetId(const char* val); + const Eina_Stringshare* GetReferenceId() const; + void SetReferenceId(const char* val); +}; + +#endif // WRT_MESSAGE_DATA_H + diff --git a/tizen/extensions/common/constants.cc b/tizen/extensions/common/constants.cc index cfc9fa4..0010130 100644 --- a/tizen/extensions/common/constants.cc +++ b/tizen/extensions/common/constants.cc @@ -25,6 +25,6 @@ const char kMethodSendSyncMessage[] = "xwalk://SendSyncMessage"; const char kMethodPostMessage[] = "xwalk://PostMessage"; const char kMethodGetAPIScript[] = "xwalk://GetAPIScript"; const char kMethodPostMessageToJS[] = "xwalk://PostMessageToJS"; - +const char kMethodLoadUserExtensions[] = "xwalk://LoadUserExtensions"; } // namespace extensions diff --git a/tizen/extensions/common/constants.h b/tizen/extensions/common/constants.h index 588f09b..2da2e20 100644 --- a/tizen/extensions/common/constants.h +++ b/tizen/extensions/common/constants.h @@ -26,6 +26,7 @@ extern const char kMethodSendSyncMessage[]; extern const char kMethodPostMessage[]; extern const char kMethodGetAPIScript[]; extern const char kMethodPostMessageToJS[]; +extern const char kMethodLoadUserExtensions[]; } // namespace extensions diff --git a/tizen/extensions/common/xwalk_extension_instance.cc b/tizen/extensions/common/xwalk_extension_instance.cc index c86bb59..7c6ffba 100644 --- a/tizen/extensions/common/xwalk_extension_instance.cc +++ b/tizen/extensions/common/xwalk_extension_instance.cc @@ -5,6 +5,7 @@ #include "extensions/common/xwalk_extension_instance.h" +#include "common/logger.h" #include "extensions/common/xwalk_extension_adapter.h" #include "extensions/public/XW_Extension_SyncMessage.h" diff --git a/tizen/extensions/common/xwalk_extension_server.cc b/tizen/extensions/common/xwalk_extension_server.cc index fc50396..3cf0acd 100644 --- a/tizen/extensions/common/xwalk_extension_server.cc +++ b/tizen/extensions/common/xwalk_extension_server.cc @@ -8,11 +8,14 @@ #include +#include "atom/common/api/api_messages.h" #include "common/logger.h" #include "common/profiler.h" #include "common/string_utils.h" +#include "content/public/browser/render_process_host.h" #include "extensions/common/constants.h" #include "extensions/common/xwalk_extension_manager.h" +#include "wrt/wrt_widget_host.h" namespace extensions { @@ -29,10 +32,6 @@ XWalkExtensionServer::XWalkExtensionServer() { XWalkExtensionServer::~XWalkExtensionServer() { } -void XWalkExtensionServer::SetupIPC(Ewk_Context* ewk_context) { - ewk_context_ = ewk_context; -} - void XWalkExtensionServer::Preload() { manager_.PreloadExtensions(); } @@ -76,7 +75,6 @@ std::string XWalkExtensionServer::GetAPIScript( std::string XWalkExtensionServer::CreateInstance( const std::string& extension_name) { std::string instance_id; - auto extensions = manager_.extensions(); auto it = extensions.find(extension_name); if (it != extensions.end()) { @@ -85,14 +83,12 @@ std::string XWalkExtensionServer::CreateInstance( instance_id = common::utils::GenerateUUID(); instance->SetPostMessageCallback( [this, instance_id](const std::string& msg) { - Ewk_IPC_Wrt_Message_Data* ans = ewk_ipc_wrt_message_data_new(); - ewk_ipc_wrt_message_data_type_set(ans, kMethodPostMessageToJS); - ewk_ipc_wrt_message_data_id_set(ans, instance_id.c_str()); - ewk_ipc_wrt_message_data_value_set(ans, msg.c_str()); - if (!ewk_ipc_wrt_message_send(ewk_context_, ans)) { - LOGGER(ERROR) << "Failed to send response"; - } - ewk_ipc_wrt_message_data_del(ans); + Wrt_Message_Data* ans = new Wrt_Message_Data(); + ans->SetType(kMethodPostMessageToJS); + ans->SetId(instance_id.c_str()); + ans->SetValue(msg.c_str()); + WrtWidgetHost::Get()->SendWrtMessage(*ans); + delete ans; }); instances_[instance_id] = instance; @@ -103,21 +99,16 @@ std::string XWalkExtensionServer::CreateInstance( } else { LOGGER(ERROR) << "No such extension '" << extension_name << "'"; } + LOGGER(ERROR) << instance_id; return instance_id; } -void XWalkExtensionServer::HandleIPCMessage(Ewk_IPC_Wrt_Message_Data* data) { +void XWalkExtensionServer::HandleIPCMessage(Wrt_Message_Data* data) { if (!data) { LOGGER(ERROR) << "Invalid parameter. data is NULL."; return; } - - if (!ewk_context_) { - LOGGER(WARN) << "IPC is not ready yet."; - return; - } - - Eina_Stringshare* msg_type = ewk_ipc_wrt_message_data_type_get(data); + Eina_Stringshare* msg_type = data->GetType(); #define TYPE_IS(x) (!strcmp(msg_type, x)) if (TYPE_IS(kMethodGetExtensions)) { @@ -138,27 +129,27 @@ void XWalkExtensionServer::HandleIPCMessage(Ewk_IPC_Wrt_Message_Data* data) { #undef TYPE_IS } -void XWalkExtensionServer::HandleGetExtensions(Ewk_IPC_Wrt_Message_Data* data) { +void XWalkExtensionServer::HandleGetExtensions(Wrt_Message_Data* data) { Json::Value reply = GetExtensions(); Json::FastWriter writer; std::string reply_str = writer.write(reply); - ewk_ipc_wrt_message_data_value_set(data, reply_str.c_str()); + data->SetValue(reply_str.c_str()); } void XWalkExtensionServer::HandleCreateInstance( - Ewk_IPC_Wrt_Message_Data* data) { - Eina_Stringshare* extension_name = ewk_ipc_wrt_message_data_value_get(data); + Wrt_Message_Data* data) { + Eina_Stringshare* extension_name = data->GetValue(); std::string instance_id = CreateInstance(extension_name); - ewk_ipc_wrt_message_data_value_set(data, instance_id.c_str()); + data->SetValue(instance_id.c_str()); eina_stringshare_del(extension_name); } void XWalkExtensionServer::HandleDestroyInstance( - Ewk_IPC_Wrt_Message_Data* data) { - Eina_Stringshare* instance_id = ewk_ipc_wrt_message_data_id_get(data); + Wrt_Message_Data* data) { + Eina_Stringshare* instance_id = data->GetId(); auto it = instances_.find(instance_id); if (it != instances_.end()) { @@ -173,12 +164,12 @@ void XWalkExtensionServer::HandleDestroyInstance( } void XWalkExtensionServer::HandlePostMessageToNative( - Ewk_IPC_Wrt_Message_Data* data) { - Eina_Stringshare* instance_id = ewk_ipc_wrt_message_data_id_get(data); + Wrt_Message_Data* data) { + Eina_Stringshare* instance_id = data->GetId(); auto it = instances_.find(instance_id); if (it != instances_.end()) { - Eina_Stringshare* msg = ewk_ipc_wrt_message_data_value_get(data); + Eina_Stringshare* msg = data->GetValue(); XWalkExtensionInstance* instance = it->second; instance->HandleMessage(msg); eina_stringshare_del(msg); @@ -190,19 +181,19 @@ void XWalkExtensionServer::HandlePostMessageToNative( } void XWalkExtensionServer::HandleSendSyncMessageToNative( - Ewk_IPC_Wrt_Message_Data* data) { - Eina_Stringshare* instance_id = ewk_ipc_wrt_message_data_id_get(data); + Wrt_Message_Data* data) { + Eina_Stringshare* instance_id = data->GetId(); auto it = instances_.find(instance_id); if (it != instances_.end()) { - Eina_Stringshare* msg = ewk_ipc_wrt_message_data_value_get(data); + Eina_Stringshare* msg = data->GetValue(); XWalkExtensionInstance* instance = it->second; std::string reply; instance->SetSendSyncReplyCallback([&reply](const std::string& msg) { reply = msg; }); instance->HandleSyncMessage(msg); - ewk_ipc_wrt_message_data_value_set(data, reply.c_str()); + data->SetValue(reply.c_str()); eina_stringshare_del(msg); } else { LOGGER(ERROR) << "No such instance '" << instance_id << "'"; @@ -212,12 +203,12 @@ void XWalkExtensionServer::HandleSendSyncMessageToNative( } void XWalkExtensionServer::HandleGetAPIScript( - Ewk_IPC_Wrt_Message_Data* data) { - Eina_Stringshare* extension_name = ewk_ipc_wrt_message_data_value_get(data); + Wrt_Message_Data* data) { + Eina_Stringshare* extension_name = data->GetValue(); std::string api = GetAPIScript(extension_name); - ewk_ipc_wrt_message_data_value_set(data, api.c_str()); + data->SetValue(api.c_str()); eina_stringshare_del(extension_name); } diff --git a/tizen/extensions/common/xwalk_extension_server.h b/tizen/extensions/common/xwalk_extension_server.h index 3cd67bf..7a45752 100644 --- a/tizen/extensions/common/xwalk_extension_server.h +++ b/tizen/extensions/common/xwalk_extension_server.h @@ -5,13 +5,11 @@ #ifndef XWALK_EXTENSIONS_XWALK_EXTENSION_SERVER_H_ #define XWALK_EXTENSIONS_XWALK_EXTENSION_SERVER_H_ -#include -#include #include #include #include - +#include "common/wrt_message_data.h" #include "extensions/common/xwalk_extension_manager.h" #include "extensions/common/xwalk_extension_instance.h" @@ -21,13 +19,12 @@ class XWalkExtensionServer { public: static XWalkExtensionServer* GetInstance(); - void SetupIPC(Ewk_Context* ewk_context); void Preload(); Json::Value GetExtensions(); std::string GetAPIScript(const std::string& extension_name); std::string CreateInstance(const std::string& extension_name); - void HandleIPCMessage(Ewk_IPC_Wrt_Message_Data* data); + void HandleIPCMessage(Wrt_Message_Data* data); void Shutdown(); void LoadUserExtensions(const std::string app_path); @@ -36,17 +33,15 @@ class XWalkExtensionServer { XWalkExtensionServer(); virtual ~XWalkExtensionServer(); - void HandleGetExtensions(Ewk_IPC_Wrt_Message_Data* data); - void HandleCreateInstance(Ewk_IPC_Wrt_Message_Data* data); - void HandleDestroyInstance(Ewk_IPC_Wrt_Message_Data* data); - void HandlePostMessageToNative(Ewk_IPC_Wrt_Message_Data* data); - void HandleSendSyncMessageToNative(Ewk_IPC_Wrt_Message_Data* data); - void HandleGetAPIScript(Ewk_IPC_Wrt_Message_Data* data); + void HandleGetExtensions(Wrt_Message_Data* data); + void HandleCreateInstance(Wrt_Message_Data* data); + void HandleDestroyInstance(Wrt_Message_Data* data); + void HandlePostMessageToNative(Wrt_Message_Data* data); + void HandleSendSyncMessageToNative(Wrt_Message_Data* data); + void HandleGetAPIScript(Wrt_Message_Data* data); typedef std::map InstanceMap; - Ewk_Context* ewk_context_; - XWalkExtensionManager manager_; InstanceMap instances_; diff --git a/tizen/extensions/extensions.gyp b/tizen/extensions/extensions.gyp index 165271b..163361d 100644 --- a/tizen/extensions/extensions.gyp +++ b/tizen/extensions/extensions.gyp @@ -45,6 +45,15 @@ 'elementary', ], }, + 'include_dirs': [ + '.', + '../..', + '<(libchromiumcontent_src_dir)', + '<(SHARED_INTERMEDIATE_DIR)', + '<(libchromiumcontent_src_dir)/gen', + '<(libchromiumcontent_src_dir)/third_party/skia/include/config', + '<(libchromiumcontent_src_dir)/third_party/skia/include/core', + ], 'direct_dependent_settings': { # 'libraries': [ # '-lxwalk_extension_shared', diff --git a/tizen/extensions/renderer/runtime_ipc_client.cc b/tizen/extensions/renderer/runtime_ipc_client.cc index 6b96828..f64676b 100644 --- a/tizen/extensions/renderer/runtime_ipc_client.cc +++ b/tizen/extensions/renderer/runtime_ipc_client.cc @@ -13,13 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include #include "extensions/renderer/runtime_ipc_client.h" #include "extensions/renderer/xwalk_extension_renderer_controller.h" +#include "atom/common/api/api_messages.h" #include "common/logger.h" #include "common/profiler.h" #include "common/string_utils.h" +#include "content/public/renderer/render_view.h" namespace extensions { @@ -112,17 +115,16 @@ void RuntimeIPCClient::SendMessage(v8::Handle context, return; } - Ewk_IPC_Wrt_Message_Data* msg = ewk_ipc_wrt_message_data_new(); - ewk_ipc_wrt_message_data_type_set(msg, type.c_str()); - ewk_ipc_wrt_message_data_id_set(msg, id.c_str()); - ewk_ipc_wrt_message_data_reference_id_set(msg, ref_id.c_str()); - ewk_ipc_wrt_message_data_value_set(msg, value.c_str()); - - if (!ewk_ipc_plugins_message_send(routing_id, msg)) { - LOGGER(ERROR) << "Failed to send message to runtime using ewk_ipc."; - } - - ewk_ipc_wrt_message_data_del(msg); + Wrt_Message_Data* msg = new Wrt_Message_Data(); + msg->SetType(type.c_str()); + msg->SetId(id.c_str()); + msg->SetValue(value.c_str()); + msg->SetReferenceId(ref_id.c_str()); + content::RenderView* render_view = + content::RenderView::FromRoutingID(routing_id); + render_view->Send( + new EwkHostMsg_WrtMessage(render_view->GetRoutingID(), *msg)); + delete msg; } std::string RuntimeIPCClient::SendSyncMessage(v8::Handle context, @@ -149,23 +151,20 @@ std::string RuntimeIPCClient::SendSyncMessage(v8::Handle context, return std::string(); } - Ewk_IPC_Wrt_Message_Data* msg = ewk_ipc_wrt_message_data_new(); - ewk_ipc_wrt_message_data_type_set(msg, type.c_str()); - ewk_ipc_wrt_message_data_id_set(msg, id.c_str()); - ewk_ipc_wrt_message_data_reference_id_set(msg, ref_id.c_str()); - ewk_ipc_wrt_message_data_value_set(msg, value.c_str()); - - if (!ewk_ipc_plugins_sync_message_send(routing_id, msg)) { - LOGGER(ERROR) << "Failed to send message to runtime using ewk_ipc."; - ewk_ipc_wrt_message_data_del(msg); - return std::string(); - } - - Eina_Stringshare* msg_value = ewk_ipc_wrt_message_data_value_get(msg); + Wrt_Message_Data* msg = new Wrt_Message_Data(); + msg->SetType(type.c_str()); + msg->SetId(id.c_str()); + msg->SetValue(value.c_str()); + msg->SetReferenceId(ref_id.c_str()); + content::RenderView* render_view = + content::RenderView::FromRoutingID(routing_id); + render_view->Send( + new EwkHostMsg_WrtSyncMessage(render_view->GetRoutingID(), *msg, &msg->value)); + Eina_Stringshare* msg_value = msg->GetValue(); std::string result(msg_value); eina_stringshare_del(msg_value); - ewk_ipc_wrt_message_data_del(msg); + delete msg; return result; } @@ -182,30 +181,27 @@ void RuntimeIPCClient::SendAsyncMessage(v8::Handle context, std::string msg_id = common::utils::GenerateUUID(); - Ewk_IPC_Wrt_Message_Data* msg = ewk_ipc_wrt_message_data_new(); - ewk_ipc_wrt_message_data_id_set(msg, msg_id.c_str()); - ewk_ipc_wrt_message_data_type_set(msg, type.c_str()); - ewk_ipc_wrt_message_data_value_set(msg, value.c_str()); - - if (!ewk_ipc_plugins_message_send(routing_id, msg)) { - LOGGER(ERROR) << "Failed to send message to runtime using ewk_ipc."; - ewk_ipc_wrt_message_data_del(msg); - return; - } - + Wrt_Message_Data* msg = new Wrt_Message_Data(); + msg->SetType(type.c_str()); + msg->SetId(msg_id.c_str()); + msg->SetValue(value.c_str()); + content::RenderView* render_view = + content::RenderView::FromRoutingID(routing_id); + render_view->Send( + new EwkHostMsg_WrtMessage(render_view->GetRoutingID(), *msg)); callbacks_[msg_id] = callback; - ewk_ipc_wrt_message_data_del(msg); + delete msg; } void RuntimeIPCClient::HandleMessageFromRuntime( - const Ewk_IPC_Wrt_Message_Data* msg) { + const Wrt_Message_Data* msg) { if (msg == NULL) { LOGGER(ERROR) << "received message is NULL"; return; } - Eina_Stringshare* msg_refid = ewk_ipc_wrt_message_data_reference_id_get(msg); + Eina_Stringshare* msg_refid = msg->GetReferenceId(); if (msg_refid == NULL || !strcmp(msg_refid, "")) { if (msg_refid) eina_stringshare_del(msg_refid); @@ -220,8 +216,8 @@ void RuntimeIPCClient::HandleMessageFromRuntime( return; } - Eina_Stringshare* msg_type = ewk_ipc_wrt_message_data_type_get(msg); - Eina_Stringshare* msg_value = ewk_ipc_wrt_message_data_value_get(msg); + Eina_Stringshare* msg_type = msg->GetType(); + Eina_Stringshare* msg_value = msg->GetValue(); ReplyCallback func = it->second; if (func) { diff --git a/tizen/extensions/renderer/runtime_ipc_client.h b/tizen/extensions/renderer/runtime_ipc_client.h index 7f94fb3..8f40d16 100644 --- a/tizen/extensions/renderer/runtime_ipc_client.h +++ b/tizen/extensions/renderer/runtime_ipc_client.h @@ -18,12 +18,11 @@ #define XWALK_EXTENSIONS_RENDERER_RUNTIME_IPC_CLIENT_H_ #include -#include -#include #include #include #include +#include "common/wrt_message_data.h" namespace extensions { @@ -83,7 +82,7 @@ class RuntimeIPCClient { const std::string& type, const std::string& value, ReplyCallback callback); - void HandleMessageFromRuntime(const Ewk_IPC_Wrt_Message_Data* msg); + void HandleMessageFromRuntime(const Wrt_Message_Data* msg); int GetRoutingId(v8::Handle context); diff --git a/tizen/extensions/renderer/xwalk_extension_client.cc b/tizen/extensions/renderer/xwalk_extension_client.cc index 383473f..d113269 100644 --- a/tizen/extensions/renderer/xwalk_extension_client.cc +++ b/tizen/extensions/renderer/xwalk_extension_client.cc @@ -6,15 +6,17 @@ #include "extensions/renderer/xwalk_extension_client.h" #include +#include #include #include -#include #include +#include "base/command_line.h" #include "common/logger.h" #include "common/profiler.h" #include "common/string_utils.h" +#include "content/public/common/content_switches.h" #include "extensions/common/constants.h" #include "extensions/common/xwalk_extension_server.h" #include "extensions/renderer/runtime_ipc_client.h" @@ -40,14 +42,22 @@ XWalkExtensionClient::~XWalkExtensionClient() { extension_apis_.clear(); } -void XWalkExtensionClient::Initialize() { +void XWalkExtensionClient::Initialize(v8::Handle context) { SCOPE_PROFILE(); if (!extension_apis_.empty()) { return; } - - XWalkExtensionServer* server = XWalkExtensionServer::GetInstance(); - Json::Value reply = server->GetExtensions(); + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + Json::Value reply; + if (command_line->HasSwitch(switches::kSingleProcess)) { + XWalkExtensionServer* server = XWalkExtensionServer::GetInstance(); + reply = server->GetExtensions(); + } else { + RuntimeIPCClient* ipc = RuntimeIPCClient::GetInstance(); + std::string extension_info =ipc->SendSyncMessage(context, kMethodGetExtensions, "", ""); + Json::Reader reader; + reader.parse(extension_info, reply, false); + } for (auto it = reply.begin(); it != reply.end(); ++it) { ExtensionCodePoints* codepoint = new ExtensionCodePoints; Json::Value entry_points = (*it)["entry_points"]; @@ -62,13 +72,20 @@ void XWalkExtensionClient::Initialize() { std::string XWalkExtensionClient::CreateInstance( v8::Handle context, const std::string& extension_name, InstanceHandler* handler) { - void* ret = ecore_main_loop_thread_safe_call_sync( - CreateInstanceInMainloop, - static_cast(const_cast(extension_name.data()))); - std::string* sp = static_cast(ret); - std::string instance_id = *sp; - delete sp; - + std::string instance_id; + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kSingleProcess)) { + void* ret = ecore_main_loop_thread_safe_call_sync( + CreateInstanceInMainloop, + static_cast(const_cast(extension_name.data()))); + std::string* sp = static_cast(ret); + instance_id = *sp; + delete sp; + } else { + RuntimeIPCClient* ipc = RuntimeIPCClient::GetInstance(); + instance_id =ipc->SendSyncMessage( + context, kMethodCreateInstance, "", extension_name.data()); + } handlers_[instance_id] = handler; return instance_id; } @@ -105,8 +122,16 @@ std::string XWalkExtensionClient::SendSyncMessageToNative( std::string XWalkExtensionClient::GetAPIScript( v8::Handle context, const std::string& extension_name) { - XWalkExtensionServer* server = XWalkExtensionServer::GetInstance(); - return server->GetAPIScript(extension_name); + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kSingleProcess)) { + XWalkExtensionServer* server = XWalkExtensionServer::GetInstance(); + return server->GetAPIScript(extension_name); + } else { + RuntimeIPCClient* ipc = RuntimeIPCClient::GetInstance(); + std::string reply = ipc->SendSyncMessage( + context, kMethodGetAPIScript, "", extension_name.data()); + return reply; + } } void XWalkExtensionClient::OnReceivedIPCMessage( diff --git a/tizen/extensions/renderer/xwalk_extension_client.h b/tizen/extensions/renderer/xwalk_extension_client.h index 5b98ee9..7cb0c11 100644 --- a/tizen/extensions/renderer/xwalk_extension_client.h +++ b/tizen/extensions/renderer/xwalk_extension_client.h @@ -28,7 +28,7 @@ class XWalkExtensionClient { XWalkExtensionClient(); virtual ~XWalkExtensionClient(); - void Initialize(); + void Initialize(v8::Handle context); std::string CreateInstance(v8::Handle context, const std::string& extension_name, diff --git a/tizen/extensions/renderer/xwalk_extension_renderer_controller.cc b/tizen/extensions/renderer/xwalk_extension_renderer_controller.cc index 6c8dd11..982ab23 100644 --- a/tizen/extensions/renderer/xwalk_extension_renderer_controller.cc +++ b/tizen/extensions/renderer/xwalk_extension_renderer_controller.cc @@ -80,7 +80,7 @@ void XWalkExtensionRendererController::DidCreateScriptContext( "objecttools", std::unique_ptr(new ObjectToolsModule)); - extensions_client_->Initialize(); + extensions_client_->Initialize(context); CreateExtensionModules(extensions_client_.get(), module_system); module_system->Initialize(); @@ -100,14 +100,14 @@ void XWalkExtensionRendererController::WillReleaseScriptContext( } void XWalkExtensionRendererController::OnReceivedIPCMessage( - const Ewk_IPC_Wrt_Message_Data* data) { + const Wrt_Message_Data* data) { - Eina_Stringshare* type = ewk_ipc_wrt_message_data_type_get(data); + Eina_Stringshare* type = data->GetType(); #define TYPE_BEGIN(x) (!strncmp(type, x, strlen(x))) if (TYPE_BEGIN("xwalk://")) { - Eina_Stringshare* id = ewk_ipc_wrt_message_data_id_get(data); - Eina_Stringshare* msg = ewk_ipc_wrt_message_data_value_get(data); + Eina_Stringshare* id = data->GetId(); + Eina_Stringshare* msg = data->GetValue(); extensions_client_->OnReceivedIPCMessage(id, msg); eina_stringshare_del(id); eina_stringshare_del(msg); @@ -121,7 +121,7 @@ void XWalkExtensionRendererController::OnReceivedIPCMessage( } void XWalkExtensionRendererController::InitializeExtensionClient() { - extensions_client_->Initialize(); +// extensions_client_->Initialize(); } void XWalkExtensionRendererController::LoadUserExtensions( diff --git a/tizen/extensions/renderer/xwalk_extension_renderer_controller.h b/tizen/extensions/renderer/xwalk_extension_renderer_controller.h index 95e3145..8fe5ff4 100644 --- a/tizen/extensions/renderer/xwalk_extension_renderer_controller.h +++ b/tizen/extensions/renderer/xwalk_extension_renderer_controller.h @@ -6,12 +6,11 @@ #ifndef XWALK_EXTENSIONS_RENDERER_XWALK_EXTENSION_RENDERER_CONTROLLER_H_ #define XWALK_EXTENSIONS_RENDERER_XWALK_EXTENSION_RENDERER_CONTROLLER_H_ -#include -#include #include #include #include +#include "common/wrt_message_data.h" namespace extensions { @@ -25,7 +24,7 @@ class XWalkExtensionRendererController { void DidCreateScriptContext(v8::Handle context); void WillReleaseScriptContext(v8::Handle context); - void OnReceivedIPCMessage(const Ewk_IPC_Wrt_Message_Data* data); + void OnReceivedIPCMessage(const Wrt_Message_Data* data); void InitializeExtensionClient(); void LoadUserExtensions(const std::string app_path); diff --git a/tizen/renderer/injected_bundle.cc b/tizen/renderer/injected_bundle.cc index a030975..cce38e6 100644 --- a/tizen/renderer/injected_bundle.cc +++ b/tizen/renderer/injected_bundle.cc @@ -15,8 +15,6 @@ */ #include -#include -#include #include #include #include @@ -30,6 +28,7 @@ #include "common/profiler.h" #include "common/resource_manager.h" #include "common/string_utils.h" +#include "common/wrt_message_data.h" #include "extensions/renderer/runtime_ipc_client.h" #include "extensions/renderer/widget_module.h" #include "extensions/renderer/xwalk_extension_renderer_controller.h" @@ -173,7 +172,7 @@ extern "C" void DynamicDatabaseAttach(int /*attach*/) { // LOGGER(DEBUG) << "InjectedBundle::DynamicDatabaseAttach !!"; } -extern "C" void DynamicOnIPCMessage(const Ewk_IPC_Wrt_Message_Data& data) { +extern "C" void DynamicOnIPCMessage(const Wrt_Message_Data& data) { SCOPE_PROFILE(); extensions::XWalkExtensionRendererController& controller = extensions::XWalkExtensionRendererController::GetInstance(); diff --git a/tizen/wrt/chromium_wrt.gyp b/tizen/wrt/chromium_wrt.gyp new file mode 100644 index 0000000..4680117 --- /dev/null +++ b/tizen/wrt/chromium_wrt.gyp @@ -0,0 +1,55 @@ +{ + 'includes':[ + '../build/common.gypi', + ], + 'targets': [ + { + 'target_name': 'chromium_wrt_shared', + 'type': 'shared_library', + 'sources': [ + "dynamicplugin.cc", + "dynamicplugin.h", + "v8widget.cc", + "v8widget.h", + "wrtwidget.cc", + "wrtwidget.h", + "wrt_dynamicplugin.cc", + "wrt_dynamicplugin.h", + "wrt_file_protocol_handler.cc", + "wrt_file_protocol_handler.h", + "wrt_widget_host.cc", + "wrt_widget_host.h", + ], + 'cflags': [ + '-fvisibility=default', + ], + 'variables': { + 'packages': [ + 'chromium-efl', + 'elementary', + ], + }, + 'include_dirs': [ + '.', + '../', + '../..', + '../tizen', + '<(libchromiumcontent_src_dir)', + '<(SHARED_INTERMEDIATE_DIR)', + '<(libchromiumcontent_src_dir)/gen', + '<(libchromiumcontent_src_dir)/third_party/skia/include/config', + '<(libchromiumcontent_src_dir)/third_party/skia/include/core', + ], + 'direct_dependent_settings': { +# 'libraries': [ +# '-lchromium_wrt_shared', +# ], + 'variables': { + 'packages': [ + 'jsoncpp', + ], + }, + }, + }, # end of target 'xwalk_extension_static' + ], # end of targets +} diff --git a/tizen/wrt/dynamicplugin.cc b/tizen/wrt/dynamicplugin.cc new file mode 100644 index 0000000..9512d3e --- /dev/null +++ b/tizen/wrt/dynamicplugin.cc @@ -0,0 +1,89 @@ +// Copyright 2014 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "dynamicplugin.h" + +#include + +#include "base/command_line.h" +#include "base/logging.h" + +namespace { +const char* const VERSION_FUNCTION = "DynamicPluginVersion"; +const char* const START_SESSION_FUNCTION = "DynamicPluginStartSession"; +const char* const STOP_SESSION_FUNCTION = "DynamicPluginStopSession"; +} + +DynamicPlugin::DynamicPlugin() + : m_handle_(0), + m_version_(0), + m_versionFunction_(0), + m_startSession_(0), + m_stopSession_(0) { + const base::CommandLine& commandLine = + *base::CommandLine::ForCurrentProcess(); + std::string injectedBundlePath = + commandLine.GetSwitchValueASCII("injected-bundle-path"); + if (injectedBundlePath.empty()) { + return; + } + m_handle_ = dlopen(injectedBundlePath.c_str(), RTLD_LAZY); + if (!m_handle_) { + LOG(ERROR) << "No handle to " << injectedBundlePath.c_str() << " " + << dlerror() << "\n"; + return; + } + + *reinterpret_cast(&m_versionFunction_) = + dlsym(m_handle_, VERSION_FUNCTION); + if (!m_versionFunction_) { + LOG(ERROR) << "No " << VERSION_FUNCTION << " symbol found!\n"; + } else { + m_version_ = m_versionFunction_(); + if (m_version_ != 0 && m_version_ != 1) { + LOG(ERROR) << "Unknown plugin version: " << m_version_ << "!\n"; + return; + } + } + + *reinterpret_cast(&m_startSession_) = + dlsym(m_handle_, START_SESSION_FUNCTION); + if (!m_startSession_) { + LOG(ERROR) << "No " << START_SESSION_FUNCTION << " symbol found!\n"; + } + *reinterpret_cast(&m_stopSession_) = + dlsym(m_handle_, STOP_SESSION_FUNCTION); + if (!m_stopSession_) { + LOG(ERROR) << "No " << STOP_SESSION_FUNCTION << " symbol found!\n"; + } +} + +void DynamicPlugin::startSession(const char* sessionId, + v8::Handle context, + int routingHandle, + const void* sessionBlob) { + if (!m_startSession_) + return; + + m_startSession_(sessionId, context, routingHandle, sessionBlob); +} + +void DynamicPlugin::stopSession(const char* sessionId, + v8::Handle context) { + if (!m_stopSession_) + return; + + m_stopSession_(sessionId, context); +} + +DynamicPlugin::~DynamicPlugin() { + if (m_handle_) + dlclose(m_handle_); +} + +DynamicPlugin& DynamicPlugin::instance() { + static DynamicPlugin dynamicPlugin; + return dynamicPlugin; +} + diff --git a/tizen/wrt/dynamicplugin.h b/tizen/wrt/dynamicplugin.h new file mode 100644 index 0000000..46a1963 --- /dev/null +++ b/tizen/wrt/dynamicplugin.h @@ -0,0 +1,46 @@ +// Copyright 2014, 2016 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WRT_DYNAMICPLUGIN_H_ +#define WRT_DYNAMICPLUGIN_H_ + +#include +#include "base/macros.h" +#include "v8/include/v8.h" + +typedef unsigned int (*versionFunction)(void); + +typedef void (*startSessionFunction)(const char* sessionId, + v8::Handle context, + int routingHandle, + const void* sessionBlob); + +typedef void (*stopSessionFunction)(const char* sessionId, + v8::Handle context); + +class DynamicPlugin { + public: + void startSession(const char* sessionId, + v8::Handle context, + int routingHandle, + const void* sessionBlob); + void stopSession(const char* sessionId, v8::Handle context); + + virtual ~DynamicPlugin(); + + static DynamicPlugin& instance(); + + protected: + DynamicPlugin(); + DynamicPlugin(const DynamicPlugin&); + DynamicPlugin& operator=(const DynamicPlugin&); + + void* m_handle_; + unsigned int m_version_; + versionFunction m_versionFunction_; + startSessionFunction m_startSession_; + stopSessionFunction m_stopSession_; +}; + +#endif // WRT_DYNAMICPLUGIN_H_ diff --git a/tizen/wrt/v8widget.cc b/tizen/wrt/v8widget.cc new file mode 100644 index 0000000..ef721b8 --- /dev/null +++ b/tizen/wrt/v8widget.cc @@ -0,0 +1,92 @@ +// Copyright 2014, 2015 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "v8widget.h" + +#include "base/logging.h" +#include "dynamicplugin.h" +#if defined(OS_TIZEN_TV_PRODUCT) +#include "wrt/hbbtv_dynamicplugin.h" +#endif +#include "wrt_dynamicplugin.h" + +V8Widget::V8Widget(Type type) : type_(type) {} + +V8Widget::~V8Widget() {} + +void V8Widget::SetId(const std::string& id) { + id_ = id; +} + +V8Widget::Type V8Widget::GetType() const { + return type_; +} + +bool V8Widget::ParseUrl(const GURL& url, + GURL& new_url, + bool& is_decrypted_file) { + if (!id_.empty()) { + std::string old_url = url.possibly_invalid_spec(); + std::string s_new_url; + if (type_ == V8Widget::Type::WRT) + WrtDynamicPlugin::instance().parseURL(&old_url, &s_new_url, id_.c_str(), + &is_decrypted_file); + +#if defined(OS_TIZEN_TV_PRODUCT) + if (type_ == V8Widget::Type::HBBTV) + HbbTVDynamicPlugin::instance().parseURL(&old_url, &s_new_url, id_.c_str(), + &is_decrypted_file); +#endif + + if (!s_new_url.empty()) { + new_url = GURL(s_new_url); + return true; + } + } + return false; +} + +#if defined(OS_TIZEN_TV_PRODUCT) +bool V8Widget::GetFileDecryptedDataBuffer(const GURL& url, + std::vector* data) { + if (!id_.empty()) { + std::string str_url = url.possibly_invalid_spec(); + if (type_ == V8Widget::Type::WRT) + return WrtDynamicPlugin::instance().getFileDecryptedDataBuffer(&str_url, + data); + + if (type_ == V8Widget::Type::HBBTV) + return HbbTVDynamicPlugin::instance().getFileDecryptedDataBuffer(&str_url, + data); + } + return false; +} +#endif + +void V8Widget::StopSession(v8::Handle context) { + if (!id_.empty() && !context.IsEmpty()) { + if (type_ == V8Widget::Type::WRT) + WrtDynamicPlugin::instance().stopSession(id_.c_str(), context); + +#if defined(OS_TIZEN_TV_PRODUCT) + if (type_ == V8Widget::Type::HBBTV) + HbbTVDynamicPlugin::instance().stopSession(id_.c_str(), context); +#endif + } +} + +void V8Widget::StartSession(v8::Handle context, + int routingHandle, + const void* sessionBlob) { + if (!id_.empty() && !context.IsEmpty()) { + if (type_ == V8Widget::Type::WRT) + NOTREACHED(); + +#if defined(OS_TIZEN_TV_PRODUCT) + if (type_ == V8Widget::Type::HBBTV) + HbbTVDynamicPlugin::instance().startSession(id_.c_str(), context, + routingHandle, sessionBlob); +#endif + } +} diff --git a/tizen/wrt/v8widget.h b/tizen/wrt/v8widget.h new file mode 100644 index 0000000..2b843a3 --- /dev/null +++ b/tizen/wrt/v8widget.h @@ -0,0 +1,41 @@ +// Copyright 2014, 2015 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WRT_V8WIDGET_H_ +#define WRT_V8WIDGET_H_ + +#include + +#include "content/public/renderer/render_thread_observer.h" +#include "url/gurl.h" +#include "v8/include/v8.h" + +// Have to be created on the RenderThread. +class V8Widget { + public: + enum class Type { HBBTV, WRT }; + + explicit V8Widget(Type type); + virtual ~V8Widget() = 0; + + void SetId(const std::string& id); + Type GetType() const; + + virtual void StartSession(v8::Handle, + int routingHandle, + const void* sessionBlob); + + virtual void StopSession(v8::Handle); + + bool ParseUrl(const GURL& url, GURL& new_url, bool& is_decrypted_file); + +#if defined(OS_TIZEN_TV_PRODUCT) + bool GetFileDecryptedDataBuffer(const GURL& url, std::vector* data); +#endif + protected: + std::string id_; + Type type_; +}; + +#endif // WRT_V8WIDGET_H_ diff --git a/tizen/wrt/wrt_dynamicplugin.cc b/tizen/wrt/wrt_dynamicplugin.cc new file mode 100644 index 0000000..68cf087 --- /dev/null +++ b/tizen/wrt/wrt_dynamicplugin.cc @@ -0,0 +1,164 @@ +// Copyright 2014 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "wrt_dynamicplugin.h" + +#include + +#include "base/command_line.h" +#include "base/logging.h" + +namespace { +const char* const URL_PARSING_FUNCTION = "DynamicUrlParsing"; +const char* const SET_WIDGET_INFO_FUNCTION = "DynamicSetWidgetInfo"; +const char* const DATABASE_ATTACH_FUNCTION = "DynamicDatabaseAttach"; +#if defined(OS_TIZEN_TV_PRODUCT) +const char* const TVURL_PARSING_FUNCTION = "DynamicTVUrlParsing"; +const char* const GET_FILEDECRYPTED_DATABUFFER = + "DynamicGetFileDecryptedDataBuffer"; +#endif + +typedef void (*startSessionFun_v0)(const char* tizen_app_id, + v8::Handle context, + int routingHandle, + double scaleFactor, + const char* encodedBundle, + const char* theme, + const char* baseURL); +} // namespace + +WrtDynamicPlugin::WrtDynamicPlugin() + : DynamicPlugin(), + m_parseURL_(0), + m_setWidgetInfo_(0), + m_databaseAttach_(0), +#if defined(OS_TIZEN_TV_PRODUCT) + m_getFileDecryptedDataBuffer_(0), + m_parseTVURL_(0), +#endif + m_onIPCMessage_(0) { + *reinterpret_cast(&m_parseURL_) = + dlsym(m_handle_, URL_PARSING_FUNCTION); + if (!m_parseURL_) { + LOG(ERROR) << "No " << URL_PARSING_FUNCTION << " symbol found!\n"; + } + *reinterpret_cast(&m_setWidgetInfo_) = + dlsym(m_handle_, SET_WIDGET_INFO_FUNCTION); + if (!m_setWidgetInfo_) { + LOG(ERROR) << "No " << SET_WIDGET_INFO_FUNCTION << " symbol found!"; + } + *reinterpret_cast(&m_databaseAttach_) = + dlsym(m_handle_, DATABASE_ATTACH_FUNCTION); + if (!m_databaseAttach_) { + LOG(ERROR) << "No " << DATABASE_ATTACH_FUNCTION << " symbol found!\n"; + return; + } + *reinterpret_cast(&m_onIPCMessage_) = + dlsym(m_handle_, "DynamicOnIPCMessage"); + if (!m_onIPCMessage_) { + LOG(ERROR) << "No DynamicOnIPCMessage symbol found!\n"; + } + m_databaseAttach_(1); + +#if defined(OS_TIZEN_TV_PRODUCT) + *reinterpret_cast(&m_parseTVURL_) = + dlsym(m_handle_, TVURL_PARSING_FUNCTION); + if (!m_parseTVURL_) { + LOG(ERROR) << "No " << TVURL_PARSING_FUNCTION << " symbol found!\n"; + } + *reinterpret_cast(&m_getFileDecryptedDataBuffer_) = + dlsym(m_handle_, GET_FILEDECRYPTED_DATABUFFER); + if (!m_getFileDecryptedDataBuffer_) { + LOG(ERROR) << "No " << GET_FILEDECRYPTED_DATABUFFER << " symbol found!\n"; + } +#endif +} + +void WrtDynamicPlugin::startSession(const char* tizen_app_id, + v8::Handle context, + int routingHandle, + double scaleFactor, + const char* encodedBundle, + const char* theme, + const char* baseURL) { + if (!m_startSession_ || !m_databaseAttach_) + return; + switch (m_version_) { + case 0: { + auto startSession_v0 = + reinterpret_cast(m_startSession_); + startSession_v0(tizen_app_id, context, routingHandle, scaleFactor, + encodedBundle, theme, baseURL); + break; + } + case 1: { + DynamicPlugin::startSession(tizen_app_id, context, routingHandle, + baseURL); + break; + } + default: + return; + } +} + +void WrtDynamicPlugin::stopSession(const char* tizen_app_id, + v8::Handle context) { + if (!m_stopSession_ || !m_databaseAttach_) + return; + DynamicPlugin::stopSession(tizen_app_id, context); +} + +void WrtDynamicPlugin::parseURL(std::string* old_url, + std::string* new_url, + const char* tizen_app_id, + bool* is_decrypted_file) { +#if defined(OS_TIZEN_TV_PRODUCT) + if (!m_databaseAttach_) + return; + if (m_parseTVURL_) { + m_parseTVURL_(old_url, new_url, tizen_app_id, is_decrypted_file); + return; + } + if (m_parseURL_) { + m_parseURL_(old_url, new_url, tizen_app_id); + *is_decrypted_file = false; + } +#else + if (!m_parseURL_ || !m_databaseAttach_) + return; + m_parseURL_(old_url, new_url, tizen_app_id); +#endif +} + +#if defined(OS_TIZEN_TV_PRODUCT) +bool WrtDynamicPlugin::getFileDecryptedDataBuffer(const std::string* url, + std::vector* data) { + if (!m_getFileDecryptedDataBuffer_) + return false; + return m_getFileDecryptedDataBuffer_(url, data); +} +#endif + +void WrtDynamicPlugin::setWidgetInfo(const std::string& tizen_app_id) { + if (!m_setWidgetInfo_) + return; + m_setWidgetInfo_(tizen_app_id.c_str()); +} + +WrtDynamicPlugin::~WrtDynamicPlugin() { + if (m_databaseAttach_) + m_databaseAttach_(0); +} + +WrtDynamicPlugin& WrtDynamicPlugin::instance() { + static WrtDynamicPlugin dynamicPlugin; + return dynamicPlugin; +} + +void WrtDynamicPlugin::messageReceived(const Wrt_Message_Data& data) { + if (!m_onIPCMessage_) + return; + + m_onIPCMessage_(data); +} diff --git a/tizen/wrt/wrt_dynamicplugin.h b/tizen/wrt/wrt_dynamicplugin.h new file mode 100644 index 0000000..9554b4d --- /dev/null +++ b/tizen/wrt/wrt_dynamicplugin.h @@ -0,0 +1,71 @@ +// Copyright 2014 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WRT_WRT_DYNAMICPLUGIN_H_ +#define WRT_WRT_DYNAMICPLUGIN_H_ + +#include +#include +#include "dynamicplugin.h" +#include "v8/include/v8.h" +#include "common/wrt_message_data.h" + +typedef void (*onIPCMessageFun)(const Wrt_Message_Data& data); +#if defined(OS_TIZEN_TV_PRODUCT) +typedef void (*TVParseUrlFun)(std::string* old_url, + std::string* new_url, + const char* tizen_app_id, + bool* is_decrypted_file); +typedef bool (*getFileDecryptedDataBufferFun)(const std::string* url, + std::vector* data); +#endif +typedef void (*parseUrlFun)(std::string* old_url, + std::string* new_url, + const char* tizen_app_id); +typedef void (*setWidgetInfoFun)(const char* tizen_app_id); +typedef void (*databaseAttachFun)(int databaseAttach); + +class WrtDynamicPlugin : public DynamicPlugin { + public: + void startSession(const char* tizen_app_id, + v8::Handle context, + int routingHandle, + double scaleFactor, + const char* encodedBundle, + const char* theme, + const char* baseURL); + void stopSession(const char* tizen_app_id, v8::Handle context); + + void parseURL(std::string* old_url, + std::string* new_url, + const char* tizen_app_id, + bool* is_decrypted_file); + +#if defined(OS_TIZEN_TV_PRODUCT) + bool getFileDecryptedDataBuffer(const std::string* url, + std::vector* data); +#endif + + void setWidgetInfo(const std::string& tizen_app_id); + void messageReceived(const Wrt_Message_Data& data); + + static WrtDynamicPlugin& instance(); + ~WrtDynamicPlugin() override; + + private: + WrtDynamicPlugin(); + + parseUrlFun m_parseURL_; + setWidgetInfoFun m_setWidgetInfo_; + databaseAttachFun m_databaseAttach_; +#if defined(OS_TIZEN_TV_PRODUCT) + getFileDecryptedDataBufferFun m_getFileDecryptedDataBuffer_; + TVParseUrlFun m_parseTVURL_; +#endif + onIPCMessageFun m_onIPCMessage_; + + DISALLOW_COPY_AND_ASSIGN(WrtDynamicPlugin); +}; + +#endif // WRT_WRT_DYNAMICPLUGIN_H_ diff --git a/tizen/wrt/wrt_file_protocol_handler.cc b/tizen/wrt/wrt_file_protocol_handler.cc new file mode 100644 index 0000000..5a8ba30 --- /dev/null +++ b/tizen/wrt/wrt_file_protocol_handler.cc @@ -0,0 +1,110 @@ +// Copyright (c) 2014,2015 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "wrt_file_protocol_handler.h" + +#include "base/command_line.h" +//#include "common/content_switches_efl.h" +#include "content/public/common/content_client.h" +#include "content/public/renderer/content_renderer_client.h" +#include "net/base/filename_util.h" +#include "net/url_request/url_request_data_job.h" +#include "net/url_request/url_request_error_job.h" +#include "net/url_request/url_request_file_dir_job.h" +#include "net/url_request/url_request_file_job.h" +#include "net/url_request/url_request_simple_job.h" +#include "wrt_dynamicplugin.h" + +namespace net { + +class WrtURLRequestDataJob : public URLRequestSimpleJob { + public: + /* LCOV_EXCL_START */ + WrtURLRequestDataJob(URLRequest* request, + NetworkDelegate* network_delegate, + const GURL& data_url) + : URLRequestSimpleJob(request, network_delegate) { + data_url_ = data_url; + } + /* LCOV_EXCL_STOP */ + + int GetData(std::string* mime_type, + std::string* charset, + std::string* data, + const CompletionCallback& callback) const override; + + private: + ~WrtURLRequestDataJob() override {} // LCOV_EXCL_LINE + GURL data_url_; +}; + +/* LCOV_EXCL_START */ +int WrtURLRequestDataJob::GetData(std::string* mime_type, + std::string* charset, + std::string* data, + const CompletionCallback& callback) const { + if (!data_url_.is_valid()) + return ERR_INVALID_URL; + + return URLRequestDataJob::BuildResponse(data_url_, mime_type, charset, data, + nullptr); +} + +bool WrtFileProtocolHandler::GetWrtParsedUrl(const GURL& url, + GURL& parsed_url) const { + static std::string tizen_app_id = + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + "widget-id"); + if (!tizen_app_id.empty()) { + bool is_decrypted_file; + std::string url_str = url.possibly_invalid_spec(); + std::string parsed_url_str; + WrtDynamicPlugin::instance().parseURL( + &url_str, &parsed_url_str, tizen_app_id.c_str(), &is_decrypted_file); + if (!parsed_url_str.empty()) { + parsed_url = GURL(parsed_url_str); + return true; + } + } + return false; +} +/* LCOV_EXCL_STOP */ + +URLRequestJob* WrtFileProtocolHandler::MaybeCreateJob( + URLRequest* request, + NetworkDelegate* network_delegate) const { + GURL parsed_url; + if (GetWrtParsedUrl(request->url(), parsed_url)) { + // Data URI scheme for WRT encryption content + if (parsed_url.SchemeIs(url::kDataScheme)) + return new WrtURLRequestDataJob(request, network_delegate, parsed_url); + } else + parsed_url = request->url(); + + base::FilePath file_path; + const bool is_file = FileURLToFilePath(parsed_url, &file_path); + + // Check file access permissions. + if (!network_delegate || + !network_delegate->CanAccessFile(*request, file_path)) { + return new URLRequestErrorJob(request, network_delegate, ERR_ACCESS_DENIED); + } + + // We need to decide whether to create URLRequestFileJob for file access or + // URLRequestFileDirJob for directory access. To avoid accessing the + // filesystem, we only look at the path string here. + // The code in the URLRequestFileJob::Start() method discovers that a path, + // which doesn't end with a slash, should really be treated as a directory, + // and it then redirects to the URLRequestFileDirJob. + if (is_file && file_path.EndsWithSeparator() && file_path.IsAbsolute()) { + return new URLRequestFileDirJob(request, network_delegate, file_path); + } + + // Use a regular file request job for all non-directories (including invalid + // file names). + return new URLRequestFileJob(request, network_delegate, file_path, + file_task_runner_); +} + +} // namespace diff --git a/tizen/wrt/wrt_file_protocol_handler.h b/tizen/wrt/wrt_file_protocol_handler.h new file mode 100644 index 0000000..6fab49f --- /dev/null +++ b/tizen/wrt/wrt_file_protocol_handler.h @@ -0,0 +1,46 @@ +// Copyright (c) 2014,2015 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WRT_FILE_PROTOCOL_HANDLER +#define WRT_FILE_PROTOCOL_HANDLER + +#include "base/memory/ref_counted.h" +#include "net/url_request/url_request_job_factory.h" + +class GURL; + +namespace base { +class TaskRunner; +} + +namespace net { + +class NetworkDelegate; +class URLRequestJob; + +class WrtFileProtocolHandler + : public URLRequestJobFactory::ProtocolHandler { + public: + explicit WrtFileProtocolHandler( + const scoped_refptr& file_task_runner) + : file_task_runner_(file_task_runner) {} + ~WrtFileProtocolHandler() override {} + URLRequestJob* MaybeCreateJob( + URLRequest* request, + NetworkDelegate* network_delegate) const override; + /* LCOV_EXCL_START */ + bool IsSafeRedirectTarget(const GURL& location) const override { + return false; + } + /* LCOV_EXCL_STOP */ + + private: + bool GetWrtParsedUrl(const GURL& url, GURL& parsed_url) const; + const scoped_refptr file_task_runner_; + DISALLOW_COPY_AND_ASSIGN(WrtFileProtocolHandler); +}; + +} // namespace net + +#endif // WRT_FILE_PROTOCOL_HANDLER diff --git a/tizen/wrt/wrt_widget_host.cc b/tizen/wrt/wrt_widget_host.cc new file mode 100644 index 0000000..d33c513 --- /dev/null +++ b/tizen/wrt/wrt_widget_host.cc @@ -0,0 +1,164 @@ +// Copyright (c) 2014,2015 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "wrt_widget_host.h" + +#include "base/lazy_instance.h" +//#include "common/render_messages_ewk.h" +#include "atom/common/api/api_messages.h" +#include "content/public/browser/browser_message_filter.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/resource_request_info.h" +//#include "ipc/ipc_message_macros.h" +//#include "ipc_message_start_ewk.h" +#include "net/url_request/url_request.h" +#include "url/gurl.h" + +namespace { +// TODO(z.kostrzewa) I would prefer not make it a singleton, check out +// if it can't be a member of ContentMainDelegateEfl (but keep the static +// getter, maybe?). +base::LazyInstance > g_wrt_widget_host = + LAZY_INSTANCE_INITIALIZER; + +bool SendToAllRenderers(IPC::Message* message) { + bool result = false; + content::RenderProcessHost::iterator it = + content::RenderProcessHost::AllHostsIterator(); + while (!it.IsAtEnd()) { + if (it.GetCurrentValue()->Send(new IPC::Message(*message))) + result = true; + it.Advance(); + } + delete message; + return result; +} + +bool SendToRenderer(int renderer_id, IPC::Message* message) { + return content::RenderProcessHost::FromID(renderer_id)->Send(message); +} +} + +class WrtWidgetHostMessageFilter : public content::BrowserMessageFilter { + public: + explicit WrtWidgetHostMessageFilter(WrtWidgetHost* wrt_widget_host); + + private: + ~WrtWidgetHostMessageFilter() override {} + bool OnMessageReceived(const IPC::Message& message) override; + + WrtWidgetHost* wrt_widget_host_; +}; + +WrtWidgetHostMessageFilter::WrtWidgetHostMessageFilter( + WrtWidgetHost* wrt_widget_host) + : content::BrowserMessageFilter(ShellMsgStart), + wrt_widget_host_(wrt_widget_host) { +} + +bool WrtWidgetHostMessageFilter::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(WrtWidgetHostMessageFilter, message) + IPC_MESSAGE_FORWARD(WrtMsg_ParseUrlResponse, wrt_widget_host_, WrtWidgetHost::OnUrlRetrieved) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +WrtWidgetHost* WrtWidgetHost::Get() { + // TODO(z.kostrzewa) LazyInstance is thread-safe but creating + // WrtWidgetHost is not - make it thread-safe. + if (!g_wrt_widget_host.Get().get()) + g_wrt_widget_host.Get().reset(new WrtWidgetHost); + return g_wrt_widget_host.Get().get(); +} + +WrtWidgetHost::WrtWidgetHost() + : message_filter_(new WrtWidgetHostMessageFilter(this)) { +} + +WrtWidgetHost::~WrtWidgetHost() {} + +void WrtWidgetHost::GetUrlForRequest( + net::URLRequest* request, + base::Callback callback) { + // TODO(z.kostrzewa) Check on which thread(s) callbacks_ is touched + // and provide synchronization if required (either via a lock or + // by assuring that it is referenced only on one thread) + int callback_id = callback_id_generator_.GetNext(); + callbacks_[callback_id] = callback; + + int renderer_id, frame_id; + if (content::ResourceRequestInfo::GetRenderFrameForRequest(request, &renderer_id, + &frame_id)) + if (SendToRenderer(renderer_id, new WrtMsg_ParseUrl(callback_id, request->url()))) + return; + + callbacks_.erase(callback_id); + callback.Run(GURL()); +} + +void WrtWidgetHost::SendWrtMessage( + const Wrt_Message_Data& message) { + SendToAllRenderers(new WrtMsg_SendWrtMessage(message)); +} + +// It's only used by the wrt_file_protocol_handler which is not going to be used in the future +// Candidate for deletion. +bool WrtWidgetHost::InWrt() const { + return false; +} + +// It's only used by the wrt_file_protocol_handler which is not going to be used in the future +// Candidate for deletion. +std::string WrtWidgetHost::TizenAppId() const { +#if defined(OS_TIZEN_TV_PRODUCT) + return tizen_app_id_; +#else + return std::string(); +#endif +} + +void WrtWidgetHost::OnUrlRetrieved(int callback_id, const GURL& url) { + callbacks_type::iterator it = callbacks_.find(callback_id); + if (callbacks_.end() == it) + return; + + callbacks_type::mapped_type callback = it->second; + callbacks_.erase(callback_id); + callback.Run(url); +} + +#if defined(OS_TIZEN_TV_PRODUCT) +void WrtWidgetHost::SetTizenAppId(const std::string& tizen_app_id) { + tizen_app_id_ = tizen_app_id; +} + +bool WrtWidgetHost::ShouldAllowRequest(const net::URLRequest& request) { + if (tizen_app_id_.empty() || !check_accessiable_path_callback_) + return true; + + return check_accessiable_path_callback_->TriggerCallback(request.url().spec(), + tizen_app_id_); +} + +bool EwkCheckAccessiablePathCallback::TriggerCallback( + const std::string& url_spec, + const std::string& tizen_app_id) const { + if (!callback_) + return true; + + Eina_Bool result = + (*callback_)(tizen_app_id.c_str(), url_spec.c_str(), user_data_); + return result == EINA_TRUE; +} + +void WrtWidgetHost::SetCheckAccessiablePathCallback( + Ewk_Context_Check_Accessible_Path_Callback callback, + void* user_data) { + check_accessiable_path_callback_.reset( + new EwkCheckAccessiablePathCallback(callback, user_data)); +} +#endif + diff --git a/tizen/wrt/wrt_widget_host.h b/tizen/wrt/wrt_widget_host.h new file mode 100644 index 0000000..11161da --- /dev/null +++ b/tizen/wrt/wrt_widget_host.h @@ -0,0 +1,89 @@ +// Copyright (c) 2014,2015 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WRT_HOST_H +#define WRT_HOST_H + +#include +#include + +#include "base/atomic_sequence_num.h" +#include "base/callback.h" +#include "content/public/browser/browser_message_filter.h" +#include "common/wrt_message_data.h" +#if defined(OS_TIZEN_TV_PRODUCT) +#include "public/ewk_context_product.h" +#endif + +namespace net { +class URLRequest; +} + +class GURL; + +class WrtWidgetHostMessageFilter; + +#if defined(OS_TIZEN_TV_PRODUCT) +class EwkCheckAccessiablePathCallback { + public: + EwkCheckAccessiablePathCallback( + Ewk_Context_Check_Accessible_Path_Callback callback, + void* user_data) + : callback_(callback), user_data_(user_data) {} + bool TriggerCallback(const std::string& url_spec, + const std::string& tizen_app_id) const; + + private: + Ewk_Context_Check_Accessible_Path_Callback callback_; + void* user_data_; +}; +#endif + +class WrtWidgetHost { + public: + static WrtWidgetHost* Get(); + + ~WrtWidgetHost(); + + void GetUrlForRequest(net::URLRequest* request, + base::Callback callback); + + void SendWrtMessage(const Wrt_Message_Data& message); + + bool InWrt() const; + + std::string TizenAppId() const; + +#if defined(OS_TIZEN_TV_PRODUCT) + void SetTizenAppId(const std::string& tizen_app_id); + bool ShouldAllowRequest(const net::URLRequest& request); + + void SetCheckAccessiablePathCallback( + Ewk_Context_Check_Accessible_Path_Callback callback, + void* user_data); +#endif + + private: + friend class WrtWidgetHostMessageFilter; + + typedef std::map > callbacks_type; + + WrtWidgetHost(); + + void OnUrlRetrieved(int callback_id, const GURL& url); + + scoped_refptr message_filter_; + base::AtomicSequenceNumber callback_id_generator_; + callbacks_type callbacks_; + +#if defined(OS_TIZEN_TV_PRODUCT) + std::string tizen_app_id_; + std::unique_ptr check_accessiable_path_callback_; +#endif + + DISALLOW_COPY_AND_ASSIGN(WrtWidgetHost); +}; + + +#endif diff --git a/tizen/wrt/wrtwidget.cc b/tizen/wrt/wrtwidget.cc new file mode 100644 index 0000000..6c877c6 --- /dev/null +++ b/tizen/wrt/wrtwidget.cc @@ -0,0 +1,97 @@ +// Copyright 2014, 2015 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "wrtwidget.h" + +//#include "common/render_messages_ewk.h" +#include "atom/common/api/api_messages.h" +#include "content/public/renderer/render_thread.h" +#include "ipc/ipc_sync_channel.h" +#include "wrt_dynamicplugin.h" + +// TODO(z.kostrzewa) +// Why it can't be implemented as IPC::ChannelProxy::MessageFilter (?) +// Tried that and it seems that Observer starts receiving messages earlier than +// MessageFilter what is crucial for message that sets widget handle +class WrtRenderThreadObserver : public content::RenderThreadObserver { + public: + explicit WrtRenderThreadObserver(WrtWidget* wrt_widget) + : wrt_widget_(wrt_widget), + channel_(content::RenderThread::Get()->GetChannel()) + { } + + bool OnControlMessageReceived(const IPC::Message& message) override { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(WrtRenderThreadObserver, message) + IPC_MESSAGE_FORWARD(WrtMsg_SendWrtMessage, wrt_widget_, WrtWidget::MessageReceived) + IPC_MESSAGE_HANDLER(WrtMsg_ParseUrl, ParseUrl) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; + } + + private: + void ParseUrl(int request_id, const GURL& url) { + GURL response; + bool is_decrypted_file = false; + wrt_widget_->ParseUrl(url, response, is_decrypted_file); + Send(new WrtMsg_ParseUrlResponse(request_id, response)); + } + + void Send(IPC::Message* message) { + if (channel_) + channel_->Send(message); + else + delete message; + } + + WrtWidget* wrt_widget_; + IPC::SyncChannel* channel_; +}; + +WrtWidget::WrtWidget() + : V8Widget(V8Widget::Type::WRT), + scale_(0), + observer_(new WrtRenderThreadObserver(this)) { + DCHECK(content::RenderThread::Get()) + << "WrtWidget must be constructed on the render thread"; +} + +WrtWidget::~WrtWidget() { + delete observer_; +} + +content::RenderThreadObserver* WrtWidget::GetObserver() { + return observer_; +} + +void WrtWidget::SetWidgetInfo(const std::string& tizen_app_id, + double scaleFactor, + const std::string& theme, + const std::string& encodedBundle) { + id_ = tizen_app_id; + scale_ = scaleFactor; + theme_ = theme; + encodedBundle_ = encodedBundle; + WrtDynamicPlugin::instance().setWidgetInfo(id_); +} + +bool WrtWidget::IsWidgetInfoSet() const { + return !id_.empty(); +} + +void WrtWidget::StartSession(v8::Handle context, + int routingHandle, + const void* sessionBlob) { + if (!id_.empty() && !context.IsEmpty()) { + WrtDynamicPlugin::instance().startSession( + id_.c_str(), context, routingHandle, scale_, encodedBundle_.c_str(), + theme_.c_str(), reinterpret_cast(sessionBlob)); + } +} + +void WrtWidget::MessageReceived(const Wrt_Message_Data& data) { + if (!id_.empty()) + WrtDynamicPlugin::instance().messageReceived(data); +} diff --git a/tizen/wrt/wrtwidget.h b/tizen/wrt/wrtwidget.h new file mode 100644 index 0000000..28af8cb --- /dev/null +++ b/tizen/wrt/wrtwidget.h @@ -0,0 +1,45 @@ +// Copyright 2014, 2015 Samsung Electronics. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WRT_WRTWIDGET_H_ +#define WRT_WRTWIDGET_H_ + +#include + +#include "content/public/renderer/render_thread_observer.h" +#include "url/gurl.h" +#include "v8widget.h" +#include "common/wrt_message_data.h" + +class WrtRenderThreadObserver; + +// Have to be created on the RenderThread. +class WrtWidget : public V8Widget { + public: + WrtWidget(); + ~WrtWidget() override; + + content::RenderThreadObserver* GetObserver(); + + void SetWidgetInfo(const std::string& tizen_app_id, + double scaleFactor, + const std::string& theme, + const std::string& encodedBundle); + + bool IsWidgetInfoSet() const; + + void MessageReceived(const Wrt_Message_Data& data); + + void StartSession(v8::Handle, + int routingHandle, + const void* sessionBlob) override; + + private: + double scale_; + std::string encodedBundle_; + std::string theme_; + WrtRenderThreadObserver* observer_; +}; + +#endif // WRT_WRTWIDGET_H_ diff --git a/vendor/brightray/browser/browser_context.cc b/vendor/brightray/browser/browser_context.cc index 4ab07e4..2f709bb 100644 --- a/vendor/brightray/browser/browser_context.cc +++ b/vendor/brightray/browser/browser_context.cc @@ -2,6 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE-CHROMIUM file. +#if defined(OS_TIZEN) +#include +#endif + #include "browser/browser_context.h" #include "browser/media/media_device_id_salt.h" @@ -40,6 +44,10 @@ using content::BrowserThread; namespace brightray { namespace { +#if defined(OS_TIZEN) +const char* const kDynamicPreloading = "DynamicPreloading"; +typedef void (*DynamicPreloading)(void); +#endif // Convert string to lower case and escape it. std::string MakePartitionName(const std::string& input) { @@ -105,16 +113,43 @@ BrowserContext::BrowserContext(const std::string& partition, bool in_memory) MakePartitionName(partition))); content::BrowserContext::Initialize(this, path_); - browser_context_map_[PartitionKey(partition, in_memory)] = GetWeakPtr(); -#if defined(OS_TIZEN) + auto command_line = base::CommandLine::ForCurrentProcess(); if (command_line->HasSwitch("injected-bundle-path")) { std::string injected_bundle_path = command_line->GetSwitchValueASCII("injected-bundle-path"); +#if defined(OS_TIZEN) + if (command_line->HasSwitch(switches::kSingleProcess)) { + // Preload injected bundle on here for process pool, + // because the zygote process doesn't exist in single process mode. + // The loaded handle must be closed on termination. + injected_bundle_handle_ = + dlopen(injected_bundle_path.c_str(), RTLD_LAZY); + if (!injected_bundle_handle_) { + LOG(ERROR) << "No handle to " << injected_bundle_path.c_str() + << " error " << dlerror(); + return; + } + + DynamicPreloading dp = reinterpret_cast( + dlsym(injected_bundle_handle_, kDynamicPreloading)); + if (dp) { + dp(); + } else { + LOG(ERROR) << "Fail to load symbol '" + << kDynamicPreloading + << "', error " << dlerror(); + } + } else { +#endif + //content::ZygoteHandle *handle = content::GetGenericZygote(); + //*handle->LoadInjectedBundlePath(injected_bundle_path); (*content::GetGenericZygote())-> LoadInjectedBundlePath(injected_bundle_path); - } +#if defined(OS_TIZEN) + } #endif + } } BrowserContext::~BrowserContext() { diff --git a/vendor/brightray/browser/browser_context.h b/vendor/brightray/browser/browser_context.h index 498fe99..f09b6f1 100644 --- a/vendor/brightray/browser/browser_context.h +++ b/vendor/brightray/browser/browser_context.h @@ -123,6 +123,10 @@ class BrowserContext : public base::RefCounted, base::FilePath path_; bool in_memory_; +#if defined(OS_TIZEN) + void* injected_bundle_handle_; +#endif + DevToolsNetworkControllerHandle network_controller_handle_; std::unique_ptr resource_context_; diff --git a/vendor/brightray/vendor/libchromiumcontent/src/base/trace_event/trace_event.h b/vendor/brightray/vendor/libchromiumcontent/src/base/trace_event/trace_event.h index f1a577f..0718f10 100644 --- a/vendor/brightray/vendor/libchromiumcontent/src/base/trace_event/trace_event.h +++ b/vendor/brightray/vendor/libchromiumcontent/src/base/trace_event/trace_event.h @@ -24,7 +24,7 @@ #include "base/trace_event/trace_log.h" #include "build/build_config.h" -#if defined(USE_EFL) +#if 0//defined(USE_EFL) #include "base/trace_event/ttrace.h" #endif diff --git a/wrt.gyp b/wrt.gyp index 6ea31d4..54377cf 100644 --- a/wrt.gyp +++ b/wrt.gyp @@ -15,6 +15,7 @@ '<(DEPTH)/tizen/loader/loader.gyp:wrt-loader', '<(DEPTH)/tizen/extensions/extensions.gyp:xwalk_extension_shared', '<(DEPTH)/tizen/renderer/injected_bundle.gyp:xwalk_injected_bundle', + '<(DEPTH)/tizen/wrt/chromium_wrt.gyp:chromium_wrt_shared', '<(DEPTH)/efl/build/system.gyp:ecore', '<(DEPTH)/efl/build/system.gyp:launchpad', '<(DEPTH)/efl/build/system.gyp:capi-appfw-application', @@ -104,6 +105,7 @@ ], 'include_dirs': [ '.', + 'tizen', 'chromium_src', 'vendor/brightray', 'vendor/native_mate', -- 2.7.4 From a6289324b1f05291eb6f0de0dccfd6f3664ac3e4 Mon Sep 17 00:00:00 2001 From: "ws29.jung" Date: Tue, 17 Apr 2018 11:13:23 +0900 Subject: [PATCH 12/16] Electron App launching implement Ironically, Electron JS Runtime was not able to execute Electron Web App, but only able to run Tizen Web app. From this patch, if Electron App is packaged as wgt, JS Runtime will parse xml then will launch Electron App from its own entry point. Change-Id: Iec5df77495063e129d99a8e1dd21bc8f489b8ffe Signed-off-by: ws29.jung --- atom/app/ui_runtime.cc | 2 +- atom/browser/api/atom_api_pwrt.cc | 5 +++++ atom/browser/api/atom_api_pwrt.h | 1 + atom/browser/browser.cc | 22 ++++++++++++++++++++++ atom/browser/browser.h | 11 +++++++++++ wrt/src/runtime.js | 19 ++++++++++++++++++- 6 files changed, 58 insertions(+), 2 deletions(-) diff --git a/atom/app/ui_runtime.cc b/atom/app/ui_runtime.cc index 7091bff..959e4ac 100644 --- a/atom/app/ui_runtime.cc +++ b/atom/app/ui_runtime.cc @@ -55,6 +55,7 @@ bool UiRuntime::OnCreate() { } void UiRuntime::OnTerminate() { + LOG(ERROR) << "OnTerminate()"; atom::Browser *browser_model = atom::Browser::Get(); } @@ -99,7 +100,6 @@ int UiRuntime::Exec() { // onCreate ops.create = [](void* data) -> bool { - LOG(ERROR) << "Create Tizen App."; UiRuntime *runtime = (UiRuntime*)data; content::ContentMain(*runtime->_params); diff --git a/atom/browser/api/atom_api_pwrt.cc b/atom/browser/api/atom_api_pwrt.cc index b63ef51..30213c5 100644 --- a/atom/browser/api/atom_api_pwrt.cc +++ b/atom/browser/api/atom_api_pwrt.cc @@ -52,6 +52,10 @@ bool PWRT::isTizenWebApp() { } } +bool PWRT::isElectronLaunch() { + return Browser::Get()->is_electron_launch(); +} + void PWRT::Log(const std::string& message) { std::string output = "[JS LOG] " + message; dlog_print(DLOG_ERROR, "WRT", output.c_str()); @@ -73,6 +77,7 @@ void PWRT::BuildPrototype( .SetMethod("getMessage", &PWRT::GetMessage) .SetMethod("getPath", &PWRT::GetPath) .SetMethod("isTizenWebApp", &PWRT::isTizenWebApp) + .SetMethod("isElectronLaunch", &PWRT::isElectronLaunch) .SetMethod("log", &PWRT::Log); } diff --git a/atom/browser/api/atom_api_pwrt.h b/atom/browser/api/atom_api_pwrt.h index 647a5ae..8b67cc2 100644 --- a/atom/browser/api/atom_api_pwrt.h +++ b/atom/browser/api/atom_api_pwrt.h @@ -19,6 +19,7 @@ class PWRT : public mate::TrackableObject { std::string GetMessage(); std::string GetPath(); bool isTizenWebApp(); + bool isElectronLaunch(); void Log(const std::string& message); protected: diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index dea0bf2..771cbee 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -21,6 +21,9 @@ namespace atom { Browser::Browser() : is_quiting_(false), +#if defined(OS_TIZEN) + is_electron_launch_(false), +#endif is_exiting_(false), is_ready_(false), is_shutdown_(false), @@ -100,6 +103,22 @@ void Browser::Shutdown() { } } +#if defined(OS_TIZEN) +void Browser::SetElectronAppLaunch() { + if (!is_electron_launch_) { + common::CommandLine* runtime_cmd = common::CommandLine::ForCurrentProcess(); + std::string appid = runtime_cmd->GetAppIdFromCommandLine("/usr/bin/electron"); + auto appdata_manager = common::ApplicationDataManager::GetInstance(); + common::ApplicationData* app_data = appdata_manager->GetApplicationData(appid); + if (!strcmp(app_data->content_info()->src().c_str(), "package.json")) { + is_electron_launch_ = true; + } + } else { + is_electron_launch_ = false; + } +} +#endif + std::string Browser::GetVersion() const { if (version_override_.empty()) { std::string version = GetExecutableFileVersion(); @@ -151,6 +170,9 @@ void Browser::Activate(bool has_visible_windows) { } void Browser::WillFinishLaunching() { +#if defined(OS_TIZEN) + SetElectronAppLaunch(); +#endif for (BrowserObserver& observer : observers_) observer.OnWillFinishLaunching(); } diff --git a/atom/browser/browser.h b/atom/browser/browser.h index 286ba29..dfc4831 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -222,6 +222,9 @@ class Browser : public WindowListObserver { bool is_shutting_down() const { return is_shutdown_; } bool is_quiting() const { return is_quiting_; } bool is_ready() const { return is_ready_; } +#if defined(OS_TIZEN) + bool is_electron_launch() const { return is_electron_launch_; } +#endif protected: // Returns the version of application bundle or executable file. @@ -245,6 +248,10 @@ class Browser : public WindowListObserver { void OnWindowCloseCancelled(NativeWindow* window) override; void OnWindowAllClosed() override; +#if defined(OS_TIZEN) + void SetElectronAppLaunch(); +#endif + // Observers of the browser. base::ObserverList observers_; @@ -257,6 +264,10 @@ class Browser : public WindowListObserver { // The browser is being shutdown. bool is_shutdown_; +#if defined(OS_TIZEN) + bool is_electron_launch_; +#endif + std::string version_override_; std::string name_override_; diff --git a/wrt/src/runtime.js b/wrt/src/runtime.js index d6c855d..0bdaa49 100644 --- a/wrt/src/runtime.js +++ b/wrt/src/runtime.js @@ -1,5 +1,5 @@ 'use strict'; -const {app, ipcMain} = require('electron'); +const {app, ipcMain, pwrt} = require('electron'); const IPC_MESSAGE = require('./ipc_message'); const WAS_EVENT = require('./was_event'); const WebApplication = require('./web_application'); @@ -13,6 +13,7 @@ class Runtime { this.quitting = false; this.handleWasEvents(); this.handleIpcMessages(); + this.isLaunched = false; var _this = this; app.on('before-quit', function(event) { @@ -40,8 +41,24 @@ class Runtime { app.on('window-all-closed', function(event) { return runtime_debug('window-all-closed'); }); + app.on('will-finish-launching', function(event) { + runtime_debug('will-finish-launching'); + if (pwrt.isElectronLaunch()) { + console.log("Electron App launch"); + let filePath = pwrt.getPath(); + let pkgJson = require(filePath.substr(7, filePath.length - 12)); + let mainJsPath = filePath.substr(7, filePath.length - 19) + + (pkgJson.main || 'index.js'); + + const Module = require('module'); + Module._load(mainJsPath, Module, true); + } + }); app.on('ready', function(event) { runtime_debug('ready'); + if (pwrt.isElectronLaunch()) { + return; + } this.webApplication = new WebApplication(options); }); } -- 2.7.4 From e2d42b261f17377d8acb44d744d591ff151ac62d Mon Sep 17 00:00:00 2001 From: "min7.choi" Date: Thu, 19 Apr 2018 19:30:05 +0900 Subject: [PATCH 13/16] Implement splash screen Implementation of splash screen used in tizen. now the hide screen is only implemented in complete. first-paint and costom will be implemented later. Also, the window state of the splash screen will be implemented later Change-Id: I444f1be7dd04be46d5cd8edca5e022616d9020ff Signed-off-by: min7.choi --- atom/app/ui_runtime.cc | 16 ++- atom/browser/api/atom_api_pwrt.cc | 7 ++ atom/browser/api/atom_api_pwrt.h | 1 + atom/browser/browser.cc | 37 ++++++ atom/browser/browser.h | 12 ++ atom/browser/splash_screen.cc | 238 ++++++++++++++++++++++++++++++++++++++ atom/browser/splash_screen.h | 69 +++++++++++ wrt.gyp | 2 + wrt/src/web_window.js | 4 +- 9 files changed, 384 insertions(+), 2 deletions(-) create mode 100755 atom/browser/splash_screen.cc create mode 100755 atom/browser/splash_screen.h diff --git a/atom/app/ui_runtime.cc b/atom/app/ui_runtime.cc index 959e4ac..e13e1bf 100644 --- a/atom/app/ui_runtime.cc +++ b/atom/app/ui_runtime.cc @@ -29,6 +29,8 @@ #include "tizen/common/app_db.h" #include "tizen/common/app_control.h" #include "tizen/common/constants.h" +#include "tizen/common/application_data.h" +#include "tizen/common/command_line.h" #include "gin/v8_initializer.h" @@ -51,6 +53,17 @@ void UiRuntime::SetParam(content::ContentMainParams *params) { } bool UiRuntime::OnCreate() { + common::CommandLine* runtime_cmd = common::CommandLine::ForCurrentProcess(); + std::string appid = runtime_cmd->GetAppIdFromCommandLine("/usr/bin/electron"); + + auto appdata_manager = common::ApplicationDataManager::GetInstance(); + common::ApplicationData* appdata = appdata_manager->GetApplicationData(appid); + + if(appdata->splash_screen_info()){ + atom::Browser* browser_model = atom::Browser::Get(); + browser_model->SetSplashScreen(); + } + return true; } @@ -72,7 +85,7 @@ void UiRuntime::OnResume() { } void UiRuntime::OnAppControl(app_control_h app_control) { - LOG(ERROR) << "OnAppControl()"; + LOG(ERROR) << "OnAppControl()"; std::unique_ptr appcontrol(new common::AppControl(app_control)); common::AppDB* appdb = common::AppDB::GetInstance(); @@ -102,6 +115,7 @@ int UiRuntime::Exec() { ops.create = [](void* data) -> bool { LOG(ERROR) << "Create Tizen App."; UiRuntime *runtime = (UiRuntime*)data; + runtime->OnCreate(); content::ContentMain(*runtime->_params); return true; }; diff --git a/atom/browser/api/atom_api_pwrt.cc b/atom/browser/api/atom_api_pwrt.cc index 30213c5..aa7b785 100644 --- a/atom/browser/api/atom_api_pwrt.cc +++ b/atom/browser/api/atom_api_pwrt.cc @@ -56,6 +56,12 @@ bool PWRT::isElectronLaunch() { return Browser::Get()->is_electron_launch(); } +void PWRT::HideSplashScreen(int reason) { + LOG(ERROR) << "PWRT::HideSplashScreen"; + atom::Browser *browser_model = atom::Browser::Get(); + browser_model->HideSplashScreen(reason); +} + void PWRT::Log(const std::string& message) { std::string output = "[JS LOG] " + message; dlog_print(DLOG_ERROR, "WRT", output.c_str()); @@ -78,6 +84,7 @@ void PWRT::BuildPrototype( .SetMethod("getPath", &PWRT::GetPath) .SetMethod("isTizenWebApp", &PWRT::isTizenWebApp) .SetMethod("isElectronLaunch", &PWRT::isElectronLaunch) + .SetMethod("hideSplashScreen", &PWRT::HideSplashScreen) .SetMethod("log", &PWRT::Log); } diff --git a/atom/browser/api/atom_api_pwrt.h b/atom/browser/api/atom_api_pwrt.h index 8b67cc2..ab25f34 100644 --- a/atom/browser/api/atom_api_pwrt.h +++ b/atom/browser/api/atom_api_pwrt.h @@ -20,6 +20,7 @@ class PWRT : public mate::TrackableObject { std::string GetPath(); bool isTizenWebApp(); bool isElectronLaunch(); + void HideSplashScreen(int reason); void Log(const std::string& message); protected: diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 771cbee..3ebba72 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -16,7 +16,14 @@ #include "base/run_loop.h" #include "base/threading/thread_task_runner_handle.h" #include "brightray/browser/brightray_paths.h" + +#if defined(OS_TIZEN) #include "tizen/common/command_line.h" +#include "tizen/common/application_data.h" +#include +#include "wgt_manifest_handlers/launch_screen_handler.h" +#endif // defined(OS_TIZEN) + namespace atom { Browser::Browser() @@ -277,4 +284,34 @@ void Browser::Launch(std::unique_ptr appcontrol) { //To do:Implementation of relaunching of app } +#if defined(OS_TIZEN) +void Browser::SetSplashScreen() { + common::CommandLine* runtime_cmd = common::CommandLine::ForCurrentProcess(); + std::string appid = runtime_cmd->GetAppIdFromCommandLine("/usr/bin/electron"); + + auto appdata_manager = common::ApplicationDataManager::GetInstance(); + common::ApplicationData* appdata = appdata_manager->GetApplicationData(appid); + + Evas_Object* window_ = elm_win_util_standard_add("", ""); + + splash_screen_.reset( + new SplashScreen( + window_, appdata->splash_screen_info(), appdata->application_path())); +} + +void Browser::HideSplashScreen(int reason) { + common::CommandLine* runtime_cmd = common::CommandLine::ForCurrentProcess(); + std::string appid = runtime_cmd->GetAppIdFromCommandLine("/usr/bin/electron"); + + auto appdata_manager = common::ApplicationDataManager::GetInstance(); + common::ApplicationData* appdata = appdata_manager->GetApplicationData(appid); + + if(appdata->splash_screen_info() == NULL) { + return; + } + + splash_screen_->HideSplashScreen(reason); +} +#endif // defined(OS_TIZEN) + } // namespace atom diff --git a/atom/browser/browser.h b/atom/browser/browser.h index dfc4831..362bfaf 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -20,6 +20,10 @@ #include "tizen/common/application_data.h" #include "tizen/common/resource_manager.h" #include "tizen/common/locale_manager.h" +#if defined(OS_TIZEN) +#include "atom/browser/splash_screen.h" +#endif // defined(OS_TIZEN) + #if defined(OS_WIN) #include "base/files/file_path.h" @@ -48,6 +52,10 @@ class Browser : public WindowListObserver { std::unique_ptr resource_manager_; std::unique_ptr locale_manager_; +#if defined(OS_TIZEN) + std::unique_ptr splash_screen_; +#endif // defined(OS_TIZEN) + void Initialize(); // Try to close all windows and quit the application. @@ -117,6 +125,10 @@ class Browser : public WindowListObserver { void Show(); void AppControl(std::unique_ptr appcontrol); void Launch(std::unique_ptr appcontrol); +#if defined(OS_TIZEN) + void SetSplashScreen(); + void HideSplashScreen(int reason); +#endif // defined(OS_TIZEN) #if defined(OS_MACOSX) // Hide the application. diff --git a/atom/browser/splash_screen.cc b/atom/browser/splash_screen.cc new file mode 100755 index 0000000..d6c1751 --- /dev/null +++ b/atom/browser/splash_screen.cc @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "atom/browser/splash_screen.h" + +#include +#include +#include + +#include + +#include "tizen/common/logger.h" + +//using ScreenOrientation = runtime::NativeWindow::ScreenOrientation; + +namespace { + +enum class BorderOption { REPEAT = 1, STRETCH, ROUND }; + +// To do : The orientation will be implemented later. + +/*wgt::parse::ScreenOrientation ChooseOrientation( + const std::map& splash_map, + ScreenOrientation screen_orientation) { + auto orientation_pair = splash_map.end(); + + if (screen_orientation == + runtime::NativeWindow::ScreenOrientation::PORTRAIT_PRIMARY || + screen_orientation == + runtime::NativeWindow::ScreenOrientation::PORTRAIT_SECONDARY) { + orientation_pair = + splash_map.find(wgt::parse::ScreenOrientation::PORTRAIT); + } else { + orientation_pair = + splash_map.find(wgt::parse::ScreenOrientation::LANDSCAPE); + } + if (orientation_pair == splash_map.end()) + orientation_pair = splash_map.find(wgt::parse::ScreenOrientation::AUTO); + + if (orientation_pair != splash_map.end()) return orientation_pair->first; + return wgt::parse::ScreenOrientation::NONE; +}*/ + +bool ParseImageBorder(const std::vector& borders, + std::vector* border_values, + std::vector* border_options) { + std::map scaling_string; + scaling_string["repeat"] = BorderOption::REPEAT; + scaling_string["stretch"] = BorderOption::STRETCH; + scaling_string["round"] = BorderOption::ROUND; + + for (const auto& border : borders) { + std::string::size_type px_index = border.find("px"); + if (px_index != std::string::npos) { + std::string border_value(border.begin(), border.begin() + px_index); + border_values->push_back(std::atoi(border_value.c_str())); + } + for (const auto& border_string_val : scaling_string) { + std::string::size_type index = border.find(border_string_val.first); + if (index != std::string::npos) { + border_options->push_back(border_string_val.second); + } + } + } + + LOGGER(DEBUG) << "Image border values:"; + for (const auto& border_value : *border_values) { + LOGGER(DEBUG) << border_value; + } + LOGGER(DEBUG) << "Image border scaling values:"; + for (const auto& border_option : *border_options) { + LOGGER(DEBUG) << static_cast(border_option); + } + + return !border_values->empty() && !border_options->empty(); +} + +} // namespace + +namespace atom { + +SplashScreen::SplashScreen( + Evas_Object* window, + //runtime::NativeWindow* window, + std::shared_ptr ss_info, + const std::string& app_path) + : ss_info_(ss_info), + window_(window), + image_(nullptr), + background_(nullptr), + background_image_(nullptr), + is_active_(false) { + if (ss_info == nullptr) return; + + auto splash_map = ss_info->launch_screen_data(); + /*auto used_orientation = + ChooseOrientation(splash_map, window->orientation()); + if (used_orientation == wgt::parse::ScreenOrientation::NONE) return; */ + + auto dimensions = GetDimensions(window); + + // To do : The orientation will be implemented later. + SetBackground(splash_map[wgt::parse::ScreenOrientation::AUTO], window, + dimensions, app_path); + SetImage(splash_map[wgt::parse::ScreenOrientation::AUTO], window, + dimensions, app_path); + is_active_ = true; +} + +void SplashScreen::HideSplashScreen(int reason) { + + if (!is_active_) return; + if (reason == HideReason::RENDERED && + ss_info_->ready_when() != wgt::parse::ReadyWhen::FIRSTPAINT) { + return; + } + if (reason == HideReason::LOADFINISHED && + ss_info_->ready_when() != wgt::parse::ReadyWhen::COMPLETE) { + return; + } + if (reason == HideReason::CUSTOM && + ss_info_->ready_when() != wgt::parse::ReadyWhen::CUSTOM) { + return; + } + + evas_object_hide(background_); + evas_object_hide(image_); + evas_object_hide(window_); + evas_object_del(background_); + evas_object_del(image_); + evas_object_hide(window_); + background_ = nullptr; + image_ = nullptr; + window_ = nullptr; + is_active_ = false; +} + +std::pair SplashScreen::GetDimensions(Evas_Object* window) { + int w, h; + elm_win_screen_size_get(window, NULL, NULL, &w, &h); + evas_object_resize(background_, w, h); + return std::make_pair(w, h); +} + +void SplashScreen::SetBackground( + const wgt::parse::LaunchScreenData& splash_data, Evas_Object* parent, + const SplashScreenBound& bound, const std::string& app_path) { + background_ = elm_bg_add(parent); + if (!background_) return; + evas_object_resize(background_, bound.first, bound.second); + + if (splash_data.background_color != nullptr) { + elm_bg_color_set(background_, + splash_data.background_color->red, + splash_data.background_color->green, + splash_data.background_color->blue); + } + + std::vector border_values; + std::vector border_options; + + if (!splash_data.background_images.empty() && + ParseImageBorder( + splash_data.image_border, &border_values, &border_options)) { + const std::string& background_image_path = + splash_data.background_images.front().first; + + background_image_ = elm_image_add(background_); + evas_object_image_file_set(background_image_, + (app_path + background_image_path).c_str(), + NULL); + elm_image_aspect_fixed_set(background_image_, 0); + evas_object_image_border_center_fill_set(background_image_, + EVAS_BORDER_FILL_DEFAULT); + + evas_object_resize(background_image_, bound.first, bound.second); + + int border_l, border_r, border_t, border_b; + switch (border_values.size()) { + case 1: + border_l = border_r = border_t = border_b = -border_values[0]; + break; + case 2: + border_t = border_b = border_values[0]; + border_l = border_r = border_values[1]; + break; + case 4: + border_t = border_values[0]; + border_r = border_values[1]; + border_b = border_values[2]; + border_l = border_values[3]; + break; + default: + border_l = border_r = border_t = border_b = 0; + } + evas_object_image_border_set(background_image_, + border_l, + border_r, + border_t, + border_b); + // TODO(a.szulakiewi): add scaling of horizontal and vertical borders + } + + evas_object_show(background_); + evas_object_show(background_image_); + evas_object_show(parent); +} + +void SplashScreen::SetImage( + const wgt::parse::LaunchScreenData& splash_data, Evas_Object* parent, + const SplashScreenBound& bound, const std::string& app_path) { + if (!background_) return; + image_ = elm_image_add(background_); + if (!image_) return; + + if (splash_data.images.empty()) return; + + const std::string& image_path = splash_data.images.front().first; + elm_image_file_set(image_, (app_path + image_path).c_str(), NULL); + evas_object_resize(image_, bound.first, bound.second); + evas_object_show(image_); + evas_object_show(parent); +} +} // namespace atom diff --git a/atom/browser/splash_screen.h b/atom/browser/splash_screen.h new file mode 100755 index 0000000..593ff06 --- /dev/null +++ b/atom/browser/splash_screen.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef XWALK_RUNTIME_BROWSER_SPLASH_SCREEN_H_ +#define XWALK_RUNTIME_BROWSER_SPLASH_SCREEN_H_ + +#include +#include +#include +#include +#include + +#include +#include "wgt_manifest_handlers/launch_screen_handler.h" + +enum HideReason { RENDERED, LOADFINISHED, CUSTOM }; + +namespace atom { + +enum class ScreenOrientation { + PORTRAIT_PRIMARY = 0, + PORTRAIT_SECONDARY = 1, + LANDSCAPE_PRIMARY = 2, + LANDSCAPE_SECONDARY = 3, + NATURAL = 4, + ANY = 5 +}; + +class SplashScreen { + public: + typedef std::pair SplashScreenBound; + + SplashScreen(Evas_Object* window, + std::shared_ptr ss_info, + const std::string& app_path); + void HideSplashScreen(int reason); + + private: + std::pair GetDimensions(Evas_Object* window); + void SetBackground(const wgt::parse::LaunchScreenData& splash_data, + Evas_Object* parent, const SplashScreenBound& bound, + const std::string& app_path); + + void SetImage(const wgt::parse::LaunchScreenData& splash_data, + Evas_Object* parent, const SplashScreenBound& bound, + const std::string& app_path); + + std::shared_ptr ss_info_; + Evas_Object* window_; + Evas_Object* image_; + Evas_Object* background_; + Evas_Object* background_image_; + bool is_active_; +}; +} // namespace atom +#endif // XWALK_RUNTIME_BROWSER_SPLASH_SCREEN_H_ diff --git a/wrt.gyp b/wrt.gyp index 54377cf..d8528b0 100644 --- a/wrt.gyp +++ b/wrt.gyp @@ -27,6 +27,8 @@ 'tizen/src/wrt_main.h', 'tizen/loader/prelauncher.h', 'tizen/loader/prelauncher.cc', + 'atom/browser/splash_screen.h', + 'atom/browser/splash_screen.cc', ], 'include_dirs': [ 'tizen/src', diff --git a/wrt/src/web_window.js b/wrt/src/web_window.js index 5258234..06b1f31 100644 --- a/wrt/src/web_window.js +++ b/wrt/src/web_window.js @@ -1,5 +1,5 @@ 'use strict'; -const {BrowserWindow, app} = require('electron'); +const {BrowserWindow, app, pwrt} = require('electron'); const IPC_MESSAGE = require('./ipc_message'); const WAS_EVENT = require('./was_event'); const events = require('./events'); @@ -121,6 +121,8 @@ class WebWindow { }); this.mainWindow.webContents.on('did-finish-load', function() { webwindow_debug('WebWindow : webContents did-finish-load'); + pwrt.hideSplashScreen(1); + if(!options.show){ webwindow_debug('WebWindow : browserWindow show options is ',options.show); self.show(); -- 2.7.4 From 45869969409a9fc62ee794439931e8fc33d38599 Mon Sep 17 00:00:00 2001 From: "surya.kumar7" Date: Tue, 15 May 2018 13:44:21 +0530 Subject: [PATCH 14/16] Set default encoding for WebContents as UTF-8 Currently, the default encoding being used is ISO-8859-1 which is a single-byte encoding and is capable of only supporting limited symbols. Change it to UTF-8(multi byte encoding) just like in crosswalk to extend support for more symbols Change-Id: I92e70445ca668c8db8c258e4ad1a6d41816dd2fb Signed-off-by: surya.kumar7 --- atom/browser/atom_browser_client.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/atom/browser/atom_browser_client.cc b/atom/browser/atom_browser_client.cc index ebbd54a..9408fcf 100644 --- a/atom/browser/atom_browser_client.cc +++ b/atom/browser/atom_browser_client.cc @@ -54,6 +54,8 @@ bool g_suppress_renderer_process_restart = false; // Custom schemes to be registered to handle service worker. std::string g_custom_service_worker_schemes = ""; +const std::string kDefaultEncoding = "UTF-8"; + void Noop(scoped_refptr) { } @@ -161,6 +163,7 @@ void AtomBrowserClient::OverrideWebkitPrefs( prefs->allow_file_access_from_file_urls = true; prefs->experimental_webgl_enabled = true; prefs->allow_running_insecure_content = false; + prefs->default_encoding = kDefaultEncoding; // Custom preferences of guest page. auto web_contents = content::WebContents::FromRenderViewHost(host); -- 2.7.4 From 08923900ea8c54f7fd42a85ace2bff2fa7fa08fb Mon Sep 17 00:00:00 2001 From: deepti Date: Fri, 11 May 2018 16:39:46 +0530 Subject: [PATCH 15/16] Initial Implementation of AppControl Function Handled condition of resetting app. Implemented SendAppControlEvent() for execution of AppControlEventscript. Change-Id: I98b9420a6f5076de598dbdbbdd0968806fc1f34f Signed-off-by: deepti --- atom/browser/browser.cc | 51 ++++++++++++++++++++++++++++++++++++++++++--- atom/browser/browser.h | 1 + atom/browser/window_list.cc | 7 +++++++ atom/browser/window_list.h | 2 +- 4 files changed, 57 insertions(+), 4 deletions(-) diff --git a/atom/browser/browser.cc b/atom/browser/browser.cc index 3ebba72..9efce42 100644 --- a/atom/browser/browser.cc +++ b/atom/browser/browser.cc @@ -14,9 +14,12 @@ #include "base/files/file_util.h" #include "base/path_service.h" #include "base/run_loop.h" +#include "base/strings/string16.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" #include "base/threading/thread_task_runner_handle.h" #include "brightray/browser/brightray_paths.h" - +#include "content/public/browser/render_frame_host.h" #if defined(OS_TIZEN) #include "tizen/common/command_line.h" #include "tizen/common/application_data.h" @@ -43,6 +46,19 @@ Browser::~Browser() { WindowList::RemoveObserver(this); } +const char* kAppControlMain = "http://tizen.org/appcontrol/operation/main"; +const char* kAppControlEventScript = + "(function(){" + "var __event = document.createEvent(\"CustomEvent\");\n" + "__event.initCustomEvent(\"appcontrol\", true, true, null);\n" + "document.dispatchEvent(__event);\n" + "\n" + "for(var i=0; i < window.frames.length; i++)\n" + "{ window.frames[i].document.dispatchEvent(__event); }" + "})()"; +const char* kDefaultCSPRule = + "default-src *; script-src 'self'; style-src 'self'; object-src 'none';"; + // static Browser* Browser::Get() { if (AtomBrowserMainParts::Get()) @@ -276,14 +292,43 @@ void Browser::AppControl(std::unique_ptr appcontrol) { std::unique_ptr res = resource_manager_->GetStartResource(appcontrol.get()); bool do_reset = res->should_reset(); -//To do: Implementation of reset case according to parsed config file parameter. + NativeWindow *last_window= WindowList::GetLastWindow(); + std::string localized_page = res->uri(); + if(!do_reset) + { + std::string current_page=last_window->web_contents()->GetURL().spec(); + if (current_page != localized_page) { + do_reset = true; + } else { + SendAppControlEvent(); + } + } + if (do_reset && (appcontrol->operation() == kAppControlMain)) { + do_reset = false; + SendAppControlEvent(); + } + if (do_reset) { + //To do :Implementation of ClearViewStack(), SetupWebWindow(),SetupWebWindowCompatibilitySettings() function + } +} + +void Browser::SendAppControlEvent() { + std::vector WindowVector; + WindowVector=WindowList::GetWindows(); + NativeWindow *last_window= WindowList::GetLastWindow(); + if (WindowVector.size() > 0 && last_window != NULL) { + content::RenderFrameHost* rfh = last_window->web_contents()->GetMainFrame(); + if (rfh) { + rfh->ExecuteJavaScriptWithUserGestureForTests( + base::UTF8ToUTF16(kAppControlEventScript)); + } + } } void Browser::Launch(std::unique_ptr appcontrol) { launched_ = true; //To do:Implementation of relaunching of app } - #if defined(OS_TIZEN) void Browser::SetSplashScreen() { common::CommandLine* runtime_cmd = common::CommandLine::ForCurrentProcess(); diff --git a/atom/browser/browser.h b/atom/browser/browser.h index 362bfaf..c089fff 100644 --- a/atom/browser/browser.h +++ b/atom/browser/browser.h @@ -125,6 +125,7 @@ class Browser : public WindowListObserver { void Show(); void AppControl(std::unique_ptr appcontrol); void Launch(std::unique_ptr appcontrol); + void SendAppControlEvent(); #if defined(OS_TIZEN) void SetSplashScreen(); void HideSplashScreen(int reason); diff --git a/atom/browser/window_list.cc b/atom/browser/window_list.cc index 374389e..39b91b2 100644 --- a/atom/browser/window_list.cc +++ b/atom/browser/window_list.cc @@ -32,6 +32,13 @@ WindowList::WindowVector WindowList::GetWindows() { } // static +NativeWindow* WindowList::GetLastWindow() { + if (!IsEmpty()) + return GetInstance()->windows_.back(); + else return NULL; +} + +// static bool WindowList::IsEmpty() { return GetInstance()->windows_.empty(); } diff --git a/atom/browser/window_list.h b/atom/browser/window_list.h index e336c80..bffac13 100644 --- a/atom/browser/window_list.h +++ b/atom/browser/window_list.h @@ -22,7 +22,7 @@ class WindowList { static WindowVector GetWindows(); static bool IsEmpty(); - + static NativeWindow* GetLastWindow(); // Adds or removes |window| from the list it is associated with. static void AddWindow(NativeWindow* window); static void RemoveWindow(NativeWindow* window); -- 2.7.4 From 4739f2e776784e72a8eace33defb27e85f161b63 Mon Sep 17 00:00:00 2001 From: "surya.kumar7" Date: Mon, 7 May 2018 17:06:57 +0530 Subject: [PATCH 16/16] Add preload manager and invoke preloadable objects in prelaunch phase Preloading the below engine independent components is giving ~50ms improvement in app launch: xwalk extension server AtomContentClient AtomBrowserClient Change-Id: Iee9bc108aeed0414962b301345c799807dfd043d Signed-off-by: surya.kumar7 --- atom/app/atom_main_delegate.cc | 20 +++++++++++++++-- atom/app/atom_main_delegate.h | 2 ++ atom/app/ui_runtime.cc | 2 ++ atom/browser/atom_browser_main_parts.cc | 9 ++++---- filenames.gypi | 2 ++ tizen/browser/preload_manager.cc | 40 +++++++++++++++++++++++++++++++++ tizen/browser/preload_manager.h | 35 +++++++++++++++++++++++++++++ tizen/src/wrt_main.cc | 2 ++ 8 files changed, 106 insertions(+), 6 deletions(-) create mode 100644 tizen/browser/preload_manager.cc create mode 100644 tizen/browser/preload_manager.h diff --git a/atom/app/atom_main_delegate.cc b/atom/app/atom_main_delegate.cc index 32e6ecf..b88049f 100644 --- a/atom/app/atom_main_delegate.cc +++ b/atom/app/atom_main_delegate.cc @@ -48,8 +48,13 @@ void InvalidParameterHandler(const wchar_t*, const wchar_t*, const wchar_t*, } #endif +bool g_prelaunch_ = false; +std::unique_ptr g_atom_content_client_; +std::unique_ptr g_atom_browser_client_; + } // namespace + AtomMainDelegate::AtomMainDelegate() { } @@ -162,7 +167,9 @@ void AtomMainDelegate::PreSandboxStartup() { } content::ContentBrowserClient* AtomMainDelegate::CreateContentBrowserClient() { - browser_client_.reset(new AtomBrowserClient); + if (!g_prelaunch_) + browser_client_.reset(new AtomBrowserClient); + else browser_client_.reset(g_atom_browser_client_.release()); return browser_client_.get(); } @@ -205,7 +212,16 @@ bool AtomMainDelegate::DelaySandboxInitialization( std::unique_ptr AtomMainDelegate::CreateContentClient() { - return std::unique_ptr(new AtomContentClient); + if (!g_prelaunch_) + return std::unique_ptr(new AtomContentClient); + else return std::unique_ptr(g_atom_content_client_.release()); +} + +// static +void AtomMainDelegate::Preload() { + g_atom_content_client_.reset(new AtomContentClient); + g_atom_browser_client_.reset(new AtomBrowserClient); + g_prelaunch_ = true; } } // namespace atom diff --git a/atom/app/atom_main_delegate.h b/atom/app/atom_main_delegate.h index 64207ae..d768ddf 100644 --- a/atom/app/atom_main_delegate.h +++ b/atom/app/atom_main_delegate.h @@ -17,6 +17,8 @@ class AtomMainDelegate : public brightray::MainDelegate { AtomMainDelegate(); ~AtomMainDelegate(); + static void Preload(); + protected: // content::ContentMainDelegate: bool BasicStartupComplete(int* exit_code) override; diff --git a/atom/app/ui_runtime.cc b/atom/app/ui_runtime.cc index e13e1bf..27f7e0e 100644 --- a/atom/app/ui_runtime.cc +++ b/atom/app/ui_runtime.cc @@ -39,6 +39,8 @@ namespace runtime { UiRuntime::UiRuntime(content::ContentMainParams *params) { _params = params; + // This line's position is essential as this creates the Browser + // object which is needed later on by ui_runtime in its ui_loop callbacks atom::AtomBrowserMainParts::SetNodeEnvironment(); } diff --git a/atom/browser/atom_browser_main_parts.cc b/atom/browser/atom_browser_main_parts.cc index f718f86..3ea0c3e 100644 --- a/atom/browser/atom_browser_main_parts.cc +++ b/atom/browser/atom_browser_main_parts.cc @@ -61,11 +61,8 @@ void Erase(T* container, typename T::iterator iter) { container->erase(iter); } -} // namespace - -// static +// static - lines have been moved to limit their visibility only to this file bool g_prelaunch = false; -AtomBrowserMainParts* AtomBrowserMainParts::self_ = nullptr; node::Environment* env_ = nullptr; scoped_refptr self_bridge_task_runner; std::unique_ptr self_browser; @@ -75,6 +72,10 @@ std::unique_ptr self_atom_bindings; std::unique_ptr self_node_env; std::unique_ptr self_node_debugger; +} // namespace + +AtomBrowserMainParts* AtomBrowserMainParts::self_ = nullptr; + AtomBrowserMainParts::AtomBrowserMainParts() : fake_browser_process_(new BrowserProcess), exit_code_(nullptr), diff --git a/filenames.gypi b/filenames.gypi index 8408b27..0535fab 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -636,6 +636,8 @@ 'chromium_src/net/test/embedded_test_server/stream_listen_socket.h', 'chromium_src/net/test/embedded_test_server/tcp_listen_socket.cc', 'chromium_src/net/test/embedded_test_server/tcp_listen_socket.h', + 'tizen/browser/preload_manager.cc', + 'tizen/browser/preload_manager.h', '<@(native_mate_files)', '<(SHARED_INTERMEDIATE_DIR)/atom_natives.h', '<(SHARED_INTERMEDIATE_DIR)/grit/pdf_viewer_resources_map.cc', diff --git a/tizen/browser/preload_manager.cc b/tizen/browser/preload_manager.cc new file mode 100644 index 0000000..18c645d --- /dev/null +++ b/tizen/browser/preload_manager.cc @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tizen/browser/preload_manager.h" + +#include "atom/app/atom_main_delegate.h" +#include "extensions/common/xwalk_extension_server.h" + +namespace tizen { + +PreloadManager* PreloadManager::GetInstance() { + static PreloadManager instance; + return &instance; +} + +PreloadManager::PreloadManager() { +} + +void PreloadManager::CreateCacheComponent() { + // Load extensions in the preload step + auto extension_server = extensions::XWalkExtensionServer::GetInstance(); + extension_server->Preload(); + + atom::AtomMainDelegate::Preload(); +} + +} // namespace tizen diff --git a/tizen/browser/preload_manager.h b/tizen/browser/preload_manager.h new file mode 100644 index 0000000..4f06612 --- /dev/null +++ b/tizen/browser/preload_manager.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TIZEN_BROWSER_PRELOAD_MANAGER_H_ +#define TIZEN_BROWSER_PRELOAD_MANAGER_H_ + +#include + + +namespace tizen { +class PreloadManager { + public: + static PreloadManager* GetInstance(); + void CreateCacheComponent(); + + private: + PreloadManager(); +}; + +} // namespace tizen + +#endif // TIZEN_BROWSER_PRELOAD_MANAGER_H_ diff --git a/tizen/src/wrt_main.cc b/tizen/src/wrt_main.cc index 0bf3635..8c8052b 100644 --- a/tizen/src/wrt_main.cc +++ b/tizen/src/wrt_main.cc @@ -44,6 +44,7 @@ #include "tizen/common/application_data.h" #include "tizen/common/command_line.h" #include "tizen/loader/prelauncher.h" +#include "tizen/browser/preload_manager.h" #endif namespace { @@ -236,6 +237,7 @@ int main(int argc, const char* argv[]) { params.argv = const_cast(argv); atom::AtomCommandLine::Init(argc, argv); runtime_ = runtime::Runtime::MakeRuntime(nullptr); + tizen::PreloadManager::GetInstance()->CreateCacheComponent(); return 0; }; auto did_launch = [](const std::string& app_path) { -- 2.7.4