Skip to content

Commit

Permalink
add apps
Browse files Browse the repository at this point in the history
  • Loading branch information
KensakuKOMATSU committed Aug 3, 2012
1 parent a06513a commit bff74d6
Show file tree
Hide file tree
Showing 10 changed files with 353 additions and 0 deletions.
14 changes: 14 additions & 0 deletions apps/css/style.css
@@ -0,0 +1,14 @@
body {
min-width: 357px;
overflow-x: hidden;
}

img {
margin: 5px;
border: 2px solid black;
vertical-align: middle;
width: 75px;
height: 75px;
}


Binary file added apps/images/icon_128.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/images/icon_16.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
70 changes: 70 additions & 0 deletions apps/javascripts/bg_script.js
@@ -0,0 +1,70 @@
var TIMEOUT = 3500;

// when receive message from content_script.
chrome.extension.onMessage.addListener(function(req, sender, sendResponse){
console.log(req);
switch(req.method) {
case "getNetworkServices":
// do M-SEARCH
doMSearch(req.type);
break;
default:
console.log("unknown method --> "+req.method);
break;
}
});



/**
* do M-SEARCCH
*
*/
function doMSearch(st /* search type */){
var upnp = new UPnP();
var res_ = [];
var usns_ = {};


var parse = function(data) {
var arr = data.split("\n"), ret = {};

for(var i = 0, l = arr.length; i < l; i++ ) {
var a = arr[i].split(":");
var k = a[0].toLowerCase();
var v = a.slice(1).join(":").replace(/^\s+/,"").replace("\r", "");

if(!!v) {
ret[k] = v;
}
}
return ret;
}

setTimeout(function(){
var urls = [];
upnp.listen(function(res){
var d = parse(res.data);

for(var i = 0, l = urls.length; i < l; i++) {
if(urls[i] === d.location) return;
}
res_.push({name: d.server, url: d.location, type: d.st, config: ""});
urls.push(d.location);
});
upnp.search(st);
}, 100);

// after timeout, send searched result.
setTimeout(function(){
// obtain current tab
chrome.tabs.getSelected(null, function(tab){
// send searched result to current tab.
chrome.tabs.sendMessage(tab.id, {"method": "getNetworkServicesResult", "res": res_});
});
upnp.destroy();

// clear searched result.
setTimeout(function(){res_.length = 0;}, 1);
}, TIMEOUT);
}
56 changes: 56 additions & 0 deletions apps/javascripts/content_script.js
@@ -0,0 +1,56 @@
// content script is working as proxy page between frontend page and background page


var ID = "___discovery___";

/**
* background to frontend
*
*/

// receive message from background page
chrome.extension.onMessage.addListener(function(req, sender, sendResponse){
console.log(req);
var method = req.method;

switch(method) {
case "getNetworkServicesResult":
fireGetNetworkServicesResult({"res": req.res});
break;
default:
console.log("unknown method --> "+method);
break;
}
});


// send background page's result to frontend via Custom DOM Event.
//
function fireGetNetworkServicesResult(data) {
var ev = document.createEvent('Event');
var hiddenDiv = document.getElementById(ID);

ev.initEvent('getNetworkServicesResult', true, true);
hiddenDiv.innerText = JSON.stringify(data);

hiddenDiv.dispatchEvent(ev);
}


/**
* frontend to background
*
*/

// transport received data from frontend page to background page.
//
document.getElementById(ID).addEventListener('getNetworkServices', function() {
var dataFromFront = this.innerText
,obj = JSON.parse(dataFromFront);
console.log(obj);

chrome.extension.sendMessage({"method": "getNetworkServices", type: obj.type}, function(res){
console.log(res);
});
});

4 changes: 4 additions & 0 deletions apps/javascripts/jquery-1.7.2.min.js

Large diffs are not rendered by default.

41 changes: 41 additions & 0 deletions apps/javascripts/popup.js
@@ -0,0 +1,41 @@
var show = function(recv){
var head = "<h3>receive from "+recv.address+":"+recv.port+"</h3>";
var str = recv.data;
var o = parse(str);

$("output").append("<hr>"+head+"</div>");
console.dir(o);

$("output").append("<dl>");
if(o.hasOwnProperty('server')) {
$("output").append("<dt>SERVER</dt><dd>"+o.server+"</dd>");
}
if(o.hasOwnProperty('location')) {
$("output").append("<dt>LOCATION</dt><dd><a href='"+o.location+"' target='_blank'>"+o.location+"</a></dd>");
}
$("output").append("<dt>Plain data</dt><dd><pre style='font-size:0.4em;background:#ccc;'>"+str+"</pre></dd>");
$("output").append("</dl>");
}

var parse = function(data) {
var arr = data.split("\n"), ret = {};

for(var i = 0, l = arr.length; i < l; i++ ) {
var a = arr[i].split(":");
var k = a[0].toLowerCase();
var v = a.slice(1).join(":");

if(!!v) {
ret[k] = v;
}
}
return ret;
}


