Merge branch 'issue/50' into develop
diff --git a/weinre.build/build.xml b/weinre.build/build.xml
index 621925e..95b4952 100644
--- a/weinre.build/build.xml
+++ b/weinre.build/build.xml
@@ -246,6 +246,7 @@
<build-html name="Installing" oDir="${WEB}/doc" iDir="../${PROJECT_DOC}"/>
<build-html name="License" oDir="${WEB}/doc" iDir="../${PROJECT_DOC}"/>
<build-html name="Running" oDir="${WEB}/doc" iDir="../${PROJECT_DOC}"/>
+ <build-html name="MultiUser" oDir="${WEB}/doc" iDir="../${PROJECT_DOC}"/>
<build-html name="Security" oDir="${WEB}/doc" iDir="../${PROJECT_DOC}"/>
<build-html name="TestDrive" oDir="${WEB}/doc" iDir="../${PROJECT_DOC}"/>
<build-html name="ChangeLog" oDir="${WEB}/doc" iDir="../${PROJECT_DOC}"/>
diff --git a/weinre.doc/MultiUser.body.html b/weinre.doc/MultiUser.body.html
new file mode 100644
index 0000000..460367a
--- /dev/null
+++ b/weinre.doc/MultiUser.body.html
@@ -0,0 +1,97 @@
+<!--
+ * weinre is available under *either* the terms of the modified BSD license *or* the
+ * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
+ *
+ * Copyright (c) 2010, 2011 IBM Corporation
+-->
+
+<p><span class="weinre">weinre</span> was originally designed so that each user
+that wanted to use <span class="weinre">weinre</span> would run their own
+<span class="weinre">weinre</span> server. The system has since been enhanced
+to support muliple users using the same server.
+
+<!-- ======================================================== -->
+<h2>Your debug id</h2>
+
+<p>To use a multi-user server, you'll need to select an id for yourself. This
+id will be used in the client and target URLs of <span class="weinre">weinre</span>
+to scope your clients and targets from the clients and targets of other users.
+
+<p>There is no password, just an id. There is no real security here.
+The id is a secret shared between your
+debug target and client, but it is sent in the clear when your target and
+client connect to the server. If someone else knows your <b>id</b>, they can
+connect to clients or targets you are running with that <b>id</b>.
+
+<p>So don't give your <b>id</b> to anyone else that you don't want to share
+with.
+
+<p>To keep your <b>id</b>'s familar but non-guessable, you might use a string
+consisting of your typical userid, followed by a dash, followed by another
+string not likely to be guessed by other people.
+
+<p>If you are paranoid, you can change your <b>id</b> every time you start
+a debug session, of course.
+
+<!-- ======================================================== -->
+<h2>Using your id with the client</h2>
+
+<p>Typically when start a <span class="weinre">weinre</span> client session
+by visiting a URL like
+
+<pre>
+http://some.server.xyz/client/
+</pre>
+
+<p>To start
+a client with a particular id, append the hash character (<code>#</code>) and
+the id you want to use the URL. For instance, to connect with the id
+<code>itsReallyMe</code>, launch the client with the URL
+
+<pre>
+http://some.server.xyz/client/#itsReallyMe
+</pre>
+
+<p>The id which is used will be displayed
+in the connected clients list for each connected client.
+
+<!-- ======================================================== -->
+<h2>Using your id with the target</h2>
+
+<p>As with the server, append the hash character (<code>#</code>) to the
+URL of the script being injected into your web page. If you had previously
+used a <script src> element of:
+
+<pre>
+<script src="http://some.server.xyz/target/target-script-min.js"></script>
+</pre>
+
+<p>use this script element to connect with id <code>itsReallyMe</code>
+
+<pre>
+<script src="http://some.server.xyz/target/target-script-min.js#itsReallyMe"></script>
+</pre>
+
+<!-- ======================================================== -->
+<h2>Notes</h2>
+
+<ul class="spaced">
+
+<li>The <span class="weinre">weinre</span> server always runs in multi-user
+mode. If you don't otherwise specify an <b>id</b>, the value of
+<code>anonymous</code> will be used for the <b>id</b>.
+
+<li>The <b>id</b> is passed in the HTTP body of a POST request during the
+initial connection of the target and client to the server, and is not sent
+thereafter. Thus, it should remain out of view in server logs and the like,
+though it will be visible for anyone who has access to the contents of
+HTTP request bodies.
+
+<li>There is no programmatic interface on the <span class="weinre">weinre</span>
+to list <b>id</b>'s in current use, for security reasons. From the Remote panel
+of weinre, each connected client and target have their channel and id's listed,
+if you can't remember what id you used with the client.
+
+<li>The client with the Mac application currently only supports the <code>anonymous</code> id.
+
+</ul>
\ No newline at end of file
diff --git a/weinre.doc/boilerplate-header.html.txt b/weinre.doc/boilerplate-header.html.txt
index 32adc4f..ed36aff 100644
--- a/weinre.doc/boilerplate-header.html.txt
+++ b/weinre.doc/boilerplate-header.html.txt
@@ -39,6 +39,7 @@
- <a href="TestDrive.html">Test Drive</a>
- <a href="Installing.html">Installing</a>
- <a href="Running.html">Running</a>
+- <a href="MultiUser.html">Multi-User</a>
- <a href="Security.html">Security</a>
- <a href="Building.html">Building</a>
- <a href="ChangeLog.html">ChangeLog</a>
diff --git a/weinre.doc/boilerplate-trailer.html.txt b/weinre.doc/boilerplate-trailer.html.txt
index 531ee60..b16be62 100644
--- a/weinre.doc/boilerplate-trailer.html.txt
+++ b/weinre.doc/boilerplate-trailer.html.txt
@@ -14,6 +14,7 @@
- <a href="TestDrive.html">Test Drive</a>
- <a href="Installing.html">Installing</a>
- <a href="Running.html">Running</a>
+- <a href="MultiUser.html">Multi-User</a>
- <a href="Security.html">Security</a>
- <a href="Building.html">Building</a>
- <a href="ChangeLog.html">ChangeLog</a>
diff --git a/weinre.server/src/weinre/server/Channel.java b/weinre.server/src/weinre/server/Channel.java
index 86ca840..71294d2 100644
--- a/weinre.server/src/weinre/server/Channel.java
+++ b/weinre.server/src/weinre/server/Channel.java
@@ -22,8 +22,11 @@
//-------------------------------------------------------------------
public class Channel {
+ static public final String AnonymousId = "anonymous";
+
private String pathPrefix;
private String name;
+ private String id;
private MessageQueue<String> requestQueue;
private MessageQueue<String> responseQueue;
private boolean isClosed;
@@ -34,9 +37,10 @@
private String remoteAddress;
//---------------------------------------------------------------
- public Channel(String pathPrefix, String name, String remoteHost, String remoteAddress) {
+ public Channel(String pathPrefix, String name, String id, String remoteHost, String remoteAddress) {
this.pathPrefix = pathPrefix;
this.name = name;
+ this.id = id;
this.remoteHost = remoteHost;
this.remoteAddress = remoteAddress;
this.requestQueue = new MessageQueue<String>();
@@ -163,6 +167,11 @@
}
//---------------------------------------------------------------
+ public String getId() {
+ return id;
+ }
+
+ //---------------------------------------------------------------
public long getLastRead() {
return lastRead;
}
diff --git a/weinre.server/src/weinre/server/ChannelManager.java b/weinre.server/src/weinre/server/ChannelManager.java
index 277be1d..77f326a 100644
--- a/weinre.server/src/weinre/server/ChannelManager.java
+++ b/weinre.server/src/weinre/server/ChannelManager.java
@@ -73,10 +73,10 @@
}
//---------------------------------------------------------------
- public Channel registerChannel(String pathPrefix, String channelName, String remoteHost, String remoteAddress) {
+ public Channel registerChannel(String pathPrefix, String channelName, String id, String remoteHost, String remoteAddress) {
if (channelMap.containsKey(channelName)) return null;
- Channel channel = new Channel(pathPrefix, channelName, remoteHost, remoteAddress);
+ Channel channel = new Channel(pathPrefix, channelName, id, remoteHost, remoteAddress);
channelMap.put(channelName, channel);
fireRegisteredEvent(channel);
diff --git a/weinre.server/src/weinre/server/Client.java b/weinre.server/src/weinre/server/Client.java
index e14bfaf..4eed575 100644
--- a/weinre.server/src/weinre/server/Client.java
+++ b/weinre.server/src/weinre/server/Client.java
@@ -65,7 +65,8 @@
JSONObject result = new JSONObject();
try {
- result.put("id", getChannel().getName());
+ result.put("channel", getChannel().getName());
+ result.put("id", getChannel().getId());
result.put("hostName", getChannel().getRemoteHost());
result.put("connectedTargetIds", new JSONArray());
}
diff --git a/weinre.server/src/weinre/server/ConnectionManager.java b/weinre.server/src/weinre/server/ConnectionManager.java
index 0d27e2f..7a3ccc1 100644
--- a/weinre.server/src/weinre/server/ConnectionManager.java
+++ b/weinre.server/src/weinre/server/ConnectionManager.java
@@ -55,51 +55,59 @@
//---------------------------------------------------------------
public void addClient(Client client) {
clientMap.put(client.getName(), client);
- _sendAllClientsEvent("WeinreClientEvents", "clientRegistered", client.getDescription());
+ _sendAllClientsEvent("WeinreClientEvents", client.getId(), "clientRegistered", client.getDescription());
}
//---------------------------------------------------------------
public void addTarget(Target target) {
targetMap.put(target.getName(), target);
- _sendAllClientsEvent("WeinreClientEvents", "targetRegistered", target.getDescription());
+ _sendAllClientsEvent("WeinreClientEvents", target.getId(), "targetRegistered", target.getDescription());
}
//---------------------------------------------------------------
private void _removeClient(Client client) {
- _sendAllClientsEvent("WeinreClientEvents", "clientUnregistered", client.getName());
+ _sendAllClientsEvent("WeinreClientEvents", client.getId(), "clientUnregistered", client.getName());
clientMap.remove(client.getName());
}
//---------------------------------------------------------------
private void _removeTarget(Target target) {
- _sendAllClientsEvent("WeinreClientEvents", "targetUnregistered", target.getName());
+ _sendAllClientsEvent("WeinreClientEvents", target.getId(), "targetUnregistered", target.getName());
targetMap.remove(target.getName());
}
//---------------------------------------------------------------
- public Client getClient(String id) {
- return clientMap.get(id);
+ public Client getClient(String name) {
+ return clientMap.get(name);
}
//---------------------------------------------------------------
- public Target getTarget(String id) {
- return targetMap.get(id);
+ public Target getTarget(String name) {
+ return targetMap.get(name);
}
//---------------------------------------------------------------
- public List<Client> getClients() {
+ public List<Client> getClients(String id) {
List<Client> result = new ArrayList<Client>();
- result.addAll(clientMap.values());
+ for (Client client: clientMap.values()) {
+ if (client.getId().equals(id)) {
+ result.add(client);
+ }
+ }
return result;
}
//---------------------------------------------------------------
- public List<Target> getTargets() {
+ public List<Target> getTargets(String id) {
List<Target> result = new ArrayList<Target>();
- result.addAll(targetMap.values());
+ for (Target target: targetMap.values()) {
+ if (target.getId().equals(id)) {
+ result.add(target);
+ }
+ }
return result;
}
@@ -144,13 +152,13 @@
String clientName = client.getChannel().getName();
String targetName = target.getChannel().getName();
- _sendAllClientsEvent("WeinreClientEvents", message, clientName, targetName);
+ _sendAllClientsEvent("WeinreClientEvents", client.getId(), message, clientName, targetName);
target.getChannel().sendEvent("WeinreTargetEvents", message, clientName, targetName);
}
//---------------------------------------------------------------
- private void _sendAllClientsEvent(String intfName, String message, Object... args) {
- for (Client aClient: getClients()) {
+ private void _sendAllClientsEvent(String intfName, String id, String message, Object... args) {
+ for (Client aClient: getClients(id)) {
aClient.getChannel().sendEvent(intfName, message, args);
}
}
diff --git a/weinre.server/src/weinre/server/Connector.java b/weinre.server/src/weinre/server/Connector.java
index b428ca0..80c2895 100644
--- a/weinre.server/src/weinre/server/Connector.java
+++ b/weinre.server/src/weinre/server/Connector.java
@@ -46,6 +46,11 @@
}
//---------------------------------------------------------------
+ public String getId() {
+ return channel.getId();
+ }
+
+ //---------------------------------------------------------------
public List<Connector> getConnections() {
List<Connector> result = new ArrayList<Connector>();
diff --git a/weinre.server/src/weinre/server/Target.java b/weinre.server/src/weinre/server/Target.java
index 54920ff..ec6a986 100644
--- a/weinre.server/src/weinre/server/Target.java
+++ b/weinre.server/src/weinre/server/Target.java
@@ -93,7 +93,8 @@
JSONObject result = new JSONObject();
try {
- result.put("id", getChannel().getName());
+ result.put("channel", getChannel().getName());
+ result.put("id", getChannel().getId());
result.put("hostName", getChannel().getRemoteHost());
result.put("url", this.url);
result.put("connectedClientIds", new JSONArray());
diff --git a/weinre.server/src/weinre/server/http/HttpSocketHandler.java b/weinre.server/src/weinre/server/http/HttpSocketHandler.java
index df8a0e5..4e39082 100644
--- a/weinre.server/src/weinre/server/http/HttpSocketHandler.java
+++ b/weinre.server/src/weinre/server/http/HttpSocketHandler.java
@@ -20,6 +20,7 @@
import org.apache.wink.json4j.JSONArray;
import org.apache.wink.json4j.JSONException;
+import org.apache.wink.json4j.JSONObject;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
@@ -138,14 +139,54 @@
//---------------------------------------------------------------
public void handleCreate(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
String channelName = "" + Utility.getNextSequenceNumber();
+ String id;
+
+ if (0 == baseRequest.getContentLength()) {
+ id = Channel.AnonymousId;
+ }
- ChannelManager.$.registerChannel(pathPrefix, channelName, request.getRemoteHost(), request.getRemoteAddr());
+ else {
+ try {
+ String json = readRequestBody(request.getInputStream());
+ JSONObject obj = new JSONObject(json);
+ if (!obj.has("id")) {
+ id = Channel.AnonymousId;
+ }
+ else {
+ id = obj.getString("id");
+ if (id.isEmpty()) {
+ id = Channel.AnonymousId;
+ }
+ }
+ }
+ catch (IOException e) {
+ response.setStatus(400);
+ return;
+ }
+ catch (JSONException e) {
+ response.setStatus(400);
+ return;
+ }
+ }
+
+ ChannelManager.$.registerChannel(pathPrefix, channelName, id, request.getRemoteHost(), request.getRemoteAddr());
response.setStatus(200);
response.setContentType("application/json");
ServletOutputStream oStream = response.getOutputStream();
- oStream.print("{\"channel\": " + channelName + "}");
+ JSONObject obj = new JSONObject();
+
+ try {
+ obj.put("channel", channelName);
+ obj.put("id", id);
+ }
+ catch (JSONException e) {
+ throw new RuntimeException(e);
+ }
+
+ String result = obj.toString();
+ oStream.print(result);
oStream.close();
}
diff --git a/weinre.server/src/weinre/server/service/WeinreClientCommands.java b/weinre.server/src/weinre/server/service/WeinreClientCommands.java
index 1c58cc2..76d08fa 100644
--- a/weinre.server/src/weinre/server/service/WeinreClientCommands.java
+++ b/weinre.server/src/weinre/server/service/WeinreClientCommands.java
@@ -11,6 +11,8 @@
import java.util.List;
import org.apache.wink.json4j.JSONArray;
+import org.apache.wink.json4j.JSONException;
+import org.apache.wink.json4j.JSONObject;
import weinre.server.Channel;
import weinre.server.Client;
@@ -25,13 +27,15 @@
public void registerClient(Channel channel, String callbackId) throws IOException {
Client client = new Client(channel);
- channel.sendCallback("WeinreClientEvents", callbackId, client.getName());
+ JSONObject description = client.getDescription();
+
+ channel.sendCallback("WeinreClientEvents", callbackId, description);
channel.sendEvent("WeinreClientEvents", "serverProperties", Main.getSettings().asProperties());
}
//---------------------------------------------------------------
public void getTargets(Channel channel, String callbackId) throws IOException {
- List<Target> targets = ConnectionManager.$.getTargets();
+ List<Target> targets = ConnectionManager.$.getTargets(channel.getId());
JSONArray targetResults = new JSONArray();
for (Target target: targets) {
@@ -43,7 +47,7 @@
//---------------------------------------------------------------
public void getClients(Channel channel, String callbackId) throws IOException {
- List<Client> clients = ConnectionManager.$.getClients();
+ List<Client> clients = ConnectionManager.$.getClients(channel.getId());
JSONArray clientResults = new JSONArray();
for (Client client: clients) {
diff --git a/weinre.server/src/weinre/server/service/WeinreTargetCommands.java b/weinre.server/src/weinre/server/service/WeinreTargetCommands.java
index bd6d3ee..2b3a12f 100644
--- a/weinre.server/src/weinre/server/service/WeinreTargetCommands.java
+++ b/weinre.server/src/weinre/server/service/WeinreTargetCommands.java
@@ -10,6 +10,9 @@
import java.io.IOException;
import java.util.List;
+import org.apache.wink.json4j.JSONException;
+import org.apache.wink.json4j.JSONObject;
+
import weinre.server.Channel;
import weinre.server.ChannelManager;
import weinre.server.Main;
@@ -22,7 +25,9 @@
public void registerTarget(Channel channel, String url, String callbackId) throws IOException {
Target target = new Target(channel, url);
- channel.sendCallback("WeinreTargetEvents", callbackId, target.getName());
+ JSONObject description = target.getDescription();
+
+ channel.sendCallback("WeinreTargetEvents", callbackId, description);
}
//---------------------------------------------------------------
diff --git a/weinre.server/weinre server using ~weinre-server.settings.launch b/weinre.server/weinre server using ~weinre-server.settings.launch
index 4b2d2ab..88ae404 100644
--- a/weinre.server/weinre server using ~weinre-server.settings.launch
+++ b/weinre.server/weinre server using ~weinre-server.settings.launch
@@ -11,5 +11,6 @@
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="weinre.server.Main"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="--verbose true --deathTimeout 120"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="weinre.server"/>
</launchConfiguration>
diff --git a/weinre.web/demo/weinre-demo-min.html b/weinre.web/demo/weinre-demo-min.html
index 9adcc3b..65e393b 100644
--- a/weinre.web/demo/weinre-demo-min.html
+++ b/weinre.web/demo/weinre-demo-min.html
@@ -10,13 +10,13 @@
<meta name="viewport" content="user-scalable=no, width=device-width, height=device-height">
<title>weinre demo</title>
<link rel="stylesheet" href="weinre-demo.css">
+<script src="weinre-demo.js"></script>
<script src="/target/target-script-min.js"></script>
<script type="text/javascript">
require("weinre/common/Weinre").showNotImplemented()
</script>
-<script src="weinre-demo.js"></script>
</head>
<body onload="onLoad()">
diff --git a/weinre.web/demo/weinre-demo-pieces.html b/weinre.web/demo/weinre-demo-pieces.html
index 2b87785..c7473b5 100644
--- a/weinre.web/demo/weinre-demo-pieces.html
+++ b/weinre.web/demo/weinre-demo-pieces.html
@@ -10,6 +10,7 @@
<meta name="viewport" content="user-scalable=no, width=device-width, height=device-height">
<title>weinre demo</title>
<link rel="stylesheet" href="weinre-demo.css">
+<script src="weinre-demo.js"></script>
<script src="/modjewel-require.js"></script>
<script type="text/javascript">require("modjewel").warnOnRecursiveRequire(true)</script>
<script src="/scooj.transportd.js"></script>
@@ -48,8 +49,6 @@
require("weinre/common/Weinre").showNotImplemented()
require('weinre/target/Target').main()
</script>
-
-<script src="weinre-demo.js"></script>
</head>
<body onload="onLoad()">
diff --git a/weinre.web/demo/weinre-demo.html b/weinre.web/demo/weinre-demo.html
index ebdd2de..6a57672 100644
--- a/weinre.web/demo/weinre-demo.html
+++ b/weinre.web/demo/weinre-demo.html
@@ -10,13 +10,12 @@
<meta name="viewport" content="user-scalable=no, width=device-width, height=device-height">
<title>weinre demo</title>
<link rel="stylesheet" href="weinre-demo.css">
+<script src="weinre-demo.js"></script>
<script src="/target/target-script.js"></script>
<script type="text/javascript">
require("weinre/common/Weinre").showNotImplemented()
</script>
-
-<script src="weinre-demo.js"></script>
</head>
<body onload="onLoad()">
diff --git a/weinre.web/demo/weinre-demo.js b/weinre.web/demo/weinre-demo.js
index 6be2622..e0b95e3 100644
--- a/weinre.web/demo/weinre-demo.js
+++ b/weinre.web/demo/weinre-demo.js
@@ -13,6 +13,11 @@
var outputElement
var storageIndex = 0
+// set the id based on the hash
+var hash = location.href.split("#")[1]
+if (!hash) hash = "anonymous"
+window.WeinreServerId = hash
+
//------------------------------------------------------------------------------
function onLoad() {
if (!buttonStartStuff) buttonStartStuff = document.getElementById("button-start-stuff")
diff --git a/weinre.web/index.html b/weinre.web/index.html
index ac7e757..1b18726 100644
--- a/weinre.web/index.html
+++ b/weinre.web/index.html
@@ -33,6 +33,9 @@
textarea {
width: 100%;
}
+pre, .indent {
+ margin-left: 2em;
+}
</style>
</head>
<body>
@@ -47,15 +50,36 @@
<tr><td>target demo: <td> <span id="url-target-demo-min">???</span> <br><i>(<span id="url-target-demo-pieces"></span>)</i>
</table>
+<h2>Target Script</h2>
+
+<p>You can use this script to inject the weinre target code into your web page.
+
+<p class="indent"><code><span id="url-target-script">???</span></code>
+
+<p>Example:
+
+<pre>
+<script src="<span id="url-target-script-raw">???</span>"></script>
+</pre>
+
<h2>Target Bookmarklet</h2>
-<p>link: <span id="url-target-bookmarklet">???</span> (drag to your bookmarks)
+<p>You can use this bookmarklet to inject the weinre target code into any
+web page you are viewing.
+
+<p>link you can drag to your bookmarks:
+
+<div class="indent">
+<span id="url-target-bookmarklet">???</span>
+</div>
<p>bookmarklet url in a pre:
<pre id="target-bookmarklet-src-pre"></pre>
<p>bookmarklet url in a textarea:
+<div class="indent">
<textarea id="target-bookmarklet-src-text-area"></textarea>
+</div>
<h2>Development</h2>
diff --git a/weinre.web/index.js b/weinre.web/index.js
index b42f890..d8b66f5 100644
--- a/weinre.web/index.js
+++ b/weinre.web/index.js
@@ -9,12 +9,19 @@
var weinre_host = location.hostname
var weinre_port = location.port
var weinre_pathname = location.pathname
+var weinre_id = "anonymous"
-replaceURL("url-client-ui", buildHttpURL("client/"))
+var hash = location.href.split("#")[1]
+if (hash) {
+ weinre_id = hash
+}
+
+replaceURL("url-client-ui", buildHttpURL("client/#" + weinre_id))
replaceURL("url-interfaces", buildHttpURL("interfaces/interfaces.html"))
-replaceURL("url-target-demo", buildHttpURL("demo/weinre-demo.html"))
-replaceURL("url-target-demo-min", buildHttpURL("demo/weinre-demo-min.html"))
-replaceURL("url-target-demo-pieces", buildHttpURL("demo/weinre-demo-pieces.html"), "pieces version")
+replaceURL("url-target-demo", buildHttpURL("demo/weinre-demo.html#" + weinre_id))
+replaceURL("url-target-demo-min", buildHttpURL("demo/weinre-demo-min.html#" + weinre_id))
+replaceURL("url-target-demo-pieces", buildHttpURL("demo/weinre-demo-pieces.html#" + weinre_id), "pieces version")
+replaceURL("url-target-script", buildHttpURL("target/target-script-min.js#" + weinre_id))
replaceURL("url-target-bookmarklet", getTargetBookmarklet(), "weinre target debug")
replaceURL("url-target-documentation", buildHttpURL("doc/"))
//replaceURL("url-client-protocol", buildHttpURL("ws/client/"))
@@ -34,6 +41,8 @@
replaceText("target-bookmarklet-src-pre", getTargetBookmarklet())
replaceText("target-bookmarklet-src-text-area", getTargetBookmarklet())
+replaceText("url-target-script-raw", buildHttpURL("target/target-script-min.js#" + weinre_id))
+
//---------------------------------------------------------------------
function buildHttpURL(uri) {
var port = weinre_port
@@ -70,7 +79,7 @@
script = script.replace(/\n/g, "")
script = script.replace("targetBookmarkletFunction","")
script = script.replace(/\s*/g, "")
- script = script.replace("???", buildHttpURL("target/target-script-min.js"))
+ script = script.replace("???", buildHttpURL("target/target-script-min.js#" + weinre_id))
script = "(" + script + ')(document.createElement("script"));void(0);'
return 'javascript:' + script
}
diff --git a/weinre.web/modules/weinre/client/Client.scoop b/weinre.web/modules/weinre/client/Client.scoop
index 08cb40f..584d0d3 100644
--- a/weinre.web/modules/weinre/client/Client.scoop
+++ b/weinre.web/modules/weinre/client/Client.scoop
@@ -38,7 +38,7 @@
window.addEventListener("load", Binding(this, "onLoaded"), false)
// create the socket
- var messageDispatcher = new MessageDispatcher("../ws/client")
+ var messageDispatcher = new MessageDispatcher("../ws/client", this._getId())
Weinre.messageDispatcher = messageDispatcher
// finish setting up InspectorBackend
@@ -55,6 +55,12 @@
WebInspector.mainResource.url = location.href
//-----------------------------------------------------------------------------
+method _getId
+ var hash = location.href.split("#")[1]
+ if (hash) return hash
+ return "anonymous"
+
+//-----------------------------------------------------------------------------
method uiAvailable
return WebInspector.panels && WebInspector.panels.remote
@@ -90,6 +96,8 @@
//-----------------------------------------------------------------------------
method onLoaded
+ Weinre.WeinreClientCommands.registerClient(Binding(this, this.cb_registerClient))
+
this._installRemotePanel()
var messageDispatcher = Weinre.messageDispatcher
@@ -99,16 +107,12 @@
messageDispatcher.registerInterface("WeinreClientEvents", new WeinreClientEventsImpl(this), false)
messageDispatcher.registerInterface("InspectorFrontendHost", InspectorFrontendHost, false)
- Weinre.WeinreClientCommands.registerClient(Binding(this, this.cb_registerClient))
-
//-----------------------------------------------------------------------------
-method cb_registerClient(clientId)
- Weinre.clientId = clientId
- Weinre.connectorId = clientId
- Callback.setConnectorId(clientId)
+method cb_registerClient(clientDescription)
+ Weinre.clientDescription = clientDescription
if (this.uiAvailable()) {
- WebInspector.panels.remote.setCurrentClient(clientId)
+ WebInspector.panels.remote.setCurrentClient(clientDescription.channel)
WebInspector.panels.remote.afterInitialConnection()
}
diff --git a/weinre.web/modules/weinre/client/ConnectorList.scoop b/weinre.web/modules/weinre/client/ConnectorList.scoop
index 92558cb..bb0746d 100644
--- a/weinre.web/modules/weinre/client/ConnectorList.scoop
+++ b/weinre.web/modules/weinre/client/ConnectorList.scoop
@@ -23,9 +23,9 @@
//-----------------------------------------------------------------------------
method add(connector)
- if (this.connectors[connector.id]) return
+ if (this.connectors[connector.channel]) return
- this.connectors[connector.id] = connector
+ this.connectors[connector.channel] = connector
var li = this.getListItem(connector)
@@ -44,12 +44,12 @@
}
//-----------------------------------------------------------------------------
-method getNewestConnectorId(ignoring)
+method getNewestConnectorChannel(ignoring)
var newest = 0
- for (var connectorId in this.connectors) {
- if (connectorId == ignoring) continue
- if (connectorId > newest) newest = connectorId
+ for (var connectorChannel in this.connectors) {
+ if (connectorChannel == ignoring) continue
+ if (connectorChannel > newest) newest = connectorChannel
}
if (newest == 0) return null
@@ -59,8 +59,8 @@
method getConnectorInsertionPoint(connector)
for (var i=0; i<this.ulConnectors.childNodes.length; i++) {
var childNode = this.ulConnectors.childNodes[i]
- if (null == childNode.connectorId) continue
- if (childNode.connectorId < connector.id) {
+ if (null == childNode.connectorChannel) continue
+ if (childNode.connectorChannel < connector.channel) {
return childNode
}
}
@@ -68,17 +68,17 @@
return null
//-----------------------------------------------------------------------------
-method remove(id, fast)
+method remove(channel, fast)
var self = this
- var element = this.getConnectorElement(id)
+ var element = this.getConnectorElement(channel)
if (!element) return
- var connector = this.connectors[id]
+ var connector = this.connectors[channel]
if (connector) {
connector.closed = true
}
- delete this.connectors[id]
+ delete this.connectors[channel]
if (fast) {
this._remove(element)
@@ -103,45 +103,45 @@
//-----------------------------------------------------------------------------
method removeAll()
this.getConnectors().forEach(function(connector) {
- this.remove(connector.id, true)
+ this.remove(connector.channel, true)
}, this)
//-----------------------------------------------------------------------------
method getConnectors()
var result = []
- for (var id in this.connectors) {
- if (!this.connectors.hasOwnProperty(id)) continue
+ for (var channel in this.connectors) {
+ if (!this.connectors.hasOwnProperty(channel)) continue
- result.push(this.connectors[id])
+ result.push(this.connectors[channel])
}
return result
//-----------------------------------------------------------------------------
-method getConnectorElement(id)
- var connector = this.connectors[id]
+method getConnectorElement(channel)
+ var connector = this.connectors[channel]
if (!connector) return null
return connector.element
//-----------------------------------------------------------------------------
-method setCurrent(id)
+method setCurrent(channel)
this.getConnectors().forEach(function(connector) {
connector.element.removeStyleClass("current")
})
- var element = this.getConnectorElement(id)
+ var element = this.getConnectorElement(channel)
if (null == element) return
element.addStyleClass("current")
//-----------------------------------------------------------------------------
-method setState(id, state)
- if (typeof id == "string") {
- var element = this.getConnectorElement(id)
+method setState(channel, state)
+ if (typeof channel == "string") {
+ var element = this.getConnectorElement(channel)
}
else {
- element = id
+ element = channel
}
if (!element) return
diff --git a/weinre.web/modules/weinre/client/RemotePanel.scoop b/weinre.web/modules/weinre/client/RemotePanel.scoop
index 2c612ef..5e0ec93 100644
--- a/weinre.web/modules/weinre/client/RemotePanel.scoop
+++ b/weinre.web/modules/weinre/client/RemotePanel.scoop
@@ -64,27 +64,27 @@
method addTarget(target)
this.targetList.add(target)
-method removeClient(id)
- this.clientList.remove(id)
+method removeClient(channel)
+ this.clientList.remove(channel)
-method removeTarget(id)
- this.targetList.remove(id)
+method removeTarget(channel)
+ this.targetList.remove(channel)
-method setCurrentClient(id)
- this.clientList.setCurrent(id)
+method setCurrentClient(channel)
+ this.clientList.setCurrent(channel)
-method setCurrentTarget(id)
- this.targetList.setCurrent(id)
+method setCurrentTarget(channel)
+ this.targetList.setCurrent(channel)
-method setClientState(id, state)
- this.clientList.setState(id, state)
+method setClientState(channel, state)
+ this.clientList.setState(channel, state)
-method setTargetState(id, state)
- this.targetList.setState(id, state)
+method setTargetState(channel, state)
+ this.targetList.setState(channel, state)
//-----------------------------------------------------------------------------
-method getNewestTargetId(ignoring)
- return this.targetList.getNewestConnectorId(ignoring)
+method getNewestTargetChannel(ignoring)
+ return this.targetList.getNewestConnectorChannel(ignoring)
//-----------------------------------------------------------------------------
method afterInitialConnection
@@ -111,10 +111,11 @@
if (!Weinre.client.autoConnect()) return
- var newestTargetId = this.getNewestTargetId()
- if (!newestTargetId) return
-
- Weinre.WeinreClientCommands.connectTarget(Weinre.connectorId, newestTargetId)
+ var newestTargetChannel = this.getNewestTargetChannel()
+ if (!newestTargetChannel) return
+ if (!Weinre.messageDispatcher) return
+
+ Weinre.WeinreClientCommands.connectTarget(Weinre.messageDispatcher.channel, newestTargetChannel)
//-----------------------------------------------------------------------------
@@ -183,34 +184,34 @@
//-----------------------------------------------------------------------------
method getListItem(target)
var self = this
- var text = target.hostName + " [id: " + target.id + "]" + " - " + target.url
+ var text = target.hostName + " [channel: " + target.channel + " id: " + target.id + "]" + " - " + target.url
var item = dt.LI(
- { $connectorId: target.id },
+ { $connectorChannel: target.channel },
text
)
item.addStyleClass("weinre-connector-item")
item.addStyleClass("target")
- item.addEventListener("click", function(e) {self.connectToTarget(target.id, e)}, false)
+ item.addEventListener("click", function(e) {self.connectToTarget(target.channel, e)}, false)
target.element = item
return item
//-----------------------------------------------------------------------------
-method connectToTarget(targetId, event)
+method connectToTarget(targetChannel, event)
if (event) {
event.preventDefault()
event.stopPropagation()
}
- var target = this.connectors[targetId]
+ var target = this.connectors[targetChannel]
if (!target) return false
if (target.closed) return false
- Weinre.WeinreClientCommands.connectTarget(Weinre.clientId, targetId)
+ Weinre.WeinreClientCommands.connectTarget(Weinre.messageDispatcher.channel, targetChannel)
return false
@@ -230,18 +231,20 @@
//-----------------------------------------------------------------------------
method getListItem(client)
- var text = client.hostName + " [id: " + client.id + "]"
+ var text = client.hostName + " [channel: " + client.channel + " id: " + client.id + "]"
var item = dt.LI(
- { $connectorId: client.id },
+ { $connectorChannel: client.channel },
text
)
item.addStyleClass("weinre-connector-item")
item.addStyleClass("client")
- if (client.id == Weinre.clientId) {
- item.addStyleClass("current")
+ if (Weinre.messageDispatcher) {
+ if (client.channel == Weinre.messageDispatcher.channel) {
+ item.addStyleClass("current")
+ }
}
client.element = item
diff --git a/weinre.web/modules/weinre/client/WeinreClientEventsImpl.scoop b/weinre.web/modules/weinre/client/WeinreClientEventsImpl.scoop
index 8c35aeb..8f925e4 100644
--- a/weinre.web/modules/weinre/client/WeinreClientEventsImpl.scoop
+++ b/weinre.web/modules/weinre/client/WeinreClientEventsImpl.scoop
@@ -26,55 +26,52 @@
}
if (!Weinre.client.autoConnect()) return
+ if (!Weinre.messageDispatcher) return
- Weinre.WeinreClientCommands.connectTarget(Weinre.clientId, targetDescription.id)
+ Weinre.WeinreClientCommands.connectTarget(Weinre.messageDispatcher.channel, targetDescription.channel)
//-----------------------------------------------------------------------------
-method clientUnregistered(/*int*/ clientId)
+method clientUnregistered(/*int*/ clientChannel)
if (this.client.uiAvailable()) {
- WebInspector.panels.remote.removeClient(clientId)
+ WebInspector.panels.remote.removeClient(clientChannel)
}
//-----------------------------------------------------------------------------
-method targetUnregistered(/*int*/ targetId)
+method targetUnregistered(/*int*/ targetChannel)
if (this.client.uiAvailable()) {
- WebInspector.panels.remote.removeTarget(targetId)
+ WebInspector.panels.remote.removeTarget(targetChannel)
}
//-----------------------------------------------------------------------------
-method connectionCreated(/*int*/ clientId, /*int*/ targetId)
+method connectionCreated(/*int*/ clientChannel, /*int*/ targetChannel)
if (this.client.uiAvailable()) {
- WebInspector.panels.remote.setClientState(clientId, "connected")
- WebInspector.panels.remote.setTargetState(targetId, "connected")
+ WebInspector.panels.remote.setClientState(clientChannel, "connected")
+ WebInspector.panels.remote.setTargetState(targetChannel, "connected")
}
- if (clientId != Weinre.clientId) return
+ if (clientChannel != Weinre.messageDispatcher.channel) return
- Weinre.targetId = targetId
-
WebInspector.panels.elements.reset()
WebInspector.panels.timeline._clearPanel()
WebInspector.panels.resources.reset()
//-----------------------------------------------------------------------------
-method connectionDestroyed(/*int*/ clientId, /*int*/ targetId)
+method connectionDestroyed(/*int*/ clientChannel, /*int*/ targetChannel)
if (this.client.uiAvailable()) {
- WebInspector.panels.remote.setClientState(clientId, "not-connected")
- WebInspector.panels.remote.setTargetState(targetId, "not-connected")
+ WebInspector.panels.remote.setClientState(clientChannel, "not-connected")
+ WebInspector.panels.remote.setTargetState(targetChannel, "not-connected")
}
- if (clientId != Weinre.clientId) return
-
- Weinre.targetId = null
+ if (clientChannel != Weinre.messageDispatcher.channel) return
if (!Weinre.client.autoConnect()) return
if (!this.client.uiAvailable()) return
- var nextTargetId = WebInspector.panels.remote.getNewestTargetId(targetId)
- if (!nextTargetId) return
+ var nextTargetChannel = WebInspector.panels.remote.getNewestTargetChannel(targetChannel)
+ if (!nextTargetChannel) return
- Weinre.WeinreClientCommands.connectTarget(Weinre.clientId, nextTargetId)
- Weinre.logInfo("autoconnecting to " + nextTargetId)
+ Weinre.WeinreClientCommands.connectTarget(Weinre.messageDispatcher.channel, nextTargetChannel)
+ Weinre.logInfo("autoconnecting to " + nextTargetChannel)
//-----------------------------------------------------------------------------
method sendCallback(/*int*/ callbackId, /*any*/ result)
diff --git a/weinre.web/modules/weinre/common/Callback.scoop b/weinre.web/modules/weinre/common/Callback.scoop
index b355714..92ded87 100644
--- a/weinre.web/modules/weinre/common/Callback.scoop
+++ b/weinre.web/modules/weinre/common/Callback.scoop
@@ -14,13 +14,13 @@
//-----------------------------------------------------------------------------
init
- var CallbackTable = {}
- var CallbackIndex = 1
- var ConnectorId = "???"
+ var CallbackTable = {}
+ var CallbackIndex = 1
+ var ConnectorChannel = "???"
//-----------------------------------------------------------------------------
-static method setConnectorId(connectorId)
- ConnectorId = "" + connectorId
+static method setConnectorChannel(connectorChannel)
+ ConnectorChannel = "" + connectorChannel
//-----------------------------------------------------------------------------
static method register(callback)
@@ -34,7 +34,7 @@
if (typeof func == "string") func = receiver.func
if (typeof func != "function") throw new Ex(arguments, "callback function was null or not found")
- var index = ConnectorId + "::" + CallbackIndex
+ var index = ConnectorChannel + "::" + CallbackIndex
CallbackIndex++
if (CallbackIndex >= 65536 * 65536) CallbackIndex = 1
diff --git a/weinre.web/modules/weinre/common/MessageDispatcher.scoop b/weinre.web/modules/weinre/common/MessageDispatcher.scoop
index f6adc72..c207e01 100644
--- a/weinre.web/modules/weinre/common/MessageDispatcher.scoop
+++ b/weinre.web/modules/weinre/common/MessageDispatcher.scoop
@@ -11,10 +11,16 @@
requireClass ./IDLTools
requireClass ./Binding
requireClass ./Ex
+requireClass ./Callback
//-----------------------------------------------------------------------------
-class MessageDispatcher(url)
+class MessageDispatcher(url, id)
+ if (!id) {
+ id = "anonymous"
+ }
+
this._url = url
+ this._id = id
this.error = null
this._opening = false
@@ -47,7 +53,7 @@
if (this._closed) throw new Ex(arguments, "socket has already been closed")
this._opening = true
- this._socket = new WebSocketXhr(this._url)
+ this._socket = new WebSocketXhr(this._url, this._id)
this._socket.addEventListener("open", Binding(this, "_handleOpen"))
this._socket.addEventListener("error", Binding(this, "_handleError"))
this._socket.addEventListener("message", Binding(this, "_handleMessage"))
@@ -122,9 +128,12 @@
return this._opened == true
//-----------------------------------------------------------------------------
-method _handleOpen
+method _handleOpen(event)
this._opening = false
this._opened = true
+ this.channel = event.channel
+
+ Callback.setConnectorChannel(this.channel)
if (Verbose) {
Weinre.logDebug(this.constructor.name + "[" + this._url + "]: opened")
diff --git a/weinre.web/modules/weinre/common/WebSocketXhr.scoop b/weinre.web/modules/weinre/common/WebSocketXhr.scoop
index 0eb5132..813e6a9 100644
--- a/weinre.web/modules/weinre/common/WebSocketXhr.scoop
+++ b/weinre.web/modules/weinre/common/WebSocketXhr.scoop
@@ -12,8 +12,8 @@
requireClass ./Native
//-----------------------------------------------------------------------------
-class WebSocketXhr(url)
- this.initialize(url)
+class WebSocketXhr(url, id)
+ this.initialize(url, id)
//-----------------------------------------------------------------------------
init
@@ -25,9 +25,14 @@
WebSocketXhr.CLOSED = 3
//-----------------------------------------------------------------------------
-method initialize(url)
+method initialize(url, id)
+ if (!id) {
+ id = "anonymous"
+ }
+
this.readyState = WebSocketXhr.CONNECTING
this._url = url
+ this._id = id
this._urlChannel = null
this._queuedSends = []
this._sendInProgress = true
@@ -43,7 +48,8 @@
//-----------------------------------------------------------------------------
method _getChannel
- this._xhr(this._url, "POST", "", this._handleXhrResponseGetChannel)
+ var body = JSON.stringify({ id: this._id})
+ this._xhr(this._url, "POST", body, this._handleXhrResponseGetChannel)
//-----------------------------------------------------------------------------
method _handleXhrResponseGetChannel(xhr)
@@ -64,12 +70,10 @@
return
}
- Weinre.connectorId = "" + object.channel
-
this._urlChannel = this._url + "/" + object.channel
this.readyState = WebSocketXhr.OPEN
- this._fireEventListeners("open", { message: "open" })
+ this._fireEventListeners("open", { message: "open", channel: object.channel })
this._sendInProgress = false
this._sendQueued()
diff --git a/weinre.web/modules/weinre/target/Target.scoop b/weinre.web/modules/weinre/target/Target.scoop
index d51ce41..38ff60b 100644
--- a/weinre.web/modules/weinre/target/Target.scoop
+++ b/weinre.web/modules/weinre/target/Target.scoop
@@ -47,7 +47,34 @@
//------------------------------------------------------------------------------
method setWeinreServerURLFromScriptSrc()
if (window.WeinreServerURL) return
+
+ var element = this.getTargetScriptElement()
+ var pattern = /(http:\/\/(.*?)\/)/
+ var match = pattern.exec(element.src)
+ if (match) {
+ window.WeinreServerURL = match[1]
+ return
+ }
+ var message = "unable to calculate the weinre server url; explicity set the variable window.WeinreServerURL instead"
+ alert(message)
+ throw new Ex(arguments, message)
+
+
+//-----------------------------------------------------------------------------
+method setWeinreServerIdFromScriptSrc()
+ if (window.WeinreServerId) return
+
+ var element = this.getTargetScriptElement()
+
+ var hash = element.src.split("#")[1]
+ if (!hash) hash = "anonymous"
+
+ window.WeinreServerId = hash
+
+//-----------------------------------------------------------------------------
+method getTargetScriptElement
+
var elements = document.getElementsByTagName("script")
var scripts = ["Target.", "target-script.", "target-script-min."]
@@ -56,23 +83,15 @@
for (j=0; j<scripts.length; j++) {
if (-1 != element.src.indexOf("/" + scripts[j])) {
- var pattern = /(http:\/\/(.*?)\/)/
- var match = pattern.exec(element.src)
- if (match) {
- window.WeinreServerURL = match[1]
- return
- }
+ return element
}
}
}
-
- var message = "unable to calculate the weinre server url; explicity set the variable window.WeinreServerURL instead"
- alert(message)
- throw new Ex(arguments, message)
//-----------------------------------------------------------------------------
method initialize()
this.setWeinreServerURLFromScriptSrc()
+ this.setWeinreServerIdFromScriptSrc()
if (window.WeinreServerURL[window.WeinreServerURL.length-1] != "/") {
window.WeinreServerURL += "/"
@@ -83,7 +102,7 @@
window.addEventListener("load", Binding(this, "onLoaded"), false)
- var messageDispatcher = new MessageDispatcher(window.WeinreServerURL + "ws/target")
+ var messageDispatcher = new MessageDispatcher(window.WeinreServerURL + "ws/target", window.WeinreServerId)
Weinre.messageDispatcher = messageDispatcher
Weinre.wi = {}
@@ -137,11 +156,8 @@
Weinre.WeinreTargetCommands.registerTarget(window.location.href, Binding(this, this.cb_registerTarget))
//-----------------------------------------------------------------------------
-method cb_registerTarget(targetId)
- Weinre.targetId = targetId
- Weinre.connectorId = targetId
-
- Callback.setConnectorId(targetId)
+method cb_registerTarget(targetDescription)
+ Weinre.targetDescription = targetDescription
//-----------------------------------------------------------------------------
method onLoaded()
diff --git a/weinre.web/modules/weinre/target/WeinreTargetEventsImpl.scoop b/weinre.web/modules/weinre/target/WeinreTargetEventsImpl.scoop
index 9adf1e9..6f8a5e3 100644
--- a/weinre.web/modules/weinre/target/WeinreTargetEventsImpl.scoop
+++ b/weinre.web/modules/weinre/target/WeinreTargetEventsImpl.scoop
@@ -15,8 +15,8 @@
class WeinreTargetEventsImpl
//-----------------------------------------------------------------------------
-method connectionCreated(/*string*/ clientId, /*string*/ targetId)
- var message = "weinre: target " + targetId + " connected to client " + clientId
+method connectionCreated(/*string*/ clientChannel, /*string*/ targetChannel)
+ var message = "weinre: target " + targetChannel + " connected to client " + clientChannel
Weinre.logInfo(message)
var oldValue = Console.useRemote(true)
@@ -28,8 +28,8 @@
Weinre.wi.DOMStorage.initialize()
//-----------------------------------------------------------------------------
-method connectionDestroyed(/*string*/ clientId, /*string*/ targetId)
- var message = "weinre: target " + targetId + " disconnected from client " + clientId
+method connectionDestroyed(/*string*/ clientChannel, /*string*/ targetChannel)
+ var message = "weinre: target " + targetChannel + " disconnected from client " + clientChannel
Weinre.logInfo(message)
var oldValue = Console.useRemote(false)