Skip to content
This repository was archived by the owner on Feb 12, 2023. It is now read-only.

Commit 5f27006

Browse files
author
Ke, Mingze
committed
init
0 parents  commit 5f27006

File tree

15 files changed

+527
-0
lines changed

15 files changed

+527
-0
lines changed

‎.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
node_modules/
2+
bower_components/
3+
build/
4+
chrome-app/json-human/

‎bower.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"name": "chrome-api-proxy",
3+
"description": "Leverage Chrome App API in Browser",
4+
"license": "MIT",
5+
"dependencies": {
6+
"json-human": "*"
7+
}
8+
}

‎chrome-app/assets/icon_128.png

22.7 KB
Loading

‎chrome-app/eventPage.js

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
+(function (scope) {
2+
3+
'use strict';
4+
5+
var slice = Array.prototype.slice,
6+
undef = undefined,
7+
transReq = scope.transforms.request,
8+
transRes = scope.transforms.response,
9+
listenerMap = {},
10+
portMap = {},
11+
objCache = {};
12+
13+
chrome.app.runtime.onLaunched.addListener(function () {
14+
15+
chrome.app.window.create('index.html', {
16+
id: "main",
17+
innerBounds: {
18+
width: 480,
19+
height: 640,
20+
minWidth: 480,
21+
minHeight: 640
22+
}
23+
});
24+
25+
chrome.runtime.onConnectExternal.addListener(function (port) {
26+
if (!port.name) {
27+
return;
28+
}
29+
30+
portMap[port.name] = port;
31+
32+
port.onMessage.addListener(function (msg) {
33+
if (msg.method) {
34+
invoke(port.name, msg.id, msg.method, msg.params);
35+
}
36+
});
37+
38+
port.onDisconnect.addListener(function (port) {
39+
delete portMap[port.name];
40+
cleanupListener(port.name);
41+
});
42+
});
43+
44+
});
45+
46+
function invoke(senderId, id, method, params) {
47+
var m = normalize(method),
48+
obj = resolve(m),
49+
ctx = resolve(m.split('.').slice(0, -1).join('.'));
50+
51+
if (m.indexOf('.addListener') === m.length - 12) {
52+
addListener(m.substr(0, m.length - 12), senderId, id);
53+
} else if (m.indexOf('.removeListener') === m.length - 15) {
54+
removeListener(m.substr(0, m.length - 15), senderId, id);
55+
} else {
56+
if (typeof obj === 'function') {
57+
params = transformParams(m, params, transReq, ctx);
58+
obj.apply(ctx, params.concat(callback));
59+
}
60+
61+
function callback() {
62+
var args = slice.call(arguments),
63+
port = portMap[senderId];
64+
65+
if (!port) {
66+
return;
67+
}
68+
69+
if (chrome.runtime.lastError) {
70+
port.postMessage({
71+
jsonrpc: '2.0',
72+
id: id,
73+
error: chrome.runtime.lastError.message
74+
});
75+
} else {
76+
args = transformParams(m, args, transRes, ctx);
77+
port.postMessage({
78+
jsonrpc: '2.0',
79+
id: id,
80+
result: args
81+
});
82+
}
83+
}
84+
}
85+
}
86+
87+
function transformParams(name, params, map, ctx) {
88+
var func = map[name];
89+
90+
if (typeof func === 'function') {
91+
return func.apply(ctx, params);
92+
}
93+
return params;
94+
}
95+
96+
function addListener(objName, portName, id) {
97+
if (listenerMap[objName]) {
98+
listenerMap[objName].receivers.push({
99+
portName: portName,
100+
id: id
101+
});
102+
} else {
103+
listenerMap[objName] = {
104+
listener: function () {
105+
var args = transformParams(objName + '.addListener', slice.call(arguments),
106+
transRes, resolve(objName));
107+
108+
listenerMap[objName].receivers.forEach(function (receiver, idx) {
109+
portMap[receiver.portName].postMessage({
110+
jsonrpc: '2.0',
111+
id: receiver.id,
112+
result: args
113+
});
114+
});
115+
},
116+
receivers: [{
117+
portName: portName,
118+
id: id
119+
}]
120+
};
121+
resolve(objName).addListener(listenerMap[objName].listener);
122+
}
123+
}
124+
125+
function removeListener(objName, portName, id) {
126+
if (listenerMap[objName]) {
127+
if (typeof id === 'undefined') {
128+
listenerMap[objName].receivers.forEach(function (receiver, idx) {
129+
if (receiver.portName === portName) {
130+
listenerMap[objName].receivers.splice(idx, 1);
131+
}
132+
});
133+
} else {
134+
listenerMap[objName].receivers.some(function (receiver, idx) {
135+
if (receiver.portName === portName && receiver.id === id) {
136+
listenerMap[objName].receivers.splice(idx, 1);
137+
return true;
138+
}
139+
});
140+
}
141+
if (listenerMap[objName].receivers.length === 0) {
142+
resolve(objName).removeListener(listenerMap[objName].listener);
143+
delete listenerMap[objName];
144+
}
145+
}
146+
}
147+
148+
function cleanupListener(portName) {
149+
Object.keys(listenerMap).forEach(function (objName) {
150+
removeListener(objName, portName);
151+
});
152+
}
153+
154+
function normalize(method) {
155+
return (method.indexOf('window.') === 0) ? method.substring(7) : method;
156+
}
157+
158+
function resolve(name) {
159+
var tmpName = '';
160+
161+
return (objCache[name]) ||
162+
name.split('.').reduce(function (obj, prop) {
163+
tmpName += ((tmpName ? '.' : '') + prop);
164+
if (obj && obj[prop]) {
165+
objCache[tmpName] = obj[prop];
166+
return obj[prop];
167+
} else {
168+
return undef;
169+
}
170+
}, scope);
171+
}
172+
173+
}(window));