// Main
var upnp = new UPnP();
upnp.onready = function(){
this.listen(show);
this.search("upnp:rootdevice");
}
125 changes: 125 additions & 0 deletions apps/javascripts/upnp.js
@@ -0,0 +1,125 @@
var UPnP;

console.log("upnp");

(function(){
/**
* utilities
*
*/
var socket = chrome.experimental.socket || chrome.socket;

// translate text string to Arrayed buffer
//
function t2ab(str /* String */) {
var buffer = new ArrayBuffer(str.length);
var view = new DataView(buffer);
for(var i = 0, l = str.length; i < l; i++) {
view.setInt8(i, str.charAt(i).charCodeAt());
}
return buffer;
}

// translate Arrayed buffer to text string
//
function ab2t(buffer /* ArrayBuffer */) {
var arr = new Int8Array(buffer);
var str = "";
for(var i = 0, l = arr.length; i < l; i++) {
str += String.fromCharCode.call(this, arr[i]);
}
console.log(str);
return str;
}


/**
* You can find API documentaion for raw socket api in
* http://code.google.com/chrome/extensions/trunk/experimental.socket.html
*
*/

// SSDP definitions
var M_SEARCH_REQUEST = "M-SEARCH * HTTP/1.1\r\n" +
"MX: 3\r\n" +
"HOST: 239.255.255.250:1900\r\n" +
"MAN: \"ssdp:discover\"\r\n" +
"ST: {{st}}\r\n\r\n"

// UPnP classes
UPnP = function(){
this.sid = null;
this.MIP_ = "239.255.255.250";
this.PORT_ = 1900;

var self = this;
socket.create('udp', {}, function(socketInfo) {
self.sid = socketInfo.socketId;
socket.bind(self.sid, "0.0.0.0", 0, function(res) {
if(res !== 0) {
throw('cannot bind socket');
}
self.onready();
});
});
}

// interface to onready
UPnP.prototype.onready = function() {
}

// do M-SEARCH
UPnP.prototype.search = function(st /* search type */, callback /* function */) {
if(!!this.sid === false) {
throw('socket id is not allocated');
}

var ssdp = M_SEARCH_REQUEST.replace("{{st}}", st);
console.log(ssdp);
var buffer = t2ab(ssdp);
var closure_ = function(e){
if(e.bytesWritten < 0) {
throw("an Error occured while sending M-SEARCH : "+e.bytesWritten);
}
console.log("=== SENT UPnP M-SEARCH ===");
console.log(e);

if(typeof(callback) === "function")
callback();
}

// send M-SEARCH twice times
for(var i = 0; i < 2; i++) {
socket.sendTo(this.sid, buffer, this.MIP_, this.PORT_, function(e) {
closure_(e);
});
}
}

// listen response to M-SEARCH
UPnP.prototype.listen = function(callback) {
if(!!this.sid === false) {
throw('socket id is not allocated');
}

var self = this;
var closure_ = function(recv){
console.log("=== RECV UPnP packet from "+recv.address+"===");
console.log(recv);
recv.data = ab2t(recv.data);
if(typeof(callback) === "function") {
callback(recv);
}
self.listen(callback);
}

socket.recvFrom(this.sid, function(recv) {
closure_(recv);
});
}
// destroy socket
UPnP.prototype.destroy = function() {
socket.destroy(this.sid);
this.sid = null;
}
}());
14 changes: 14 additions & 0 deletions apps/main.html
@@ -0,0 +1,14 @@
<!doctype html>
<html>
<head>
<title>Getting Started Extension's Popup</title>
<link rel="stylesheet" type="text/css" href="/css/style.css">
<script src="/javascripts/jquery-1.7.2.min.js"></script>
</head>
<body>
<a href="http://upnp.komasshu.info/" target="_blank">demo site</a><br>
<output></output>
<script src="/javascripts/upnp.js"></script>
<script src="/javascripts/popup.js"></script>
</body>
</html>
29 changes: 29 additions & 0 deletions apps/manifest.json
@@ -0,0 +1,29 @@
{
"name": "UPnP M-Search app",
"version": "0.1",
"manifest_version": 2,
"description": "show UPnP M-Search result in your local network. This web app is utilizing Chrome's raw socket api :)",
"background": {
"scripts": ["/javascripts/upnp.js", "/javascripts/bg_script.js"]
},
"content_scripts": [
{
"matches":["http://*/*", "https://*/*"],
"js":["/javascripts/content_script.js"]
}
],
"app": {
"launch": {
"local_path": "main.html"
}
},
"icons": {
"16": "/images/icon_16.png",
"128": "/images/icon_128.png"
},
"permissions": [
"experimental",
"socket",
"tabs"
]
}

0 comments on commit bff74d6

Please sign in to comment.