
<!--
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
-->

<p><span class="weinre">weinre</span> is <b>WE</b>b <b>IN</b>spector <b>RE</b>mote.
Pronounced like the word "winery".  Or maybe like the word "weiner".  Who knows,
really.

<p><span class="weinre">weinre</span> is a debugger for web pages, like
FireBug (for FireFox)
and
Web Inspector (for WebKit-based browsers), except it's designed
to work <b>remotely</b>, and in particular, to <b>allow you debug web pages
on a mobile device such as a phone</b>.

<p>Interesting places to visit:
<table>

<tr><td>videos at YouTube:
<td><a href="http://www.youtube.com/results?search_query=weinre">http://www.youtube.com/results?search_query=weinre</a>

<tr><td>this documentation:
<td><a href="http://people.apache.org/~pmuellr/weinre/">http://people.apache.org/~pmuellr/weinre/</a> [temporary]</a>

<tr><td>unofficial binary packages:
<td><a href="http://people.apache.org/~pmuellr/weinre/">http://people.apache.org/~pmuellr/weinre/</a> [temporary]</a>

<tr><td>issues:
<td><a href="https://issues.apache.org/jira/secure/IssueNavigator.jspa?jqlQuery=project=CB+and+component=weinre">https://issues.apache.org/jira/gobble-de-gook/...</a>

<tr><td>create a new issue:
<td>
<a href="https://issues.apache.org/jira/secure/CreateIssueDetails!init.jspa?pid=12312420&components=12316604&issuetype=1">bug</a>
or
<a href="https://issues.apache.org/jira/secure/CreateIssueDetails!init.jspa?pid=12312420&components=12316604&issuetype=2">new feature</a>

<tr><td>cloneable source at Apache:
<td><a href="https://git-wip-us.apache.org/repos/asf/incubator-cordova-weinre.git">https://git-wip-us.apache.org/repos/asf/incubator-cordova-weinre.git</a>

<tr><td>Apache repo cloned at GitHub:
<td><a href="https://github.com/apache/incubator-cordova-weinre">https://github.com/apache/incubator-cordova-weinre</a>

<tr><td>mailing lists at Apache:
<td><a href="http://incubator.apache.org/cordova/#mailing-list">http://incubator.apache.org/cordova/#mailing-list</a> (use callback-dev)

<tr><td>discussion at Google Group:
<td><a href="http://groups.google.com/group/weinre">http://groups.google.com/group/weinre</a>

</table>

<p>More information on <span class="weinre">weinre</span>'s big brothers, Web Inspector / Google Chrome
Developer Tools, is available at
<a href="http://code.google.com/chrome/devtools/docs/overview.html">Google's Chrome Dev Tools pages</a>
and
<a href="http://developer.apple.com/library/safari/#documentation/appleapplications/Conceptual/Safari_Developer_Guide/DebuggingYourWebsite/DebuggingYourWebsite.html">Apple's Web Inspector pages</a>.

<p>If you aren't familiar with FireBug or Web Inspector,
<span class="weinre">weinre</span> isn't going to make too much sense to you.
<span class="weinre">weinre</span> reuses the user interface code from the
<a href="http://trac.webkit.org/wiki/WebInspector">Web Inspector project at WebKit</a>,
so if you've used Safari's Web Inspector or Chrome's Developer Tools,
<span class="weinre">weinre</span> will be very familiar.  If you're not
familiar with Web Inspector, the links above to Google's and Apple's documentation
will be useful.

<p>Here's an example session using <span class="weinre">weinre</span>:

<p><img src="images/weinre-demo.jpg">

<p>Two screen captures are shown above.  On the left is the
<span class="weinre">weinre</span> <b>client</b> application, displaying debug
information.
On the right is the <b>target</b> web page, running in Mobile Safari in the iOS Simulator.

<p>In normal usage, you will be running the <b>client</b> application in a browser
on your desktop/laptop, and running a <b>target</b> web page on your mobile device.

<p>In the session above, the debugger is display the Elements panel, with the
embedded console expanded in the bottom third of the window.  In the console
area, we've entered two statements:

<pre>
document.body.style.backgroundColor
document.body.style.backgroundColor = "pink"
</pre>

<p>The result of running the first statement shows the value of the body's background style is not set.
The second statement sets the body's background to pink.  That horrifying pink
background is then rendered in the <b>target</b>'s window.

<p>In addition, an <tt>h1</tt> element is selected in the upper third of the
Elements panel, which causes the side panels on the right to be filled in with
relevant information.  In this case, the matched CSS rules for that <tt>h1</tt>
element are being shown.

<p>If you are familiar with WebKit's Web Inspector,
a partial list of differences between it and <span class="weinre">weinre</span>
are listed below:

<ul class="spaced">

<li><span class="weinre">weinre</span> does not make use of any 'native' code,
it's all JavaScript (and currently Java code for the 'server').

<li>Because <span class="weinre">weinre</span> doesn't use 'native' code,
it's functionality is limited.  For instance, source level debug of JavaScript
is not <span class="strike">possible</span>
<a href="http://lexandera.com/aardwolf/">easy</a>.

<li>Because <span class="weinre">weinre</span> doesn't use 'native' code,
the debug target code will run on browsers
without specialized debug support.  For instance, a browser running on your phone.

<li><span class="weinre">weinre</span> supports 'remote' interaction,
so you can run the debugger user interface on one
machine and can debug a web page running
on another machine.  For instance, debug a web page displayed on your phone from your
laptop.

<li>Because <span class="weinre">weinre</span> supports 'remote' interaction,
multiple debug clients can be debugging the same debug target at the same time.

<li>One thing <b>not</b> different from Web Inspector is that the debug client
user interface only runs on WebKit-based browsers.

</ul>

<!-- ======================================================== -->
<h2>Supported Libraries and Platforms</h2>

<p>Generally version numbers listed here are the earliest
versions of the relevant thing that have been tested.
Later versions of those things are also hopefully supported,
but let us know.

<h3>Libraries not supported</h3>

<ul>
<li>versions of Prototype.js before version 1.7 are not supported,
as they do not support the <tt>JSON.stringify()</tt> API correctly.  You
will get an <tt>alert()</tt> in the web page you are debugging if you
attempt to debug it with <span class="weinre">weinre</span> and you are using an unsupported
version of Prototype.js.
</ul>

<h3>Platforms supported - debug server</h3>
<p>Any platform that supports <a href="http://nodejs.org/">node.js</a>.

<h3>Platforms supported - debug client</h3>
<p>The browser where the debugger user interface runs.

<ul>
<li>Google Chrome
<li>Apple Safari
<li>Other recent-ish WebKit-based browsers
</ul>

<h3>Platforms supported - debug target</h3>
<p>The browser with the page you are debugging.

<ul>
<li>Android Browser application
<li>iOS Mobile Safari application
<li>PhoneGap/Cordova
<li>other
</ul>

<h3>Platforms not supported - debug target</h3>

<ul>
<li>iOS 3.1.3 or earlier
<li>webOS 1.45 or earlier
</ul>