‎chrome-app/index.html

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<meta charset="utf-8">
6+
<title>Chrome API Proxy</title>
7+
<script src="json-human/src/json.human.js"></script>
8+
<script src="main.js"></script>
9+
<link rel="stylesheet" href="json-human/css/json.human.css"></link>
10+
<style>
11+
html,
12+
body {
13+
overflow-y: auto;
14+
}
15+
16+
body {
17+
-webkit-user-select: text
18+
}
19+
20+
.button {
21+
font-size: 26px;
22+
}
23+
</style>
24+
</head>
25+
26+
<body>
27+
<button class='button' id='refresh'>刷新</button>
28+
<h1>Serial Port Status</h1>
29+
<div id='serial-port-status'></div>
30+
<div>
31+
<input id='disconnId' type='text' size='5' />
32+
<button id='disconnect'>Disconnect</button>
33+
<span id='disconnStatus'></span>
34+
</div>
35+
</body>
36+
37+
</html>

‎chrome-app/main.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
+(function () {
2+
3+
'use strict';
4+
5+
var node;
6+
7+
document.addEventListener('DOMContentLoaded', function () {
8+
node = document.querySelector('#serial-port-status');
9+
10+
getNode('refresh').addEventListener('click', function () {
11+
refreshStatus(node);
12+
}, false);
13+
14+
getNode('disconnect').addEventListener('click', function () {
15+
chrome.serial.disconnect(parseInt(getNode('disconnId').value), function (e) {
16+
refreshStatus(node);
17+
if (e !== true) {
18+
alert(e + '');
19+
}
20+
});
21+
});
22+
23+
refreshStatus(node);
24+
}, false);
25+
26+
function refreshStatus(node) {
27+
var status = {};
28+
29+
getNode('disconnId').value = '';
30+
getNode('disconnStatus').innerHTML = '';
31+
32+
chrome.serial.getDevices(function (devs) {
33+
status.devices = devs;
34+
chrome.serial.getConnections(function (conns) {
35+
status.connections = conns;
36+
node.innerHTML = '';
37+
node.appendChild(JsonHuman.format(status));
38+
});
39+
});
40+
}
41+
42+
function getNode(id) {
43+
return document.getElementById(id);
44+
}
45+
46+
}());

