]> git.wh0rd.org Git - chrome-ext/wake-on-lan.git/commitdiff
initial commit v0.1.0
authorMike Frysinger <vapier@gentoo.org>
Sat, 23 May 2015 02:36:50 +0000 (22:36 -0400)
committerMike Frysinger <vapier@gentoo.org>
Sat, 23 May 2015 02:36:50 +0000 (22:36 -0400)
14 files changed:
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
images/icon-128x128.png [new file with mode: 0644]
images/icon-48x48.png [new file with mode: 0644]
images/icon.svg [new file with mode: 0644]
images/tile-small.png [new file with mode: 0644]
js/common.js [new file with mode: 0644]
js/launcher.js [new file with mode: 0644]
js/main.js [new file with mode: 0644]
js/net_error_list.js [new file with mode: 0644]
main.html [new file with mode: 0644]
makedist.sh [new file with mode: 0755]
manifest.files [new file with mode: 0644]
manifest.json [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..c4c4ffc
--- /dev/null
@@ -0,0 +1 @@
+*.zip
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..5e88047
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,23 @@
+CLOSURE = closure-compiler --language_in ECMASCRIPT5
+YUICOMPRESSOR = yuicompressor
+
+all:
+
+%.js.min: %.js
+       $(CLOSURE) $< > $@
+
+JS_FILES = $(shell grep '[.]js$$' manifest.files)
+js-min: $(JS_FILES:=.min)
+
+%.css.min: %.css
+       $(YUICOMPRESSOR) $< > $@
+
+CSS_FILES = $(shell grep '[.]css$$' manifest.files)
+css-min: $(CSS_FILES:=.min)
+
+check: css-min js-min
+
+dist:
+       ./makedist.sh
+
+.PHONY: all clean check css-min dist js-min
diff --git a/images/icon-128x128.png b/images/icon-128x128.png
new file mode 100644 (file)
index 0000000..c1bf91b
Binary files /dev/null and b/images/icon-128x128.png differ
diff --git a/images/icon-48x48.png b/images/icon-48x48.png
new file mode 100644 (file)
index 0000000..37d4f18
Binary files /dev/null and b/images/icon-48x48.png differ
diff --git a/images/icon.svg b/images/icon.svg
new file mode 100644 (file)
index 0000000..66aff87
--- /dev/null
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   viewBox="0 0 122.11087 141.51784"
+   id="svg2996"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   width="100%"
+   height="100%"
+   sodipodi:docname="icon.svg"
+   inkscape:export-filename="icon.png"
+   inkscape:export-xdpi="81.07386"
+   inkscape:export-ydpi="81.07386">
+  <metadata
+     id="metadata3030">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs3028">
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient1570"
+       x2="0"
+       y1="119.7196"
+       y2="163.79573">
+      <stop
+         offset="0"
+         stop-color="#ffc800"
+         id="stop7" />
+      <stop
+         offset="1"
+         stop-color="#ffc800"
+         stop-opacity="0"
+         id="stop9" />
+    </linearGradient>
+    <linearGradient
+       y2="163.79573"
+       x2="0"
+       y1="119.7196"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3122"
+       xlink:href="#linearGradient1570"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient1570"
+       id="linearGradient3166"
+       gradientUnits="userSpaceOnUse"
+       y1="119.7196"
+       x2="0"
+       y2="163.79573" />
+  </defs>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1600"
+     inkscape:window-height="879"
+     id="namedview3026"
+     showgrid="false"
+     inkscape:zoom="6.7302061"
+     inkscape:cx="54.159796"
+     inkscape:cy="83.495276"
+     inkscape:window-x="-4"
+     inkscape:window-y="-4"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg2996"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0" />
+  <g
+     transform="translate(-57.895832,-45.259034)"
+     id="g2998">
+    <path
+       d="m 64.40972,69.93056 h 108.85419 a 4.51389,4.51389 0 0 1 4.51389,4.51389 v 81.59722 a 4.51389,4.51389 0 0 1 -4.51389,4.51389 H 64.40972 a 4.51389,4.51389 0 0 1 -4.51389,-4.51389 V 74.44445 a 4.51389,4.51389 0 0 1 4.51389,-4.51389"
+       id="path3000"
+       inkscape:connector-curvature="0"
+       style="fill:#ffffff;stroke:#0a0a0a;stroke-width:4;stroke-linecap:square" />
+    <path
+       d="m 73.95833,75.65972 h 89.40973 c 2.30833,0 4.16666,1.85833 4.16666,4.16667 l 2.8e-4,52.65261 h -21.742 v 9.414 h -8.694 l 4e-5,12.586 h -36.871 l -4e-5,-12.586 h -8.694 v -9.414 H 69.79204 L 69.7917,79.82639 c -1.1e-5,-2.30833 1.85833,-4.16667 4.16667,-4.16667 z"
+       id="path3002"
+       inkscape:connector-curvature="0"
+       style="fill:#dcdcdc;stroke:#0a0a0a;stroke-width:2.5;stroke-linecap:square" />
+    <g
+       transform="translate(-0.36789,0)"
+       id="g3004">
+      <path
+         d="m 80.55555,75.74653 h 3.90624 v 22.78646 h -3.90624 z"
+         id="path3006"
+         inkscape:connector-curvature="0"
+         style="fill:#666666;stroke:#191919;stroke-linecap:square" />
+      <path
+         d="m 153.60065,75.74653 h 3.90624 v 22.78646 h -3.90624 z"
+         id="path3008"
+         inkscape:connector-curvature="0"
+         style="fill:#666666;stroke:#191919;stroke-linecap:square" />
+      <path
+         d="m 132.73062,75.74653 h 3.90624 v 22.78646 h -3.90624 z"
+         id="path3010"
+         inkscape:connector-curvature="0"
+         style="fill:#666666;stroke:#191919;stroke-linecap:square" />
+      <path
+         d="m 122.29561,75.74653 h 3.90624 v 22.78646 h -3.90624 z"
+         id="path3012"
+         inkscape:connector-curvature="0"
+         style="fill:#666666;stroke:#191919;stroke-linecap:square" />
+      <path
+         d="m 111.8606,75.74653 h 3.90624 v 22.78646 h -3.90624 z"
+         id="path3014"
+         inkscape:connector-curvature="0"
+         style="fill:#666666;stroke:#191919;stroke-linecap:square" />
+      <path
+         d="m 101.42558,75.74653 h 3.90624 v 22.78646 h -3.90624 z"
+         id="path3016"
+         inkscape:connector-curvature="0"
+         style="fill:#666666;stroke:#191919;stroke-linecap:square" />
+      <path
+         d="m 90.99057,75.74653 h 3.90624 v 22.78646 h -3.90624 z"
+         id="path3018"
+         inkscape:connector-curvature="0"
+         style="fill:#666666;stroke:#191919;stroke-linecap:square" />
+      <path
+         d="m 143.16563,75.74653 h 3.90624 v 22.78646 h -3.90624 z"
+         id="path3020"
+         inkscape:connector-curvature="0"
+         style="fill:#666666;stroke:#191919;stroke-linecap:square" />
+    </g>
+    <path
+       d="m 69.5417,137.03125 h 17.1007 v 13.88889 H 69.5417 z"
+       id="path3022"
+       inkscape:connector-curvature="0"
+       style="fill:#1dfe0a;stroke:#0a0a0a;stroke-width:2;stroke-linecap:square" />
+    <path
+       d="m 150.68431,137.03125 h 17.1007 v 13.88889 h -17.1007 z"
+       id="path3024"
+       inkscape:connector-curvature="0"
+       style="fill:#ffd10a;stroke:#0a0a0a;stroke-width:2;stroke-linecap:square" />
+  </g>
+  <g
+     transform="matrix(2.7330179,0,0,2.3357807,-505.79438,-272.03481)"
+     id="g11">
+    <path
+       style="fill:#fff000;fill-rule:evenodd;stroke:#6b5400"
+       inkscape:connector-curvature="0"
+       d="m 213.57143,117.00504 h 15.71428 l -16.34821,28.31593 -5.35932,-3.0942 -19.79361,34.28353 12.89812,-48.13644 5.45925,3.1519 7.42949,-14.52072 z"
+       id="path13" />
+    <path
+       style="opacity:0.8;fill:url(#linearGradient3166);fill-rule:evenodd"
+       inkscape:connector-curvature="0"
+       d="m 214.77394,119.89818 9.40882,-0.17858 -12.44687,21.71154 -4.54868,-2.62618 -14.12113,24.99077 9.34005,-31.74834 4.63351,2.67515 7.7343,-14.82436 z"
+       id="path15" />
+  </g>
+</svg>
diff --git a/images/tile-small.png b/images/tile-small.png
new file mode 100644 (file)
index 0000000..833d8c9
Binary files /dev/null and b/images/tile-small.png differ
diff --git a/js/common.js b/js/common.js
new file mode 100644 (file)
index 0000000..4bda93e
--- /dev/null
@@ -0,0 +1,6 @@
+// Written by Mike Frysinger <vapier@gmail.com>.
+// Released into the public domain.
+
+function $(s) { return document.querySelectorAll(s); }
+function $$(s) { return document.querySelector(s); }
+function nullcb() {}
diff --git a/js/launcher.js b/js/launcher.js
new file mode 100644 (file)
index 0000000..3dbd4ac
--- /dev/null
@@ -0,0 +1,6 @@
+// Written by Mike Frysinger <vapier@gmail.com>.
+// Released into the public domain.
+
+chrome.app.runtime.onLaunched.addListener(function() {
+       chrome.app.window.create('main.html')
+});
diff --git a/js/main.js b/js/main.js
new file mode 100644 (file)
index 0000000..b6ce2a9
--- /dev/null
@@ -0,0 +1,243 @@
+// Written by Mike Frysinger <vapier@gmail.com>.
+// Released into the public domain.
+
+function status(msg) {
+       $$('[name=status]').innerText = msg;
+}
+
+// Create a packet following the spec:
+// https://en.wikipedia.org/wiki/Wake-on-LAN#Magic_packet
+function magicpacket(mac, pass) {
+       var data = new ArrayBuffer(6 + 16 * 6 + 6 + 6);
+       var bytes = new Uint8Array(data);
+       var i, j, base = 0;
+
+       // First 6 bytes should be all 0xFF.
+       for (i = 0; i < 6; ++i)
+               bytes[base + i] = 0xff;
+       base += 6;
+
+       // Then the MAC address is repeated 16 times.
+       for (i = 0; i < 6; ++i)
+               for (j = 0; j < 16 * 6; j += 6)
+                       bytes[base + j + i] = mac[i];
+       base += 16 * 6;
+
+       // Then 6 bytes before the pass should be 0xFF.
+       for (i = 0; i < 6; ++i)
+               bytes[base + i] = 0xff;
+       base += 6;
+
+       // Finally the 6 bytes of the password.
+       for (i = 0; i < 6; ++i)
+               bytes[base + i] = pass[i];
+
+       return data;
+}
+
+function split_data(v) {
+       var data = Array(6);
+       var i, idata;
+
+       window['sync_' + v]();
+
+       for (i = 0; i < 6; ++i) {
+               idata = $$('input[name=' + v + i + ']');
+               if (!/^[0-9a-fA-F]?[0-9a-fA-F]$/.test(idata.value.replace(' ', ''))) {
+                       status(v + ' byte ' + i + ' is invalid; must be 2 hex characters');
+                       idata.focus();
+                       idata.setSelectionRange(0, idata.value.length);
+                       return false;
+               }
+               data[i] = parseInt(idata.value, 16);
+       }
+
+       return data;
+}
+
+function send() {
+       status('initializing');
+
+       var form = $$('form[name=settings]');
+       var shost = '0.0.0.0';
+       var dhost = form.host.value;
+       var port = parseInt(form.port.value);
+
+       // Get the MAC address & password to convert to packet data.
+       var mac = split_data('mac');
+       var pass = split_data('pass');
+       var data = magicpacket(mac, pass);
+       console.log('packet', new Uint8Array(data));
+
+       var checkresult = function(s, step, result) {
+               if (result < 0) {
+                       status('error in ' + step + ': ' + net_error_list[result]);
+                       chrome.sockets.udp.close(s, nullcb);
+                       return false;
+               }
+               return true;
+       };
+
+       // Create the socket ...
+       chrome.sockets.udp.create({}, function(createInfo) {
+               var s = createInfo.socketId;
+
+               console.log('[create] socketInfo', createInfo);
+               status('binding ' + shost);
+
+               // Bind it locally ...
+               chrome.sockets.udp.bind(s, shost, 0, function(result) {
+                       console.log('[bind] result', result);
+
+                       if (!checkresult(s, 'bind', result))
+                               return false;
+
+                       status('enabling broadcast');
+
+                       // Turn on broadcast support ...
+                       chrome.sockets.udp.setBroadcast(s, true, function(result) {
+                               console.log('[setBroadcast] result', result);
+
+                               if (!checkresult(s, 'broadcast', result))
+                                       return false;
+
+                               status('sending to ' + dhost + ':' + port);
+
+                               // Send the backet ...
+                               chrome.sockets.udp.send(s, data, dhost, port, function(sendInfo) {
+                                       console.log('[send] sendInfo', sendInfo);
+
+                                       if (!checkresult(s, 'send', sendInfo.resultCode))
+                                               return false;
+
+                                       status('closing');
+
+                                       // Shut it down ...
+                                       chrome.sockets.udp.close(s, function() {
+                                               status('sent to ' + dhost + ':' + port);
+                                               store_settings();
+                                       });
+                               });
+                       });
+               });
+       });
+
+       // Keep the form from submitting.
+       return false;
+}
+
+function sync_it(v) {
+       var smany = $$('span[name=' + v + '-many]');
+       var sone = $$('span[name=' + v + '-one]');
+
+       // Sync the two sets of fields.
+       var i;
+       if (smany.hidden) {
+               var idata = $$('input[name=' + v + ']');
+               var data = idata.value.split(':');
+
+               if (data.length != 6) {
+                       data = idata.value.replace(/[ :]/g, '');
+                       if (data.length != 6 * 2) {
+                               status('invalid ' + v + '; please fix');
+                               return false;
+                       }
+                       data = data.match(/../g);
+               } else {
+                       for (i = 0; i < 6; ++i)
+                               if (data[i].length > 2) {
+                                       status('invalid ' + v + ' please fix');
+                                       return false;
+                               }
+               }
+
+               for (i = 0; i < 6; ++i)
+                       $$('input[name=' + v + i + ']').value = data[i];
+       } else {
+               var data = '';
+
+               for (i = 0; i < 6; ++i) {
+                       data += $$('input[name=' + v + i + ']').value;
+                       if (i < 5)
+                               data += ':';
+               }
+
+               $$('input[name=' + v + ']').value = data;
+       }
+}
+function sync_mac()  { return sync_it('mac');  }
+function sync_pass() { return sync_it('pass'); }
+
+
+function paste_mac() {
+       sync_mac();
+
+       var smany = $$('span[name=mac-many]');
+       var sone = $$('span[name=mac-one]');
+       smany.hidden = !smany.hidden;
+       sone.hidden = !sone.hidden;
+
+       return false;
+}
+
+function paste_pass() {
+       sync_pass();
+
+       var smany = $$('span[name=pass-many]');
+       var sone = $$('span[name=pass-one]');
+       smany.hidden = !smany.hidden;
+       sone.hidden = !sone.hidden;
+
+       return false;
+}
+
+/*
+ * Storage logic.
+ */
+var settings_keys = [
+       'host',
+       'mac',
+       'pass',
+       'port',
+];
+
+function load_settings() {
+       var storage = chrome.storage.local;
+
+       chrome.storage.local.get(settings_keys, function(settings) {
+               var form = $$('form[name=settings]');
+               form.host.value = settings['host'] || '192.168.0.255';
+               form.port.value = settings['port'] || '40000';
+               // We assume we only get called during init.
+               paste_mac();
+               form.mac.value = settings['mac'] || '20:00:00:00:00:00';
+               paste_mac();
+               paste_pass();
+               form.pass.value = settings['pass'] || '00:00:00:00:00:00';
+               paste_pass();
+       });
+}
+
+function store_settings() {
+       var form = $$('form[name=settings]');
+       sync_mac();
+       sync_pass();
+       var settings = {
+               'host': form.host.value,
+               'mac': form.mac.value,
+               'pass': form.pass.value,
+               'port': form.port.value,
+       };
+       chrome.storage.local.set(settings);
+}
+
+/*
+ * Startup.
+ */
+window.onload = function() {
+       $$('form[name=settings]').onsubmit = send;
+       $$('a[name=mac-paste]').onclick = paste_mac;
+       $$('a[name=pass-paste]').onclick = paste_pass;
+
+       load_settings();
+};
diff --git a/js/net_error_list.js b/js/net_error_list.js
new file mode 100644 (file)
index 0000000..7a13d9f
--- /dev/null
@@ -0,0 +1,361 @@
+/* Auto-generated from chromium/src/net/base/net_error_list.h; do not edit. */
+
+var net_error_list = {
+       "-1": "IO_PENDING",
+       "-2": "FAILED",
+       "-3": "ABORTED",
+       "-4": "INVALID_ARGUMENT",
+       "-5": "INVALID_HANDLE",
+       "-6": "FILE_NOT_FOUND",
+       "-7": "TIMED_OUT",
+       "-8": "FILE_TOO_BIG",
+       "-9": "UNEXPECTED",
+       "-10": "ACCESS_DENIED",
+       "-11": "NOT_IMPLEMENTED",
+       "-12": "INSUFFICIENT_RESOURCES",
+       "-13": "OUT_OF_MEMORY",
+       "-14": "UPLOAD_FILE_CHANGED",
+       "-15": "SOCKET_NOT_CONNECTED",
+       "-16": "FILE_EXISTS",
+       "-17": "FILE_PATH_TOO_LONG",
+       "-18": "FILE_NO_SPACE",
+       "-19": "FILE_VIRUS_INFECTED",
+       "-20": "BLOCKED_BY_CLIENT",
+       "-21": "NETWORK_CHANGED",
+       "-22": "BLOCKED_BY_ADMINISTRATOR",
+       "-23": "SOCKET_IS_CONNECTED",
+       "-100": "CONNECTION_CLOSED",
+       "-101": "CONNECTION_RESET",
+       "-102": "CONNECTION_REFUSED",
+       "-103": "CONNECTION_ABORTED",
+       "-104": "CONNECTION_FAILED",
+       "-105": "NAME_NOT_RESOLVED",
+       "-106": "INTERNET_DISCONNECTED",
+       "-107": "SSL_PROTOCOL_ERROR",
+       "-108": "ADDRESS_INVALID",
+       "-109": "ADDRESS_UNREACHABLE",
+       "-110": "SSL_CLIENT_AUTH_CERT_NEEDED",
+       "-111": "TUNNEL_CONNECTION_FAILED",
+       "-112": "NO_SSL_VERSIONS_ENABLED",
+       "-113": "SSL_VERSION_OR_CIPHER_MISMATCH",
+       "-114": "SSL_RENEGOTIATION_REQUESTED",
+       "-115": "PROXY_AUTH_UNSUPPORTED",
+       "-116": "CERT_ERROR_IN_SSL_RENEGOTIATION",
+       "-117": "BAD_SSL_CLIENT_AUTH_CERT",
+       "-118": "CONNECTION_TIMED_OUT",
+       "-119": "HOST_RESOLVER_QUEUE_TOO_LARGE",
+       "-120": "SOCKS_CONNECTION_FAILED",
+       "-121": "SOCKS_CONNECTION_HOST_UNREACHABLE",
+       "-122": "NPN_NEGOTIATION_FAILED",
+       "-123": "SSL_NO_RENEGOTIATION",
+       "-124": "WINSOCK_UNEXPECTED_WRITTEN_BYTES",
+       "-125": "SSL_DECOMPRESSION_FAILURE_ALERT",
+       "-126": "SSL_BAD_RECORD_MAC_ALERT",
+       "-127": "PROXY_AUTH_REQUESTED",
+       "-128": "SSL_UNSAFE_NEGOTIATION",
+       "-129": "SSL_WEAK_SERVER_EPHEMERAL_DH_KEY",
+       "-130": "PROXY_CONNECTION_FAILED",
+       "-131": "MANDATORY_PROXY_CONFIGURATION_FAILED",
+       "-133": "PRECONNECT_MAX_SOCKET_LIMIT",
+       "-134": "SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED",
+       "-135": "SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY",
+       "-136": "PROXY_CERTIFICATE_INVALID",
+       "-137": "NAME_RESOLUTION_FAILED",
+       "-138": "NETWORK_ACCESS_DENIED",
+       "-139": "TEMPORARILY_THROTTLED",
+       "-140": "HTTPS_PROXY_TUNNEL_RESPONSE",
+       "-141": "SSL_CLIENT_AUTH_SIGNATURE_FAILED",
+       "-142": "MSG_TOO_BIG",
+       "-143": "SPDY_SESSION_ALREADY_EXISTS",
+       "-145": "WS_PROTOCOL_ERROR",
+       "-146": "PROTOCOL_SWITCHED",
+       "-147": "ADDRESS_IN_USE",
+       "-148": "SSL_HANDSHAKE_NOT_COMPLETED",
+       "-149": "SSL_BAD_PEER_PUBLIC_KEY",
+       "-150": "SSL_PINNED_KEY_NOT_IN_CERT_CHAIN",
+       "-151": "CLIENT_AUTH_CERT_TYPE_UNSUPPORTED",
+       "-152": "ORIGIN_BOUND_CERT_GENERATION_TYPE_MISMATCH",
+       "-153": "SSL_DECRYPT_ERROR_ALERT",
+       "-154": "WS_THROTTLE_QUEUE_TOO_LARGE",
+       "-155": "TOO_MANY_SOCKET_STREAMS",
+       "-156": "SSL_SERVER_CERT_CHANGED",
+       "-157": "SSL_INAPPROPRIATE_FALLBACK",
+       "-158": "CT_NO_SCTS_VERIFIED_OK",
+       "-200": "CERT_COMMON_NAME_INVALID",
+       "-201": "CERT_DATE_INVALID",
+       "-202": "CERT_AUTHORITY_INVALID",
+       "-203": "CERT_CONTAINS_ERRORS",
+       "-204": "CERT_NO_REVOCATION_MECHANISM",
+       "-205": "CERT_UNABLE_TO_CHECK_REVOCATION",
+       "-206": "CERT_REVOKED",
+       "-207": "CERT_INVALID",
+       "-208": "CERT_WEAK_SIGNATURE_ALGORITHM",
+       "-210": "CERT_NON_UNIQUE_NAME",
+       "-211": "CERT_WEAK_KEY",
+       "-212": "CERT_NAME_CONSTRAINT_VIOLATION",
+       "-213": "CERT_END",
+       "-300": "INVALID_URL",
+       "-301": "DISALLOWED_URL_SCHEME",
+       "-302": "UNKNOWN_URL_SCHEME",
+       "-310": "TOO_MANY_REDIRECTS",
+       "-311": "UNSAFE_REDIRECT",
+       "-312": "UNSAFE_PORT",
+       "-320": "INVALID_RESPONSE",
+       "-321": "INVALID_CHUNKED_ENCODING",
+       "-322": "METHOD_NOT_SUPPORTED",
+       "-323": "UNEXPECTED_PROXY_AUTH",
+       "-324": "EMPTY_RESPONSE",
+       "-325": "RESPONSE_HEADERS_TOO_BIG",
+       "-326": "PAC_STATUS_NOT_OK",
+       "-327": "PAC_SCRIPT_FAILED",
+       "-328": "REQUEST_RANGE_NOT_SATISFIABLE",
+       "-329": "MALFORMED_IDENTITY",
+       "-330": "CONTENT_DECODING_FAILED",
+       "-331": "NETWORK_IO_SUSPENDED",
+       "-332": "SYN_REPLY_NOT_RECEIVED",
+       "-333": "ENCODING_CONVERSION_FAILED",
+       "-334": "UNRECOGNIZED_FTP_DIRECTORY_LISTING_FORMAT",
+       "-335": "INVALID_SPDY_STREAM",
+       "-336": "NO_SUPPORTED_PROXIES",
+       "-337": "SPDY_PROTOCOL_ERROR",
+       "-338": "INVALID_AUTH_CREDENTIALS",
+       "-339": "UNSUPPORTED_AUTH_SCHEME",
+       "-340": "ENCODING_DETECTION_FAILED",
+       "-341": "MISSING_AUTH_CREDENTIALS",
+       "-342": "UNEXPECTED_SECURITY_LIBRARY_STATUS",
+       "-343": "MISCONFIGURED_AUTH_ENVIRONMENT",
+       "-344": "UNDOCUMENTED_SECURITY_LIBRARY_STATUS",
+       "-345": "RESPONSE_BODY_TOO_BIG_TO_DRAIN",
+       "-346": "RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH",
+       "-347": "INCOMPLETE_SPDY_HEADERS",
+       "-348": "PAC_NOT_IN_DHCP",
+       "-349": "RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION",
+       "-350": "RESPONSE_HEADERS_MULTIPLE_LOCATION",
+       "-351": "SPDY_SERVER_REFUSED_STREAM",
+       "-352": "SPDY_PING_FAILED",
+       "-353": "PIPELINE_EVICTION",
+       "-354": "CONTENT_LENGTH_MISMATCH",
+       "-355": "INCOMPLETE_CHUNKED_ENCODING",
+       "-356": "QUIC_PROTOCOL_ERROR",
+       "-357": "RESPONSE_HEADERS_TRUNCATED",
+       "-358": "QUIC_HANDSHAKE_FAILED",
+       "-400": "CACHE_MISS",
+       "-401": "CACHE_READ_FAILURE",
+       "-402": "CACHE_WRITE_FAILURE",
+       "-403": "CACHE_OPERATION_NOT_SUPPORTED",
+       "-404": "CACHE_OPEN_FAILURE",
+       "-405": "CACHE_CREATE_FAILURE",
+       "-406": "CACHE_RACE",
+       "-407": "CACHE_CHECKSUM_READ_FAILURE",
+       "-408": "CACHE_CHECKSUM_MISMATCH",
+       "-501": "INSECURE_RESPONSE",
+       "-502": "NO_PRIVATE_KEY_FOR_CERT",
+       "-503": "ADD_USER_CERT_FAILED",
+       "-601": "FTP_FAILED",
+       "-602": "FTP_SERVICE_UNAVAILABLE",
+       "-603": "FTP_TRANSFER_ABORTED",
+       "-604": "FTP_FILE_BUSY",
+       "-605": "FTP_SYNTAX_ERROR",
+       "-606": "FTP_COMMAND_NOT_SUPPORTED",
+       "-607": "FTP_BAD_COMMAND_SEQUENCE",
+       "-701": "PKCS12_IMPORT_BAD_PASSWORD",
+       "-702": "PKCS12_IMPORT_FAILED",
+       "-703": "IMPORT_CA_CERT_NOT_CA",
+       "-704": "IMPORT_CERT_ALREADY_EXISTS",
+       "-705": "IMPORT_CA_CERT_FAILED",
+       "-706": "IMPORT_SERVER_CERT_FAILED",
+       "-707": "PKCS12_IMPORT_INVALID_MAC",
+       "-708": "PKCS12_IMPORT_INVALID_FILE",
+       "-709": "PKCS12_IMPORT_UNSUPPORTED",
+       "-710": "KEY_GENERATION_FAILED",
+       "-711": "ORIGIN_BOUND_CERT_GENERATION_FAILED",
+       "-712": "PRIVATE_KEY_EXPORT_FAILED",
+       "-713": "SELF_SIGNED_CERT_GENERATION_FAILED",
+       "-714": "CERT_DATABASE_CHANGED",
+       "-800": "DNS_MALFORMED_RESPONSE",
+       "-801": "DNS_SERVER_REQUIRES_TCP",
+       "-802": "DNS_SERVER_FAILED",
+       "-803": "DNS_TIMED_OUT",
+       "-804": "DNS_CACHE_MISS",
+       "-805": "DNS_SEARCH_EMPTY",
+       "-806": "DNS_SORT_ERROR",
+};
+
+var NET_ERR_IO_PENDING = -1;
+var NET_ERR_FAILED = -2;
+var NET_ERR_ABORTED = -3;
+var NET_ERR_INVALID_ARGUMENT = -4;
+var NET_ERR_INVALID_HANDLE = -5;
+var NET_ERR_FILE_NOT_FOUND = -6;
+var NET_ERR_TIMED_OUT = -7;
+var NET_ERR_FILE_TOO_BIG = -8;
+var NET_ERR_UNEXPECTED = -9;
+var NET_ERR_ACCESS_DENIED = -10;
+var NET_ERR_NOT_IMPLEMENTED = -11;
+var NET_ERR_INSUFFICIENT_RESOURCES = -12;
+var NET_ERR_OUT_OF_MEMORY = -13;
+var NET_ERR_UPLOAD_FILE_CHANGED = -14;
+var NET_ERR_SOCKET_NOT_CONNECTED = -15;
+var NET_ERR_FILE_EXISTS = -16;
+var NET_ERR_FILE_PATH_TOO_LONG = -17;
+var NET_ERR_FILE_NO_SPACE = -18;
+var NET_ERR_FILE_VIRUS_INFECTED = -19;
+var NET_ERR_BLOCKED_BY_CLIENT = -20;
+var NET_ERR_NETWORK_CHANGED = -21;
+var NET_ERR_BLOCKED_BY_ADMINISTRATOR = -22;
+var NET_ERR_SOCKET_IS_CONNECTED = -23;
+var NET_ERR_CONNECTION_CLOSED = -100;
+var NET_ERR_CONNECTION_RESET = -101;
+var NET_ERR_CONNECTION_REFUSED = -102;
+var NET_ERR_CONNECTION_ABORTED = -103;
+var NET_ERR_CONNECTION_FAILED = -104;
+var NET_ERR_NAME_NOT_RESOLVED = -105;
+var NET_ERR_INTERNET_DISCONNECTED = -106;
+var NET_ERR_SSL_PROTOCOL_ERROR = -107;
+var NET_ERR_ADDRESS_INVALID = -108;
+var NET_ERR_ADDRESS_UNREACHABLE = -109;
+var NET_ERR_SSL_CLIENT_AUTH_CERT_NEEDED = -110;
+var NET_ERR_TUNNEL_CONNECTION_FAILED = -111;
+var NET_ERR_NO_SSL_VERSIONS_ENABLED = -112;
+var NET_ERR_SSL_VERSION_OR_CIPHER_MISMATCH = -113;
+var NET_ERR_SSL_RENEGOTIATION_REQUESTED = -114;
+var NET_ERR_PROXY_AUTH_UNSUPPORTED = -115;
+var NET_ERR_CERT_ERROR_IN_SSL_RENEGOTIATION = -116;
+var NET_ERR_BAD_SSL_CLIENT_AUTH_CERT = -117;
+var NET_ERR_CONNECTION_TIMED_OUT = -118;
+var NET_ERR_HOST_RESOLVER_QUEUE_TOO_LARGE = -119;
+var NET_ERR_SOCKS_CONNECTION_FAILED = -120;
+var NET_ERR_SOCKS_CONNECTION_HOST_UNREACHABLE = -121;
+var NET_ERR_NPN_NEGOTIATION_FAILED = -122;
+var NET_ERR_SSL_NO_RENEGOTIATION = -123;
+var NET_ERR_WINSOCK_UNEXPECTED_WRITTEN_BYTES = -124;
+var NET_ERR_SSL_DECOMPRESSION_FAILURE_ALERT = -125;
+var NET_ERR_SSL_BAD_RECORD_MAC_ALERT = -126;
+var NET_ERR_PROXY_AUTH_REQUESTED = -127;
+var NET_ERR_SSL_UNSAFE_NEGOTIATION = -128;
+var NET_ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY = -129;
+var NET_ERR_PROXY_CONNECTION_FAILED = -130;
+var NET_ERR_MANDATORY_PROXY_CONFIGURATION_FAILED = -131;
+var NET_ERR_PRECONNECT_MAX_SOCKET_LIMIT = -133;
+var NET_ERR_SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED = -134;
+var NET_ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY = -135;
+var NET_ERR_PROXY_CERTIFICATE_INVALID = -136;
+var NET_ERR_NAME_RESOLUTION_FAILED = -137;
+var NET_ERR_NETWORK_ACCESS_DENIED = -138;
+var NET_ERR_TEMPORARILY_THROTTLED = -139;
+var NET_ERR_HTTPS_PROXY_TUNNEL_RESPONSE = -140;
+var NET_ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED = -141;
+var NET_ERR_MSG_TOO_BIG = -142;
+var NET_ERR_SPDY_SESSION_ALREADY_EXISTS = -143;
+var NET_ERR_WS_PROTOCOL_ERROR = -145;
+var NET_ERR_PROTOCOL_SWITCHED = -146;
+var NET_ERR_ADDRESS_IN_USE = -147;
+var NET_ERR_SSL_HANDSHAKE_NOT_COMPLETED = -148;
+var NET_ERR_SSL_BAD_PEER_PUBLIC_KEY = -149;
+var NET_ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN = -150;
+var NET_ERR_CLIENT_AUTH_CERT_TYPE_UNSUPPORTED = -151;
+var NET_ERR_ORIGIN_BOUND_CERT_GENERATION_TYPE_MISMATCH = -152;
+var NET_ERR_SSL_DECRYPT_ERROR_ALERT = -153;
+var NET_ERR_WS_THROTTLE_QUEUE_TOO_LARGE = -154;
+var NET_ERR_TOO_MANY_SOCKET_STREAMS = -155;
+var NET_ERR_SSL_SERVER_CERT_CHANGED = -156;
+var NET_ERR_SSL_INAPPROPRIATE_FALLBACK = -157;
+var NET_ERR_CT_NO_SCTS_VERIFIED_OK = -158;
+var NET_ERR_CERT_COMMON_NAME_INVALID = -200;
+var NET_ERR_CERT_DATE_INVALID = -201;
+var NET_ERR_CERT_AUTHORITY_INVALID = -202;
+var NET_ERR_CERT_CONTAINS_ERRORS = -203;
+var NET_ERR_CERT_NO_REVOCATION_MECHANISM = -204;
+var NET_ERR_CERT_UNABLE_TO_CHECK_REVOCATION = -205;
+var NET_ERR_CERT_REVOKED = -206;
+var NET_ERR_CERT_INVALID = -207;
+var NET_ERR_CERT_WEAK_SIGNATURE_ALGORITHM = -208;
+var NET_ERR_CERT_NON_UNIQUE_NAME = -210;
+var NET_ERR_CERT_WEAK_KEY = -211;
+var NET_ERR_CERT_NAME_CONSTRAINT_VIOLATION = -212;
+var NET_ERR_CERT_END = -213;
+var NET_ERR_INVALID_URL = -300;
+var NET_ERR_DISALLOWED_URL_SCHEME = -301;
+var NET_ERR_UNKNOWN_URL_SCHEME = -302;
+var NET_ERR_TOO_MANY_REDIRECTS = -310;
+var NET_ERR_UNSAFE_REDIRECT = -311;
+var NET_ERR_UNSAFE_PORT = -312;
+var NET_ERR_INVALID_RESPONSE = -320;
+var NET_ERR_INVALID_CHUNKED_ENCODING = -321;
+var NET_ERR_METHOD_NOT_SUPPORTED = -322;
+var NET_ERR_UNEXPECTED_PROXY_AUTH = -323;
+var NET_ERR_EMPTY_RESPONSE = -324;
+var NET_ERR_RESPONSE_HEADERS_TOO_BIG = -325;
+var NET_ERR_PAC_STATUS_NOT_OK = -326;
+var NET_ERR_PAC_SCRIPT_FAILED = -327;
+var NET_ERR_REQUEST_RANGE_NOT_SATISFIABLE = -328;
+var NET_ERR_MALFORMED_IDENTITY = -329;
+var NET_ERR_CONTENT_DECODING_FAILED = -330;
+var NET_ERR_NETWORK_IO_SUSPENDED = -331;
+var NET_ERR_SYN_REPLY_NOT_RECEIVED = -332;
+var NET_ERR_ENCODING_CONVERSION_FAILED = -333;
+var NET_ERR_UNRECOGNIZED_FTP_DIRECTORY_LISTING_FORMAT = -334;
+var NET_ERR_INVALID_SPDY_STREAM = -335;
+var NET_ERR_NO_SUPPORTED_PROXIES = -336;
+var NET_ERR_SPDY_PROTOCOL_ERROR = -337;
+var NET_ERR_INVALID_AUTH_CREDENTIALS = -338;
+var NET_ERR_UNSUPPORTED_AUTH_SCHEME = -339;
+var NET_ERR_ENCODING_DETECTION_FAILED = -340;
+var NET_ERR_MISSING_AUTH_CREDENTIALS = -341;
+var NET_ERR_UNEXPECTED_SECURITY_LIBRARY_STATUS = -342;
+var NET_ERR_MISCONFIGURED_AUTH_ENVIRONMENT = -343;
+var NET_ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS = -344;
+var NET_ERR_RESPONSE_BODY_TOO_BIG_TO_DRAIN = -345;
+var NET_ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH = -346;
+var NET_ERR_INCOMPLETE_SPDY_HEADERS = -347;
+var NET_ERR_PAC_NOT_IN_DHCP = -348;
+var NET_ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION = -349;
+var NET_ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION = -350;
+var NET_ERR_SPDY_SERVER_REFUSED_STREAM = -351;
+var NET_ERR_SPDY_PING_FAILED = -352;
+var NET_ERR_PIPELINE_EVICTION = -353;
+var NET_ERR_CONTENT_LENGTH_MISMATCH = -354;
+var NET_ERR_INCOMPLETE_CHUNKED_ENCODING = -355;
+var NET_ERR_QUIC_PROTOCOL_ERROR = -356;
+var NET_ERR_RESPONSE_HEADERS_TRUNCATED = -357;
+var NET_ERR_QUIC_HANDSHAKE_FAILED = -358;
+var NET_ERR_CACHE_MISS = -400;
+var NET_ERR_CACHE_READ_FAILURE = -401;
+var NET_ERR_CACHE_WRITE_FAILURE = -402;
+var NET_ERR_CACHE_OPERATION_NOT_SUPPORTED = -403;
+var NET_ERR_CACHE_OPEN_FAILURE = -404;
+var NET_ERR_CACHE_CREATE_FAILURE = -405;
+var NET_ERR_CACHE_RACE = -406;
+var NET_ERR_CACHE_CHECKSUM_READ_FAILURE = -407;
+var NET_ERR_CACHE_CHECKSUM_MISMATCH = -408;
+var NET_ERR_INSECURE_RESPONSE = -501;
+var NET_ERR_NO_PRIVATE_KEY_FOR_CERT = -502;
+var NET_ERR_ADD_USER_CERT_FAILED = -503;
+var NET_ERR_FTP_FAILED = -601;
+var NET_ERR_FTP_SERVICE_UNAVAILABLE = -602;
+var NET_ERR_FTP_TRANSFER_ABORTED = -603;
+var NET_ERR_FTP_FILE_BUSY = -604;
+var NET_ERR_FTP_SYNTAX_ERROR = -605;
+var NET_ERR_FTP_COMMAND_NOT_SUPPORTED = -606;
+var NET_ERR_FTP_BAD_COMMAND_SEQUENCE = -607;
+var NET_ERR_PKCS12_IMPORT_BAD_PASSWORD = -701;
+var NET_ERR_PKCS12_IMPORT_FAILED = -702;
+var NET_ERR_IMPORT_CA_CERT_NOT_CA = -703;
+var NET_ERR_IMPORT_CERT_ALREADY_EXISTS = -704;
+var NET_ERR_IMPORT_CA_CERT_FAILED = -705;
+var NET_ERR_IMPORT_SERVER_CERT_FAILED = -706;
+var NET_ERR_PKCS12_IMPORT_INVALID_MAC = -707;
+var NET_ERR_PKCS12_IMPORT_INVALID_FILE = -708;
+var NET_ERR_PKCS12_IMPORT_UNSUPPORTED = -709;
+var NET_ERR_KEY_GENERATION_FAILED = -710;
+var NET_ERR_ORIGIN_BOUND_CERT_GENERATION_FAILED = -711;
+var NET_ERR_PRIVATE_KEY_EXPORT_FAILED = -712;
+var NET_ERR_SELF_SIGNED_CERT_GENERATION_FAILED = -713;
+var NET_ERR_CERT_DATABASE_CHANGED = -714;
+var NET_ERR_DNS_MALFORMED_RESPONSE = -800;
+var NET_ERR_DNS_SERVER_REQUIRES_TCP = -801;
+var NET_ERR_DNS_SERVER_FAILED = -802;
+var NET_ERR_DNS_TIMED_OUT = -803;
+var NET_ERR_DNS_CACHE_MISS = -804;
+var NET_ERR_DNS_SEARCH_EMPTY = -805;
+var NET_ERR_DNS_SORT_ERROR = -806;
diff --git a/main.html b/main.html
new file mode 100644 (file)
index 0000000..e694264
--- /dev/null
+++ b/main.html
@@ -0,0 +1,118 @@
+<!-- Written by Mike Frysinger <vapier@gmail.com>.  Released into the public domain.  -->
+<!doctype html>
+<html>
+
+<head>
+<title>Wake-On-Lan (WOL)</title>
+<script src='js/net_error_list.js'></script>
+<script src='js/common.js'></script>
+<script src='js/main.js'></script>
+<style>
+body {
+       background-color: black;
+       color: white;
+       font-family: monospace;
+       white-space: nowrap;
+}
+
+input.mac {
+       text-align: center;
+}
+
+input[name=port] {
+       text-align: center;
+}
+
+a {
+       color: grey;
+}
+</style>
+</head>
+
+<body>
+
+<p class='header' style='text-align:center'>
+ <a href='https://en.wikipedia.org/wiki/Wake-on-LAN' target='_blank'>
+ Wake-On-Lan (WOL) Magic Packet Generator
+ </a>
+</p>
+
+<div class='settings'>
+ <form name='settings'>
+ <table width='100%'>
+  <tr>
+   <td>
+    <a href='https://en.wikipedia.org/wiki/IP_address' target='_blank'>IP</a>
+    /
+    <a href='https://en.wikipedia.org/wiki/Hostname' target='_blank'>Hostname</a>:
+   </td>
+   <td><input tabindex='1' name='host' value='255.255.255.255' size='40' autofocus></td>
+  </tr>
+  <tr>
+   <td><a href='https://en.wikipedia.org/wiki/MAC_address' target='_blank'>MAC address</a>:</td>
+   <td>
+    <span name='mac-many'>
+     <input tabindex='2' class='mac' name='mac0' value='20' size='1' maxlength='2'>
+     <input tabindex='3' class='mac' name='mac1' value='00' size='1' maxlength='2'>
+     <input tabindex='4' class='mac' name='mac2' value='00' size='1' maxlength='2'>
+     <input tabindex='5' class='mac' name='mac3' value='00' size='1' maxlength='2'>
+     <input tabindex='6' class='mac' name='mac4' value='00' size='1' maxlength='2'>
+     <input tabindex='7' class='mac' name='mac5' value='00' size='1' maxlength='2'>
+    </span>
+    <span name='mac-one' hidden>
+     <input tabindex='8' class='mac' name='mac' size='39' maxlength='20'>
+    </span>
+    <a tabindex='9' name='mac-paste' href=''>Paste</a>
+   </td>
+  </tr>
+  <tr>
+   <td><a href='https://en.wikipedia.org/wiki/Port_(computer_networking)' target='_blank'>Port</a>:</td>
+   <td><input tabindex='10' type='number' name='port' min='1' max='65535' step='1' value='9'></td>
+  </tr>
+  <tr>
+   <td><a href='https://en.wikipedia.org/wiki/Wake-on-LAN#Security_considerations' target='_blank'>SecureOn</a>:</td>
+   <td>
+    <span name='pass-many'>
+     <input tabindex='11' class='mac' name='pass0' value='00' size='1' maxlength='2'>
+     <input tabindex='12' class='mac' name='pass1' value='00' size='1' maxlength='2'>
+     <input tabindex='13' class='mac' name='pass2' value='00' size='1' maxlength='2'>
+     <input tabindex='14' class='mac' name='pass3' value='00' size='1' maxlength='2'>
+     <input tabindex='15' class='mac' name='pass4' value='00' size='1' maxlength='2'>
+     <input tabindex='16' class='mac' name='pass5' value='00' size='1' maxlength='2'>
+    </span>
+    <span name='pass-one' hidden>
+     <input tabindex='17' class='mac' name='pass' size='39' maxlength='20'>
+    </span>
+    <a tabindex='18' name='pass-paste' href=''>Paste</a>
+   </td>
+  </tr>
+  <tr>
+   <td colspan=2 align='middle'>
+    <input tabindex='19' type='submit' name='send' value='Send'>
+   </td>
+  </tr>
+ </table>
+ </form>
+</div>
+
+<p class='status'>Status: <span name='status'>idle</span></p>
+
+<br>
+
+<p>
+Problems?  Try
+<a href='https://en.wikipedia.org/wiki/Wake-on-LAN#Troubleshooting_magic_packets' target='_blank'>troubleshooting</a>.<br>
+<br>
+Random tips (applies to all WOL and is not specific to this app):<br>
+<ul>
+ <li>You have to be on the same local network as the target</li>
+ <li>i.e. You cannot wake up computers over the internet</li>
+ <li>WiFi computers often cannot be woken up remotely</li>
+ <li>WOL support has to be turned on in the BIOS/OS</li>
+ <li>Make sure the MAC address matches the computer</li>
+ <li>The SecureOn (password) is not supported by many devices;<br>feel free to leave the default value</li>
+</ul>
+</p>
+
+</body>
+</html>
diff --git a/makedist.sh b/makedist.sh
new file mode 100755 (executable)
index 0000000..2c21c87
--- /dev/null
@@ -0,0 +1,52 @@
+#!/bin/bash -e
+# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+case $1 in
+-h|--help)
+  echo "Usage: $0 [rev]"
+  exit 0
+  ;;
+esac
+
+json_value() {
+  local key=$1
+  sed -n -r \
+    -e '/^[[:space:]]*"'"${key}"'"/s|.*:[[:space:]]*"([^"]*)",?$|\1|p' \
+    manifest.json
+}
+
+PN=$(json_value name | sed 's:[[:space:]/]:_:g' | tr '[:upper:]' '[:lower:]')
+if [[ ${PN} == "__msg_name__" ]] ; then
+       PN=$(basename "$(pwd)")
+fi
+PV=$(json_value version)
+rev=${1:-0}
+PVR="${PV}.${rev}"
+P="${PN}-${PVR}"
+
+rm -rf "${P}"
+mkdir "${P}"
+
+while read line ; do
+  [[ ${line} == */* ]] && mkdir -p "${P}/${line%/*}"
+  ln "${line}" "${P}/${line}"
+done < <(sed 's:#.*::' manifest.files)
+cp Makefile manifest.files manifest.json "${P}/"
+
+make -C "${P}" -j {css,js}-min
+while read line ; do
+       mv "${line}.min" "${line}"
+done < <(find "${P}" -name '*.js' -o -name '*.css')
+rm "${P}"/{manifest.files,Makefile}
+
+sed -i \
+  -e '/"version"/s:"[^"]*",:"'${PVR}'",:' \
+  "${P}/manifest.json"
+
+zip="${P}.zip"
+rm -f "${zip}"
+zip -r "${zip}" "${P}"
+rm -rf "${P}"
+du -b "${zip}"
diff --git a/manifest.files b/manifest.files
new file mode 100644 (file)
index 0000000..9deef5c
--- /dev/null
@@ -0,0 +1,7 @@
+images/icon-48x48.png
+images/icon-128x128.png
+js/common.js
+js/launcher.js
+js/main.js
+js/net_error_list.js
+main.html
diff --git a/manifest.json b/manifest.json
new file mode 100644 (file)
index 0000000..90d1af0
--- /dev/null
@@ -0,0 +1,26 @@
+{
+       "manifest_version": 2,
+       "minimum_chrome_version": "44",
+       "name": "Wake-On-Lan (WOL)",
+       "version": "0.1",
+       "description": "Wake up other computers with WOL magic packets",
+       "icons": {
+               "48": "images/icon-48x48.png",
+               "128": "images/icon-128x128.png"
+       },
+       "app": {
+               "background": {
+                       "scripts": ["js/launcher.js"]
+               }
+       },
+       "offline_enabled": true,
+       "permissions": [
+               "storage"
+       ],
+       "sockets": {
+               "udp": {
+                       "send": ["*"],
+                       "bind": ["*"]
+               }
+       }
+}