Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files
Merge branch 'issue/50' into develop
  • Loading branch information
pmuellr committed May 3, 2011
2 parents 3f28244 + 2896549 commit 1ed3bdc6879fbf23afe732d09521f855da151f79
Show file tree
Hide file tree
Showing 29 changed files with 398 additions and 154 deletions.
@@ -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}"/>
@@ -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 &lt;script src&gt; element of:

<pre>
&lt;script src="http://some.server.xyz/target/target-script-min.js"&gt;&lt;/script&gt;
</pre>

<p>use this script element to connect with id <code>itsReallyMe</code>

<pre>
&lt;script src="http://some.server.xyz/target/target-script-min.js#itsReallyMe"&gt;&lt;/script&gt;
</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>
@@ -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>
@@ -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>
@@ -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 @@ public class Channel {
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>();
@@ -162,6 +166,11 @@ public String getName() {
return name;
}

//---------------------------------------------------------------
public String getId() {
return id;
}

//---------------------------------------------------------------
public long getLastRead() {
return lastRead;
@@ -73,10 +73,10 @@ public List<Channel> getChannels() {
}

//---------------------------------------------------------------
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);
@@ -65,7 +65,8 @@ public JSONObject getDescription() {
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());
}
@@ -55,51 +55,59 @@ public void channelDeregistered(Channel channel) {
//---------------------------------------------------------------
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 @@ private void _sendConnectionEvent(Client client, Target target, String message)
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);
}
}
@@ -45,6 +45,11 @@ public String getName() {
return channel.getName();
}

//---------------------------------------------------------------
public String getId() {
return channel.getId();
}

//---------------------------------------------------------------
public List<Connector> getConnections() {
List<Connector> result = new ArrayList<Connector>();
@@ -93,7 +93,8 @@ public JSONObject getDescription() {
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());
@@ -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 handleOptions(String target, Request baseRequest, HttpServletRequest
//---------------------------------------------------------------
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();
}

@@ -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 class WeinreClientCommands {
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 getTargets(Channel channel, String callbackId) throws IOException {

//---------------------------------------------------------------
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) {

0 comments on commit 1ed3bdc

Please sign in to comment.