‎chrome-app/manifest.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "Chrome API Proxy",
3+
"version": "0.0.3",
4+
"manifest_version": 2,
5+
"minimum_chrome_version": "23",
6+
"app": {
7+
"background": {
8+
"scripts": [
9+
"transforms.js",
10+
"eventPage.js"
11+
]
12+
}
13+
},
14+
"permissions": [
15+
"serial"
16+
],
17+
"icons": {
18+
"128": "assets/icon_128.png"
19+
}
20+
}

‎chrome-app/transforms.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
+(function (scope) {
2+
3+
'use strict';
4+
5+
var slice = Array.prototype.slice;
6+
7+
scope.transforms = scope.transforms || {
8+
request: {},
9+
response: {}
10+
};
11+
12+
scope.transforms.request['chrome.serial.send'] = function (connectionId, data) {
13+
return [connectionId, new Uint8Array(data).buffer];
14+
};
15+
16+
scope.transforms.response['chrome.serial.onReceive.addListener'] = function (event) {
17+
return [{
18+
connectionId: event.connectionId,
19+
data: slice.call(new Uint8Array(event.data))
20+
}];
21+
};
22+
23+
}(window));

‎chrome-extension/assets/icon_128.png

22.7 KB
Loading

‎chrome-extension/contentScript.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
+(function (window) {
2+
3+
'use strict';
4+
5+
var PROXY_ID = 'pddlkidaibpbhpkfbhkbeolbagpmkhhn';
6+
7+
var ready, port;
8+
9+
ready = true;
10+
port = chrome.runtime.connect(PROXY_ID, {
11+
name: randomId()
12+
});
13+
port.onMessage.addListener(receiveMessage);
14+
port.onDisconnect.addListener(onDisconnect);
15+
16+
window.addEventListener('message', function (event) {
17+
var msg = event.data;
18+
19+
if (msg.jsonrpc && msg.method) {
20+
ready && port.postMessage(msg);
21+
}
22+
}, false);
23+
24+
function receiveMessage(msg) {
25+
window.postMessage(msg, '*');
26+
}
27+
28+
function onDisconnect() {
29+
ready = false;
30+
port.onMessage.removeListener(receiveMessage);
31+
port.onDisconnect.removeListener(onDisconnect);
32+
}
33+
34+
function randomId() {
35+
return (Math.random() * Date.now()).toString(36).replace(/\./g, '');
36+
}
37+
38+
}(window));

‎chrome-extension/manifest.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "Chrome API Proxy - Agent",
3+
"version": "0.0.3",
4+
"manifest_version": 2,
5+
"minimum_chrome_version": "23",
6+
"content_scripts": [{
7+
"matches": [
8+
"<all_urls>"
9+
],
10+
"js": [
11+
"contentScript.js"
12+
],
13+
"run_at": "document_start"
14+
}],
15+
"icons": {
16+
"128": "assets/icon_128.png"
17+
}
18+
}

‎examples/chrome.serial.html

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<html>
2+
3+
<head>
4+
<script src="../lib/chrome.serial.js"></script>
5+
<script src="../bower_components/json-human/src/json.human.js"></script>
6+
<script>
7+
chrome.serial.getDevices(function(devs) {
8+
document.body.appendChild(JsonHuman.format(devs));
9+
});
10+
11+
chrome.serial.connect('/dev/cu.usbmodem1411', function(info) {
12+
document.body.appendChild(JsonHuman.format(info));
13+
});
14+
</script>
15+
</head>
16+
17+
<body>
18+
</body>
19+
20+
</html>

0 commit comments

Comments
 (0)